diff --git a/.circleci/config.yml b/.circleci/config.yml index 5917b7f91d019..0dffb662b1168 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -29,12 +29,18 @@ parameters: kontrol_dispatch: type: boolean default: false + cannon_full_test_dispatch: + type: boolean + default: false sdk_dispatch: type: boolean default: false docker_publish_dispatch: type: boolean default: false + publish_contract_artifacts_dispatch: + type: boolean + default: false orbs: go: circleci/go@1.8.0 @@ -127,17 +133,45 @@ commands: branch_pattern: develop mentions: "<< parameters.mentions >>" + run-contracts-check: + parameters: + command: + description: Just command that runs the check + type: string + steps: + - run: + name: <> + command: | + git reset --hard + just <> + git diff --quiet --exit-code + working_directory: packages/contracts-bedrock + when: always + environment: + FOUNDRY_PROFILE: ci + jobs: cannon-go-lint-and-test: docker: - image: <> - resource_class: medium + parameters: + skip_slow_tests: + type: boolean + default: false + notify: + description: Whether to notify on failure + type: boolean + default: false + resource_class: xlarge steps: - checkout - check-changed: patterns: cannon,packages/contracts-bedrock/src/cannon,op-preimage,go.mod - attach_workspace: at: "." + - restore_cache: + name: Restore Go modules cache + key: gomod-{{ checksum "go.sum" }} - run: name: prep Cannon results dir command: mkdir -p /tmp/test-results @@ -153,9 +187,10 @@ jobs: - run: name: Cannon Go tests command: | + export SKIP_SLOW_TESTS=<> mkdir -p /testlogs gotestsum --format=testname --junitfile=/tmp/test-results/cannon.xml --jsonfile=/testlogs/log.json \ - -- -parallel=2 -coverpkg=github.com/ethereum-optimism/optimism/cannon/... -coverprofile=coverage.out ./... + -- -parallel=8 -coverpkg=github.com/ethereum-optimism/optimism/cannon/... -coverprofile=coverage.out ./... working_directory: cannon - run: name: upload Cannon coverage @@ -165,6 +200,12 @@ jobs: - store_artifacts: path: /testlogs when: always + - when: + condition: <> + steps: + - notify-failures-on-develop: + mentions: "@proofs-squad" + cannon-build-test-vectors: docker: - image: <> @@ -178,81 +219,87 @@ jobs: command: python3 maketests.py && git diff --exit-code working_directory: cannon/mipsevm/tests/open_mips_tests - pnpm-monorepo: + contracts-bedrock-build: docker: - image: <> resource_class: xlarge + parameters: + skip_pattern: + description: Glob pattern of tests to skip + type: string + default: "" steps: - checkout -# - run: # temporarily disabled, to update ci-builder. -# name: "Check L1 geth version" -# command: ./ops/scripts/geth-version-checker.sh || (echo "geth version is wrong, update ci-builder"; false) - install-contracts-dependencies - restore_cache: name: Restore Go modules cache - key: gomod-{{ checksum "go.sum" }} + keys: + - gomod-contracts-build-{{ checksum "go.sum" }} + - gomod-contracts-build- + - restore_cache: + name: Restore Go build cache + keys: + - golang-build-cache-contracts-build-{{ checksum "go.sum" }} + - golang-build-cache-contracts-build- - run: - name: print forge version + name: Print forge version command: forge --version + - run: + name: Pull artifacts + command: bash scripts/ops/pull-artifacts.sh + working_directory: packages/contracts-bedrock - run: name: Build contracts + command: forge build --deny-warnings --skip <> environment: FOUNDRY_PROFILE: ci - command: just build working_directory: packages/contracts-bedrock - run: name: Generate L2OO allocs - command: DEVNET_L2OO="true" make devnet-allocs - - run: - name: Copy L2OO allocs to .devnet-l2oo - command: cp -r .devnet/ .devnet-l2oo/ + command: | + DEVNET_L2OO="true" make devnet-allocs + cp -r .devnet/ .devnet-l2oo/ - run: name: Generate AltDA allocs - command: DEVNET_ALTDA="true" make devnet-allocs - - run: - name: Copy AltDA allocs to .devnet-altda - command: cp -r .devnet/ .devnet-altda/ + command: | + DEVNET_ALTDA="true" make devnet-allocs + cp -r .devnet/ .devnet-altda/ - run: name: Generate Generic AltDA allocs - command: DEVNET_ALTDA="true" GENERIC_ALTDA="true" make devnet-allocs + command: | + DEVNET_ALTDA="true" GENERIC_ALTDA="true" make devnet-allocs + cp -r .devnet/ .devnet-altda-generic/ - run: - name: Copy AltDA allocs to .devnet-altda - command: cp -r .devnet/ .devnet-altda-generic/ + name: Generate MT-Cannon allocs + command: | + USE_MT_CANNON="true" make devnet-allocs + cp -r .devnet/ .devnet-mt-cannon/ - run: name: Generate default allocs command: make devnet-allocs + - save_cache: + name: Save Go modules cache + key: gomod-contracts-build-{{ checksum "go.sum" }} + paths: + - "/go/pkg/mod" + - save_cache: + name: Save Go build cache + key: golang-build-cache-contracts-build-{{ checksum "go.sum" }} + paths: + - "/root/.cache/go-build" - persist_to_workspace: root: "." paths: - "packages/contracts-bedrock/cache" - "packages/contracts-bedrock/artifacts" - "packages/contracts-bedrock/forge-artifacts" - - ".devnet/allocs-l1.json" - - ".devnet/allocs-l2-delta.json" - - ".devnet/allocs-l2-ecotone.json" - - ".devnet/allocs-l2-fjord.json" - - ".devnet/allocs-l2-granite.json" - - ".devnet/addresses.json" - - ".devnet-l2oo/allocs-l1.json" - - ".devnet-l2oo/addresses.json" - - ".devnet-l2oo/allocs-l2-delta.json" - - ".devnet-l2oo/allocs-l2-ecotone.json" - - ".devnet-l2oo/allocs-l2-fjord.json" - - ".devnet-l2oo/allocs-l2-granite.json" - - ".devnet-altda/allocs-l1.json" - - ".devnet-altda/addresses.json" - - ".devnet-altda/allocs-l2-delta.json" - - ".devnet-altda/allocs-l2-ecotone.json" - - ".devnet-altda/allocs-l2-fjord.json" - - ".devnet-altda/allocs-l2-granite.json" - - ".devnet-altda-generic/allocs-l1.json" - - ".devnet-altda-generic/addresses.json" - - ".devnet-altda-generic/allocs-l2-delta.json" - - ".devnet-altda-generic/allocs-l2-ecotone.json" - - ".devnet-altda-generic/allocs-l2-fjord.json" - - ".devnet-altda-generic/allocs-l2-granite.json" - "packages/contracts-bedrock/deploy-config/devnetL1.json" - "packages/contracts-bedrock/deployments/devnetL1" + - ".devnet" + - ".devnet-l2oo" + - ".devnet-altda" + - ".devnet-altda-generic" + - ".devnet-mt-cannon" - notify-failures-on-develop docker-build: @@ -523,33 +570,97 @@ jobs: docker: - image: <> resource_class: xlarge + parameters: + test_parallelism: + description: Number of test jobs to run in parallel + type: integer + default: 4 + test_list: + description: List of test files to run + type: string + test_fuzz_runs: + description: Number of fuzz runs to apply + type: integer + default: 512 + test_invariant_runs: + description: Number of invariant runs to apply + type: integer + default: 32 + test_invariant_depth: + description: Depth of invariant runs + type: integer + default: 64 + test_timeout: + description: Timeout for running tests + type: string + default: 15m + parallelism: <> steps: - checkout + - attach_workspace: { at: "." } + - install-contracts-dependencies + - run: + name: Check if test list is empty + command: | + TEST_FILES=$(<>) + if [ -z "$TEST_FILES" ]; then + echo "No test files to run. Exiting early." + circleci-agent step halt + fi + working_directory: packages/contracts-bedrock - check-changed: patterns: contracts-bedrock,op-node - - install-contracts-dependencies + - restore_cache: + name: Restore Go modules cache + key: gomod-{{ checksum "go.sum" }} + - restore_cache: + name: Restore Go build cache + keys: + - golang-build-cache-contracts-bedrock-tests-{{ checksum "go.sum" }} + - golang-build-cache-contracts-bedrock-tests- - run: - name: print dependencies + name: Print dependencies command: just dep-status working_directory: packages/contracts-bedrock - run: - name: print forge version + name: Print forge version command: forge --version working_directory: packages/contracts-bedrock - run: - name: run tests - command: just test + name: Pull artifacts + command: bash scripts/ops/pull-artifacts.sh + working_directory: packages/contracts-bedrock + - run: + name: Build go-ffi + command: just build-go-ffi + working_directory: packages/contracts-bedrock + - run: + name: Run tests + command: | + TEST_FILES=$(<>) + TEST_FILES=$(echo "$TEST_FILES" | circleci tests split --split-by=timings) + TEST_FILES=$(echo "$TEST_FILES" | sed 's|^test/||') + MATCH_PATH="./test/{$(echo "$TEST_FILES" | paste -sd "," -)}" + export FOUNDRY_INVARIANT_RUNS=<> + export FOUNDRY_INVARIANT_DEPTH=<> + forge test --deny-warnings --fuzz-runs <> --match-path "$MATCH_PATH" environment: FOUNDRY_PROFILE: ci working_directory: packages/contracts-bedrock - no_output_timeout: 15m + no_output_timeout: <> - run: - name: print failed test traces + name: Print failed test traces command: just test-rerun environment: FOUNDRY_PROFILE: ci working_directory: packages/contracts-bedrock when: on_fail + - save_cache: + name: Save Go build cache + key: golang-build-cache-contracts-bedrock-tests-{{ checksum "go.sum" }} + paths: + - "/root/.cache/go-build" + - notify-failures-on-develop contracts-bedrock-checks: docker: @@ -564,111 +675,49 @@ jobs: - setup_remote_docker: docker_layer_caching: true - run: - name: forge version + name: print forge version command: forge --version - - run: - name: solc warnings check - command: | - forge build --force --deny-warnings || echo "export SOLC_WARNINGS_CHECK=1" >> "$BASH_ENV" - environment: - FOUNDRY_PROFILE: ci - working_directory: packages/contracts-bedrock - - run: - # Semver lock must come second because one of the later steps may modify the cache & force a contracts rebuild. - name: semver lock - command: | - just semver-lock - git diff --exit-code semver-lock.json || echo "export SEMVER_LOCK_STATUS=1" >> "$BASH_ENV" - working_directory: packages/contracts-bedrock - - run: - name: check deploy configs - command: just validate-deploy-configs || echo "export DEPLOY_CONFIGS_STATUS=1" >> "$BASH_ENV" - working_directory: packages/contracts-bedrock - - run: - name: lint - command: | - just lint-check || echo "export LINT_STATUS=1" >> "$BASH_ENV" - working_directory: packages/contracts-bedrock - - run: - name: gas snapshot - command: | - just gas-snapshot-check || echo "export GAS_SNAPSHOT_STATUS=1" >> "$BASH_ENV" - environment: - FOUNDRY_PROFILE: ci - working_directory: packages/contracts-bedrock - no_output_timeout: 15m - - run: - name: invariant docs - command: | - just autogen-invariant-docs - git diff --exit-code ./invariant-docs/*.md || echo "export INVARIANT_DOCS_STATUS=1" >> "$BASH_ENV" - working_directory: packages/contracts-bedrock - - run: - name: snapshots - command: | - just snapshots-check || echo "export SNAPSHOTS_STATUS=1" >> "$BASH_ENV" - working_directory: packages/contracts-bedrock - - run: - name: size check - command: | - forge build --sizes --skip "/**/test/**" --skip "/**/scripts/**" || echo "export SIZE_CHECK=1" >> "$BASH_ENV" - environment: - FOUNDRY_PROFILE: ci - working_directory: packages/contracts-bedrock - - run: - name: check statuses - command: | - if [[ "$LINT_STATUS" -ne 0 ]]; then - echo "Linting failed, see job output for details." - FAILED=1 - fi - if [[ "$SOLC_WARNINGS_CHECK" -ne 0 ]]; then - echo "Solidity emitted warnings, see job output for details." - FAILED=1 - fi - if [[ "$GAS_SNAPSHOT_STATUS" -ne 0 ]]; then - 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." - FAILED=1 - fi - if [[ "$INVARIANT_DOCS_STATUS" -ne 0 ]]; then - echo "Invariant docs failed, see job output for details." - FAILED=1 - fi - if [[ "$DEPLOY_CONFIGS_STATUS" -ne 0 ]]; then - echo "Deploy config check failed, see job output for details." - FAILED=1 - fi - if [[ "$SNAPSHOTS_STATUS" -ne 0 ]]; then - echo "Snapshots check failed, see job output for details." - FAILED=1 - fi - if [[ "$SIZE_CHECK" -ne 0 ]]; then - echo "Contract(s) exceed size limit, see job output for details." - FAILED=1 - fi - if [[ "$FAILED" -ne 0 ]]; then - exit 1 - fi + - run-contracts-check: + command: semver-lock + - run-contracts-check: + command: semver-diff-check-no-build + - run-contracts-check: + command: semver-natspec-check-no-build + - run-contracts-check: + command: validate-deploy-configs + - run-contracts-check: + command: lint + - run-contracts-check: + command: gas-snapshot-check + - run-contracts-check: + command: snapshots-check-no-build + - run-contracts-check: + command: kontrol-deployment-check + - run-contracts-check: + command: interfaces-check-no-build + - run-contracts-check: + command: size-check - contracts-bedrock-validate-spaces: + contracts-bedrock-validate-spacers: docker: - image: <> resource_class: medium steps: - checkout - attach_workspace: { at: "." } + - install-contracts-dependencies - check-changed: patterns: contracts-bedrock - run: name: validate spacers - command: just validate-spacers + command: just validate-spacers-no-build working_directory: packages/contracts-bedrock todo-issues: + parameters: + check_closed: + type: boolean + default: true machine: image: <> steps: @@ -678,7 +727,7 @@ jobs: command: sudo apt-get install -y ripgrep - run: name: Check TODO issues - command: ./ops/scripts/todo-checker.sh --verbose + command: ./ops/scripts/todo-checker.sh --verbose <<#parameters.check_closed>> --check-closed <> - notify-failures-on-develop fuzz-golang: @@ -707,25 +756,19 @@ jobs: key: gomod-{{ checksum "go.sum" }} - restore_cache: name: Restore Go build cache - key: golang-build-cache + keys: + - golang-build-cache-fuzz-golang-{{ checksum "go.sum" }} + - golang-build-cache-fuzz-golang- - run: name: Fuzz command: make fuzz working_directory: "<>" - save_cache: - key: golang-build-cache + name: Save Go build cache + key: golang-build-cache-fuzz-golang-{{ checksum "go.sum" }} paths: - "/root/.cache/go-build" - l1-geth-version-check: - docker: - - image: <> - steps: - - checkout - - run: - name: "Check L1 geth version" - command: ./ops/scripts/geth-version-checker.sh || (echo "geth version is wrong, update ci-builder"; false) - go-lint: docker: - image: <> @@ -735,9 +778,15 @@ jobs: name: Restore Go modules cache key: gomod-{{ checksum "go.sum" }} - restore_cache: - key: golang-build-cache + name: Restore Go build cache + keys: + - golang-build-cache-lint-{{ checksum "go.sum" }} + - golang-build-cache-lint- - restore_cache: - key: golang-lint-cache + name: Restore Go lint cache + keys: + - golang-lint-cache-{{ checksum "go.sum" }} + - golang-lint-cache- - run: name: run Go linter command: | @@ -746,21 +795,81 @@ jobs: make lint-go working_directory: . - save_cache: - key: golang-build-cache + name: Save Go build cache + key: golang-build-cache-lint-{{ checksum "go.sum" }} paths: - "/root/.cache/go-build" - save_cache: - key: golang-lint-cache + name: Save Go lint cache + key: golang-lint-cache-{{ checksum "go.sum" }} paths: - "/root/.cache/golangci-lint" + go-test-kurtosis: + parameters: + module: + description: Go Module Name + type: string + uses_artifacts: + description: Uses contract artifacts + type: boolean + default: false + test_directory: + description: Test directory + type: string + default: "./..." + machine: + image: <> # only used to enable codecov. + resource_class: xlarge + steps: + - run: + name: Install components + command: | + go version + go install gotest.tools/gotestsum@v1.11.0 + - run: + name: Install Kurtosis + command: | + echo "deb [trusted=yes] https://apt.fury.io/kurtosis-tech/ /" | sudo tee /etc/apt/sources.list.d/kurtosis.list + sudo apt update + sudo apt install kurtosis-cli=1.3.0 + kurtosis engine start + - checkout + - when: + condition: <> + steps: + - attach_workspace: { at: "." } + - run: + name: prep results dir + command: | + # Make sure the workspace is properly owned + sudo chown -R $USER:$USER . + mkdir -p /tmp/test-results + mkdir -p /tmp/testlogs + - run: + name: run tests + command: | + ENABLE_KURTOSIS=true gotestsum \ + --format=testname \ + --junitfile=/tmp/test-results/<>.xml \ + --jsonfile=/tmp/testlogs/log.json \ + -- -parallel=8 \ + -coverpkg=github.com/ethereum-optimism/optimism/... \ + -coverprofile=coverage.out <> + working_directory: <> + - store_test_results: + path: /tmp/test-results + - store_artifacts: + path: /tmp/testlogs + when: always + go-test: parameters: module: description: Go Module Name type: string docker: - - image: <> # only used to enable codecov. + - image: <> resource_class: xlarge steps: - checkout @@ -768,30 +877,33 @@ jobs: name: Restore Go modules cache key: gomod-{{ checksum "go.sum" }} - restore_cache: + name: Restore Go build cache keys: - - golang-build-cache-<> - - golang-build-cache- + - golang-build-cache-test-<>-{{ checksum "go.sum" }} + - golang-build-cache-test- + - run: + name: Install components + command: | + go version + go install gotest.tools/gotestsum@v1.11.0 - run: name: prep results dir - command: mkdir -p /tmp/test-results && mkdir -p /testlogs + command: mkdir -p /tmp/test-results && mkdir -p /tmp/testlogs - run: name: run tests command: | - gotestsum --format=testname --junitfile=/tmp/test-results/<>.xml --jsonfile=/testlogs/log.json \ + gotestsum --format=testname --junitfile=/tmp/test-results/<>.xml --jsonfile=/tmp/testlogs/log.json \ -- -parallel=8 -coverpkg=github.com/ethereum-optimism/optimism/... -coverprofile=coverage.out ./... working_directory: <> - save_cache: - key: golang-build-cache-<> + name: Save Go build cache + key: golang-build-cache-test-<>-{{ checksum "go.sum" }} paths: - "/root/.cache/go-build" - # TODO(CLI-148): Fix codecov - #- run: - #name: upload coverage - #command: codecov --verbose --clean --flags bedrock-go-tests - store_test_results: path: /tmp/test-results - store_artifacts: - path: /testlogs + path: /tmp/testlogs when: always go-e2e-test: @@ -843,6 +955,13 @@ jobs: - run: name: Set OP_E2E_USE_ALTDA = true command: echo 'export OP_E2E_USE_ALTDA=true' >> $BASH_ENV + - when: + condition: + equal: ['-mt-cannon', <>] + steps: + - run: + name: Set OP_E2E_USE_MT_CANNON = true + command: echo 'export OP_E2E_USE_MT_CANNON=true' >> $BASH_ENV - check-changed: patterns: op-(.+),cannon,contracts-bedrock - run: @@ -853,7 +972,9 @@ jobs: key: gomod-{{ checksum "go.sum" }} - restore_cache: name: Restore Go build cache - key: golang-build-cache + keys: + - golang-build-cache-e2e-{{ checksum "go.sum" }} + - golang-build-cache-e2e- - attach_workspace: at: /tmp/workspace - run: @@ -894,59 +1015,17 @@ jobs: when: always - store_test_results: path: /tmp/test-results + - save_cache: + name: Save Go build cache + key: golang-build-cache-e2e-{{ checksum "go.sum" }} + paths: + - "/root/.cache/go-build" - when: condition: "<>" steps: - notify-failures-on-develop: mentions: "<>" - go-lint-test-build: - parameters: - binary_name: - description: Binary name to build - type: string - working_directory: - description: Working directory - type: string - build: - description: Whether or not to build the binary - type: boolean - default: true - dependencies: - description: Regex matching dependent packages - type: string - default: this-package-does-not-exist - docker: - - image: <> - resource_class: medium - steps: - - checkout - - check-changed: - patterns: <>,<> - - run: - name: Lint - command: make lint - working_directory: <> - - run: - name: Test - command: | - mkdir -p /test-results - gotestsum --format=testname --junitfile /test-results/tests.xml --jsonfile /test-results/log.json -- -parallel=2 - working_directory: <> - - store_test_results: - path: /test-results - - store_artifacts: - path: /testlogs - when: always - - when: - condition: - equal: [ true, <> ] - steps: - - run: - name: Build - command: make <> - working_directory: <> - cannon-prestate: docker: - image: <> @@ -956,10 +1035,22 @@ jobs: name: Restore Go modules cache key: gomod-{{ checksum "go.sum" }} - restore_cache: - key: golang-build-cache + name: Restore Go build cache + keys: + - golang-build-cache-cannon-prestate-{{ checksum "go.sum" }} + - golang-build-cache-cannon-prestate- + - run: + name: Build cannon + command: make cannon + - run: + name: Build op-program + command: make op-program - restore_cache: + name: Restore cannon prestate cache key: cannon-prestate-{{ checksum "./cannon/bin/cannon" }}-{{ checksum "op-program/bin/op-program-client.elf" }} - name: Load cannon prestate cache + - run: + name: Sanitize op-program guest + command: make -f cannon/Makefile sanitize-program GUEST_PROGRAM=op-program/bin/op-program-client.elf - run: name: generate cannon prestate command: make cannon-prestate @@ -970,6 +1061,21 @@ jobs: - "op-program/bin/prestate.json" - "op-program/bin/meta.json" - "op-program/bin/prestate-proof.json" + - run: + name: generate cannon-mt prestate + command: make cannon-prestate-mt + - save_cache: + key: cannon-prestate-mt-{{ checksum "./cannon/bin/cannon" }}-{{ checksum "op-program/bin/op-program-client.elf" }} + name: Save MT-Cannon prestate to cache + paths: + - "op-program/bin/prestate-mt.json" + - "op-program/bin/meta-mt.json" + - "op-program/bin/prestate-proof-mt.json" + - save_cache: + name: Save Go build cache + key: golang-build-cache-cannon-prestate-{{ checksum "go.sum" }} + paths: + - "/root/.cache/go-build" - persist_to_workspace: root: . paths: @@ -1007,6 +1113,16 @@ jobs: echo 'export EXPECTED_PRESTATE_HASH="0x03e69d3de5155f4a80da99dd534561cbddd4f9dd56c9ecc704d6886625711d2b"' >> $BASH_ENV elif [[ "<>" == "1.2.0" ]]; then echo 'export EXPECTED_PRESTATE_HASH="0x03617abec0b255dc7fc7a0513a2c2220140a1dcd7a1c8eca567659bd67e05cea"' >> $BASH_ENV + elif [[ "<>" == "1.3.0-rc.1" ]]; then + echo 'export EXPECTED_PRESTATE_HASH="0x0367c4aa897bffbded0b523f277ca892298dc3c691baf37bc2099b86024f9673"' >> $BASH_ENV + elif [[ "<>" == "1.3.0-rc.2" ]]; then + echo 'export EXPECTED_PRESTATE_HASH="0x0385c3f8ee78491001d92b90b07d0cf387b7b52ab9b83b4d87c994e92cf823ba"' >> $BASH_ENV + elif [[ "<>" == "1.3.0-rc.3" ]]; then + echo 'export EXPECTED_PRESTATE_HASH="0x030de10d9da911a2b180ecfae2aeaba8758961fc28262ce989458c6f9a547922"' >> $BASH_ENV + elif [[ "<>" == "1.3.1-rc.1" ]]; then + echo 'export EXPECTED_PRESTATE_HASH="0x03e806a2859a875267a563462a06d4d1d1b455a9efee959a46e21e54b6caf69a"' >> $BASH_ENV + elif [[ "<>" == "1.3.1-rc.2" ]]; then + echo 'export EXPECTED_PRESTATE_HASH="0x038512e02c4c3f7bdaec27d00edf55b7155e0905301e1a88083e4e0a6764d54c"' >> $BASH_ENV else echo "Unknown prestate version <>" exit 1 @@ -1028,34 +1144,6 @@ jobs: - notify-failures-on-develop: mentions: "@proofs-squad" - - devnet-allocs: - docker: - - image: <> - resource_class: xlarge - steps: - - checkout - - restore_cache: - name: Restore Go modules cache - key: gomod-{{ checksum "go.sum" }} - - restore_cache: - key: golang-build-cache - - install-contracts-dependencies - - run: - name: generate devnet allocs - command: make devnet-allocs - - persist_to_workspace: - root: . - paths: - - ".devnet/allocs-l2-delta.json" - - ".devnet/allocs-l2-ecotone.json" - - ".devnet/allocs-l2-fjord.json" - - ".devnet/allocs-l2-granite.json" - - ".devnet/allocs-l1.json" - - ".devnet/addresses.json" - - "packages/contracts-bedrock/deploy-config/devnetL1.json" - - "packages/contracts-bedrock/deployments/devnetL1" - devnet: machine: image: <> @@ -1070,6 +1158,9 @@ jobs: DEVNET_ALTDA: 'false' steps: - checkout + - attach_workspace: { at: "." } + - check-changed: + patterns: op-(.+),packages,ops-bedrock,bedrock-devnet - when: condition: equal: ['altda', <>] @@ -1087,8 +1178,14 @@ jobs: - run: name: Set GENERIC_ALTDA = true command: echo 'export GENERIC_ALTDA=true' >> $BASH_ENV - - check-changed: - patterns: op-(.+),packages,ops-bedrock,bedrock-devnet + - restore_cache: + name: Restore Go modules cache + key: gomod-{{ checksum "go.sum" }} + - restore_cache: + name: Restore Go build cache + keys: + - golang-build-cache-devnet-{{ checksum "go.sum" }} + - golang-build-cache-devnet- - run: name: Install latest golang command: | @@ -1123,8 +1220,6 @@ jobs: curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | bash -s -- --to $HOME/bin --tag "${VER}" echo 'export PATH="${PATH}:$HOME/bin"' >> $BASH_ENV - install-contracts-dependencies - - attach_workspace: - at: "." - when: condition: not: @@ -1149,10 +1244,6 @@ jobs: docker tag "$IMAGE_BASE_PREFIX/op-batcher:<>" "$IMAGE_BASE_PREFIX/op-batcher:devnet" docker tag "$IMAGE_BASE_PREFIX/op-challenger:<>" "$IMAGE_BASE_PREFIX/op-challenger:devnet" docker tag "$IMAGE_BASE_PREFIX/da-server:<>" "$IMAGE_BASE_PREFIX/da-server:devnet" - - run: - name: Build contracts - working_directory: packages/contracts-bedrock - command: just build - run: name: Bring up the stack command: | @@ -1226,6 +1317,11 @@ jobs: ls -R forge-artifacts || echo "No forge artifacts found" when: on_fail working_directory: packages/contracts-bedrock + - save_cache: + name: Save Go build cache + key: golang-build-cache-devnet-{{ checksum "go.sum" }} + paths: + - /home/circleci/.cache/go-build semgrep-scan: parameters: @@ -1237,13 +1333,9 @@ jobs: SEMGREP_REPO_URL: << pipeline.project.git_url >> SEMGREP_BRANCH: << pipeline.git.branch >> SEMGREP_COMMIT: << pipeline.git.revision >> - - # Change job timeout (default is 1800 seconds; set to 0 to disable) - SEMGREP_TIMEOUT: 3000 - docker: - image: returntocorp/semgrep - resource_class: medium + resource_class: xlarge steps: - checkout - unless: @@ -1264,7 +1356,12 @@ jobs: echo 'export SEMGREP_REPO_NAME=$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME' >> $BASH_ENV - run: name: "Semgrep scan" - command: semgrep ci + # --timeout (in seconds) limits the time per rule and file. + # SEMGREP_TIMEOUT is the same, but docs have conflicting defaults (5s in CLI flag, 1800 in some places) + # https://semgrep.dev/docs/troubleshooting/semgrep-app#if-the-job-is-aborted-due-to-taking-too-long + command: semgrep ci --timeout=100 + # If semgrep hangs, stop the scan after 20m, to prevent a useless 5h job + no_output_timeout: 20m - notify-failures-on-develop go-mod-download: @@ -1293,58 +1390,12 @@ jobs: - 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" - op-service-rethdb-tests: - docker: - - image: <> - steps: - - checkout - - check-changed: - patterns: op-service,op-node - - restore_cache: - name: Restore Go modules cache - key: gomod-{{ checksum "go.sum" }} - - run: - name: Cargo fmt + clippy - command: | - cargo +nightly fmt -- --check - cargo +nightly clippy --all --all-features -- -D warnings - working_directory: op-service/rethdb-reader - - run: - name: Generate testdata db - command: cargo test - working_directory: op-service/rethdb-reader - - run: - name: Build dylib - command: cargo build --release - working_directory: op-service/rethdb-reader - - run: - name: Update LD_LIBRARY_PATH - command: echo 'export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:/root/project/op-service/rethdb-reader/target/release"' >> $BASH_ENV - - run: - name: Run op-service RethDB tests - command: | - gotestsum --format=standard-verbose --junitfile=/tmp/test-results/op-service.xml \ - -- -parallel=8 -coverpkg=github.com/ethereum-optimism/optimism/... -coverprofile=coverage.out \ - -run TestRethDB -tags rethdb -v - working_directory: op-service/sources - # TODO(CLI-148): Fix codecov - #- run: - #name: upload coverage - #command: codecov --verbose --clean --flags bedrock-rethdb-go-tests - bedrock-go-tests: # just a helper, that depends on all the actual test jobs docker: # Use a smaller base image to avoid pulling the huge ci-builder @@ -1377,12 +1428,17 @@ jobs: name: Restore Go modules cache key: gomod-{{ checksum "go.sum" }} - restore_cache: - key: golang-build-cache + key: golang-build-cache-op-program-compat-{{ checksum "go.sum" }} - run: name: compat-sepolia command: | make verify-compat working_directory: op-program + - save_cache: + name: Save Go build cache + key: golang-build-cache-op-program-compat-{{ checksum "go.sum" }} + paths: + - "/root/.cache/go-build" check-generated-mocks-op-node: docker: @@ -1406,29 +1462,6 @@ jobs: name: check-generated-mocks command: make generate-mocks-op-service && git diff --exit-code - check-values-match: - parameters: - pattern_file1: - type: string - default: "" - pattern_file2: - type: string - default: "" - file1_path: - type: string - default: "" - file2_path: - type: string - default: "" - docker: - - image: <> - steps: - - checkout - - run: - name: Verify Values Match - command: | - ./ops/scripts/ci-match-values-between-files.sh "<< parameters.file1_path >>" "<< parameters.pattern_file1 >>" "<< parameters.file2_path >>" "<< parameters.pattern_file2 >>" - kontrol-tests: docker: - image: << pipeline.parameters.ci_builder_image >> @@ -1461,6 +1494,34 @@ jobs: working_directory: ./packages/contracts-bedrock - notify-failures-on-develop + publish-contract-artifacts: + docker: + - image: <> + resource_class: xlarge + steps: + - gcp-cli/install + - gcp-oidc-authenticate: + gcp_cred_config_file_path: /root/gcp_cred_config.json + oidc_token_file_path: /root/oidc_token.json + project_id: GCP_TOOLS_ARTIFACTS_PROJECT_ID + service_account_email: GCP_CONTRACTS_PUBLISHER_SERVICE_ACCOUNT_EMAIL + - checkout + - install-contracts-dependencies + - run: + name: Pull artifacts + command: bash scripts/ops/pull-artifacts.sh + working_directory: packages/contracts-bedrock + - run: + name: Build contracts + environment: + FOUNDRY_PROFILE: ci + command: just build + working_directory: packages/contracts-bedrock + - run: + name: Publish artifacts + command: bash scripts/ops/publish-artifacts.sh + working_directory: packages/contracts-bedrock + workflows: main: when: @@ -1473,90 +1534,87 @@ workflows: - not: equal: [ scheduled_pipeline, << pipeline.trigger_source >> ] jobs: - - pnpm-monorepo: - name: pnpm-monorepo - - contracts-bedrock-tests + - go-mod-download + - contracts-bedrock-build: + # Build with just core + script contracts. + skip_pattern: test + - contracts-bedrock-tests: + # Test everything except PreimageOracle.t.sol since it's slow. + name: contracts-bedrock-tests + test_parallelism: 4 + test_list: find test -name "*.t.sol" -not -name "PreimageOracle.t.sol" + - contracts-bedrock-tests: + # PreimageOracle test is slow, run it separately to unblock CI. + name: contracts-bedrock-tests-preimage-oracle + test_parallelism: 1 + test_list: find test -name "PreimageOracle.t.sol" + - contracts-bedrock-tests: + # Heavily fuzz any fuzz tests within added or modified test files. + name: contracts-bedrock-tests-heavy-fuzz-modified + test_parallelism: 1 + test_list: git diff origin/develop...HEAD --name-only -- './test/**/*.t.sol' | sed 's|packages/contracts-bedrock/||' + test_timeout: 1h + test_fuzz_runs: 10000 + test_invariant_runs: 128 + test_invariant_depth: 512 - contracts-bedrock-coverage - contracts-bedrock-checks: requires: - - pnpm-monorepo - - contracts-bedrock-validate-spaces: + - contracts-bedrock-build + - contracts-bedrock-validate-spacers: requires: - - pnpm-monorepo + - contracts-bedrock-build - semgrep-scan - - go-mod-download - - fuzz-golang: - name: op-challenger-fuzz - package_name: op-challenger - on_changes: op-challenger - requires: ["go-mod-download"] - - fuzz-golang: - name: op-node-fuzz - package_name: op-node - on_changes: op-node - requires: ["go-mod-download"] - - fuzz-golang: - name: op-service-fuzz - package_name: op-service - on_changes: op-service - requires: ["go-mod-download"] + - go-lint: + requires: + - go-mod-download - fuzz-golang: - name: op-chain-ops-fuzz - package_name: op-chain-ops - on_changes: op-chain-ops - requires: ["go-mod-download"] + name: fuzz-golang-<> + requires: + - go-mod-download + on_changes: <> + matrix: + parameters: + package_name: + - op-challenger + - op-node + - op-service + - op-chain-ops - fuzz-golang: name: cannon-fuzz package_name: cannon on_changes: cannon,packages/contracts-bedrock/src/cannon uses_artifacts: true - requires: ["go-mod-download", "pnpm-monorepo"] + requires: ["go-mod-download", "contracts-bedrock-build"] - fuzz-golang: name: op-e2e-fuzz package_name: op-e2e on_changes: op-e2e,packages/contracts-bedrock/src uses_artifacts: true - requires: ["go-mod-download", "pnpm-monorepo"] - - go-test: - name: op-batcher-tests - module: op-batcher - requires: ["go-mod-download"] + requires: ["go-mod-download", "contracts-bedrock-build"] - go-test: - name: op-chain-ops-tests + name: <>-tests + requires: + - go-mod-download + matrix: + parameters: + module: + - op-batcher + - op-chain-ops + - op-node + - op-proposer + - op-challenger + - op-dispute-mon + - op-conductor + - op-program + - op-service + - op-supervisor + - go-test-kurtosis: + name: op-chain-ops-integration module: op-chain-ops - requires: ["go-mod-download"] - - go-test: - name: op-node-tests - module: op-node - requires: ["go-mod-download"] - - go-test: - name: op-proposer-tests - module: op-proposer - requires: ["go-mod-download"] - - go-test: - name: op-challenger-tests - module: op-challenger - 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: ["go-mod-download"] - - go-test: - name: op-program-tests - module: op-program - requires: ["go-mod-download"] - - go-test: - name: op-service-tests - module: op-service - requires: ["go-mod-download"] - - go-test: - name: op-supervisor-tests - module: op-supervisor - requires: ["go-mod-download"] + test_directory: ./deployer/integration_test + uses_artifacts: true + requires: ["contracts-bedrock-build"] - go-e2e-test: name: op-e2e-HTTP-tests<< matrix.variant >> matrix: @@ -1567,7 +1625,7 @@ workflows: parallelism: 4 requires: - go-mod-download - - pnpm-monorepo + - contracts-bedrock-build - go-e2e-test: name: op-e2e-action-tests<< matrix.variant >> matrix: @@ -1578,24 +1636,22 @@ workflows: parallelism: 1 requires: - go-mod-download - - pnpm-monorepo + - contracts-bedrock-build - go-e2e-test: name: op-e2e-fault-proof-tests module: op-e2e target: test-fault-proofs parallelism: 4 requires: - - pnpm-monorepo + - contracts-bedrock-build - cannon-prestate - - op-service-rethdb-tests: - requires: - - go-mod-download - op-program-compat: requires: - op-program-tests - bedrock-go-tests: requires: - go-mod-download + - go-lint - cannon-build-test-vectors - cannon-go-lint-and-test - check-generated-mocks-op-node @@ -1603,6 +1659,7 @@ workflows: - go-mod-download - op-batcher-tests - op-chain-ops-tests + - op-chain-ops-integration - op-node-tests - op-proposer-tests - op-challenger-tests @@ -1612,56 +1669,35 @@ workflows: - op-program-compat - op-service-tests - op-supervisor-tests - - op-service-rethdb-tests - op-e2e-HTTP-tests - op-e2e-fault-proof-tests - op-e2e-action-tests - op-e2e-action-tests-altda + # Not needed for the devnet but we want to make sure they build successfully + - cannon-docker-build + - op-dispute-mon-docker-build + - op-program-docker-build + - op-supervisor-docker-build + - proofs-tools-docker-build - docker-build: - name: op-node-docker-build - docker_name: op-node - docker_tags: <>,<> - save_image_tag: <> # for devnet later - - docker-build: - name: op-batcher-docker-build - docker_name: op-batcher - docker_tags: <>,<> - save_image_tag: <> # for devnet later - - docker-build: - name: op-program-docker-build - docker_name: op-program + name: <>-docker-build docker_tags: <>,<> - # op-program is not part of the devnet, we don't save it. - - docker-build: - name: op-proposer-docker-build - docker_name: op-proposer - docker_tags: <>,<> - save_image_tag: <> # for devnet later - - docker-build: - name: op-challenger-docker-build - docker_name: op-challenger - docker_tags: <>,<> - save_image_tag: <> # for devnet later - - docker-build: - name: op-dispute-mon-docker-build - docker_name: op-dispute-mon - docker_tags: <>,<> - save_image_tag: <> # for devnet later - - docker-build: - name: op-conductor-docker-build - docker_name: op-conductor - docker_tags: <>,<> - # op-conductor is not part of the devnet, we don't save it. - - docker-build: - name: da-server-docker-build - docker_name: da-server - docker_tags: <>,<> - save_image_tag: <> # for devnet later - - docker-build: - name: op-supervisor-docker-build - docker_name: op-supervisor - docker_tags: <>,<> - # op-supervisor is not (yet) part of the devnet, we don't save it + save_image_tag: <> + matrix: + parameters: + docker_name: + - op-node + - op-batcher + - op-program + - op-proposer + - op-challenger + - proofs-tools + - op-dispute-mon + - op-conductor + - da-server + - op-supervisor + - op-deployer + - cannon - cannon-prestate: requires: - go-mod-download @@ -1670,7 +1706,7 @@ workflows: parameters: variant: ["default", "altda", "altda-generic"] requires: - - pnpm-monorepo + - contracts-bedrock-build - op-batcher-docker-build - op-proposer-docker-build - op-node-docker-build @@ -1681,8 +1717,13 @@ workflows: - check-generated-mocks-op-service - cannon-go-lint-and-test: requires: - - pnpm-monorepo + - contracts-bedrock-build + skip_slow_tests: true + notify: true - cannon-build-test-vectors + - todo-issues: + name: todo-issues-check + check_closed: false - shellcheck/check: name: shell-check # We don't need the `exclude` key as the orb detects the `.shellcheckrc` @@ -1695,218 +1736,93 @@ workflows: not: equal: [ scheduled_pipeline, << pipeline.trigger_source >> ] jobs: + # Wait for approval on the release - hold: type: approval filters: tags: - only: /^(da-server|ci-builder(-rust)?|ufm-[a-z0-9\-]*|op-[a-z0-9\-]*)\/v.*/ + only: /^(da-server|ci-builder(-rust)?|proofs-tools|cannon|ufm-[a-z0-9\-]*|op-[a-z0-9\-]*)\/v.*/ branches: ignore: /.*/ + # Standard (medium) cross-platform docker images go here - docker-build: - name: op-node-docker-release - filters: - tags: - only: /^op-node\/v.*/ - branches: - ignore: /.*/ - docker_name: op-node + matrix: + parameters: + docker_name: + - op-node + - op-batcher + - op-proposer + - op-challenger + - op-dispute-mon + - op-conductor + - da-server + - op-ufm + - op-supervisor + - op-deployer + - cannon + name: <>-docker-release docker_tags: <> - requires: ['hold'] platforms: "linux/amd64,linux/arm64" publish: true release: true - context: - - oplabs-gcr-release - - check-cross-platform: - name: op-node-cross-platform - op_component: op-node - requires: - - op-node-docker-release - - docker-build: - name: op-batcher-docker-release filters: tags: - only: /^op-batcher\/v.*/ + only: /^<>\/v.*/ branches: ignore: /.*/ - docker_name: op-batcher - docker_tags: <> - requires: ['hold'] - platforms: "linux/amd64,linux/arm64" - publish: true - release: true context: - oplabs-gcr-release - - check-cross-platform: - name: op-batcher-cross-platform - op_component: op-batcher requires: - - op-batcher-docker-release - - docker-build: - name: op-proposer-docker-release - filters: - tags: - only: /^op-proposer\/v.*/ - branches: - ignore: /.*/ - docker_name: op-proposer - docker_tags: <> - requires: ['hold'] - platforms: "linux/amd64,linux/arm64" - publish: true - release: true - context: - - oplabs-gcr-release + - hold + # Checks for cross-platform images go here - check-cross-platform: - name: op-proposer-cross-platform - op_component: op-proposer + matrix: + parameters: + op_component: + - op-node + - op-batcher + - op-proposer + - op-challenger + - op-dispute-mon + - op-conductor + - da-server + - op-ufm + - op-supervisor + - op-deployer + - cannon + name: <>-cross-platform requires: + - op-node-docker-release + - op-batcher-docker-release - op-proposer-docker-release - - docker-build: - name: op-challenger-docker-release - filters: - tags: - only: /^op-challenger\/v.*/ - branches: - ignore: /.*/ - docker_name: op-challenger - docker_tags: <> - requires: ['hold'] - platforms: "linux/amd64,linux/arm64" - publish: true - release: true - context: - - oplabs-gcr-release - - check-cross-platform: - name: op-challenger-cross-platform - op_component: op-challenger - requires: - op-challenger-docker-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: ['hold'] - platforms: "linux/amd64,linux/arm64" - publish: true - release: true - context: - - oplabs-gcr-release - - check-cross-platform: - name: op-dispute-mon-cross-platform - op_component: op-dispute-mon - requires: - op-dispute-mon-docker-release - - docker-build: - name: op-conductor-docker-release - filters: - tags: - only: /^op-conductor\/v.*/ - branches: - ignore: /.*/ - docker_name: op-conductor - docker_tags: <> - requires: ['hold'] - platforms: "linux/amd64,linux/arm64" - publish: true - release: true - context: - - oplabs-gcr-release - - check-cross-platform: - name: op-conductor-cross-platform - op_component: op-conductor - requires: - op-conductor-docker-release - - docker-build: - name: da-server-docker-release - filters: - tags: - only: /^da-server\/v.*/ - branches: - ignore: /.*/ - docker_name: da-server - docker_tags: <> - requires: ['hold'] - platforms: "linux/amd64,linux/arm64" - publish: true - release: true - context: - - oplabs-gcr-release - - check-cross-platform: - name: da-server-cross-platform - op_component: da-server - requires: - da-server-docker-release + - op-ufm-docker-release + - op-supervisor-docker-release + - op-deployer-docker-release + - cannon-docker-release + # Standard (xlarge) AMD-only docker images go here - docker-build: - name: op-ufm-docker-release - filters: - tags: - only: /^op-ufm\/v.*/ - branches: - ignore: /.*/ - docker_name: op-ufm + matrix: + parameters: + docker_name: + - ci-builder + - ci-builder-rust + - proofs-tools + name: <>-docker-release + resource_class: xlarge docker_tags: <> publish: true release: true - context: - - oplabs-gcr-release - requires: - - hold - - docker-build: - name: op-supervisor-docker-release filters: tags: - only: /^op-supervisor\/v.*/ + only: /^<>\/v.*/ branches: ignore: /.*/ - docker_name: op-supervisor - docker_tags: <> - requires: ['hold'] - platforms: "linux/amd64,linux/arm64" - publish: true - release: true context: - oplabs-gcr-release - - check-cross-platform: - name: op-supervisor-cross-platform - op_component: op-supervisor - requires: - - op-supervisor-docker-release - - docker-build: - name: ci-builder-docker-release - filters: - tags: - only: /^ci-builder\/v.*/ - branches: - ignore: /.*/ - docker_name: ci-builder - docker_tags: <>,latest - publish: true - release: true - resource_class: xlarge - context: - - 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 @@ -1928,6 +1844,14 @@ workflows: - slack - oplabs-fpp-nodes + develop-publish-contract-artifacts: + when: + or: + - equal: [ "develop", <> ] + - equal: [ true, <> ] + jobs: + - publish-contract-artifacts + develop-fault-proofs: when: and: @@ -1941,19 +1865,22 @@ workflows: - cannon-prestate: requires: - go-mod-download - - pnpm-monorepo: - name: pnpm-monorepo - requires: - - go-mod-download + - contracts-bedrock-build: + skip_pattern: test + context: + - slack - go-e2e-test: - name: op-e2e-cannon-tests + name: op-e2e-cannon-tests<< matrix.variant >> + matrix: + parameters: + variant: ["", "-mt-cannon"] module: op-e2e target: test-cannon parallelism: 4 notify: true mentions: "@proofs-squad" requires: - - pnpm-monorepo + - contracts-bedrock-build - cannon-prestate context: - slack @@ -1972,6 +1899,20 @@ workflows: - slack - runtimeverification + scheduled-cannon-full-tests: + when: + or: + - equal: [ build_four_hours, <> ] + - equal: [ true, << pipeline.parameters.cannon_full_test_dispatch >> ] + jobs: + - contracts-bedrock-build: + skip_pattern: test + - cannon-go-lint-and-test: + requires: + - contracts-bedrock-build + context: + - slack + scheduled-docker-publish: when: or: @@ -1980,106 +1921,19 @@ workflows: - equal: [ true, << pipeline.parameters.docker_publish_dispatch >> ] jobs: - docker-build: - name: op-node-docker-publish - docker_name: op-node - docker_tags: <>,<> - platforms: "linux/amd64,linux/arm64" - publish: true - context: - - oplabs-gcr - - slack - - check-cross-platform: - name: op-node-cross-platform - op_component: op-node - requires: - - op-node-docker-publish - - docker-build: - name: op-batcher-docker-publish - docker_name: op-batcher - docker_tags: <>,<> - platforms: "linux/amd64,linux/arm64" - publish: true - context: - - oplabs-gcr - - slack - - check-cross-platform: - name: op-batcher-cross-platform - op_component: op-batcher - requires: - - op-batcher-docker-publish - - docker-build: - name: op-program-docker-publish - docker_name: op-program - docker_tags: <>,<> - platforms: "linux/amd64,linux/arm64" - publish: true - context: - - oplabs-gcr - - slack - - check-cross-platform: - name: op-program-cross-platform - op_component: op-program - requires: - - op-program-docker-publish - - docker-build: - name: op-proposer-docker-publish - docker_name: op-proposer - docker_tags: <>,<> - platforms: "linux/amd64,linux/arm64" - publish: true - context: - - oplabs-gcr - - slack - - check-cross-platform: - name: op-proposer-cross-platform - op_component: op-proposer - requires: - - op-proposer-docker-publish - - docker-build: - name: op-challenger-docker-publish - docker_name: op-challenger - docker_tags: <>,<> - platforms: "linux/amd64,linux/arm64" - publish: true - context: - - oplabs-gcr - - slack - - check-cross-platform: - name: op-challenger-cross-platform - op_component: op-challenger - requires: - - op-challenger-docker-publish - - docker-build: - name: op-dispute-mon-docker-publish - docker_name: op-dispute-mon - docker_tags: <>,<> - platforms: "linux/amd64,linux/arm64" - publish: true - context: - - oplabs-gcr - - slack - - check-cross-platform: - name: op-dispute-mon-cross-platform - op_component: op-dispute-mon - requires: - - op-dispute-mon-docker-publish - - docker-build: - name: op-conductor-docker-publish - docker_name: op-conductor - docker_tags: <>,<> - platforms: "linux/amd64,linux/arm64" - publish: true - context: - - oplabs-gcr - - slack - - check-cross-platform: - name: op-conductor-cross-platform - op_component: op-conductor - requires: - - op-conductor-docker-publish - - docker-build: - name: op-supervisor-docker-publish - docker_name: op-supervisor + matrix: + parameters: + docker_name: + - op-node + - op-batcher + - op-program + - op-proposer + - op-challenger + - op-dispute-mon + - op-conductor + - op-supervisor + - cannon + name: <>-docker-publish docker_tags: <>,<> platforms: "linux/amd64,linux/arm64" publish: true @@ -2087,10 +1941,21 @@ workflows: - oplabs-gcr - slack - check-cross-platform: - name: op-supervisor-cross-platform - op_component: op-supervisor + matrix: + parameters: + op_component: + - op-node + - op-batcher + - op-program + - op-proposer + - op-challenger + - op-dispute-mon + - op-conductor + - op-supervisor + - cannon + name: <>-cross-platform requires: - - op-supervisor-docker-publish + - <>-docker-publish - docker-build: name: contracts-bedrock-docker-publish docker_name: contracts-bedrock @@ -2111,6 +1976,17 @@ workflows: - preimage-reproducibility: matrix: parameters: - version: ["0.1.0", "0.2.0", "0.3.0", "1.0.0", "1.1.0", "1.2.0"] + version: + - "0.1.0" + - "0.2.0" + - "0.3.0" + - "1.0.0" + - "1.1.0" + - "1.2.0" + - "1.3.0-rc.1" + - "1.3.0-rc.2" + - "1.3.0-rc.3" + - "1.3.1-rc.1" + - "1.3.1-rc.2" context: slack diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 23ac0fa26cf5c..46196699f6462 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,27 +1,31 @@ -# Packages -/packages/contracts-bedrock @ethereum-optimism/contract-reviewers -/packages/sdk @ethereum-optimism/devxpod +# Monorepo - default to go-reviewers +* @ethereum-optimism/go-reviewers + +# OP Stack general +/bedrock-devnet @ethereum-optimism/op-stack @ethereum-optimism/go-reviewers +/op-alt-da @ethereum-optimism/op-stack @ethereum-optimism/go-reviewers +/op-batcher @ethereum-optimism/op-stack @ethereum-optimism/go-reviewers +/op-chain-ops @ethereum-optimism/op-stack @ethereum-optimism/go-reviewers +/op-e2e @ethereum-optimism/op-stack @ethereum-optimism/go-reviewers +/op-node @ethereum-optimism/op-stack @ethereum-optimism/go-reviewers +/op-proposer @ethereum-optimism/op-stack @ethereum-optimism/go-reviewers +/op-wheel @ethereum-optimism/op-stack @ethereum-optimism/go-reviewers +/ops-bedrock @ethereum-optimism/op-stack @ethereum-optimism/go-reviewers + +# Expert areas +/op-node/rollup @ethereum-optimism/consensus @ethereum-optimism/go-reviewers + +/op-supervisor @ethereum-optimism/interop @ethereum-optimism/go-reviewers -# Bedrock codebases -/bedrock-devnet @ethereum-optimism/go-reviewers -/cannon @ethereum-optimism/go-reviewers -/op-batcher @ethereum-optimism/go-reviewers -/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-node @ethereum-optimism/go-reviewers -/op-node/rollup @protolambda @ajsutton -/op-alt-da @ethereum-optimism/go-reviewers -/op-preimage @ethereum-optimism/go-reviewers -/op-program @ethereum-optimism/go-reviewers -/op-proposer @ethereum-optimism/go-reviewers -/op-service @ethereum-optimism/go-reviewers -/op-supervisor @ethereum-optimism/go-reviewers -/op-wheel @ethereum-optimism/go-reviewers -/ops-bedrock @ethereum-optimism/go-reviewers -/op-conductor @0x00101010 @zhwrd @mslipper +/op-conductor @ethereum-optimism/op-conductor @ethereum-optimism/go-reviewers + +/cannon @ethereum-optimism/proofs @ethereum-optimism/go-reviewers +/op-challenger @ethereum-optimism/proofs @ethereum-optimism/go-reviewers +/op-dispute-mon @ethereum-optimism/proofs @ethereum-optimism/go-reviewers +/op-preimage @ethereum-optimism/proofs @ethereum-optimism/go-reviewers +/op-program @ethereum-optimism/proofs @ethereum-optimism/go-reviewers +/op-e2e/actions/proofs @ethereum-optimism/proofs @ethereum-optimism/go-reviewers +/op-e2e/faultproofs @ethereum-optimism/proofs @ethereum-optimism/go-reviewers # Ops /.circleci @ethereum-optimism/monorepo-ops-reviewers @@ -29,15 +33,5 @@ /ops @ethereum-optimism/monorepo-ops-reviewers /docker-bake.hcl @ethereum-optimism/monorepo-ops-reviewers -# Misc -/proxyd @ethereum-optimism/infra-reviewers -/infra @ethereum-optimism/infra-reviewers -/specs @ethereum-optimism/contract-reviewers @ethereum-optimism/go-reviewers - -# Don't add owners if only package.json is updated -/packages/*/package.json -/*/package.json - -# JavaScript Releases -/packages/*/CHANGELOG.md @ethereum-optimism/release-managers -/*/CHANGELOG.md @ethereum-optimism/release-managers +# Contracts +/packages/contracts-bedrock @ethereum-optimism/contract-reviewers diff --git a/.github/workflows/tag-service.yml b/.github/workflows/tag-service.yml index 42e06c9debb9a..439b48f13d4e6 100644 --- a/.github/workflows/tag-service.yml +++ b/.github/workflows/tag-service.yml @@ -36,6 +36,9 @@ on: type: boolean default: false +permissions: + contents: write + jobs: release: runs-on: ubuntu-latest diff --git a/.npmrc b/.npmrc deleted file mode 100644 index abbc18350ff46..0000000000000 --- a/.npmrc +++ /dev/null @@ -1,4 +0,0 @@ -# run prefoo scripts -# npm and yarn support this as a default pnpm defaults to false -enable-pre-post-scripts=true -lockfile=true diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 79135484302d1..0e0528fd33e22 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,7 +1,7 @@ { "recommendations": [ "editorconfig.editorconfig", - "juanblanco.solidity", + "nomicfoundation.hardhat-solidity", "golang.go" ] } diff --git a/Makefile b/Makefile index 5431c5ff383d3..4f329a4241e2b 100644 --- a/Makefile +++ b/Makefile @@ -133,23 +133,25 @@ reproducible-prestate: ## Builds reproducible-prestate binary make -C ./op-program reproducible-prestate .PHONY: reproducible-prestate -# Include any files required for the devnet to build and run. This appears to be the only one that's actually needed. -DEVNET_CANNON_PRESTATE_FILES := op-program/bin/prestate-proof.json op-program/bin/prestate.json +# Include any files required for the devnet to build and run. +DEVNET_CANNON_PRESTATE_FILES := op-program/bin/prestate-proof.json op-program/bin/prestate.json op-program/bin/prestate-proof-mt.json op-program/bin/prestate-mt.bin.gz + $(DEVNET_CANNON_PRESTATE_FILES): make cannon-prestate + make cannon-prestate-mt cannon-prestate: op-program cannon ## Generates prestate using cannon and op-program - ./cannon/bin/cannon load-elf --path op-program/bin/op-program-client.elf --out op-program/bin/prestate.json --meta op-program/bin/meta.json - ./cannon/bin/cannon run --proof-at '=0' --stop-at '=1' --input op-program/bin/prestate.json --meta op-program/bin/meta.json --proof-fmt 'op-program/bin/%d.json' --output "" + ./cannon/bin/cannon load-elf --type singlethreaded --path op-program/bin/op-program-client.elf --out op-program/bin/prestate.json --meta op-program/bin/meta.json + ./cannon/bin/cannon run --proof-at '=0' --stop-at '=1' --input op-program/bin/prestate.json --meta op-program/bin/meta.json --proof-fmt 'op-program/bin/%d.json' --output "" mv op-program/bin/0.json op-program/bin/prestate-proof.json .PHONY: cannon-prestate cannon-prestate-mt: op-program cannon ## Generates prestate using cannon and op-program in the multithreaded cannon format - ./cannon/bin/cannon load-elf --type mt --path op-program/bin/op-program-client.elf --out op-program/bin/prestate-mt.json --meta op-program/bin/meta-mt.json - ./cannon/bin/cannon run --type mt --proof-at '=0' --stop-at '=1' --input op-program/bin/prestate-mt.json --meta op-program/bin/meta-mt.json --proof-fmt 'op-program/bin/%d-mt.json' --output "" + ./cannon/bin/cannon load-elf --type multithreaded --path op-program/bin/op-program-client.elf --out op-program/bin/prestate-mt.bin.gz --meta op-program/bin/meta-mt.json + ./cannon/bin/cannon run --proof-at '=0' --stop-at '=1' --input op-program/bin/prestate-mt.bin.gz --meta op-program/bin/meta-mt.json --proof-fmt 'op-program/bin/%d-mt.json' --output "" mv op-program/bin/0-mt.json op-program/bin/prestate-proof-mt.json -.PHONY: cannon-prestate +.PHONY: cannon-prestate-mt mod-tidy: ## Cleans up unused dependencies in Go modules # Below GOPRIVATE line allows mod-tidy to be run immediately after diff --git a/bedrock-devnet/devnet/__init__.py b/bedrock-devnet/devnet/__init__.py index ccf080c18566f..8a3fb0ee4c994 100644 --- a/bedrock-devnet/devnet/__init__.py +++ b/bedrock-devnet/devnet/__init__.py @@ -11,6 +11,8 @@ from multiprocessing import Process, Queue import concurrent.futures from collections import namedtuple +# This import is necessary for devnet logs to be shown. +from . import log_setup pjoin = os.path.join diff --git a/cannon/.gitignore b/cannon/.gitignore index c3e45199f0edd..68424370890f6 100644 --- a/cannon/.gitignore +++ b/cannon/.gitignore @@ -13,3 +13,4 @@ state.json *.pprof *.out bin +multicannon/embeds/cannon* diff --git a/cannon/Makefile b/cannon/Makefile index 0f3836fb62fbb..e914ad542eae6 100644 --- a/cannon/Makefile +++ b/cannon/Makefile @@ -4,8 +4,8 @@ VERSION ?= v0.0.0 LDFLAGSSTRING +=-X main.GitCommit=$(GITCOMMIT) LDFLAGSSTRING +=-X main.GitDate=$(GITDATE) -LDFLAGSSTRING +=-X github.com/ethereum-optimism/optimism/op-program/version.Version=$(VERSION) -LDFLAGSSTRING +=-X github.com/ethereum-optimism/optimism/op-program/version.Meta=$(VERSION_META) +LDFLAGSSTRING +=-X github.com/ethereum-optimism/optimism/cannon/multicannon/version.Version=$(VERSION) +LDFLAGSSTRING +=-X github.com/ethereum-optimism/optimism/cannon/multicannon/version.Meta=$(VERSION_META) LDFLAGS := -ldflags "$(LDFLAGSSTRING)" # Use the old Apple linker to workaround broken xcode - https://github.com/golang/go/issues/65169 @@ -13,8 +13,15 @@ ifeq ($(shell uname),Darwin) FUZZLDFLAGS := -ldflags=-extldflags=-Wl,-ld_classic endif -cannon: - env GO111MODULE=on GOOS=$(TARGETOS) GOARCH=$(TARGETARCH) go build -v $(LDFLAGS) -o ./bin/cannon . +cannon-impl: + env GO111MODULE=on GOOS=$(TARGETOS) GOARCH=$(TARGETARCH) go build -v $(LDFLAGS) -o ./bin/cannon-impl . + +cannon-embeds: cannon-impl + @cp bin/cannon-impl ./multicannon/embeds/cannon-0 + @cp bin/cannon-impl ./multicannon/embeds/cannon-1 + +cannon: cannon-embeds + env GO111MODULE=on GOOS=$(TARGETOS) GOARCH=$(TARGETARCH) go build -v $(LDFLAGS) -o ./bin/cannon ./multicannon/ clean: rm -rf bin @@ -22,6 +29,14 @@ clean: elf: make -C ./testdata/example elf +sanitize-program: + @if ! { mips-linux-gnu-objdump -d -j .text $$GUEST_PROGRAM | awk '{print $3}' | grep -Ew -m1 '(bgezal|bltzal)'; }; then \ + echo "guest program is sanitized for unsupported instructions"; \ + else \ + echo "found unsupported instructions in the guest program"; \ + exit 1; \ + fi + contract: cd ../packages/contracts-bedrock && forge build diff --git a/cannon/README.md b/cannon/README.md index e9e751ce2ffe3..a3b9171939010 100644 --- a/cannon/README.md +++ b/cannon/README.md @@ -30,7 +30,7 @@ make cannon # Transform MIPS op-program client binary into first VM state. # This outputs state.json (VM state) and meta.json (for debug symbols). -./bin/cannon load-elf --path=../op-program/bin/op-program-client.elf +./bin/cannon load-elf --type singlethreaded --path=../op-program/bin/op-program-client.elf # Run cannon emulator (with example inputs) # Note that the server-mode op-program command is passed into cannon (after the --), diff --git a/cannon/cmd/load_elf.go b/cannon/cmd/load_elf.go index 39e389ff23ca8..816eb7c02e466 100644 --- a/cannon/cmd/load_elf.go +++ b/cannon/cmd/load_elf.go @@ -4,31 +4,34 @@ import ( "debug/elf" "fmt" - "github.com/ethereum-optimism/optimism/cannon/mipsevm" - "github.com/ethereum-optimism/optimism/cannon/mipsevm/multithreaded" "github.com/urfave/cli/v2" + "github.com/ethereum-optimism/optimism/cannon/mipsevm" + "github.com/ethereum-optimism/optimism/cannon/mipsevm/multithreaded" "github.com/ethereum-optimism/optimism/cannon/mipsevm/program" "github.com/ethereum-optimism/optimism/cannon/mipsevm/singlethreaded" + "github.com/ethereum-optimism/optimism/cannon/mipsevm/versions" + "github.com/ethereum-optimism/optimism/cannon/serialize" + openum "github.com/ethereum-optimism/optimism/op-service/enum" + "github.com/ethereum-optimism/optimism/op-service/ioutil" "github.com/ethereum-optimism/optimism/op-service/jsonutil" ) var ( + LoadELFVMTypeFlag = &cli.StringFlag{ + Name: "type", + Usage: "VM type to create state for. Valid options: " + openum.EnumString(stateVersions()), + Required: true, + } LoadELFPathFlag = &cli.PathFlag{ Name: "path", Usage: "Path to 32-bit big-endian MIPS ELF file", TakesFile: true, Required: true, } - LoadELFPatchFlag = &cli.StringSliceFlag{ - Name: "patch", - Usage: "Type of patching to do", - Value: cli.NewStringSlice("go", "stack"), - Required: false, - } LoadELFOutFlag = &cli.PathFlag{ Name: "out", - Usage: "Output path to write JSON state to. State is dumped to stdout if set to -. Not written if empty.", + Usage: "Output path to write state to. State is dumped to stdout if set to '-'. Not written if empty. Use file extension '.bin', '.bin.gz', or '.json' for binary, compressed binary, or JSON formats.", Value: "state.json", Required: false, } @@ -40,74 +43,88 @@ var ( } ) +func stateVersions() []string { + vers := make([]string, len(versions.StateVersionTypes)) + for i, v := range versions.StateVersionTypes { + vers[i] = v.String() + } + return vers +} + func LoadELF(ctx *cli.Context) error { + elfPath := ctx.Path(LoadELFPathFlag.Name) + elfProgram, err := elf.Open(elfPath) + if err != nil { + return fmt.Errorf("failed to open ELF file %q: %w", elfPath, err) + } + if elfProgram.Machine != elf.EM_MIPS { + return fmt.Errorf("ELF is not big-endian MIPS R3000, but got %q", elfProgram.Machine.String()) + } + var createInitialState func(f *elf.File) (mipsevm.FPVMState, error) - var writeState func(path string, state mipsevm.FPVMState) error - if vmType, err := vmTypeFromString(ctx); err != nil { + var patcher = program.PatchStack + ver, err := versions.ParseStateVersion(ctx.String(LoadELFVMTypeFlag.Name)) + if err != nil { return err - } else if vmType == cannonVMType { + } + switch ver { + case versions.VersionSingleThreaded: createInitialState = func(f *elf.File) (mipsevm.FPVMState, error) { return program.LoadELF(f, singlethreaded.CreateInitialState) } - writeState = func(path string, state mipsevm.FPVMState) error { - return jsonutil.WriteJSON[*singlethreaded.State](path, state.(*singlethreaded.State), OutFilePerm) + patcher = func(state mipsevm.FPVMState) error { + err := program.PatchGoGC(elfProgram, state) + if err != nil { + return err + } + return program.PatchStack(state) } - } else if vmType == mtVMType { + case versions.VersionMultiThreaded: createInitialState = func(f *elf.File) (mipsevm.FPVMState, error) { return program.LoadELF(f, multithreaded.CreateInitialState) } - writeState = func(path string, state mipsevm.FPVMState) error { - return jsonutil.WriteJSON[*multithreaded.State](path, state.(*multithreaded.State), OutFilePerm) - } - } else { - return fmt.Errorf("invalid VM type: %q", vmType) - } - elfPath := ctx.Path(LoadELFPathFlag.Name) - elfProgram, err := elf.Open(elfPath) - if err != nil { - return fmt.Errorf("failed to open ELF file %q: %w", elfPath, err) - } - if elfProgram.Machine != elf.EM_MIPS { - return fmt.Errorf("ELF is not big-endian MIPS R3000, but got %q", elfProgram.Machine.String()) + default: + return fmt.Errorf("unsupported state version: %d (%s)", ver, ver.String()) } + state, err := createInitialState(elfProgram) if err != nil { return fmt.Errorf("failed to load ELF data into VM state: %w", err) } - for _, typ := range ctx.StringSlice(LoadELFPatchFlag.Name) { - switch typ { - case "stack": - err = program.PatchStack(state) - case "go": - err = program.PatchGo(elfProgram, state) - default: - return fmt.Errorf("unrecognized form of patching: %q", typ) - } - if err != nil { - return fmt.Errorf("failed to apply patch %s: %w", typ, err) - } + err = patcher(state) + if err != nil { + return fmt.Errorf("failed to patch state: %w", err) } meta, err := program.MakeMetadata(elfProgram) if err != nil { return fmt.Errorf("failed to compute program metadata: %w", err) } - if err := jsonutil.WriteJSON[*program.Metadata](ctx.Path(LoadELFMetaFlag.Name), meta, OutFilePerm); err != nil { + if err := jsonutil.WriteJSON[*program.Metadata](meta, ioutil.ToStdOutOrFileOrNoop(ctx.Path(LoadELFMetaFlag.Name), OutFilePerm)); err != nil { return fmt.Errorf("failed to output metadata: %w", err) } - return writeState(ctx.Path(LoadELFOutFlag.Name), state) + + // Ensure the state is written with appropriate version information + versionedState, err := versions.NewFromState(state) + if err != nil { + return fmt.Errorf("failed to create versioned state: %w", err) + } + return serialize.Write(ctx.Path(LoadELFOutFlag.Name), versionedState, OutFilePerm) } -var LoadELFCommand = &cli.Command{ - Name: "load-elf", - Usage: "Load ELF file into Cannon JSON state", - Description: "Load ELF file into Cannon JSON state, optionally patch out functions", - Action: LoadELF, - Flags: []cli.Flag{ - VMTypeFlag, - LoadELFPathFlag, - LoadELFPatchFlag, - LoadELFOutFlag, - LoadELFMetaFlag, - }, +func CreateLoadELFCommand(action cli.ActionFunc) *cli.Command { + return &cli.Command{ + Name: "load-elf", + Usage: "Load ELF file into Cannon state", + Description: "Load ELF file into Cannon state", + Action: action, + Flags: []cli.Flag{ + LoadELFVMTypeFlag, + LoadELFPathFlag, + LoadELFOutFlag, + LoadELFMetaFlag, + }, + } } + +var LoadELFCommand = CreateLoadELFCommand(LoadELF) diff --git a/cannon/cmd/run.go b/cannon/cmd/run.go index 23b6e1b757199..21f4f7c298253 100644 --- a/cannon/cmd/run.go +++ b/cannon/cmd/run.go @@ -2,6 +2,7 @@ package cmd import ( "context" + "errors" "fmt" "os" "os/exec" @@ -10,7 +11,9 @@ import ( "strings" "time" - "github.com/ethereum-optimism/optimism/cannon/mipsevm/multithreaded" + "github.com/ethereum-optimism/optimism/cannon/mipsevm/versions" + "github.com/ethereum-optimism/optimism/cannon/serialize" + "github.com/ethereum-optimism/optimism/op-service/ioutil" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/log" @@ -19,7 +22,6 @@ import ( "github.com/ethereum-optimism/optimism/cannon/mipsevm" "github.com/ethereum-optimism/optimism/cannon/mipsevm/program" - "github.com/ethereum-optimism/optimism/cannon/mipsevm/singlethreaded" preimage "github.com/ethereum-optimism/optimism/op-preimage" "github.com/ethereum-optimism/optimism/op-service/jsonutil" ) @@ -217,16 +219,37 @@ func (p *ProcessPreimageOracle) Close() error { if p.cmd == nil { return nil } + + tryWait := func(dur time.Duration) (bool, error) { + ctx, cancel := context.WithTimeout(context.Background(), dur) + defer cancel() + select { + case <-ctx.Done(): + return false, nil + case err := <-p.waitErr: + return true, err + } + } // Give the pre-image server time to exit cleanly before killing it. - time.Sleep(time.Second * 1) + if exited, err := tryWait(1 * time.Second); exited { + return err + } + // Politely ask the process to exit and give it some more time _ = p.cmd.Process.Signal(os.Interrupt) + if exited, err := tryWait(30 * time.Second); exited { + return err + } + + // Force the process to exit + _ = p.cmd.Process.Signal(os.Kill) return <-p.waitErr } func (p *ProcessPreimageOracle) wait() { err := p.cmd.Wait() var waitErr error - if err, ok := err.(*exec.ExitError); !ok || !err.Success() { + var exitErr *exec.ExitError + if errors.As(err, &exitErr) && !exitErr.Success() { waitErr = err } p.cancelIO(fmt.Errorf("%w: pre-image server has exited", waitErr)) @@ -257,11 +280,6 @@ func Run(ctx *cli.Context) error { defer profile.Start(profile.NoShutdownHook, profile.ProfilePath("."), profile.CPUProfile).Stop() } - vmType, err := vmTypeFromString(ctx) - if err != nil { - return err - } - guestLogger := Logger(os.Stderr, log.LevelInfo) outLog := &mipsevm.LoggingWriter{Log: guestLogger.With("module", "guest", "stream", "stdout")} errLog := &mipsevm.LoggingWriter{Log: guestLogger.With("module", "guest", "stream", "stderr")} @@ -351,42 +369,19 @@ func Run(ctx *cli.Context) error { } } - var vm mipsevm.FPVM - var debugProgram bool - if vmType == cannonVMType { - l.Info("Using cannon VM") - cannon, err := singlethreaded.NewInstrumentedStateFromFile(ctx.Path(RunInputFlag.Name), po, outLog, errLog, meta) - if err != nil { - return err - } - debugProgram = ctx.Bool(RunDebugFlag.Name) - if debugProgram { - if metaPath := ctx.Path(RunMetaFlag.Name); metaPath == "" { - return fmt.Errorf("cannot enable debug mode without a metadata file") - } - if err := cannon.InitDebug(); err != nil { - return fmt.Errorf("failed to initialize debug mode: %w", err) - } - } - vm = cannon - } else if vmType == mtVMType { - l.Info("Using cannon multithreaded VM") - cannon, err := multithreaded.NewInstrumentedStateFromFile(ctx.Path(RunInputFlag.Name), po, outLog, errLog, l) - if err != nil { - return err + state, err := versions.LoadStateFromFile(ctx.Path(RunInputFlag.Name)) + if err != nil { + return fmt.Errorf("failed to load state: %w", err) + } + vm := state.CreateVM(l, po, outLog, errLog, meta) + debugProgram := ctx.Bool(RunDebugFlag.Name) + if debugProgram { + if metaPath := ctx.Path(RunMetaFlag.Name); metaPath == "" { + return errors.New("cannot enable debug mode without a metadata file") } - debugProgram = ctx.Bool(RunDebugFlag.Name) - if debugProgram { - if metaPath := ctx.Path(RunMetaFlag.Name); metaPath == "" { - return fmt.Errorf("cannot enable debug mode without a metadata file") - } - if err := cannon.InitDebug(meta); err != nil { - return fmt.Errorf("failed to initialize debug mode: %w", err) - } + if err := vm.InitDebug(); err != nil { + return fmt.Errorf("failed to initialize debug mode: %w", err) } - vm = cannon - } else { - return fmt.Errorf("unknown VM type %q", vmType) } proofFmt := ctx.String(RunProofFmtFlag.Name) @@ -399,7 +394,6 @@ func Run(ctx *cli.Context) error { start := time.Now() - state := vm.GetState() startStep := state.GetStep() for !state.GetExited() { @@ -434,7 +428,7 @@ func Run(ctx *cli.Context) error { } if snapshotAt(state) { - if err := jsonutil.WriteJSON(fmt.Sprintf(snapshotFmt, step), state, OutFilePerm); err != nil { + if err := serialize.Write(fmt.Sprintf(snapshotFmt, step), state, OutFilePerm); err != nil { return fmt.Errorf("failed to write state snapshot: %w", err) } } @@ -457,7 +451,7 @@ func Run(ctx *cli.Context) error { proof.OracleValue = witness.PreimageValue proof.OracleOffset = witness.PreimageOffset } - if err := jsonutil.WriteJSON(fmt.Sprintf(proofFmt, step), proof, OutFilePerm); err != nil { + if err := jsonutil.WriteJSON(proof, ioutil.ToStdOutOrFileOrNoop(fmt.Sprintf(proofFmt, step), OutFilePerm)); err != nil { return fmt.Errorf("failed to write proof data: %w", err) } } else { @@ -491,38 +485,41 @@ func Run(ctx *cli.Context) error { vm.Traceback() } - if err := jsonutil.WriteJSON(ctx.Path(RunOutputFlag.Name), state, OutFilePerm); err != nil { + if err := serialize.Write(ctx.Path(RunOutputFlag.Name), state, OutFilePerm); err != nil { return fmt.Errorf("failed to write state output: %w", err) } if debugInfoFile := ctx.Path(RunDebugInfoFlag.Name); debugInfoFile != "" { - if err := jsonutil.WriteJSON(debugInfoFile, vm.GetDebugInfo(), OutFilePerm); err != nil { + if err := jsonutil.WriteJSON(vm.GetDebugInfo(), ioutil.ToStdOutOrFileOrNoop(debugInfoFile, OutFilePerm)); err != nil { return fmt.Errorf("failed to write benchmark data: %w", err) } } return nil } -var RunCommand = &cli.Command{ - Name: "run", - Usage: "Run VM step(s) and generate proof data to replicate onchain.", - Description: "Run VM step(s) and generate proof data to replicate onchain. See flags to match when to output a proof, a snapshot, or to stop early.", - Action: Run, - Flags: []cli.Flag{ - VMTypeFlag, - RunInputFlag, - RunOutputFlag, - RunProofAtFlag, - RunProofFmtFlag, - RunSnapshotAtFlag, - RunSnapshotFmtFlag, - RunStopAtFlag, - RunStopAtPreimageFlag, - RunStopAtPreimageTypeFlag, - RunStopAtPreimageLargerThanFlag, - RunMetaFlag, - RunInfoAtFlag, - RunPProfCPU, - RunDebugFlag, - RunDebugInfoFlag, - }, +func CreateRunCommand(action cli.ActionFunc) *cli.Command { + return &cli.Command{ + Name: "run", + Usage: "Run VM step(s) and generate proof data to replicate onchain.", + Description: "Run VM step(s) and generate proof data to replicate onchain. See flags to match when to output a proof, a snapshot, or to stop early.", + Action: action, + Flags: []cli.Flag{ + RunInputFlag, + RunOutputFlag, + RunProofAtFlag, + RunProofFmtFlag, + RunSnapshotAtFlag, + RunSnapshotFmtFlag, + RunStopAtFlag, + RunStopAtPreimageFlag, + RunStopAtPreimageTypeFlag, + RunStopAtPreimageLargerThanFlag, + RunMetaFlag, + RunInfoAtFlag, + RunPProfCPU, + RunDebugFlag, + RunDebugInfoFlag, + }, + } } + +var RunCommand = CreateRunCommand(Run) diff --git a/cannon/cmd/vmtype.go b/cannon/cmd/vmtype.go deleted file mode 100644 index 0efc22370c94d..0000000000000 --- a/cannon/cmd/vmtype.go +++ /dev/null @@ -1,29 +0,0 @@ -package cmd - -import ( - "fmt" - - "github.com/urfave/cli/v2" -) - -type VMType string - -var cannonVMType VMType = "cannon" -var mtVMType VMType = "cannon-mt" - -var VMTypeFlag = &cli.StringFlag{ - Name: "type", - Usage: "VM type to create state for. Options are 'cannon' (default), 'cannon-mt'", - Value: "cannon", - Required: false, -} - -func vmTypeFromString(ctx *cli.Context) (VMType, error) { - if vmTypeStr := ctx.String(VMTypeFlag.Name); vmTypeStr == string(cannonVMType) { - return cannonVMType, nil - } else if vmTypeStr == string(mtVMType) { - return mtVMType, nil - } else { - return "", fmt.Errorf("unknown VM type %q", vmTypeStr) - } -} diff --git a/cannon/cmd/witness.go b/cannon/cmd/witness.go index eda5fbca5fa0a..753438493f954 100644 --- a/cannon/cmd/witness.go +++ b/cannon/cmd/witness.go @@ -4,12 +4,8 @@ import ( "fmt" "os" - "github.com/ethereum-optimism/optimism/cannon/mipsevm" - "github.com/ethereum-optimism/optimism/cannon/mipsevm/multithreaded" + factory "github.com/ethereum-optimism/optimism/cannon/mipsevm/versions" "github.com/urfave/cli/v2" - - "github.com/ethereum-optimism/optimism/cannon/mipsevm/singlethreaded" - "github.com/ethereum-optimism/optimism/op-service/jsonutil" ) var ( @@ -29,23 +25,10 @@ var ( func Witness(ctx *cli.Context) error { input := ctx.Path(WitnessInputFlag.Name) output := ctx.Path(WitnessOutputFlag.Name) - var state mipsevm.FPVMState - if vmType, err := vmTypeFromString(ctx); err != nil { - return err - } else if vmType == cannonVMType { - state, err = jsonutil.LoadJSON[singlethreaded.State](input) - if err != nil { - return fmt.Errorf("invalid input state (%v): %w", input, err) - } - } else if vmType == mtVMType { - state, err = jsonutil.LoadJSON[multithreaded.State](input) - if err != nil { - return fmt.Errorf("invalid input state (%v): %w", input, err) - } - } else { - return fmt.Errorf("invalid VM type: %q", vmType) + state, err := factory.LoadStateFromFile(input) + if err != nil { + return fmt.Errorf("invalid input state (%v): %w", input, err) } - witness, h := state.EncodeWitness() if output != "" { if err := os.WriteFile(output, witness, 0755); err != nil { @@ -56,14 +39,17 @@ func Witness(ctx *cli.Context) error { return nil } -var WitnessCommand = &cli.Command{ - Name: "witness", - Usage: "Convert a Cannon JSON state into a binary witness", - Description: "Convert a Cannon JSON state into a binary witness. The hash of the witness is written to stdout", - Action: Witness, - Flags: []cli.Flag{ - VMTypeFlag, - WitnessInputFlag, - WitnessOutputFlag, - }, +func CreateWitnessCommand(action cli.ActionFunc) *cli.Command { + return &cli.Command{ + Name: "witness", + Usage: "Convert a Cannon JSON state into a binary witness", + Description: "Convert a Cannon JSON state into a binary witness. The hash of the witness is written to stdout", + Action: action, + Flags: []cli.Flag{ + WitnessInputFlag, + WitnessOutputFlag, + }, + } } + +var WitnessCommand = CreateWitnessCommand(Witness) diff --git a/cannon/main.go b/cannon/main.go index 769c1da0b6fe8..176ce315708f0 100644 --- a/cannon/main.go +++ b/cannon/main.go @@ -5,9 +5,8 @@ import ( "errors" "fmt" "os" - "os/signal" - "syscall" + "github.com/ethereum-optimism/optimism/op-service/ctxinterrupt" "github.com/urfave/cli/v2" "github.com/ethereum-optimism/optimism/cannon/cmd" @@ -23,18 +22,7 @@ func main() { cmd.WitnessCommand, cmd.RunCommand, } - ctx, cancel := context.WithCancel(context.Background()) - - c := make(chan os.Signal, 1) - signal.Notify(c, syscall.SIGINT, syscall.SIGTERM) - go func() { - for { - <-c - cancel() - fmt.Println("\r\nExiting...") - } - }() - + ctx := ctxinterrupt.WithSignalWaiterMain(context.Background()) err := app.RunContext(ctx, os.Args) if err != nil { if errors.Is(err, ctx.Err()) { diff --git a/cannon/mipsevm/exec/memory.go b/cannon/mipsevm/exec/memory.go index d006a6f905604..3dea28dce29bd 100644 --- a/cannon/mipsevm/exec/memory.go +++ b/cannon/mipsevm/exec/memory.go @@ -14,7 +14,10 @@ type MemoryTrackerImpl struct { memory *memory.Memory lastMemAccess uint32 memProofEnabled bool - memProof [memory.MEM_PROOF_SIZE]byte + // proof of first unique memory access + memProof [memory.MEM_PROOF_SIZE]byte + // proof of second unique memory access + memProof2 [memory.MEM_PROOF_SIZE]byte } func NewMemoryTracker(memory *memory.Memory) *MemoryTrackerImpl { @@ -31,6 +34,16 @@ func (m *MemoryTrackerImpl) TrackMemAccess(effAddr uint32) { } } +// TrackMemAccess2 creates a proof for a memory access following a call to TrackMemAccess +// This is used to generate proofs for contiguous memory accesses within the same step +func (m *MemoryTrackerImpl) TrackMemAccess2(effAddr uint32) { + if m.memProofEnabled && m.lastMemAccess+4 != effAddr { + panic(fmt.Errorf("unexpected disjointed mem access at %08x, last memory access is at %08x buffered", effAddr, m.lastMemAccess)) + } + m.lastMemAccess = effAddr + m.memProof2 = m.memory.MerkleProof(effAddr) +} + func (m *MemoryTrackerImpl) Reset(enableProof bool) { m.memProofEnabled = enableProof m.lastMemAccess = ^uint32(0) @@ -39,3 +52,7 @@ func (m *MemoryTrackerImpl) Reset(enableProof bool) { func (m *MemoryTrackerImpl) MemProof() [memory.MEM_PROOF_SIZE]byte { return m.memProof } + +func (m *MemoryTrackerImpl) MemProof2() [memory.MEM_PROOF_SIZE]byte { + return m.memProof2 +} diff --git a/cannon/mipsevm/exec/mips_instructions.go b/cannon/mipsevm/exec/mips_instructions.go index 0c4eb919e99f8..aec14192df93d 100644 --- a/cannon/mipsevm/exec/mips_instructions.go +++ b/cannon/mipsevm/exec/mips_instructions.go @@ -5,6 +5,11 @@ import ( "github.com/ethereum-optimism/optimism/cannon/mipsevm/memory" ) +const ( + OpLoadLinked = 0x30 + OpStoreConditional = 0x38 +) + func GetInstructionDetails(pc uint32, memory *memory.Memory) (insn, opcode, fun uint32) { insn = memory.GetMemory(pc) opcode = insn >> 26 // First 6-bits @@ -13,7 +18,7 @@ func GetInstructionDetails(pc uint32, memory *memory.Memory) (insn, opcode, fun return insn, opcode, fun } -func ExecMipsCoreStepLogic(cpu *mipsevm.CpuScalars, registers *[32]uint32, memory *memory.Memory, insn, opcode, fun uint32, memTracker MemTracker, stackTracker StackTracker) error { +func ExecMipsCoreStepLogic(cpu *mipsevm.CpuScalars, registers *[32]uint32, memory *memory.Memory, insn, opcode, fun uint32, memTracker MemTracker, stackTracker StackTracker) (memUpdated bool, memAddr uint32, err error) { // j-type j/jal if opcode == 2 || opcode == 3 { linkReg := uint32(0) @@ -23,7 +28,8 @@ func ExecMipsCoreStepLogic(cpu *mipsevm.CpuScalars, registers *[32]uint32, memor // Take top 4 bits of the next PC (its 256 MB region), and concatenate with the 26-bit offset target := (cpu.NextPC & 0xF0000000) | ((insn & 0x03FFFFFF) << 2) stackTracker.PushStack(cpu.PC, target) - return HandleJump(cpu, registers, linkReg, target) + err = HandleJump(cpu, registers, linkReg, target) + return } // register fetch @@ -57,7 +63,8 @@ func ExecMipsCoreStepLogic(cpu *mipsevm.CpuScalars, registers *[32]uint32, memor } if (opcode >= 4 && opcode < 8) || opcode == 1 { - return HandleBranch(cpu, registers, opcode, insn, rtReg, rs) + err = HandleBranch(cpu, registers, opcode, insn, rtReg, rs) + return } storeAddr := uint32(0xFF_FF_FF_FF) @@ -70,7 +77,7 @@ func ExecMipsCoreStepLogic(cpu *mipsevm.CpuScalars, registers *[32]uint32, memor addr := rs & 0xFFFFFFFC memTracker.TrackMemAccess(addr) mem = memory.GetMemory(addr) - if opcode >= 0x28 && opcode != 0x30 { + if opcode >= 0x28 { // store storeAddr = addr // store opcodes don't write back to a register @@ -86,38 +93,46 @@ func ExecMipsCoreStepLogic(cpu *mipsevm.CpuScalars, registers *[32]uint32, memor linkReg := uint32(0) if fun == 9 { linkReg = rdReg + stackTracker.PushStack(cpu.PC, rs) + } else { + stackTracker.PopStack() } - stackTracker.PopStack() - return HandleJump(cpu, registers, linkReg, rs) + err = HandleJump(cpu, registers, linkReg, rs) + return } if fun == 0xa { // movz - return HandleRd(cpu, registers, rdReg, rs, rt == 0) + err = HandleRd(cpu, registers, rdReg, rs, rt == 0) + return } if fun == 0xb { // movn - return HandleRd(cpu, registers, rdReg, rs, rt != 0) + err = HandleRd(cpu, registers, rdReg, rs, rt != 0) + return } // lo and hi registers // can write back if fun >= 0x10 && fun < 0x1c { - return HandleHiLo(cpu, registers, fun, rs, rt, rdReg) + err = HandleHiLo(cpu, registers, fun, rs, rt, rdReg) + return } } - // store conditional, write a 1 to rt - if opcode == 0x38 && rtReg != 0 { - registers[rtReg] = 1 - } - // write memory if storeAddr != 0xFF_FF_FF_FF { memTracker.TrackMemAccess(storeAddr) memory.SetMemory(storeAddr, val) + memUpdated = true + memAddr = storeAddr } // write back the value to destination register - return HandleRd(cpu, registers, rdReg, val, true) + err = HandleRd(cpu, registers, rdReg, val, true) + return +} + +func SignExtendImmediate(insn uint32) uint32 { + return SignExtend(insn&0xFFFF, 16) } func ExecuteMipsInstruction(insn, opcode, fun, rs, rt, mem uint32) uint32 { @@ -270,10 +285,6 @@ func ExecuteMipsInstruction(insn, opcode, fun, rs, rt, mem uint32) uint32 { val := rt << (24 - (rs&3)*8) mask := uint32(0xFFFFFFFF) << (24 - (rs&3)*8) return (mem & ^mask) | val - case 0x30: // ll - return mem - case 0x38: // sc - return rt default: panic("invalid instruction") } @@ -380,6 +391,7 @@ func HandleRd(cpu *mipsevm.CpuScalars, registers *[32]uint32, storeReg uint32, v panic("invalid register") } if storeReg != 0 && conditional { + // Register 0 is a special register that always holds a value of 0 registers[storeReg] = val } cpu.PC = cpu.NextPC diff --git a/cannon/mipsevm/exec/mips_syscalls.go b/cannon/mipsevm/exec/mips_syscalls.go index af205ab5f46a5..caf3b9bec6306 100644 --- a/cannon/mipsevm/exec/mips_syscalls.go +++ b/cannon/mipsevm/exec/mips_syscalls.go @@ -14,24 +14,26 @@ import ( // Syscall codes const ( - SysMmap = 4090 - SysMunmap = 4091 - SysBrk = 4045 - SysClone = 4120 - SysExitGroup = 4246 - SysRead = 4003 - SysWrite = 4004 - SysFcntl = 4055 - SysExit = 4001 - SysSchedYield = 4162 - SysGetTID = 4222 - SysFutex = 4238 - SysOpen = 4005 - SysNanosleep = 4166 + SysMmap = 4090 + SysBrk = 4045 + SysClone = 4120 + SysExitGroup = 4246 + SysRead = 4003 + SysWrite = 4004 + SysFcntl = 4055 + SysExit = 4001 + SysSchedYield = 4162 + SysGetTID = 4222 + SysFutex = 4238 + SysOpen = 4005 + SysNanosleep = 4166 + SysClockGetTime = 4263 + SysGetpid = 4020 ) // Noop Syscall codes const ( + SysMunmap = 4091 SysGetAffinity = 4240 SysMadvise = 4218 SysRtSigprocmask = 4195 @@ -57,17 +59,11 @@ const ( SysLlseek = 4140 SysMinCore = 4217 SysTgkill = 4266 -) - -// Profiling-related syscalls -// Should be able to ignore if we patch out prometheus calls and disable memprofiling -// TODO(cp-903) - Update patching for mt-cannon so that these can be ignored -const ( + // Profiling-related syscalls SysSetITimer = 4104 SysTimerCreate = 4257 SysTimerSetTime = 4258 SysTimerDelete = 4261 - SysClockGetTime = 4263 ) // File descriptors @@ -132,7 +128,21 @@ const ( // Other constants const ( + // SchedQuantum is the number of steps dedicated for a thread before it's preempted. Effectively used to emulate thread "time slices" SchedQuantum = 100_000 + + // HZ is the assumed clock rate of an emulated MIPS32 CPU. + // The value of HZ is a rough estimate of the Cannon instruction count / second on a typical machine. + // HZ is used to emulate the clock_gettime syscall used by guest programs that have a Go runtime. + // The Go runtime consumes the system time to determine when to initiate gc assists and for goroutine scheduling. + // A HZ value that is too low (i.e. lower than the emulation speed) results in the main goroutine attempting to assist with GC more often. + // Adjust this value accordingly as the emulation speed changes. The HZ value should be within the same order of magnitude as the emulation speed. + HZ = 10_000_000 + + // ClockGettimeRealtimeFlag is the clock_gettime clock id for Linux's realtime clock: https://github.com/torvalds/linux/blob/ad618736883b8970f66af799e34007475fe33a68/include/uapi/linux/time.h#L49 + ClockGettimeRealtimeFlag = 0 + // ClockGettimeMonotonicFlag is the clock_gettime clock id for Linux's monotonic clock: https://github.com/torvalds/linux/blob/ad618736883b8970f66af799e34007475fe33a68/include/uapi/linux/time.h#L50 + ClockGettimeMonotonicFlag = 1 ) func GetSyscallArgs(registers *[32]uint32) (syscallNum, a0, a1, a2, a3 uint32) { @@ -172,7 +182,7 @@ func HandleSysMmap(a0, a1, heap uint32) (v0, v1, newHeap uint32) { return v0, v1, newHeap } -func HandleSysRead(a0, a1, a2 uint32, preimageKey [32]byte, preimageOffset uint32, preimageReader PreimageReader, memory *memory.Memory, memTracker MemTracker) (v0, v1, newPreimageOffset uint32) { +func HandleSysRead(a0, a1, a2 uint32, preimageKey [32]byte, preimageOffset uint32, preimageReader PreimageReader, memory *memory.Memory, memTracker MemTracker) (v0, v1, newPreimageOffset uint32, memUpdated bool, memAddr uint32) { // args: a0 = fd, a1 = addr, a2 = count // returns: v0 = read, v1 = err code v0 = uint32(0) @@ -200,6 +210,8 @@ func HandleSysRead(a0, a1, a2 uint32, preimageKey [32]byte, preimageOffset uint3 binary.BigEndian.PutUint32(outMem[:], mem) copy(outMem[alignment:], dat[:datLen]) memory.SetMemory(effAddr, binary.BigEndian.Uint32(outMem[:])) + memUpdated = true + memAddr = effAddr newPreimageOffset += datLen v0 = datLen //fmt.Printf("read %d pre-image bytes, new offset: %d, eff addr: %08x mem: %08x\n", datLen, m.state.PreimageOffset, effAddr, outMem) @@ -211,7 +223,7 @@ func HandleSysRead(a0, a1, a2 uint32, preimageKey [32]byte, preimageOffset uint3 v1 = MipsEBADF } - return v0, v1, newPreimageOffset + return v0, v1, newPreimageOffset, memUpdated, memAddr } func HandleSysWrite(a0, a1, a2 uint32, lastHint hexutil.Bytes, preimageKey [32]byte, preimageOffset uint32, oracle mipsevm.PreimageOracle, memory *memory.Memory, memTracker MemTracker, stdOut, stdErr io.Writer) (v0, v1 uint32, newLastHint hexutil.Bytes, newPreimageKey common.Hash, newPreimageOffset uint32) { diff --git a/cannon/mipsevm/exec/preimage.go b/cannon/mipsevm/exec/preimage.go index f8039447d4830..15c1f98e95304 100644 --- a/cannon/mipsevm/exec/preimage.go +++ b/cannon/mipsevm/exec/preimage.go @@ -49,7 +49,7 @@ func (p *TrackingPreimageOracleReader) ReadPreimage(key [32]byte, offset uint32) preimage := p.lastPreimage if key != p.lastPreimageKey { p.lastPreimageKey = key - data := p.po.GetPreimage(key) + data := p.GetPreimage(key) // add the length prefix preimage = make([]byte, 0, 8+len(data)) preimage = binary.BigEndian.AppendUint64(preimage, uint64(len(data))) @@ -57,6 +57,9 @@ func (p *TrackingPreimageOracleReader) ReadPreimage(key [32]byte, offset uint32) p.lastPreimage = preimage } p.lastPreimageOffset = offset + if offset >= uint32(len(preimage)) { + panic("Preimage offset out-of-bounds") + } datLen = uint32(copy(dat[:], preimage[offset:])) return } diff --git a/cannon/mipsevm/exec/stack.go b/cannon/mipsevm/exec/stack.go index 378c07b558c07..06e919c0352fa 100644 --- a/cannon/mipsevm/exec/stack.go +++ b/cannon/mipsevm/exec/stack.go @@ -5,7 +5,6 @@ import ( "fmt" "github.com/ethereum-optimism/optimism/cannon/mipsevm" - "github.com/ethereum-optimism/optimism/cannon/mipsevm/program" ) type StackTracker interface { @@ -31,10 +30,10 @@ type StackTrackerImpl struct { stack []uint32 caller []uint32 - meta *program.Metadata + meta mipsevm.Metadata } -func NewStackTracker(state mipsevm.FPVMState, meta *program.Metadata) (*StackTrackerImpl, error) { +func NewStackTracker(state mipsevm.FPVMState, meta mipsevm.Metadata) (*StackTrackerImpl, error) { if meta == nil { return nil, errors.New("metadata is nil") } @@ -42,7 +41,7 @@ func NewStackTracker(state mipsevm.FPVMState, meta *program.Metadata) (*StackTra } // NewStackTrackerUnsafe creates a new TraceableStackTracker without verifying meta is not nil -func NewStackTrackerUnsafe(state mipsevm.FPVMState, meta *program.Metadata) *StackTrackerImpl { +func NewStackTrackerUnsafe(state mipsevm.FPVMState, meta mipsevm.Metadata) *StackTrackerImpl { return &StackTrackerImpl{state: state, meta: meta} } diff --git a/cannon/mipsevm/iface.go b/cannon/mipsevm/iface.go index 5cbab811ca893..8e8d758e90488 100644 --- a/cannon/mipsevm/iface.go +++ b/cannon/mipsevm/iface.go @@ -1,13 +1,19 @@ package mipsevm import ( + "io" + + "github.com/ethereum-optimism/optimism/cannon/serialize" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/log" "github.com/ethereum-optimism/optimism/cannon/mipsevm/memory" ) type FPVMState interface { + serialize.Serializable + GetMemory() *memory.Memory // GetHeap returns the current memory address at the top of the heap @@ -49,6 +55,16 @@ type FPVMState interface { // EncodeWitness returns the witness for the current state and the state hash EncodeWitness() (witness []byte, hash common.Hash) + + // CreateVM creates a FPVM that can operate on this state. + CreateVM(logger log.Logger, po PreimageOracle, stdOut, stdErr io.Writer, meta Metadata) FPVM +} + +type SymbolMatcher func(addr uint32) bool + +type Metadata interface { + LookupSymbol(addr uint32) string + CreateSymbolMatcher(name string) SymbolMatcher } type FPVM interface { @@ -70,6 +86,9 @@ type FPVM interface { // GetDebugInfo returns debug information about the VM GetDebugInfo() *DebugInfo + // InitDebug initializes the debug mode of the VM + InitDebug() error + // LookupSymbol returns the symbol located at the specified address. // May return an empty string if there's no symbol table available. LookupSymbol(addr uint32) string diff --git a/cannon/mipsevm/memory/memory.go b/cannon/mipsevm/memory/memory.go index e02720a2c0d64..392a0482c48e5 100644 --- a/cannon/mipsevm/memory/memory.go +++ b/cannon/mipsevm/memory/memory.go @@ -286,6 +286,62 @@ func (m *Memory) SetMemoryRange(addr uint32, r io.Reader) error { } } +// Serialize writes the memory in a simple binary format which can be read again using Deserialize +// The format is a simple concatenation of fields, with prefixed item count for repeating items and using big endian +// encoding for numbers. +// +// len(PageCount) uint32 +// For each page (order is arbitrary): +// +// page index uint32 +// page Data [PageSize]byte +func (m *Memory) Serialize(out io.Writer) error { + if err := binary.Write(out, binary.BigEndian, uint32(m.PageCount())); err != nil { + return err + } + for pageIndex, page := range m.pages { + if err := binary.Write(out, binary.BigEndian, pageIndex); err != nil { + return err + } + if _, err := out.Write(page.Data[:]); err != nil { + return err + } + } + return nil +} + +func (m *Memory) Deserialize(in io.Reader) error { + var pageCount uint32 + if err := binary.Read(in, binary.BigEndian, &pageCount); err != nil { + return err + } + for i := uint32(0); i < pageCount; i++ { + var pageIndex uint32 + if err := binary.Read(in, binary.BigEndian, &pageIndex); err != nil { + return err + } + page := m.AllocPage(pageIndex) + if _, err := io.ReadFull(in, page.Data[:]); err != nil { + return err + } + } + return nil +} + +func (m *Memory) Copy() *Memory { + out := NewMemory() + out.nodes = make(map[uint64]*[32]byte) + out.pages = make(map[uint32]*CachedPage) + out.lastPageKeys = [2]uint32{^uint32(0), ^uint32(0)} + out.lastPage = [2]*CachedPage{nil, nil} + for k, page := range m.pages { + data := new(Page) + *data = *page.Data + out.AllocPage(k).Data = data + } + return out +} + type memReader struct { m *Memory addr uint32 diff --git a/cannon/mipsevm/memory/memory_test.go b/cannon/mipsevm/memory/memory_test.go index a2b0e745562b8..5f3f9301e5525 100644 --- a/cannon/mipsevm/memory/memory_test.go +++ b/cannon/mipsevm/memory/memory_test.go @@ -187,3 +187,11 @@ func TestMemoryJSON(t *testing.T) { require.NoError(t, json.Unmarshal(dat, &res)) require.Equal(t, uint32(123), res.GetMemory(8)) } + +func TestMemoryCopy(t *testing.T) { + m := NewMemory() + m.SetMemory(0x8000, 123) + mcpy := m.Copy() + require.Equal(t, uint32(123), mcpy.GetMemory(0x8000)) + require.Equal(t, m.MerkleRoot(), mcpy.MerkleRoot()) +} diff --git a/cannon/mipsevm/multithreaded/instrumented.go b/cannon/mipsevm/multithreaded/instrumented.go index 21fb5d9f76571..ac76d6cdb532e 100644 --- a/cannon/mipsevm/multithreaded/instrumented.go +++ b/cannon/mipsevm/multithreaded/instrumented.go @@ -8,8 +8,6 @@ import ( "github.com/ethereum-optimism/optimism/cannon/mipsevm" "github.com/ethereum-optimism/optimism/cannon/mipsevm/exec" - "github.com/ethereum-optimism/optimism/cannon/mipsevm/program" - "github.com/ethereum-optimism/optimism/op-service/jsonutil" ) type InstrumentedState struct { @@ -23,12 +21,12 @@ type InstrumentedState struct { stackTracker ThreadedStackTracker preimageOracle *exec.TrackingPreimageOracleReader - meta *program.Metadata + meta mipsevm.Metadata } var _ mipsevm.FPVM = (*InstrumentedState)(nil) -func NewInstrumentedState(state *State, po mipsevm.PreimageOracle, stdOut, stdErr io.Writer, log log.Logger) *InstrumentedState { +func NewInstrumentedState(state *State, po mipsevm.PreimageOracle, stdOut, stdErr io.Writer, log log.Logger, meta mipsevm.Metadata) *InstrumentedState { return &InstrumentedState{ state: state, log: log, @@ -37,24 +35,16 @@ func NewInstrumentedState(state *State, po mipsevm.PreimageOracle, stdOut, stdEr memoryTracker: exec.NewMemoryTracker(state.Memory), stackTracker: &NoopThreadedStackTracker{}, preimageOracle: exec.NewTrackingPreimageOracleReader(po), + meta: meta, } } -func NewInstrumentedStateFromFile(stateFile string, po mipsevm.PreimageOracle, stdOut, stdErr io.Writer, log log.Logger) (*InstrumentedState, error) { - state, err := jsonutil.LoadJSON[State](stateFile) - if err != nil { - return nil, err - } - return NewInstrumentedState(state, po, stdOut, stdErr, log), nil -} - -func (m *InstrumentedState) InitDebug(meta *program.Metadata) error { - stackTracker, err := NewThreadedStackTracker(m.state, meta) +func (m *InstrumentedState) InitDebug() error { + stackTracker, err := NewThreadedStackTracker(m.state, m.meta) if err != nil { return err } m.stackTracker = stackTracker - m.meta = meta return nil } @@ -83,7 +73,9 @@ func (m *InstrumentedState) Step(proof bool) (wit *mipsevm.StepWitness, err erro if proof { memProof := m.memoryTracker.MemProof() + memProof2 := m.memoryTracker.MemProof2() wit.ProofData = append(wit.ProofData, memProof[:]...) + wit.ProofData = append(wit.ProofData, memProof2[:]...) lastPreimageKey, lastPreimage, lastPreimageOffset := m.preimageOracle.LastPreimage() if lastPreimageOffset != ^uint32(0) { wit.PreimageOffset = lastPreimageOffset diff --git a/cannon/mipsevm/multithreaded/instrumented_test.go b/cannon/mipsevm/multithreaded/instrumented_test.go index c60db57dcfdbf..b3ce2d95eac33 100644 --- a/cannon/mipsevm/multithreaded/instrumented_test.go +++ b/cannon/mipsevm/multithreaded/instrumented_test.go @@ -15,28 +15,32 @@ import ( ) func vmFactory(state *State, po mipsevm.PreimageOracle, stdOut, stdErr io.Writer, log log.Logger) mipsevm.FPVM { - return NewInstrumentedState(state, po, stdOut, stdErr, log) + return NewInstrumentedState(state, po, stdOut, stdErr, log, nil) } func TestInstrumentedState_OpenMips(t *testing.T) { - // TODO(cp-903): Add mt-specific tests here + t.Parallel() + // TODO: Add mt-specific tests here testutil.RunVMTests_OpenMips(t, CreateEmptyState, vmFactory, "clone.bin") } func TestInstrumentedState_Hello(t *testing.T) { + t.Parallel() testutil.RunVMTest_Hello(t, CreateInitialState, vmFactory, false) } func TestInstrumentedState_Claim(t *testing.T) { + t.Parallel() testutil.RunVMTest_Claim(t, CreateInitialState, vmFactory, false) } func TestInstrumentedState_MultithreadedProgram(t *testing.T) { + t.Parallel() state, _ := testutil.LoadELFProgram(t, "../../testdata/example/bin/multithreaded.elf", CreateInitialState, false) oracle := testutil.StaticOracle(t, []byte{}) var stdOutBuf, stdErrBuf bytes.Buffer - us := NewInstrumentedState(state, oracle, io.MultiWriter(&stdOutBuf, os.Stdout), io.MultiWriter(&stdErrBuf, os.Stderr), testutil.CreateLogger()) + us := NewInstrumentedState(state, oracle, io.MultiWriter(&stdOutBuf, os.Stdout), io.MultiWriter(&stdErrBuf, os.Stderr), testutil.CreateLogger(), nil) for i := 0; i < 1_000_000; i++ { if us.GetState().GetExited() { break @@ -54,26 +58,47 @@ func TestInstrumentedState_MultithreadedProgram(t *testing.T) { } func TestInstrumentedState_Alloc(t *testing.T) { - t.Skip("TODO(client-pod#906): Currently failing - need to debug.") + if os.Getenv("SKIP_SLOW_TESTS") == "true" { + t.Skip("Skipping slow test because SKIP_SLOW_TESTS is enabled") + } - state, _ := testutil.LoadELFProgram(t, "../../testdata/example/bin/alloc.elf", CreateInitialState, false) - const numAllocs = 100 // where each alloc is a 32 MiB chunk - oracle := testutil.AllocOracle(t, numAllocs) + const MiB = 1024 * 1024 - // completes in ~870 M steps - us := NewInstrumentedState(state, oracle, os.Stdout, os.Stderr, testutil.CreateLogger()) - for i := 0; i < 20_000_000_000; i++ { - if us.GetState().GetExited() { - break - } - _, err := us.Step(false) - require.NoError(t, err) - if state.Step%10_000_000 == 0 { - t.Logf("Completed %d steps", state.Step) - } + cases := []struct { + name string + numAllocs int + allocSize int + maxMemoryUsageCheck int + }{ + {name: "10 32MiB allocations", numAllocs: 10, allocSize: 32 * MiB, maxMemoryUsageCheck: 256 * MiB}, + {name: "5 64MiB allocations", numAllocs: 5, allocSize: 64 * MiB, maxMemoryUsageCheck: 256 * MiB}, + {name: "5 128MiB allocations", numAllocs: 5, allocSize: 128 * MiB, maxMemoryUsageCheck: 128 * 3 * MiB}, + } + + for _, test := range cases { + test := test + t.Run(test.name, func(t *testing.T) { + t.Parallel() + state, _ := testutil.LoadELFProgram(t, "../../testdata/example/bin/alloc.elf", CreateInitialState, false) + oracle := testutil.AllocOracle(t, test.numAllocs, test.allocSize) + + us := NewInstrumentedState(state, oracle, os.Stdout, os.Stderr, testutil.CreateLogger(), nil) + // emulation shouldn't take more than 20 B steps + for i := 0; i < 20_000_000_000; i++ { + if us.GetState().GetExited() { + break + } + _, err := us.Step(false) + require.NoError(t, err) + if state.Step%10_000_000 == 0 { + t.Logf("Completed %d steps", state.Step) + } + } + memUsage := state.Memory.PageCount() * memory.PageSize + t.Logf("Completed in %d steps. cannon memory usage: %d KiB", state.Step, memUsage/1024/1024.0) + require.True(t, state.Exited, "must complete program") + require.Equal(t, uint8(0), state.ExitCode, "exit with 0") + require.Less(t, memUsage, test.maxMemoryUsageCheck, "memory allocation is too large") + }) } - t.Logf("Completed in %d steps", state.Step) - require.True(t, state.Exited, "must complete program") - require.Equal(t, uint8(0), state.ExitCode, "exit with 0") - require.Less(t, state.Memory.PageCount()*memory.PageSize, 1*1024*1024*1024, "must not allocate more than 1 GiB") } diff --git a/cannon/mipsevm/multithreaded/mips.go b/cannon/mipsevm/multithreaded/mips.go index 7949bbe6c7716..b06ad3917724d 100644 --- a/cannon/mipsevm/multithreaded/mips.go +++ b/cannon/mipsevm/multithreaded/mips.go @@ -75,8 +75,13 @@ func (m *InstrumentedState) handleSyscall() error { return nil case exec.SysRead: var newPreimageOffset uint32 - v0, v1, newPreimageOffset = exec.HandleSysRead(a0, a1, a2, m.state.PreimageKey, m.state.PreimageOffset, m.preimageOracle, m.state.Memory, m.memoryTracker) + var memUpdated bool + var memAddr uint32 + v0, v1, newPreimageOffset, memUpdated, memAddr = exec.HandleSysRead(a0, a1, a2, m.state.PreimageKey, m.state.PreimageOffset, m.preimageOracle, m.state.Memory, m.memoryTracker) m.state.PreimageOffset = newPreimageOffset + if memUpdated { + m.handleMemoryUpdate(memAddr) + } case exec.SysWrite: var newLastHint hexutil.Bytes var newPreimageKey common.Hash @@ -100,15 +105,16 @@ func (m *InstrumentedState) handleSyscall() error { return nil case exec.SysFutex: // args: a0 = addr, a1 = op, a2 = val, a3 = timeout + effAddr := a0 & 0xFFffFFfc switch a1 { case exec.FutexWaitPrivate: - thread.FutexAddr = a0 - m.memoryTracker.TrackMemAccess(a0) - mem := m.state.Memory.GetMemory(a0) + m.memoryTracker.TrackMemAccess(effAddr) + mem := m.state.Memory.GetMemory(effAddr) if mem != a2 { v0 = exec.SysErrorSignal v1 = exec.MipsEAGAIN } else { + thread.FutexAddr = effAddr thread.FutexVal = a2 if a3 == 0 { thread.FutexTimeoutStep = exec.FutexNoTimeout @@ -121,7 +127,7 @@ func (m *InstrumentedState) handleSyscall() error { case exec.FutexWakePrivate: // Trigger thread traversal starting from the left stack until we find one waiting on the wakeup // address - m.state.Wakeup = a0 + m.state.Wakeup = effAddr // Don't indicate to the program that we've woken up a waiting thread, as there are no guarantees. // The woken up thread should indicate this in userspace. v0 = 0 @@ -143,6 +149,32 @@ func (m *InstrumentedState) handleSyscall() error { case exec.SysOpen: v0 = exec.SysErrorSignal v1 = exec.MipsEBADF + case exec.SysClockGetTime: + switch a0 { + case exec.ClockGettimeRealtimeFlag, exec.ClockGettimeMonotonicFlag: + v0, v1 = 0, 0 + var secs, nsecs uint32 + if a0 == exec.ClockGettimeMonotonicFlag { + // monotonic clock_gettime is used by Go guest programs for goroutine scheduling and to implement + // `time.Sleep` (and other sleep related operations). + secs = uint32(m.state.Step / exec.HZ) + nsecs = uint32((m.state.Step % exec.HZ) * (1_000_000_000 / exec.HZ)) + } // else realtime set to Unix Epoch + + effAddr := a1 & 0xFFffFFfc + m.memoryTracker.TrackMemAccess(effAddr) + m.state.Memory.SetMemory(effAddr, secs) + m.handleMemoryUpdate(effAddr) + m.memoryTracker.TrackMemAccess2(effAddr + 4) + m.state.Memory.SetMemory(effAddr+4, nsecs) + m.handleMemoryUpdate(effAddr + 4) + default: + v0 = exec.SysErrorSignal + v1 = exec.MipsEINVAL + } + case exec.SysGetpid: + v0 = 0 + v1 = 0 case exec.SysMunmap: case exec.SysGetAffinity: case exec.SysMadvise: @@ -173,7 +205,6 @@ func (m *InstrumentedState) handleSyscall() error { case exec.SysTimerCreate: case exec.SysTimerSetTime: case exec.SysTimerDelete: - case exec.SysClockGetTime: default: m.Traceback() panic(fmt.Sprintf("unrecognized syscall: %d", syscallNum)) @@ -225,8 +256,9 @@ func (m *InstrumentedState) mipsStep() error { m.onWaitComplete(thread, true) return nil } else { - m.memoryTracker.TrackMemAccess(thread.FutexAddr) - mem := m.state.Memory.GetMemory(thread.FutexAddr) + effAddr := thread.FutexAddr & 0xFFffFFfc + m.memoryTracker.TrackMemAccess(effAddr) + mem := m.state.Memory.GetMemory(effAddr) if thread.FutexVal == mem { // still got expected value, continue sleeping, try next thread. m.preemptThread(thread) @@ -242,11 +274,11 @@ func (m *InstrumentedState) mipsStep() error { if m.state.StepsSinceLastContextSwitch >= exec.SchedQuantum { // Force a context switch as this thread has been active too long - if m.state.threadCount() > 1 { + if m.state.ThreadCount() > 1 { // Log if we're hitting our context switch limit - only matters if we have > 1 thread if m.log.Enabled(context.Background(), log.LevelTrace) { msg := fmt.Sprintf("Thread has reached maximum execution steps (%v) - preempting.", exec.SchedQuantum) - m.log.Trace(msg, "threadId", thread.ThreadId, "threadCount", m.state.threadCount(), "pc", thread.Cpu.PC) + m.log.Trace(msg, "threadId", thread.ThreadId, "threadCount", m.state.ThreadCount(), "pc", thread.Cpu.PC) } } m.preemptThread(thread) @@ -263,11 +295,75 @@ func (m *InstrumentedState) mipsStep() error { return m.handleSyscall() } + // Handle RMW (read-modify-write) ops + if opcode == exec.OpLoadLinked || opcode == exec.OpStoreConditional { + return m.handleRMWOps(insn, opcode) + } + // Exec the rest of the step logic - return exec.ExecMipsCoreStepLogic(m.state.getCpuRef(), m.state.GetRegistersRef(), m.state.Memory, insn, opcode, fun, m.memoryTracker, m.stackTracker) + memUpdated, memAddr, err := exec.ExecMipsCoreStepLogic(m.state.getCpuRef(), m.state.GetRegistersRef(), m.state.Memory, insn, opcode, fun, m.memoryTracker, m.stackTracker) + if err != nil { + return err + } + if memUpdated { + m.handleMemoryUpdate(memAddr) + } + + return nil +} + +func (m *InstrumentedState) handleMemoryUpdate(memAddr uint32) { + if memAddr == m.state.LLAddress { + // Reserved address was modified, clear the reservation + m.clearLLMemoryReservation() + } +} + +func (m *InstrumentedState) clearLLMemoryReservation() { + m.state.LLReservationActive = false + m.state.LLAddress = 0 + m.state.LLOwnerThread = 0 +} + +// handleRMWOps handles LL and SC operations which provide the primitives to implement read-modify-write operations +func (m *InstrumentedState) handleRMWOps(insn, opcode uint32) error { + baseReg := (insn >> 21) & 0x1F + base := m.state.GetRegistersRef()[baseReg] + rtReg := (insn >> 16) & 0x1F + offset := exec.SignExtendImmediate(insn) + + effAddr := (base + offset) & 0xFFFFFFFC + m.memoryTracker.TrackMemAccess(effAddr) + mem := m.state.Memory.GetMemory(effAddr) + + var retVal uint32 + threadId := m.state.GetCurrentThread().ThreadId + if opcode == exec.OpLoadLinked { + retVal = mem + m.state.LLReservationActive = true + m.state.LLAddress = effAddr + m.state.LLOwnerThread = threadId + } else if opcode == exec.OpStoreConditional { + // Check if our memory reservation is still intact + if m.state.LLReservationActive && m.state.LLOwnerThread == threadId && m.state.LLAddress == effAddr { + // Complete atomic update: set memory and return 1 for success + m.clearLLMemoryReservation() + rt := m.state.GetRegistersRef()[rtReg] + m.state.Memory.SetMemory(effAddr, rt) + retVal = 1 + } else { + // Atomic update failed, return 0 for failure + retVal = 0 + } + } else { + panic(fmt.Sprintf("Invalid instruction passed to handleRMWOps (opcode %08x)", opcode)) + } + + return exec.HandleRd(m.state.getCpuRef(), m.state.GetRegistersRef(), rtReg, retVal, true) } func (m *InstrumentedState) onWaitComplete(thread *ThreadState, isTimedOut bool) { + // Note: no need to reset m.state.Wakeup. If we're here, the Wakeup field has already been reset // Clear the futex state thread.FutexAddr = exec.FutexEmptyAddr thread.FutexVal = 0 @@ -281,9 +377,6 @@ func (m *InstrumentedState) onWaitComplete(thread *ThreadState, isTimedOut bool) v1 = exec.MipsETIMEDOUT } exec.HandleSyscallUpdates(&thread.Cpu, &thread.Registers, v0, v1) - - // Clear wakeup signal - m.state.Wakeup = exec.FutexEmptyAddr } func (m *InstrumentedState) preemptThread(thread *ThreadState) bool { @@ -339,5 +432,5 @@ func (m *InstrumentedState) popThread() { } func (m *InstrumentedState) lastThreadRemaining() bool { - return m.state.threadCount() == 1 + return m.state.ThreadCount() == 1 } diff --git a/cannon/mipsevm/multithreaded/stack.go b/cannon/mipsevm/multithreaded/stack.go index ab710267fbe81..4fc32c221ee87 100644 --- a/cannon/mipsevm/multithreaded/stack.go +++ b/cannon/mipsevm/multithreaded/stack.go @@ -3,8 +3,8 @@ package multithreaded import ( "errors" + "github.com/ethereum-optimism/optimism/cannon/mipsevm" "github.com/ethereum-optimism/optimism/cannon/mipsevm/exec" - "github.com/ethereum-optimism/optimism/cannon/mipsevm/program" ) type ThreadedStackTracker interface { @@ -21,14 +21,14 @@ var _ ThreadedStackTracker = (*ThreadedStackTrackerImpl)(nil) func (n *NoopThreadedStackTracker) DropThread(threadId uint32) {} type ThreadedStackTrackerImpl struct { - meta *program.Metadata + meta mipsevm.Metadata state *State trackersByThreadId map[uint32]exec.TraceableStackTracker } var _ ThreadedStackTracker = (*ThreadedStackTrackerImpl)(nil) -func NewThreadedStackTracker(state *State, meta *program.Metadata) (*ThreadedStackTrackerImpl, error) { +func NewThreadedStackTracker(state *State, meta mipsevm.Metadata) (*ThreadedStackTrackerImpl, error) { if meta == nil { return nil, errors.New("metadata is nil") } diff --git a/cannon/mipsevm/multithreaded/state.go b/cannon/mipsevm/multithreaded/state.go index 6602357747bf8..f93a99564958d 100644 --- a/cannon/mipsevm/multithreaded/state.go +++ b/cannon/mipsevm/multithreaded/state.go @@ -3,24 +3,30 @@ package multithreaded import ( "encoding/binary" "fmt" + "io" "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" "github.com/ethereum-optimism/optimism/cannon/mipsevm" "github.com/ethereum-optimism/optimism/cannon/mipsevm/exec" "github.com/ethereum-optimism/optimism/cannon/mipsevm/memory" + "github.com/ethereum-optimism/optimism/cannon/serialize" ) // STATE_WITNESS_SIZE is the size of the state witness encoding in bytes. -const STATE_WITNESS_SIZE = 163 +const STATE_WITNESS_SIZE = 172 const ( MEMROOT_WITNESS_OFFSET = 0 PREIMAGE_KEY_WITNESS_OFFSET = MEMROOT_WITNESS_OFFSET + 32 PREIMAGE_OFFSET_WITNESS_OFFSET = PREIMAGE_KEY_WITNESS_OFFSET + 32 HEAP_WITNESS_OFFSET = PREIMAGE_OFFSET_WITNESS_OFFSET + 4 - EXITCODE_WITNESS_OFFSET = HEAP_WITNESS_OFFSET + 4 + LL_RESERVATION_ACTIVE_OFFSET = HEAP_WITNESS_OFFSET + 4 + LL_ADDRESS_OFFSET = LL_RESERVATION_ACTIVE_OFFSET + 1 + LL_OWNER_THREAD_OFFSET = LL_ADDRESS_OFFSET + 4 + EXITCODE_WITNESS_OFFSET = LL_OWNER_THREAD_OFFSET + 4 EXITED_WITNESS_OFFSET = EXITCODE_WITNESS_OFFSET + 1 STEP_WITNESS_OFFSET = EXITED_WITNESS_OFFSET + 1 STEPS_SINCE_CONTEXT_SWITCH_WITNESS_OFFSET = STEP_WITNESS_OFFSET + 8 @@ -32,27 +38,30 @@ const ( ) type State struct { - Memory *memory.Memory `json:"memory"` + Memory *memory.Memory - PreimageKey common.Hash `json:"preimageKey"` - PreimageOffset uint32 `json:"preimageOffset"` // note that the offset includes the 8-byte length prefix + PreimageKey common.Hash + PreimageOffset uint32 // note that the offset includes the 8-byte length prefix - Heap uint32 `json:"heap"` // to handle mmap growth + Heap uint32 // to handle mmap growth + LLReservationActive bool // Whether there is an active memory reservation initiated via the LL (load linked) op + LLAddress uint32 // The "linked" memory address reserved via the LL (load linked) op + LLOwnerThread uint32 // The id of the thread that holds the reservation on LLAddress - ExitCode uint8 `json:"exit"` - Exited bool `json:"exited"` + ExitCode uint8 + Exited bool - Step uint64 `json:"step"` - StepsSinceLastContextSwitch uint64 `json:"stepsSinceLastContextSwitch"` - Wakeup uint32 `json:"wakeup"` + Step uint64 + StepsSinceLastContextSwitch uint64 + Wakeup uint32 - TraverseRight bool `json:"traverseRight"` - LeftThreadStack []*ThreadState `json:"leftThreadStack"` - RightThreadStack []*ThreadState `json:"rightThreadStack"` - NextThreadId uint32 `json:"nextThreadId"` + TraverseRight bool + LeftThreadStack []*ThreadState + RightThreadStack []*ThreadState + NextThreadId uint32 // LastHint is optional metadata, and not part of the VM state itself. - LastHint hexutil.Bytes `json:"lastHint,omitempty"` + LastHint hexutil.Bytes } var _ mipsevm.FPVMState = (*State)(nil) @@ -61,16 +70,19 @@ func CreateEmptyState() *State { initThread := CreateEmptyThread() return &State{ - Memory: memory.NewMemory(), - Heap: 0, - ExitCode: 0, - Exited: false, - Step: 0, - Wakeup: exec.FutexEmptyAddr, - TraverseRight: false, - LeftThreadStack: []*ThreadState{initThread}, - RightThreadStack: []*ThreadState{}, - NextThreadId: initThread.ThreadId + 1, + Memory: memory.NewMemory(), + Heap: 0, + LLReservationActive: false, + LLAddress: 0, + LLOwnerThread: 0, + ExitCode: 0, + Exited: false, + Step: 0, + Wakeup: exec.FutexEmptyAddr, + TraverseRight: false, + LeftThreadStack: []*ThreadState{initThread}, + RightThreadStack: []*ThreadState{}, + NextThreadId: initThread.ThreadId + 1, } } @@ -84,6 +96,11 @@ func CreateInitialState(pc, heapStart uint32) *State { return state } +func (s *State) CreateVM(logger log.Logger, po mipsevm.PreimageOracle, stdOut, stdErr io.Writer, meta mipsevm.Metadata) mipsevm.FPVM { + logger.Info("Using cannon multithreaded VM") + return NewInstrumentedState(s, po, stdOut, stdErr, logger, meta) +} + func (s *State) GetCurrentThread() *ThreadState { activeStack := s.getActiveThreadStack() @@ -179,6 +196,9 @@ func (s *State) EncodeWitness() ([]byte, common.Hash) { out = append(out, s.PreimageKey[:]...) out = binary.BigEndian.AppendUint32(out, s.PreimageOffset) out = binary.BigEndian.AppendUint32(out, s.Heap) + out = mipsevm.AppendBoolToWitness(out, s.LLReservationActive) + out = binary.BigEndian.AppendUint32(out, s.LLAddress) + out = binary.BigEndian.AppendUint32(out, s.LLOwnerThread) out = append(out, s.ExitCode) out = mipsevm.AppendBoolToWitness(out, s.Exited) @@ -215,10 +235,178 @@ func (s *State) EncodeThreadProof() []byte { return out } -func (s *State) threadCount() int { +func (s *State) ThreadCount() int { return len(s.LeftThreadStack) + len(s.RightThreadStack) } +// Serialize writes the state in a simple binary format which can be read again using Deserialize +// The format is a simple concatenation of fields, with prefixed item count for repeating items and using big endian +// encoding for numbers. +// +// StateVersion uint8(1) +// Memory As per Memory.Serialize +// PreimageKey [32]byte +// PreimageOffset uint32 +// Heap uint32 +// ExitCode uint8 +// Exited uint8 - 0 for false, 1 for true +// Step uint64 +// StepsSinceLastContextSwitch uint64 +// Wakeup uint32 +// TraverseRight uint8 - 0 for false, 1 for true +// NextThreadId uint32 +// len(LeftThreadStack) uint32 +// LeftThreadStack entries as per ThreadState.Serialize +// len(RightThreadStack) uint32 +// RightThreadStack entries as per ThreadState.Serialize +// len(LastHint) uint32 (0 when LastHint is nil) +// LastHint []byte +func (s *State) Serialize(out io.Writer) error { + bout := serialize.NewBinaryWriter(out) + + if err := s.Memory.Serialize(out); err != nil { + return err + } + if err := bout.WriteHash(s.PreimageKey); err != nil { + return err + } + if err := bout.WriteUInt(s.PreimageOffset); err != nil { + return err + } + if err := bout.WriteUInt(s.Heap); err != nil { + return err + } + if err := bout.WriteBool(s.LLReservationActive); err != nil { + return err + } + if err := bout.WriteUInt(s.LLAddress); err != nil { + return err + } + if err := bout.WriteUInt(s.LLOwnerThread); err != nil { + return err + } + if err := bout.WriteUInt(s.ExitCode); err != nil { + return err + } + if err := bout.WriteBool(s.Exited); err != nil { + return err + } + if err := bout.WriteUInt(s.Step); err != nil { + return err + } + if err := bout.WriteUInt(s.StepsSinceLastContextSwitch); err != nil { + return err + } + if err := bout.WriteUInt(s.Wakeup); err != nil { + return err + } + if err := bout.WriteBool(s.TraverseRight); err != nil { + return err + } + if err := bout.WriteUInt(s.NextThreadId); err != nil { + return err + } + + if err := bout.WriteUInt(uint32(len(s.LeftThreadStack))); err != nil { + return err + } + for _, stack := range s.LeftThreadStack { + if err := stack.Serialize(out); err != nil { + return err + } + } + if err := bout.WriteUInt(uint32(len(s.RightThreadStack))); err != nil { + return err + } + for _, stack := range s.RightThreadStack { + if err := stack.Serialize(out); err != nil { + return err + } + } + if err := bout.WriteBytes(s.LastHint); err != nil { + return err + } + + return nil +} + +func (s *State) Deserialize(in io.Reader) error { + bin := serialize.NewBinaryReader(in) + s.Memory = memory.NewMemory() + if err := s.Memory.Deserialize(in); err != nil { + return err + } + if err := bin.ReadHash(&s.PreimageKey); err != nil { + return err + } + if err := bin.ReadUInt(&s.PreimageOffset); err != nil { + return err + } + if err := bin.ReadUInt(&s.Heap); err != nil { + return err + } + if err := bin.ReadBool(&s.LLReservationActive); err != nil { + return err + } + if err := bin.ReadUInt(&s.LLAddress); err != nil { + return err + } + if err := bin.ReadUInt(&s.LLOwnerThread); err != nil { + return err + } + if err := bin.ReadUInt(&s.ExitCode); err != nil { + return err + } + if err := bin.ReadBool(&s.Exited); err != nil { + return err + } + if err := bin.ReadUInt(&s.Step); err != nil { + return err + } + if err := bin.ReadUInt(&s.StepsSinceLastContextSwitch); err != nil { + return err + } + if err := bin.ReadUInt(&s.Wakeup); err != nil { + return err + } + if err := bin.ReadBool(&s.TraverseRight); err != nil { + return err + } + + if err := bin.ReadUInt(&s.NextThreadId); err != nil { + return err + } + + var leftThreadStackSize uint32 + if err := bin.ReadUInt(&leftThreadStackSize); err != nil { + return err + } + s.LeftThreadStack = make([]*ThreadState, leftThreadStackSize) + for i := range s.LeftThreadStack { + s.LeftThreadStack[i] = &ThreadState{} + if err := s.LeftThreadStack[i].Deserialize(in); err != nil { + return err + } + } + + var rightThreadStackSize uint32 + if err := bin.ReadUInt(&rightThreadStackSize); err != nil { + return err + } + s.RightThreadStack = make([]*ThreadState, rightThreadStackSize) + for i := range s.RightThreadStack { + s.RightThreadStack[i] = &ThreadState{} + if err := s.RightThreadStack[i].Deserialize(in); err != nil { + return err + } + } + + if err := bin.ReadBytes((*[]byte)(&s.LastHint)); err != nil { + return err + } + return nil +} + type StateWitness []byte func (sw StateWitness) StateHash() (common.Hash, error) { diff --git a/cannon/mipsevm/multithreaded/state_test.go b/cannon/mipsevm/multithreaded/state_test.go index c267416b8ae4c..6d776632bf0f0 100644 --- a/cannon/mipsevm/multithreaded/state_test.go +++ b/cannon/mipsevm/multithreaded/state_test.go @@ -1,16 +1,20 @@ package multithreaded import ( + "bytes" "debug/elf" "encoding/json" "testing" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/crypto" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/ethereum-optimism/optimism/cannon/mipsevm" "github.com/ethereum-optimism/optimism/cannon/mipsevm/exec" + "github.com/ethereum-optimism/optimism/cannon/mipsevm/memory" "github.com/ethereum-optimism/optimism/cannon/mipsevm/program" ) @@ -38,6 +42,8 @@ func TestState_EncodeWitness(t *testing.T) { } heap := uint32(12) + llAddress := uint32(55) + llThreadOwner := uint32(99) preimageKey := crypto.Keccak256Hash([]byte{1, 2, 3, 4}) preimageOffset := uint32(24) step := uint64(33) @@ -49,6 +55,9 @@ func TestState_EncodeWitness(t *testing.T) { state.PreimageKey = preimageKey state.PreimageOffset = preimageOffset state.Heap = heap + state.LLReservationActive = true + state.LLAddress = llAddress + state.LLOwnerThread = llThreadOwner state.Step = step state.StepsSinceLastContextSwitch = stepsSinceContextSwitch @@ -62,6 +71,9 @@ func TestState_EncodeWitness(t *testing.T) { setWitnessField(expectedWitness, PREIMAGE_KEY_WITNESS_OFFSET, preimageKey[:]) setWitnessField(expectedWitness, PREIMAGE_OFFSET_WITNESS_OFFSET, []byte{0, 0, 0, byte(preimageOffset)}) setWitnessField(expectedWitness, HEAP_WITNESS_OFFSET, []byte{0, 0, 0, byte(heap)}) + setWitnessField(expectedWitness, LL_RESERVATION_ACTIVE_OFFSET, []byte{1}) + setWitnessField(expectedWitness, LL_ADDRESS_OFFSET, []byte{0, 0, 0, byte(llAddress)}) + setWitnessField(expectedWitness, LL_OWNER_THREAD_OFFSET, []byte{0, 0, 0, byte(llThreadOwner)}) setWitnessField(expectedWitness, EXITCODE_WITNESS_OFFSET, []byte{c.exitCode}) if c.exited { setWitnessField(expectedWitness, EXITED_WITNESS_OFFSET, []byte{1}) @@ -123,6 +135,157 @@ func TestState_JSONCodec(t *testing.T) { require.Equal(t, state.LastHint, newState.LastHint) } +func TestState_Binary(t *testing.T) { + elfProgram, err := elf.Open("../../testdata/example/bin/hello.elf") + require.NoError(t, err, "open ELF file") + state, err := program.LoadELF(elfProgram, CreateInitialState) + require.NoError(t, err, "load ELF into state") + // Set a few additional fields + state.PreimageKey = crypto.Keccak256Hash([]byte{1, 2, 3, 4}) + state.PreimageOffset = 4 + state.Heap = 555 + state.Step = 99_999 + state.StepsSinceLastContextSwitch = 123 + state.Exited = true + state.ExitCode = 2 + state.LastHint = []byte{11, 12, 13} + + buf := new(bytes.Buffer) + err = state.Serialize(buf) + require.NoError(t, err) + + newState := new(State) + require.NoError(t, newState.Deserialize(bytes.NewReader(buf.Bytes()))) + + require.Equal(t, state.PreimageKey, newState.PreimageKey) + require.Equal(t, state.PreimageOffset, newState.PreimageOffset) + require.Equal(t, state.Heap, newState.Heap) + require.Equal(t, state.ExitCode, newState.ExitCode) + require.Equal(t, state.Exited, newState.Exited) + require.Equal(t, state.Memory.MerkleRoot(), newState.Memory.MerkleRoot()) + require.Equal(t, state.Step, newState.Step) + require.Equal(t, state.StepsSinceLastContextSwitch, newState.StepsSinceLastContextSwitch) + require.Equal(t, state.Wakeup, newState.Wakeup) + require.Equal(t, state.TraverseRight, newState.TraverseRight) + require.Equal(t, state.LeftThreadStack, newState.LeftThreadStack) + require.Equal(t, state.RightThreadStack, newState.RightThreadStack) + require.Equal(t, state.NextThreadId, newState.NextThreadId) + require.Equal(t, state.LastHint, newState.LastHint) +} + +func TestSerializeStateRoundTrip(t *testing.T) { + // Construct a test case with populated fields + mem := memory.NewMemory() + mem.AllocPage(5) + p := mem.AllocPage(123) + p.Data[2] = 0x01 + state := &State{ + Memory: mem, + PreimageKey: common.Hash{0xFF}, + PreimageOffset: 5, + Heap: 0xc0ffee, + LLReservationActive: true, + LLAddress: 0x12345678, + LLOwnerThread: 0x02, + ExitCode: 1, + Exited: true, + Step: 0xdeadbeef, + StepsSinceLastContextSwitch: 334, + Wakeup: 42, + TraverseRight: true, + LeftThreadStack: []*ThreadState{ + { + ThreadId: 45, + ExitCode: 46, + Exited: true, + FutexAddr: 47, + FutexVal: 48, + FutexTimeoutStep: 49, + Cpu: mipsevm.CpuScalars{ + PC: 0xFF, + NextPC: 0xFF + 4, + LO: 0xbeef, + HI: 0xbabe, + }, + Registers: [32]uint32{ + 0xdeadbeef, + 0xdeadbeef, + 0xc0ffee, + 0xbeefbabe, + 0xdeadc0de, + 0xbadc0de, + 0xdeaddead, + }, + }, + { + ThreadId: 55, + ExitCode: 56, + Exited: false, + FutexAddr: 57, + FutexVal: 58, + FutexTimeoutStep: 59, + Cpu: mipsevm.CpuScalars{ + PC: 0xEE, + NextPC: 0xEE + 4, + LO: 0xeeef, + HI: 0xeabe, + }, + Registers: [32]uint32{ + 0xabcdef, + 0x123456, + }, + }, + }, + RightThreadStack: []*ThreadState{ + { + ThreadId: 65, + ExitCode: 66, + Exited: false, + FutexAddr: 67, + FutexVal: 68, + FutexTimeoutStep: 69, + Cpu: mipsevm.CpuScalars{ + PC: 0xdd, + NextPC: 0xdd + 4, + LO: 0xdeef, + HI: 0xdabe, + }, + Registers: [32]uint32{ + 0x654321, + }, + }, + { + ThreadId: 75, + ExitCode: 76, + Exited: true, + FutexAddr: 77, + FutexVal: 78, + FutexTimeoutStep: 79, + Cpu: mipsevm.CpuScalars{ + PC: 0xcc, + NextPC: 0xcc + 4, + LO: 0xceef, + HI: 0xcabe, + }, + Registers: [32]uint32{ + 0x987653, + 0xfedbca, + }, + }, + }, + NextThreadId: 489, + LastHint: hexutil.Bytes{1, 2, 3, 4, 5}, + } + + ser := new(bytes.Buffer) + err := state.Serialize(ser) + require.NoError(t, err, "must serialize state") + state2 := &State{} + err = state2.Deserialize(ser) + require.NoError(t, err, "must deserialize state") + require.Equal(t, state, state2, "must roundtrip state") +} + func TestState_EmptyThreadsRoot(t *testing.T) { data := [64]byte{} expectedEmptyRoot := crypto.Keccak256Hash(data[:]) diff --git a/cannon/mipsevm/multithreaded/testutil/expectations.go b/cannon/mipsevm/multithreaded/testutil/expectations.go new file mode 100644 index 0000000000000..559ed2de8c4fd --- /dev/null +++ b/cannon/mipsevm/multithreaded/testutil/expectations.go @@ -0,0 +1,226 @@ +package testutil + +import ( + "fmt" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/stretchr/testify/require" + + "github.com/ethereum-optimism/optimism/cannon/mipsevm/memory" + "github.com/ethereum-optimism/optimism/cannon/mipsevm/multithreaded" +) + +// ExpectedMTState is a test utility that basically stores a copy of a state that can be explicitly mutated +// to define an expected post-state. The post-state is then validated with ExpectedMTState.Validate(t, postState) +type ExpectedMTState struct { + PreimageKey common.Hash + PreimageOffset uint32 + Heap uint32 + LLReservationActive bool + LLAddress uint32 + LLOwnerThread uint32 + ExitCode uint8 + Exited bool + Step uint64 + LastHint hexutil.Bytes + MemoryRoot common.Hash + expectedMemory *memory.Memory + // Threading-related expectations + StepsSinceLastContextSwitch uint64 + Wakeup uint32 + TraverseRight bool + NextThreadId uint32 + ThreadCount int + RightStackSize int + LeftStackSize int + prestateActiveThreadId uint32 + prestateActiveThreadOrig ExpectedThreadState // Cached for internal use + ActiveThreadId uint32 + threadExpectations map[uint32]*ExpectedThreadState +} + +type ExpectedThreadState struct { + ThreadId uint32 + ExitCode uint8 + Exited bool + FutexAddr uint32 + FutexVal uint32 + FutexTimeoutStep uint64 + PC uint32 + NextPC uint32 + HI uint32 + LO uint32 + Registers [32]uint32 + Dropped bool +} + +func NewExpectedMTState(fromState *multithreaded.State) *ExpectedMTState { + currentThread := fromState.GetCurrentThread() + + expectedThreads := make(map[uint32]*ExpectedThreadState) + for _, t := range GetAllThreads(fromState) { + expectedThreads[t.ThreadId] = newExpectedThreadState(t) + } + + return &ExpectedMTState{ + // General Fields + PreimageKey: fromState.GetPreimageKey(), + PreimageOffset: fromState.GetPreimageOffset(), + Heap: fromState.GetHeap(), + LLReservationActive: fromState.LLReservationActive, + LLAddress: fromState.LLAddress, + LLOwnerThread: fromState.LLOwnerThread, + ExitCode: fromState.GetExitCode(), + Exited: fromState.GetExited(), + Step: fromState.GetStep(), + LastHint: fromState.GetLastHint(), + MemoryRoot: fromState.GetMemory().MerkleRoot(), + // Thread-related global fields + StepsSinceLastContextSwitch: fromState.StepsSinceLastContextSwitch, + Wakeup: fromState.Wakeup, + TraverseRight: fromState.TraverseRight, + NextThreadId: fromState.NextThreadId, + ThreadCount: fromState.ThreadCount(), + RightStackSize: len(fromState.RightThreadStack), + LeftStackSize: len(fromState.LeftThreadStack), + // ThreadState expectations + prestateActiveThreadId: currentThread.ThreadId, + prestateActiveThreadOrig: *newExpectedThreadState(currentThread), // Cache prestate thread for internal use + ActiveThreadId: currentThread.ThreadId, + threadExpectations: expectedThreads, + expectedMemory: fromState.Memory.Copy(), + } +} + +func newExpectedThreadState(fromThread *multithreaded.ThreadState) *ExpectedThreadState { + return &ExpectedThreadState{ + ThreadId: fromThread.ThreadId, + ExitCode: fromThread.ExitCode, + Exited: fromThread.Exited, + FutexAddr: fromThread.FutexAddr, + FutexVal: fromThread.FutexVal, + FutexTimeoutStep: fromThread.FutexTimeoutStep, + PC: fromThread.Cpu.PC, + NextPC: fromThread.Cpu.NextPC, + HI: fromThread.Cpu.HI, + LO: fromThread.Cpu.LO, + Registers: fromThread.Registers, + Dropped: false, + } +} + +func (e *ExpectedMTState) ExpectStep() { + // Set some standard expectations for a normal step + e.Step += 1 + e.PrestateActiveThread().PC += 4 + e.PrestateActiveThread().NextPC += 4 + e.StepsSinceLastContextSwitch += 1 +} + +func (e *ExpectedMTState) ExpectMemoryWrite(addr uint32, val uint32) { + e.expectedMemory.SetMemory(addr, val) + e.MemoryRoot = e.expectedMemory.MerkleRoot() +} + +func (e *ExpectedMTState) ExpectMemoryWriteMultiple(addr uint32, val uint32, addr2 uint32, val2 uint32) { + e.expectedMemory.SetMemory(addr, val) + e.expectedMemory.SetMemory(addr2, val2) + e.MemoryRoot = e.expectedMemory.MerkleRoot() +} + +func (e *ExpectedMTState) ExpectPreemption(preState *multithreaded.State) { + e.ActiveThreadId = FindNextThread(preState).ThreadId + e.StepsSinceLastContextSwitch = 0 + if preState.TraverseRight { + e.TraverseRight = e.RightStackSize > 1 + e.RightStackSize -= 1 + e.LeftStackSize += 1 + } else { + e.TraverseRight = e.LeftStackSize == 1 + e.LeftStackSize -= 1 + e.RightStackSize += 1 + } +} + +func (e *ExpectedMTState) ExpectNewThread() *ExpectedThreadState { + newThreadId := e.NextThreadId + e.NextThreadId += 1 + e.ThreadCount += 1 + + // Clone expectations from prestate active thread's original state (bf changing any expectations) + newThread := &ExpectedThreadState{} + *newThread = e.prestateActiveThreadOrig + + newThread.ThreadId = newThreadId + e.threadExpectations[newThreadId] = newThread + + return newThread +} + +func (e *ExpectedMTState) ActiveThread() *ExpectedThreadState { + return e.threadExpectations[e.ActiveThreadId] +} + +func (e *ExpectedMTState) PrestateActiveThread() *ExpectedThreadState { + return e.threadExpectations[e.prestateActiveThreadId] +} + +func (e *ExpectedMTState) Thread(threadId uint32) *ExpectedThreadState { + return e.threadExpectations[threadId] +} + +func (e *ExpectedMTState) Validate(t require.TestingT, actualState *multithreaded.State) { + require.Equalf(t, e.PreimageKey, actualState.GetPreimageKey(), "Expect preimageKey = %v", e.PreimageKey) + require.Equalf(t, e.PreimageOffset, actualState.GetPreimageOffset(), "Expect preimageOffset = %v", e.PreimageOffset) + require.Equalf(t, e.Heap, actualState.GetHeap(), "Expect heap = 0x%x", e.Heap) + require.Equalf(t, e.LLReservationActive, actualState.LLReservationActive, "Expect LLReservationActive = %v", e.LLReservationActive) + require.Equalf(t, e.LLAddress, actualState.LLAddress, "Expect LLAddress = 0x%x", e.LLAddress) + require.Equalf(t, e.LLOwnerThread, actualState.LLOwnerThread, "Expect LLOwnerThread = %v", e.LLOwnerThread) + require.Equalf(t, e.ExitCode, actualState.GetExitCode(), "Expect exitCode = 0x%x", e.ExitCode) + require.Equalf(t, e.Exited, actualState.GetExited(), "Expect exited = %v", e.Exited) + require.Equalf(t, e.Step, actualState.GetStep(), "Expect step = %d", e.Step) + require.Equalf(t, e.LastHint, actualState.GetLastHint(), "Expect lastHint = %v", e.LastHint) + require.Equalf(t, e.MemoryRoot, common.Hash(actualState.GetMemory().MerkleRoot()), "Expect memory root = %v", e.MemoryRoot) + // Thread-related global fields + require.Equalf(t, e.StepsSinceLastContextSwitch, actualState.StepsSinceLastContextSwitch, "Expect StepsSinceLastContextSwitch = %v", e.StepsSinceLastContextSwitch) + require.Equalf(t, e.Wakeup, actualState.Wakeup, "Expect Wakeup = %v", e.Wakeup) + require.Equalf(t, e.TraverseRight, actualState.TraverseRight, "Expect TraverseRight = %v", e.TraverseRight) + require.Equalf(t, e.NextThreadId, actualState.NextThreadId, "Expect NextThreadId = %v", e.NextThreadId) + require.Equalf(t, e.ThreadCount, actualState.ThreadCount(), "Expect thread count = %v", e.ThreadCount) + require.Equalf(t, e.RightStackSize, len(actualState.RightThreadStack), "Expect right stack size = %v", e.RightStackSize) + require.Equalf(t, e.LeftStackSize, len(actualState.LeftThreadStack), "Expect right stack size = %v", e.LeftStackSize) + + // Check active thread + activeThread := actualState.GetCurrentThread() + require.Equal(t, e.ActiveThreadId, activeThread.ThreadId) + // Check all threads + expectedThreadCount := 0 + for tid, exp := range e.threadExpectations { + actualThread := FindThread(actualState, tid) + isActive := tid == activeThread.ThreadId + if exp.Dropped { + require.Nil(t, actualThread, "Thread %v should have been dropped", tid) + } else { + require.NotNil(t, actualThread, "Could not find thread matching expected thread with id %v", tid) + e.validateThread(t, exp, actualThread, isActive) + expectedThreadCount++ + } + } + require.Equal(t, expectedThreadCount, actualState.ThreadCount(), "Thread expectations do not match thread count") +} + +func (e *ExpectedMTState) validateThread(t require.TestingT, et *ExpectedThreadState, actual *multithreaded.ThreadState, isActive bool) { + threadInfo := fmt.Sprintf("tid = %v, active = %v", actual.ThreadId, isActive) + require.Equalf(t, et.ThreadId, actual.ThreadId, "Expect ThreadId = 0x%x (%v)", et.ThreadId, threadInfo) + require.Equalf(t, et.PC, actual.Cpu.PC, "Expect PC = 0x%x (%v)", et.PC, threadInfo) + require.Equalf(t, et.NextPC, actual.Cpu.NextPC, "Expect nextPC = 0x%x (%v)", et.NextPC, threadInfo) + require.Equalf(t, et.HI, actual.Cpu.HI, "Expect HI = 0x%x (%v)", et.HI, threadInfo) + require.Equalf(t, et.LO, actual.Cpu.LO, "Expect LO = 0x%x (%v)", et.LO, threadInfo) + require.Equalf(t, et.Registers, actual.Registers, "Expect registers to match (%v)", threadInfo) + require.Equalf(t, et.ExitCode, actual.ExitCode, "Expect exitCode = %v (%v)", et.ExitCode, threadInfo) + require.Equalf(t, et.Exited, actual.Exited, "Expect exited = %v (%v)", et.Exited, threadInfo) + require.Equalf(t, et.FutexAddr, actual.FutexAddr, "Expect futexAddr = %v (%v)", et.FutexAddr, threadInfo) + require.Equalf(t, et.FutexVal, actual.FutexVal, "Expect futexVal = %v (%v)", et.FutexVal, threadInfo) + require.Equalf(t, et.FutexTimeoutStep, actual.FutexTimeoutStep, "Expect futexTimeoutStep = %v (%v)", et.FutexTimeoutStep, threadInfo) +} diff --git a/cannon/mipsevm/multithreaded/testutil/expectations_test.go b/cannon/mipsevm/multithreaded/testutil/expectations_test.go new file mode 100644 index 0000000000000..a40e15e0f8d57 --- /dev/null +++ b/cannon/mipsevm/multithreaded/testutil/expectations_test.go @@ -0,0 +1,182 @@ +package testutil + +import ( + "fmt" + "testing" + + //"github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" + + "github.com/ethereum-optimism/optimism/cannon/mipsevm/multithreaded" +) + +type ExpectationMutator func(e *ExpectedMTState, st *multithreaded.State) + +func TestValidate_shouldCatchMutations(t *testing.T) { + states := []*multithreaded.State{ + RandomState(0), + RandomState(1), + RandomState(2), + } + var emptyHash [32]byte + someThread := RandomThread(123) + + cases := []struct { + name string + mut ExpectationMutator + }{ + {name: "PreimageKey", mut: func(e *ExpectedMTState, st *multithreaded.State) { e.PreimageKey = emptyHash }}, + {name: "PreimageOffset", mut: func(e *ExpectedMTState, st *multithreaded.State) { e.PreimageOffset += 1 }}, + {name: "Heap", mut: func(e *ExpectedMTState, st *multithreaded.State) { e.Heap += 1 }}, + {name: "LLReservationActive", mut: func(e *ExpectedMTState, st *multithreaded.State) { e.LLReservationActive = !e.LLReservationActive }}, + {name: "LLAddress", mut: func(e *ExpectedMTState, st *multithreaded.State) { e.LLAddress += 1 }}, + {name: "LLOwnerThread", mut: func(e *ExpectedMTState, st *multithreaded.State) { e.LLOwnerThread += 1 }}, + {name: "ExitCode", mut: func(e *ExpectedMTState, st *multithreaded.State) { e.ExitCode += 1 }}, + {name: "Exited", mut: func(e *ExpectedMTState, st *multithreaded.State) { e.Exited = !e.Exited }}, + {name: "Step", mut: func(e *ExpectedMTState, st *multithreaded.State) { e.Step += 1 }}, + {name: "LastHint", mut: func(e *ExpectedMTState, st *multithreaded.State) { e.LastHint = []byte{7, 8, 9, 10} }}, + {name: "MemoryRoot", mut: func(e *ExpectedMTState, st *multithreaded.State) { e.MemoryRoot = emptyHash }}, + {name: "StepsSinceLastContextSwitch", mut: func(e *ExpectedMTState, st *multithreaded.State) { e.StepsSinceLastContextSwitch += 1 }}, + {name: "Wakeup", mut: func(e *ExpectedMTState, st *multithreaded.State) { e.Wakeup += 1 }}, + {name: "TraverseRight", mut: func(e *ExpectedMTState, st *multithreaded.State) { e.TraverseRight = !e.TraverseRight }}, + {name: "NextThreadId", mut: func(e *ExpectedMTState, st *multithreaded.State) { e.NextThreadId += 1 }}, + {name: "ThreadCount", mut: func(e *ExpectedMTState, st *multithreaded.State) { e.ThreadCount += 1 }}, + {name: "RightStackSize", mut: func(e *ExpectedMTState, st *multithreaded.State) { e.RightStackSize += 1 }}, + {name: "LeftStackSize", mut: func(e *ExpectedMTState, st *multithreaded.State) { e.LeftStackSize += 1 }}, + {name: "ActiveThreadId", mut: func(e *ExpectedMTState, st *multithreaded.State) { e.ActiveThreadId += 1 }}, + {name: "Empty thread expectations", mut: func(e *ExpectedMTState, st *multithreaded.State) { + e.threadExpectations = map[uint32]*ExpectedThreadState{} + }}, + {name: "Mismatched thread expectations", mut: func(e *ExpectedMTState, st *multithreaded.State) { + e.threadExpectations = map[uint32]*ExpectedThreadState{someThread.ThreadId: newExpectedThreadState(someThread)} + }}, + {name: "Active threadId", mut: func(e *ExpectedMTState, st *multithreaded.State) { + e.threadExpectations[st.GetCurrentThread().ThreadId].ThreadId += 1 + }}, + {name: "Active thread exitCode", mut: func(e *ExpectedMTState, st *multithreaded.State) { + e.threadExpectations[st.GetCurrentThread().ThreadId].ExitCode += 1 + }}, + {name: "Active thread exited", mut: func(e *ExpectedMTState, st *multithreaded.State) { + e.threadExpectations[st.GetCurrentThread().ThreadId].Exited = !st.GetCurrentThread().Exited + }}, + {name: "Active thread futexAddr", mut: func(e *ExpectedMTState, st *multithreaded.State) { + e.threadExpectations[st.GetCurrentThread().ThreadId].FutexAddr += 1 + }}, + {name: "Active thread futexVal", mut: func(e *ExpectedMTState, st *multithreaded.State) { + e.threadExpectations[st.GetCurrentThread().ThreadId].FutexVal += 1 + }}, + {name: "Active thread FutexTimeoutStep", mut: func(e *ExpectedMTState, st *multithreaded.State) { + e.threadExpectations[st.GetCurrentThread().ThreadId].FutexTimeoutStep += 1 + }}, + {name: "Active thread PC", mut: func(e *ExpectedMTState, st *multithreaded.State) { + e.threadExpectations[st.GetCurrentThread().ThreadId].PC += 1 + }}, + {name: "Active thread NextPC", mut: func(e *ExpectedMTState, st *multithreaded.State) { + e.threadExpectations[st.GetCurrentThread().ThreadId].NextPC += 1 + }}, + {name: "Active thread HI", mut: func(e *ExpectedMTState, st *multithreaded.State) { + e.threadExpectations[st.GetCurrentThread().ThreadId].HI += 1 + }}, + {name: "Active thread LO", mut: func(e *ExpectedMTState, st *multithreaded.State) { + e.threadExpectations[st.GetCurrentThread().ThreadId].LO += 1 + }}, + {name: "Active thread Registers", mut: func(e *ExpectedMTState, st *multithreaded.State) { + e.threadExpectations[st.GetCurrentThread().ThreadId].Registers[0] += 1 + }}, + {name: "Active thread dropped", mut: func(e *ExpectedMTState, st *multithreaded.State) { + e.threadExpectations[st.GetCurrentThread().ThreadId].Dropped = true + }}, + {name: "Inactive threadId", mut: func(e *ExpectedMTState, st *multithreaded.State) { + e.threadExpectations[FindNextThread(st).ThreadId].ThreadId += 1 + }}, + {name: "Inactive thread exitCode", mut: func(e *ExpectedMTState, st *multithreaded.State) { + e.threadExpectations[FindNextThread(st).ThreadId].ExitCode += 1 + }}, + {name: "Inactive thread exited", mut: func(e *ExpectedMTState, st *multithreaded.State) { + e.threadExpectations[FindNextThread(st).ThreadId].Exited = !FindNextThread(st).Exited + }}, + {name: "Inactive thread futexAddr", mut: func(e *ExpectedMTState, st *multithreaded.State) { + e.threadExpectations[FindNextThread(st).ThreadId].FutexAddr += 1 + }}, + {name: "Inactive thread futexVal", mut: func(e *ExpectedMTState, st *multithreaded.State) { + e.threadExpectations[FindNextThread(st).ThreadId].FutexVal += 1 + }}, + {name: "Inactive thread FutexTimeoutStep", mut: func(e *ExpectedMTState, st *multithreaded.State) { + e.threadExpectations[FindNextThread(st).ThreadId].FutexTimeoutStep += 1 + }}, + {name: "Inactive thread PC", mut: func(e *ExpectedMTState, st *multithreaded.State) { + e.threadExpectations[FindNextThread(st).ThreadId].PC += 1 + }}, + {name: "Inactive thread NextPC", mut: func(e *ExpectedMTState, st *multithreaded.State) { + e.threadExpectations[FindNextThread(st).ThreadId].NextPC += 1 + }}, + {name: "Inactive thread HI", mut: func(e *ExpectedMTState, st *multithreaded.State) { + e.threadExpectations[FindNextThread(st).ThreadId].HI += 1 + }}, + {name: "Inactive thread LO", mut: func(e *ExpectedMTState, st *multithreaded.State) { + e.threadExpectations[FindNextThread(st).ThreadId].LO += 1 + }}, + {name: "Inactive thread Registers", mut: func(e *ExpectedMTState, st *multithreaded.State) { + e.threadExpectations[FindNextThread(st).ThreadId].Registers[0] += 1 + }}, + {name: "Inactive thread dropped", mut: func(e *ExpectedMTState, st *multithreaded.State) { + e.threadExpectations[FindNextThread(st).ThreadId].Dropped = true + }}, + } + for _, c := range cases { + for i, state := range states { + testName := fmt.Sprintf("%v (state #%v)", c.name, i) + t.Run(testName, func(t *testing.T) { + expected := NewExpectedMTState(state) + c.mut(expected, state) + + // We should detect the change and fail + mockT := &MockTestingT{} + expected.Validate(mockT, state) + mockT.RequireFailed(t) + }) + } + + } +} + +func TestValidate_shouldPassUnchangedExpectations(t *testing.T) { + states := []*multithreaded.State{ + RandomState(0), + RandomState(1), + RandomState(2), + } + + for i, state := range states { + testName := fmt.Sprintf("State #%v", i) + t.Run(testName, func(t *testing.T) { + expected := NewExpectedMTState(state) + + mockT := &MockTestingT{} + expected.Validate(mockT, state) + mockT.RequireNoFailure(t) + }) + } +} + +type MockTestingT struct { + errCount int +} + +var _ require.TestingT = (*MockTestingT)(nil) + +func (m *MockTestingT) Errorf(format string, args ...interface{}) { + m.errCount += 1 +} + +func (m *MockTestingT) FailNow() { + m.errCount += 1 +} + +func (m *MockTestingT) RequireFailed(t require.TestingT) { + require.Greater(t, m.errCount, 0, "Should have tracked a failure") +} + +func (m *MockTestingT) RequireNoFailure(t require.TestingT) { + require.Equal(t, m.errCount, 0, "Should not have tracked a failure") +} diff --git a/cannon/mipsevm/multithreaded/testutil/mutators.go b/cannon/mipsevm/multithreaded/testutil/mutators.go new file mode 100644 index 0000000000000..a44ba23a4fac2 --- /dev/null +++ b/cannon/mipsevm/multithreaded/testutil/mutators.go @@ -0,0 +1,95 @@ +package testutil + +import ( + "math" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + + "github.com/ethereum-optimism/optimism/cannon/mipsevm/exec" + "github.com/ethereum-optimism/optimism/cannon/mipsevm/multithreaded" + "github.com/ethereum-optimism/optimism/cannon/mipsevm/testutil" +) + +type StateMutatorMultiThreaded struct { + state *multithreaded.State +} + +var _ testutil.StateMutator = (*StateMutatorMultiThreaded)(nil) + +func NewStateMutatorMultiThreaded(state *multithreaded.State) testutil.StateMutator { + return &StateMutatorMultiThreaded{state: state} +} + +func (m *StateMutatorMultiThreaded) Randomize(randSeed int64) { + r := testutil.NewRandHelper(randSeed) + + step := r.RandStep() + + m.state.PreimageKey = r.RandHash() + m.state.PreimageOffset = r.Uint32() + m.state.Step = step + m.state.LastHint = r.RandHint() + m.state.StepsSinceLastContextSwitch = uint64(r.Intn(exec.SchedQuantum)) + + // Randomize memory-related fields + halfMemory := math.MaxUint32 / 2 + m.state.Heap = uint32(r.Intn(halfMemory) + halfMemory) + m.state.LLReservationActive = r.Intn(2) == 1 + if m.state.LLReservationActive { + m.state.LLAddress = uint32(r.Intn(halfMemory)) + m.state.LLOwnerThread = uint32(r.Intn(10)) + } + + // Randomize threads + activeStackThreads := r.Intn(2) + 1 + inactiveStackThreads := r.Intn(3) + traverseRight := r.Intn(2) == 1 + SetupThreads(randSeed+1, m.state, traverseRight, activeStackThreads, inactiveStackThreads) +} + +func (m *StateMutatorMultiThreaded) SetHI(val uint32) { + m.state.GetCurrentThread().Cpu.HI = val +} + +func (m *StateMutatorMultiThreaded) SetLO(val uint32) { + m.state.GetCurrentThread().Cpu.LO = val +} + +func (m *StateMutatorMultiThreaded) SetExitCode(val uint8) { + m.state.ExitCode = val +} + +func (m *StateMutatorMultiThreaded) SetExited(val bool) { + m.state.Exited = val +} + +func (m *StateMutatorMultiThreaded) SetPC(val uint32) { + thread := m.state.GetCurrentThread() + thread.Cpu.PC = val +} + +func (m *StateMutatorMultiThreaded) SetHeap(val uint32) { + m.state.Heap = val +} + +func (m *StateMutatorMultiThreaded) SetNextPC(val uint32) { + thread := m.state.GetCurrentThread() + thread.Cpu.NextPC = val +} + +func (m *StateMutatorMultiThreaded) SetLastHint(val hexutil.Bytes) { + m.state.LastHint = val +} + +func (m *StateMutatorMultiThreaded) SetPreimageKey(val common.Hash) { + m.state.PreimageKey = val +} + +func (m *StateMutatorMultiThreaded) SetPreimageOffset(val uint32) { + m.state.PreimageOffset = val +} + +func (m *StateMutatorMultiThreaded) SetStep(val uint64) { + m.state.Step = val +} diff --git a/cannon/mipsevm/multithreaded/testutil/state.go b/cannon/mipsevm/multithreaded/testutil/state.go index d7896005eafd3..b240c95c0bba1 100644 --- a/cannon/mipsevm/multithreaded/testutil/state.go +++ b/cannon/mipsevm/multithreaded/testutil/state.go @@ -1,69 +1,24 @@ package testutil import ( - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/stretchr/testify/require" + "github.com/ethereum-optimism/optimism/cannon/mipsevm" "github.com/ethereum-optimism/optimism/cannon/mipsevm/multithreaded" - "github.com/ethereum-optimism/optimism/cannon/mipsevm/testutil" ) -type StateMutatorMultiThreaded struct { - state *multithreaded.State +func GetMtState(t require.TestingT, vm mipsevm.FPVM) *multithreaded.State { + state := vm.GetState() + mtState, ok := state.(*multithreaded.State) + if !ok { + require.Fail(t, "Failed to cast FPVMState to multithreaded State type") + } + return mtState } -var _ testutil.StateMutator = (*StateMutatorMultiThreaded)(nil) - -func NewStateMutatorMultiThreaded(state *multithreaded.State) testutil.StateMutator { - return &StateMutatorMultiThreaded{state: state} -} - -func (m *StateMutatorMultiThreaded) SetHI(val uint32) { - m.state.GetCurrentThread().Cpu.HI = val -} - -func (m *StateMutatorMultiThreaded) SetLO(val uint32) { - m.state.GetCurrentThread().Cpu.LO = val -} - -func (m *StateMutatorMultiThreaded) SetExitCode(val uint8) { - m.state.ExitCode = val -} - -func (m *StateMutatorMultiThreaded) SetExited(val bool) { - m.state.Exited = val -} - -func (m *StateMutatorMultiThreaded) SetPC(val uint32) { - thread := m.state.GetCurrentThread() - thread.Cpu.PC = val -} - -func (m *StateMutatorMultiThreaded) SetHeap(val uint32) { - m.state.Heap = val -} - -func (m *StateMutatorMultiThreaded) SetNextPC(val uint32) { - thread := m.state.GetCurrentThread() - thread.Cpu.NextPC = val -} - -func (m *StateMutatorMultiThreaded) SetLastHint(val hexutil.Bytes) { - m.state.LastHint = val -} - -func (m *StateMutatorMultiThreaded) SetPreimageKey(val common.Hash) { - m.state.PreimageKey = val -} - -func (m *StateMutatorMultiThreaded) SetPreimageOffset(val uint32) { - m.state.PreimageOffset = val -} - -func (m *StateMutatorMultiThreaded) SetStep(val uint64) { - m.state.Step = val -} - -func (m *StateMutatorMultiThreaded) GetRegistersRef() *[32]uint32 { - return m.state.GetRegistersRef() +func RandomState(seed int) *multithreaded.State { + state := multithreaded.CreateEmptyState() + mut := StateMutatorMultiThreaded{state} + mut.Randomize(int64(seed)) + return state } diff --git a/cannon/mipsevm/multithreaded/testutil/thread.go b/cannon/mipsevm/multithreaded/testutil/thread.go new file mode 100644 index 0000000000000..f5b1d29a8dd60 --- /dev/null +++ b/cannon/mipsevm/multithreaded/testutil/thread.go @@ -0,0 +1,164 @@ +package testutil + +import ( + "github.com/ethereum-optimism/optimism/cannon/mipsevm/multithreaded" + "github.com/ethereum-optimism/optimism/cannon/mipsevm/testutil" +) + +func RandomThread(randSeed int64) *multithreaded.ThreadState { + r := testutil.NewRandHelper(randSeed) + thread := multithreaded.CreateEmptyThread() + + pc := r.RandPC() + + thread.Registers = *r.RandRegisters() + thread.Cpu.PC = pc + thread.Cpu.NextPC = pc + 4 + thread.Cpu.HI = r.Uint32() + thread.Cpu.LO = r.Uint32() + + return thread +} + +func InitializeSingleThread(randSeed int, state *multithreaded.State, traverseRight bool) { + singleThread := RandomThread(int64(randSeed)) + + state.NextThreadId = singleThread.ThreadId + 1 + state.TraverseRight = traverseRight + if traverseRight { + state.RightThreadStack = []*multithreaded.ThreadState{singleThread} + state.LeftThreadStack = []*multithreaded.ThreadState{} + } else { + state.RightThreadStack = []*multithreaded.ThreadState{} + state.LeftThreadStack = []*multithreaded.ThreadState{singleThread} + } +} + +func SetupThreads(randomSeed int64, state *multithreaded.State, traverseRight bool, activeStackSize, otherStackSize int) { + var activeStack, otherStack []*multithreaded.ThreadState + + tid := uint32(0) + for i := 0; i < activeStackSize; i++ { + thread := RandomThread(randomSeed + int64(i)) + thread.ThreadId = tid + activeStack = append(activeStack, thread) + tid++ + } + + for i := 0; i < otherStackSize; i++ { + thread := RandomThread(randomSeed + int64(i+activeStackSize)) + thread.ThreadId = tid + otherStack = append(otherStack, thread) + tid++ + } + + state.NextThreadId = tid + state.TraverseRight = traverseRight + if traverseRight { + state.RightThreadStack = activeStack + state.LeftThreadStack = otherStack + } else { + state.LeftThreadStack = activeStack + state.RightThreadStack = otherStack + } +} + +type ThreadIterator struct { + left []*multithreaded.ThreadState + right []*multithreaded.ThreadState + traverseRight bool +} + +func NewThreadIterator(state *multithreaded.State) ThreadIterator { + return ThreadIterator{ + left: state.LeftThreadStack, + right: state.RightThreadStack, + traverseRight: state.TraverseRight, + } +} + +func (i *ThreadIterator) currentThread() *multithreaded.ThreadState { + var currentThread *multithreaded.ThreadState + if i.traverseRight { + currentThread = i.right[len(i.right)-1] + } else { + currentThread = i.left[len(i.left)-1] + } + return currentThread +} + +func (i *ThreadIterator) Next() *multithreaded.ThreadState { + rightLen := len(i.right) + leftLen := len(i.left) + activeThread := i.currentThread() + + if i.traverseRight { + i.right = i.right[:rightLen-1] + i.left = append(i.left, activeThread) + i.traverseRight = len(i.right) > 0 + } else { + i.left = i.left[:leftLen-1] + i.right = append(i.right, activeThread) + i.traverseRight = len(i.left) == 0 + } + + return i.currentThread() +} + +// FindNextThread Finds the next thread in line according to thread traversal logic +func FindNextThread(state *multithreaded.State) *multithreaded.ThreadState { + it := NewThreadIterator(state) + return it.Next() +} + +type ThreadFilter func(thread *multithreaded.ThreadState) bool + +func FindNextThreadFiltered(state *multithreaded.State, filter ThreadFilter) *multithreaded.ThreadState { + it := NewThreadIterator(state) + + // Worst case - walk all the way left, then all the way back right + // Example w 3 threads: 1,2,3,3,2,1,0 -> 7 steps to find thread 0 + maxIterations := state.ThreadCount()*2 + 1 + for i := 0; i < maxIterations; i++ { + next := it.Next() + if filter(next) { + return next + } + } + + return nil +} + +func FindNextThreadExcluding(state *multithreaded.State, threadId uint32) *multithreaded.ThreadState { + return FindNextThreadFiltered(state, func(t *multithreaded.ThreadState) bool { + return t.ThreadId != threadId + }) +} + +func FindThread(state *multithreaded.State, threadId uint32) *multithreaded.ThreadState { + for _, t := range GetAllThreads(state) { + if t.ThreadId == threadId { + return t + } + } + return nil +} + +func GetAllThreads(state *multithreaded.State) []*multithreaded.ThreadState { + allThreads := make([]*multithreaded.ThreadState, 0, state.ThreadCount()) + allThreads = append(allThreads, state.RightThreadStack[:]...) + allThreads = append(allThreads, state.LeftThreadStack[:]...) + + return allThreads +} + +func GetThreadStacks(state *multithreaded.State) (activeStack, inactiveStack []*multithreaded.ThreadState) { + if state.TraverseRight { + activeStack = state.RightThreadStack + inactiveStack = state.LeftThreadStack + } else { + activeStack = state.LeftThreadStack + inactiveStack = state.RightThreadStack + } + return activeStack, inactiveStack +} diff --git a/cannon/mipsevm/multithreaded/thread.go b/cannon/mipsevm/multithreaded/thread.go index fd91900d3e835..f811a52be4676 100644 --- a/cannon/mipsevm/multithreaded/thread.go +++ b/cannon/mipsevm/multithreaded/thread.go @@ -2,6 +2,7 @@ package multithreaded import ( "encoding/binary" + "io" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" @@ -74,6 +75,55 @@ func (t *ThreadState) serializeThread() []byte { return out } +// Serialize writes the ThreadState in a simple binary format which can be read again using Deserialize +// The format exactly matches the serialization generated by serializeThread used for thread proofs. +func (t *ThreadState) Serialize(out io.Writer) error { + _, err := out.Write(t.serializeThread()) + return err +} + +func (t *ThreadState) Deserialize(in io.Reader) error { + if err := binary.Read(in, binary.BigEndian, &t.ThreadId); err != nil { + return err + } + if err := binary.Read(in, binary.BigEndian, &t.ExitCode); err != nil { + return err + } + var exited uint8 + if err := binary.Read(in, binary.BigEndian, &exited); err != nil { + return err + } + t.Exited = exited != 0 + if err := binary.Read(in, binary.BigEndian, &t.FutexAddr); err != nil { + return err + } + if err := binary.Read(in, binary.BigEndian, &t.FutexVal); err != nil { + return err + } + if err := binary.Read(in, binary.BigEndian, &t.FutexTimeoutStep); err != nil { + return err + } + if err := binary.Read(in, binary.BigEndian, &t.Cpu.PC); err != nil { + return err + } + if err := binary.Read(in, binary.BigEndian, &t.Cpu.NextPC); err != nil { + return err + } + if err := binary.Read(in, binary.BigEndian, &t.Cpu.LO); err != nil { + return err + } + if err := binary.Read(in, binary.BigEndian, &t.Cpu.HI); err != nil { + return err + } + // Read the registers as big endian uint32s + for i := range t.Registers { + if err := binary.Read(in, binary.BigEndian, &t.Registers[i]); err != nil { + return err + } + } + return nil +} + func computeThreadRoot(prevStackRoot common.Hash, threadToPush *ThreadState) common.Hash { hashedThread := crypto.Keccak256Hash(threadToPush.serializeThread()) diff --git a/cannon/mipsevm/program/metadata.go b/cannon/mipsevm/program/metadata.go index e90cbe14815c4..fb34da7694c78 100644 --- a/cannon/mipsevm/program/metadata.go +++ b/cannon/mipsevm/program/metadata.go @@ -4,6 +4,8 @@ import ( "debug/elf" "fmt" "sort" + + "github.com/ethereum-optimism/optimism/cannon/mipsevm" ) type Symbol struct { @@ -16,6 +18,8 @@ type Metadata struct { Symbols []Symbol `json:"symbols"` } +var _ mipsevm.Metadata = (*Metadata)(nil) + func MakeMetadata(elfProgram *elf.File) (*Metadata, error) { syms, err := elfProgram.Symbols() if err != nil { @@ -50,9 +54,7 @@ func (m *Metadata) LookupSymbol(addr uint32) string { return out.Name } -type SymbolMatcher func(addr uint32) bool - -func (m *Metadata) CreateSymbolMatcher(name string) SymbolMatcher { +func (m *Metadata) CreateSymbolMatcher(name string) mipsevm.SymbolMatcher { for _, s := range m.Symbols { if s.Name == name { start := s.Start diff --git a/cannon/mipsevm/program/patch.go b/cannon/mipsevm/program/patch.go index 52a262fee585b..e8e2e3ebc0855 100644 --- a/cannon/mipsevm/program/patch.go +++ b/cannon/mipsevm/program/patch.go @@ -4,15 +4,16 @@ import ( "bytes" "debug/elf" "encoding/binary" + "errors" "fmt" "github.com/ethereum-optimism/optimism/cannon/mipsevm" "github.com/ethereum-optimism/optimism/cannon/mipsevm/memory" ) -// TODO(cp-903) Consider breaking up go patching into performance and threading-related patches so we can -// selectively apply the perf patching to MTCannon -func PatchGo(f *elf.File, st mipsevm.FPVMState) error { +// PatchGoGC patches out garbage-collection-related symbols to disable garbage collection +// and improves performance by patching out floating-point-related symbols +func PatchGoGC(f *elf.File, st mipsevm.FPVMState) error { symbols, err := f.Symbols() if err != nil { return fmt.Errorf("failed to read symbols data, cannot patch program: %w", err) @@ -47,22 +48,18 @@ func PatchGo(f *elf.File, st mipsevm.FPVMState) error { })); err != nil { return fmt.Errorf("failed to patch Go runtime.gcenable: %w", err) } - case "runtime.MemProfileRate": - if err := st.GetMemory().SetMemoryRange(uint32(s.Value), bytes.NewReader(make([]byte, 4))); err != nil { // disable mem profiling, to avoid a lot of unnecessary floating point ops - return err - } } } return nil } -// TODO(cp-903) Consider setting envar "GODEBUG=memprofilerate=0" for go programs to disable memprofiling, instead of patching it out in PatchGo() +// PatchStack sets up the program's initial stack frame and stack pointer func PatchStack(st mipsevm.FPVMState) error { // setup stack pointer sp := uint32(0x7f_ff_d0_00) // allocate 1 page for the initial stack data, and 16KB = 4 pages for the stack to grow if err := st.GetMemory().SetMemoryRange(sp-4*memory.PageSize, bytes.NewReader(make([]byte, 5*memory.PageSize))); err != nil { - return fmt.Errorf("failed to allocate page for stack content") + return errors.New("failed to allocate page for stack content") } st.GetRegistersRef()[29] = sp @@ -73,16 +70,27 @@ func PatchStack(st mipsevm.FPVMState) error { } // init argc, argv, aux on stack - storeMem(sp+4*1, 0x42) // argc = 0 (argument count) - storeMem(sp+4*2, 0x35) // argv[n] = 0 (terminating argv) - storeMem(sp+4*3, 0) // envp[term] = 0 (no env vars) - storeMem(sp+4*4, 6) // auxv[0] = _AT_PAGESZ = 6 (key) - storeMem(sp+4*5, 4096) // auxv[1] = page size of 4 KiB (value) - (== minPhysPageSize) - storeMem(sp+4*6, 25) // auxv[2] = AT_RANDOM - storeMem(sp+4*7, sp+4*9) // auxv[3] = address of 16 bytes containing random value - storeMem(sp+4*8, 0) // auxv[term] = 0 + storeMem(sp+4*0, 1) // argc = 1 (argument count) + storeMem(sp+4*1, sp+4*21) // argv[0] + storeMem(sp+4*2, 0) // argv[1] = terminating + storeMem(sp+4*3, sp+4*14) // envp[0] = x (offset to first env var) + storeMem(sp+4*4, 0) // envp[1] = terminating + storeMem(sp+4*5, 6) // auxv[0] = _AT_PAGESZ = 6 (key) + storeMem(sp+4*6, 4096) // auxv[1] = page size of 4 KiB (value) - (== minPhysPageSize) + storeMem(sp+4*7, 25) // auxv[2] = AT_RANDOM + storeMem(sp+4*8, sp+4*10) // auxv[3] = address of 16 bytes containing random value + storeMem(sp+4*9, 0) // auxv[term] = 0 + + _ = st.GetMemory().SetMemoryRange(sp+4*10, bytes.NewReader([]byte("4;byfairdiceroll"))) // 16 bytes of "randomness" + + // append 4 extra zero bytes to end at 4-byte alignment + envar := append([]byte("GODEBUG=memprofilerate=0"), 0x0, 0x0, 0x0, 0x0) + _ = st.GetMemory().SetMemoryRange(sp+4*14, bytes.NewReader(envar)) - _ = st.GetMemory().SetMemoryRange(sp+4*9, bytes.NewReader([]byte("4;byfairdiceroll"))) // 16 bytes of "randomness" + // 24 bytes for GODEBUG=memprofilerate=0 + 4 null bytes + // Then append program name + 2 null bytes for 4-byte alignment + programName := append([]byte("op-program"), 0x0, 0x0) + _ = st.GetMemory().SetMemoryRange(sp+4*21, bytes.NewReader(programName)) return nil } diff --git a/cannon/mipsevm/singlethreaded/instrumented.go b/cannon/mipsevm/singlethreaded/instrumented.go index 89331f31dcae1..800cc1a92f7a7 100644 --- a/cannon/mipsevm/singlethreaded/instrumented.go +++ b/cannon/mipsevm/singlethreaded/instrumented.go @@ -5,14 +5,12 @@ import ( "github.com/ethereum-optimism/optimism/cannon/mipsevm" "github.com/ethereum-optimism/optimism/cannon/mipsevm/exec" - "github.com/ethereum-optimism/optimism/cannon/mipsevm/program" - "github.com/ethereum-optimism/optimism/op-service/jsonutil" "github.com/ethereum/go-ethereum/common/hexutil" ) type InstrumentedState struct { - meta *program.Metadata - sleepCheck program.SymbolMatcher + meta mipsevm.Metadata + sleepCheck mipsevm.SymbolMatcher state *State @@ -27,16 +25,14 @@ type InstrumentedState struct { var _ mipsevm.FPVM = (*InstrumentedState)(nil) -func NewInstrumentedState(state *State, po mipsevm.PreimageOracle, stdOut, stdErr io.Writer, meta *program.Metadata) *InstrumentedState { - var sleepCheck program.SymbolMatcher +func NewInstrumentedState(state *State, po mipsevm.PreimageOracle, stdOut, stdErr io.Writer, meta mipsevm.Metadata) *InstrumentedState { + var sleepCheck mipsevm.SymbolMatcher if meta == nil { sleepCheck = func(addr uint32) bool { return false } } else { sleepCheck = meta.CreateSymbolMatcher("runtime.notesleep") } - return &InstrumentedState{ - meta: meta, sleepCheck: sleepCheck, state: state, stdOut: stdOut, @@ -44,17 +40,10 @@ func NewInstrumentedState(state *State, po mipsevm.PreimageOracle, stdOut, stdEr memoryTracker: exec.NewMemoryTracker(state.Memory), stackTracker: &exec.NoopStackTracker{}, preimageOracle: exec.NewTrackingPreimageOracleReader(po), + meta: meta, } } -func NewInstrumentedStateFromFile(stateFile string, po mipsevm.PreimageOracle, stdOut, stdErr io.Writer, meta *program.Metadata) (*InstrumentedState, error) { - state, err := jsonutil.LoadJSON[State](stateFile) - if err != nil { - return nil, err - } - return NewInstrumentedState(state, po, stdOut, stdErr, meta), nil -} - func (m *InstrumentedState) InitDebug() error { stackTracker, err := exec.NewStackTracker(m.state, m.meta) if err != nil { diff --git a/cannon/mipsevm/singlethreaded/mips.go b/cannon/mipsevm/singlethreaded/mips.go index 48a25e084291b..a88d0c66b0e61 100644 --- a/cannon/mipsevm/singlethreaded/mips.go +++ b/cannon/mipsevm/singlethreaded/mips.go @@ -1,6 +1,8 @@ package singlethreaded import ( + "fmt" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" @@ -30,7 +32,7 @@ func (m *InstrumentedState) handleSyscall() error { return nil case exec.SysRead: var newPreimageOffset uint32 - v0, v1, newPreimageOffset = exec.HandleSysRead(a0, a1, a2, m.state.PreimageKey, m.state.PreimageOffset, m.preimageOracle, m.state.Memory, m.memoryTracker) + v0, v1, newPreimageOffset, _, _ = exec.HandleSysRead(a0, a1, a2, m.state.PreimageKey, m.state.PreimageOffset, m.preimageOracle, m.state.Memory, m.memoryTracker) m.state.PreimageOffset = newPreimageOffset case exec.SysWrite: var newLastHint hexutil.Bytes @@ -62,6 +64,37 @@ func (m *InstrumentedState) mipsStep() error { return m.handleSyscall() } + // Handle RMW (read-modify-write) ops + if opcode == exec.OpLoadLinked || opcode == exec.OpStoreConditional { + return m.handleRMWOps(insn, opcode) + } + // Exec the rest of the step logic - return exec.ExecMipsCoreStepLogic(&m.state.Cpu, &m.state.Registers, m.state.Memory, insn, opcode, fun, m.memoryTracker, m.stackTracker) + _, _, err := exec.ExecMipsCoreStepLogic(&m.state.Cpu, &m.state.Registers, m.state.Memory, insn, opcode, fun, m.memoryTracker, m.stackTracker) + return err +} + +// handleRMWOps handles LL and SC operations which provide the primitives to implement read-modify-write operations +func (m *InstrumentedState) handleRMWOps(insn, opcode uint32) error { + baseReg := (insn >> 21) & 0x1F + base := m.state.Registers[baseReg] + rtReg := (insn >> 16) & 0x1F + offset := exec.SignExtendImmediate(insn) + + effAddr := (base + offset) & 0xFFFFFFFC + m.memoryTracker.TrackMemAccess(effAddr) + mem := m.state.Memory.GetMemory(effAddr) + + var retVal uint32 + if opcode == exec.OpLoadLinked { + retVal = mem + } else if opcode == exec.OpStoreConditional { + rt := m.state.Registers[rtReg] + m.state.Memory.SetMemory(effAddr, rt) + retVal = 1 // 1 for success + } else { + panic(fmt.Sprintf("Invalid instruction passed to handleRMWOps (opcode %08x)", opcode)) + } + + return exec.HandleRd(&m.state.Cpu, &m.state.Registers, rtReg, retVal, true) } diff --git a/cannon/mipsevm/singlethreaded/state.go b/cannon/mipsevm/singlethreaded/state.go index 638dcf6f3b6b3..e0be88d998574 100644 --- a/cannon/mipsevm/singlethreaded/state.go +++ b/cannon/mipsevm/singlethreaded/state.go @@ -4,10 +4,13 @@ import ( "encoding/binary" "encoding/json" "fmt" + "io" + "github.com/ethereum-optimism/optimism/cannon/serialize" "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" "github.com/ethereum-optimism/optimism/cannon/mipsevm" "github.com/ethereum-optimism/optimism/cannon/mipsevm/memory" @@ -65,6 +68,11 @@ func CreateInitialState(pc, heapStart uint32) *State { return state } +func (s *State) CreateVM(logger log.Logger, po mipsevm.PreimageOracle, stdOut, stdErr io.Writer, meta mipsevm.Metadata) mipsevm.FPVM { + logger.Info("Using cannon VM") + return NewInstrumentedState(s, po, stdOut, stdErr, meta) +} + type stateMarshaling struct { Memory *memory.Memory `json:"memory"` PreimageKey common.Hash `json:"preimageKey"` @@ -177,6 +185,119 @@ func (s *State) EncodeWitness() ([]byte, common.Hash) { return out, stateHashFromWitness(out) } +// Serialize writes the state in a simple binary format which can be read again using Deserialize +// The format is a simple concatenation of fields, with prefixed item count for repeating items and using big endian +// encoding for numbers. +// +// StateVersion uint8(0) +// Memory As per Memory.Serialize +// PreimageKey [32]byte +// PreimageOffset uint32 +// Cpu.PC uint32 +// Cpu.NextPC uint32 +// Cpu.LO uint32 +// Cpu.HI uint32 +// Heap uint32 +// ExitCode uint8 +// Exited uint8 - 0 for false, 1 for true +// Step uint64 +// Registers [32]uint32 +// len(LastHint) uint32 (0 when LastHint is nil) +// LastHint []byte +func (s *State) Serialize(out io.Writer) error { + bout := serialize.NewBinaryWriter(out) + + if err := s.Memory.Serialize(out); err != nil { + return err + } + if err := bout.WriteHash(s.PreimageKey); err != nil { + return err + } + if err := bout.WriteUInt(s.PreimageOffset); err != nil { + return err + } + if err := bout.WriteUInt(s.Cpu.PC); err != nil { + return err + } + if err := bout.WriteUInt(s.Cpu.NextPC); err != nil { + return err + } + if err := bout.WriteUInt(s.Cpu.LO); err != nil { + return err + } + if err := bout.WriteUInt(s.Cpu.HI); err != nil { + return err + } + if err := bout.WriteUInt(s.Heap); err != nil { + return err + } + if err := bout.WriteUInt(s.ExitCode); err != nil { + return err + } + if err := bout.WriteBool(s.Exited); err != nil { + return err + } + if err := bout.WriteUInt(s.Step); err != nil { + return err + } + for _, r := range s.Registers { + if err := bout.WriteUInt(r); err != nil { + return err + } + } + if err := bout.WriteBytes(s.LastHint); err != nil { + return err + } + return nil +} + +func (s *State) Deserialize(in io.Reader) error { + bin := serialize.NewBinaryReader(in) + s.Memory = memory.NewMemory() + if err := s.Memory.Deserialize(in); err != nil { + return err + } + if err := bin.ReadHash(&s.PreimageKey); err != nil { + return err + } + if err := bin.ReadUInt(&s.PreimageOffset); err != nil { + return err + } + if err := bin.ReadUInt(&s.Cpu.PC); err != nil { + return err + } + if err := bin.ReadUInt(&s.Cpu.NextPC); err != nil { + return err + } + if err := bin.ReadUInt(&s.Cpu.LO); err != nil { + return err + } + if err := bin.ReadUInt(&s.Cpu.HI); err != nil { + return err + } + if err := bin.ReadUInt(&s.Heap); err != nil { + return err + } + if err := bin.ReadUInt(&s.ExitCode); err != nil { + return err + } + if err := bin.ReadBool(&s.Exited); err != nil { + return err + } + if err := bin.ReadUInt(&s.Step); err != nil { + return err + } + for i := range s.Registers { + if err := bin.ReadUInt(&s.Registers[i]); err != nil { + return err + } + } + if err := bin.ReadBytes((*[]byte)(&s.LastHint)); err != nil { + return err + } + return nil +} + type StateWitness []byte func (sw StateWitness) StateHash() (common.Hash, error) { diff --git a/cannon/mipsevm/singlethreaded/state_test.go b/cannon/mipsevm/singlethreaded/state_test.go index 27588f8b67edd..c3dfd5cd41af6 100644 --- a/cannon/mipsevm/singlethreaded/state_test.go +++ b/cannon/mipsevm/singlethreaded/state_test.go @@ -1,9 +1,12 @@ package singlethreaded import ( + "bytes" "debug/elf" "testing" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/crypto" "github.com/stretchr/testify/require" @@ -79,3 +82,69 @@ func TestStateJSONCodec(t *testing.T) { require.Equal(t, state.Registers, newState.Registers) require.Equal(t, state.Step, newState.Step) } + +func TestStateBinaryCodec(t *testing.T) { + elfProgram, err := elf.Open("../../testdata/example/bin/hello.elf") + require.NoError(t, err, "open ELF file") + state, err := program.LoadELF(elfProgram, CreateInitialState) + require.NoError(t, err, "load ELF into state") + + buf := new(bytes.Buffer) + err = state.Serialize(buf) + require.NoError(t, err) + + newState := new(State) + require.NoError(t, newState.Deserialize(bytes.NewReader(buf.Bytes()))) + + require.Equal(t, state.PreimageKey, newState.PreimageKey) + require.Equal(t, state.PreimageOffset, newState.PreimageOffset) + require.Equal(t, state.Cpu, newState.Cpu) + require.Equal(t, state.Heap, newState.Heap) + require.Equal(t, state.ExitCode, newState.ExitCode) + require.Equal(t, state.Exited, newState.Exited) + require.Equal(t, state.Memory.PageCount(), newState.Memory.PageCount()) + require.Equal(t, state.Memory.MerkleRoot(), newState.Memory.MerkleRoot()) + require.Equal(t, state.Registers, newState.Registers) + require.Equal(t, state.Step, newState.Step) +} + +func TestSerializeStateRoundTrip(t *testing.T) { + // Construct a test case with populated fields + mem := memory.NewMemory() + mem.AllocPage(5) + p := mem.AllocPage(123) + p.Data[2] = 0x01 + state := &State{ + Memory: mem, + PreimageKey: common.Hash{0xFF}, + PreimageOffset: 5, + Cpu: mipsevm.CpuScalars{ + PC: 0xFF, + NextPC: 0xFF + 4, + LO: 0xbeef, + HI: 0xbabe, + }, + Heap: 0xc0ffee, + ExitCode: 1, + Exited: true, + Step: 0xdeadbeef, + Registers: [32]uint32{ + 0xdeadbeef, + 0xdeadbeef, + 0xc0ffee, + 0xbeefbabe, + 0xdeadc0de, + 0xbadc0de, + 0xdeaddead, + }, + LastHint: hexutil.Bytes{1, 2, 3, 4, 5}, + } + + ser := new(bytes.Buffer) + err := state.Serialize(ser) + require.NoError(t, err, "must serialize state") + state2 := &State{} + err = state2.Deserialize(ser) + require.NoError(t, err, "must deserialize state") + require.Equal(t, state, state2, "must roundtrip state") +} diff --git a/cannon/mipsevm/singlethreaded/testutil/state.go b/cannon/mipsevm/singlethreaded/testutil/state.go index 9d8909eee772e..079827500e45a 100644 --- a/cannon/mipsevm/singlethreaded/testutil/state.go +++ b/cannon/mipsevm/singlethreaded/testutil/state.go @@ -12,6 +12,24 @@ type StateMutatorSingleThreaded struct { state *singlethreaded.State } +func (m *StateMutatorSingleThreaded) Randomize(randSeed int64) { + r := testutil.NewRandHelper(randSeed) + + pc := r.RandPC() + step := r.RandStep() + + m.state.PreimageKey = r.RandHash() + m.state.PreimageOffset = r.Uint32() + m.state.Cpu.PC = pc + m.state.Cpu.NextPC = pc + 4 + m.state.Cpu.HI = r.Uint32() + m.state.Cpu.LO = r.Uint32() + m.state.Heap = r.Uint32() + m.state.Step = step + m.state.LastHint = r.RandHint() + m.state.Registers = *r.RandRegisters() +} + var _ testutil.StateMutator = (*StateMutatorSingleThreaded)(nil) func NewStateMutatorSingleThreaded(state *singlethreaded.State) testutil.StateMutator { @@ -61,7 +79,3 @@ func (m *StateMutatorSingleThreaded) SetPreimageOffset(val uint32) { func (m *StateMutatorSingleThreaded) SetStep(val uint64) { m.state.Step = val } - -func (m *StateMutatorSingleThreaded) GetRegistersRef() *[32]uint32 { - return m.state.GetRegistersRef() -} diff --git a/cannon/mipsevm/tests/evm_common_test.go b/cannon/mipsevm/tests/evm_common_test.go index 8294cb12c3df6..21aea97a7a14d 100644 --- a/cannon/mipsevm/tests/evm_common_test.go +++ b/cannon/mipsevm/tests/evm_common_test.go @@ -10,13 +10,10 @@ import ( "testing" "time" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/tracing" - "github.com/ethereum/go-ethereum/core/vm" "github.com/stretchr/testify/require" - "github.com/ethereum-optimism/optimism/cannon/mipsevm" "github.com/ethereum-optimism/optimism/cannon/mipsevm/exec" "github.com/ethereum-optimism/optimism/cannon/mipsevm/memory" "github.com/ethereum-optimism/optimism/cannon/mipsevm/program" @@ -118,7 +115,7 @@ func TestEVM(t *testing.T) { } } -func TestEVMSingleStep(t *testing.T) { +func TestEVMSingleStep_Jump(t *testing.T) { var tracer *tracing.Hooks versions := GetMipsVersionTestCases(t) @@ -143,10 +140,10 @@ func TestEVMSingleStep(t *testing.T) { goVm := v.VMFactory(nil, os.Stdout, os.Stderr, testutil.CreateLogger(), testutil.WithRandomization(int64(i)), testutil.WithPC(tt.pc), testutil.WithNextPC(tt.nextPC)) state := goVm.GetState() state.GetMemory().SetMemory(tt.pc, tt.insn) - curStep := state.GetStep() + step := state.GetStep() // Setup expectations - expected := testutil.CreateExpectedState(state) + expected := testutil.NewExpectedState(state) expected.Step += 1 expected.PC = state.GetCpu().NextPC expected.NextPC = tt.expectNextPC @@ -159,15 +156,70 @@ func TestEVMSingleStep(t *testing.T) { // Check expectations expected.Validate(t, state) + testutil.ValidateEVM(t, stepWitness, step, goVm, v.StateHashFn, v.Contracts, tracer) + }) + } + } +} - evm := testutil.NewMIPSEVM(v.Contracts) - evm.SetTracer(tracer) - testutil.LogStepFailureAtCleanup(t, evm) +func TestEVMSingleStep_Add(t *testing.T) { + var tracer *tracing.Hooks - evmPost := evm.Step(t, stepWitness, curStep, v.StateHashFn) - goPost, _ := goVm.GetState().EncodeWitness() - require.Equal(t, hexutil.Bytes(goPost).String(), hexutil.Bytes(evmPost).String(), - "mipsevm produced different state than EVM") + versions := GetMipsVersionTestCases(t) + cases := []struct { + name string + insn uint32 + ifImm bool + rs uint32 + rt uint32 + imm uint16 + expectRD uint32 + expectImm uint32 + }{ + {name: "add", insn: 0x02_32_40_20, ifImm: false, rs: uint32(12), rt: uint32(20), expectRD: uint32(32)}, // add t0, s1, s2 + {name: "addu", insn: 0x02_32_40_21, ifImm: false, rs: uint32(12), rt: uint32(20), expectRD: uint32(32)}, // addu t0, s1, s2 + {name: "addi", insn: 0x22_28_00_28, ifImm: true, rs: uint32(4), rt: uint32(1), imm: uint16(40), expectImm: uint32(44)}, // addi t0, s1, 40 + {name: "addi sign", insn: 0x22_28_ff_fe, ifImm: true, rs: uint32(2), rt: uint32(1), imm: uint16(0xfffe), expectImm: uint32(0)}, // addi t0, s1, -2 + {name: "addiu", insn: 0x26_28_00_28, ifImm: true, rs: uint32(4), rt: uint32(1), imm: uint16(40), expectImm: uint32(44)}, // addiu t0, s1, 40 + } + + for _, v := range versions { + for i, tt := range cases { + testName := fmt.Sprintf("%v (%v)", tt.name, v.Name) + t.Run(testName, func(t *testing.T) { + goVm := v.VMFactory(nil, os.Stdout, os.Stderr, testutil.CreateLogger(), testutil.WithRandomization(int64(i)), testutil.WithPC(0), testutil.WithNextPC(4)) + state := goVm.GetState() + if tt.ifImm { + state.GetRegistersRef()[8] = tt.rt + state.GetRegistersRef()[17] = tt.rs + } else { + state.GetRegistersRef()[17] = tt.rs + state.GetRegistersRef()[18] = tt.rt + } + state.GetMemory().SetMemory(0, tt.insn) + step := state.GetStep() + + // Setup expectations + expected := testutil.NewExpectedState(state) + expected.Step += 1 + expected.PC = 4 + expected.NextPC = 8 + + if tt.ifImm { + expected.Registers[8] = tt.expectImm + expected.Registers[17] = tt.rs + } else { + expected.Registers[8] = tt.expectRD + expected.Registers[17] = tt.rs + expected.Registers[18] = tt.rt + } + + stepWitness, err := goVm.Step(true) + require.NoError(t, err) + + // Check expectations + expected.Validate(t, state) + testutil.ValidateEVM(t, stepWitness, step, goVm, v.StateHashFn, v.Contracts, tracer) }) } } @@ -209,7 +261,7 @@ func TestEVM_MMap(t *testing.T) { state.GetRegistersRef()[5] = c.size step := state.GetStep() - expected := testutil.CreateExpectedState(state) + expected := testutil.NewExpectedState(state) expected.Step += 1 expected.PC = state.GetCpu().NextPC expected.NextPC = state.GetCpu().NextPC + 4 @@ -232,15 +284,7 @@ func TestEVM_MMap(t *testing.T) { // Check expectations expected.Validate(t, state) - - evm := testutil.NewMIPSEVM(v.Contracts) - evm.SetTracer(tracer) - testutil.LogStepFailureAtCleanup(t, evm) - - evmPost := evm.Step(t, stepWitness, step, v.StateHashFn) - goPost, _ := goVm.GetState().EncodeWitness() - require.Equal(t, hexutil.Bytes(goPost).String(), hexutil.Bytes(evmPost).String(), - "mipsevm produced different state than EVM") + testutil.ValidateEVM(t, stepWitness, step, goVm, v.StateHashFn, v.Contracts, tracer) }) } } @@ -420,9 +464,9 @@ func TestEVMSysWriteHint(t *testing.T) { err := state.GetMemory().SetMemoryRange(uint32(tt.memOffset), bytes.NewReader(tt.hintData)) require.NoError(t, err) state.GetMemory().SetMemory(state.GetPC(), insn) - curStep := state.GetStep() + step := state.GetStep() - expected := testutil.CreateExpectedState(state) + expected := testutil.NewExpectedState(state) expected.Step += 1 expected.PC = state.GetCpu().NextPC expected.NextPC = state.GetCpu().NextPC + 4 @@ -435,15 +479,7 @@ func TestEVMSysWriteHint(t *testing.T) { expected.Validate(t, state) require.Equal(t, tt.expectedHints, oracle.Hints()) - - evm := testutil.NewMIPSEVM(v.Contracts) - evm.SetTracer(tracer) - testutil.LogStepFailureAtCleanup(t, evm) - - evmPost := evm.Step(t, stepWitness, curStep, v.StateHashFn) - goPost, _ := goVm.GetState().EncodeWitness() - require.Equal(t, hexutil.Bytes(goPost).String(), hexutil.Bytes(evmPost).String(), - "mipsevm produced different state than EVM") + testutil.ValidateEVM(t, stepWitness, step, goVm, v.StateHashFn, v.Contracts, tracer) }) } } @@ -451,7 +487,6 @@ func TestEVMSysWriteHint(t *testing.T) { func TestEVMFault(t *testing.T) { var tracer *tracing.Hooks // no-tracer by default, but see test_util.MarkdownTracer - sender := common.Address{0x13, 0x37} versions := GetMipsVersionTestCases(t) cases := []struct { @@ -468,9 +503,6 @@ func TestEVMFault(t *testing.T) { for _, tt := range cases { testName := fmt.Sprintf("%v (%v)", tt.name, v.Name) t.Run(testName, func(t *testing.T) { - env, evmState := testutil.NewEVMEnv(v.Contracts) - env.Config.Tracer = tracer - goVm := v.VMFactory(nil, os.Stdout, os.Stderr, testutil.CreateLogger(), testutil.WithNextPC(tt.nextPC)) state := goVm.GetState() state.GetMemory().SetMemory(0, tt.insn) @@ -478,31 +510,21 @@ func TestEVMFault(t *testing.T) { state.GetRegistersRef()[31] = testutil.EndAddr require.Panics(t, func() { _, _ = goVm.Step(true) }) - - insnProof := state.GetMemory().MerkleProof(0) - encodedWitness, _ := state.EncodeWitness() - stepWitness := &mipsevm.StepWitness{ - State: encodedWitness, - ProofData: insnProof[:], - } - input := testutil.EncodeStepInput(t, stepWitness, mipsevm.LocalContext{}, v.Contracts.Artifacts.MIPS) - startingGas := uint64(30_000_000) - - _, _, err := env.Call(vm.AccountRef(sender), v.Contracts.Addresses.MIPS, input, startingGas, common.U2560) - require.EqualValues(t, err, vm.ErrExecutionReverted) - logs := evmState.Logs() - require.Equal(t, 0, len(logs)) + testutil.AssertEVMReverts(t, state, v.Contracts, tracer) }) } } } func TestHelloEVM(t *testing.T) { + t.Parallel() var tracer *tracing.Hooks // no-tracer by default, but see test_util.MarkdownTracer versions := GetMipsVersionTestCases(t) for _, v := range versions { + v := v t.Run(v.Name, func(t *testing.T) { + t.Parallel() evm := testutil.NewMIPSEVM(v.Contracts) evm.SetTracer(tracer) testutil.LogStepFailureAtCleanup(t, evm) @@ -514,7 +536,7 @@ func TestHelloEVM(t *testing.T) { start := time.Now() for i := 0; i < 400_000; i++ { - curStep := goVm.GetState().GetStep() + step := goVm.GetState().GetStep() if goVm.GetState().GetExited() { break } @@ -525,12 +547,12 @@ func TestHelloEVM(t *testing.T) { stepWitness, err := goVm.Step(true) require.NoError(t, err) - evmPost := evm.Step(t, stepWitness, curStep, v.StateHashFn) + evmPost := evm.Step(t, stepWitness, step, v.StateHashFn) // verify the post-state matches. // TODO: maybe more readable to decode the evmPost state, and do attribute-wise comparison. goPost, _ := goVm.GetState().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. insn: %x", insn) } end := time.Now() delta := end.Sub(start) @@ -546,11 +568,14 @@ func TestHelloEVM(t *testing.T) { } func TestClaimEVM(t *testing.T) { + t.Parallel() var tracer *tracing.Hooks // no-tracer by default, but see test_util.MarkdownTracer versions := GetMipsVersionTestCases(t) for _, v := range versions { + v := v t.Run(v.Name, func(t *testing.T) { + t.Parallel() evm := testutil.NewMIPSEVM(v.Contracts) evm.SetTracer(tracer) testutil.LogStepFailureAtCleanup(t, evm) @@ -591,3 +616,50 @@ func TestClaimEVM(t *testing.T) { }) } } + +func TestEntryEVM(t *testing.T) { + t.Parallel() + var tracer *tracing.Hooks // no-tracer by default, but see test_util.MarkdownTracer + versions := GetMipsVersionTestCases(t) + + for _, v := range versions { + v := v + t.Run(v.Name, func(t *testing.T) { + t.Parallel() + evm := testutil.NewMIPSEVM(v.Contracts) + evm.SetTracer(tracer) + testutil.LogStepFailureAtCleanup(t, evm) + + var stdOutBuf, stdErrBuf bytes.Buffer + elfFile := "../../testdata/example/bin/entry.elf" + goVm := v.ElfVMFactory(t, elfFile, nil, io.MultiWriter(&stdOutBuf, os.Stdout), io.MultiWriter(&stdErrBuf, os.Stderr), testutil.CreateLogger()) + state := goVm.GetState() + + start := time.Now() + for i := 0; i < 400_000; i++ { + curStep := goVm.GetState().GetStep() + if goVm.GetState().GetExited() { + break + } + insn := state.GetMemory().GetMemory(state.GetPC()) + if i%10_000 == 0 { // avoid spamming test logs, we are executing many steps + t.Logf("step: %4d pc: 0x%08x insn: 0x%08x", state.GetStep(), state.GetPC(), insn) + } + + stepWitness, err := goVm.Step(true) + require.NoError(t, err) + evmPost := evm.Step(t, stepWitness, curStep, v.StateHashFn) + // verify the post-state matches. + goPost, _ := goVm.GetState().EncodeWitness() + require.Equal(t, hexutil.Bytes(goPost).String(), hexutil.Bytes(evmPost).String(), + "mipsevm produced different state than EVM") + } + end := time.Now() + delta := end.Sub(start) + t.Logf("test took %s, %d instructions, %s per instruction", delta, state.GetStep(), delta/time.Duration(state.GetStep())) + + require.True(t, state.GetExited(), "must complete program") + require.Equal(t, uint8(0), state.GetExitCode(), "exit with 0") + }) + } +} diff --git a/cannon/mipsevm/tests/evm_multithreaded_test.go b/cannon/mipsevm/tests/evm_multithreaded_test.go index 32d90b74211c7..a26ebe96eb372 100644 --- a/cannon/mipsevm/tests/evm_multithreaded_test.go +++ b/cannon/mipsevm/tests/evm_multithreaded_test.go @@ -1,20 +1,393 @@ package tests import ( + "encoding/binary" + "fmt" "os" + "slices" "testing" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/tracing" + "github.com/ethereum/go-ethereum/crypto" "github.com/stretchr/testify/require" + "golang.org/x/exp/maps" "github.com/ethereum-optimism/optimism/cannon/mipsevm" "github.com/ethereum-optimism/optimism/cannon/mipsevm/exec" "github.com/ethereum-optimism/optimism/cannon/mipsevm/multithreaded" + mttestutil "github.com/ethereum-optimism/optimism/cannon/mipsevm/multithreaded/testutil" "github.com/ethereum-optimism/optimism/cannon/mipsevm/testutil" + preimage "github.com/ethereum-optimism/optimism/op-preimage" ) -func TestEVM_CloneFlags(t *testing.T) { +func TestEVM_MT_LL(t *testing.T) { + var tracer *tracing.Hooks + + cases := []struct { + name string + base uint32 + offset int + value uint32 + effAddr uint32 + rtReg int + }{ + {name: "Aligned effAddr", base: 0x00_00_00_01, offset: 0x0133, value: 0xABCD, effAddr: 0x00_00_01_34, rtReg: 5}, + {name: "Aligned effAddr, signed extended", base: 0x00_00_00_01, offset: 0xFF33, value: 0xABCD, effAddr: 0xFF_FF_FF_34, rtReg: 5}, + {name: "Unaligned effAddr", base: 0xFF_12_00_01, offset: 0x3401, value: 0xABCD, effAddr: 0xFF_12_34_00, rtReg: 5}, + {name: "Unaligned effAddr, sign extended w overflow", base: 0xFF_12_00_01, offset: 0x8401, value: 0xABCD, effAddr: 0xFF_11_84_00, rtReg: 5}, + {name: "Return register set to 0", base: 0xFF_12_00_01, offset: 0x8401, value: 0xABCD, effAddr: 0xFF_11_84_00, rtReg: 0}, + } + for i, c := range cases { + for _, withExistingReservation := range []bool{true, false} { + tName := fmt.Sprintf("%v (withExistingReservation = %v)", c.name, withExistingReservation) + t.Run(tName, func(t *testing.T) { + rtReg := c.rtReg + baseReg := 6 + pc := uint32(0x44) + insn := uint32((0b11_0000 << 26) | (baseReg & 0x1F << 21) | (rtReg & 0x1F << 16) | (0xFFFF & c.offset)) + goVm, state, contracts := setup(t, i, nil) + step := state.GetStep() + + // Set up state + state.GetCurrentThread().Cpu.PC = pc + state.GetCurrentThread().Cpu.NextPC = pc + 4 + state.GetMemory().SetMemory(pc, insn) + state.GetMemory().SetMemory(c.effAddr, c.value) + state.GetRegistersRef()[baseReg] = c.base + if withExistingReservation { + state.LLReservationActive = true + state.LLAddress = c.effAddr + uint32(4) + state.LLOwnerThread = 123 + } else { + state.LLReservationActive = false + state.LLAddress = 0 + state.LLOwnerThread = 0 + } + + // Set up expectations + expected := mttestutil.NewExpectedMTState(state) + expected.ExpectStep() + expected.LLReservationActive = true + expected.LLAddress = c.effAddr + expected.LLOwnerThread = state.GetCurrentThread().ThreadId + if rtReg != 0 { + expected.ActiveThread().Registers[rtReg] = c.value + } + + stepWitness, err := goVm.Step(true) + require.NoError(t, err) + + // Check expectations + expected.Validate(t, state) + testutil.ValidateEVM(t, stepWitness, step, goVm, multithreaded.GetStateHashFn(), contracts, tracer) + }) + } + } +} + +func TestEVM_MT_SC(t *testing.T) { + var tracer *tracing.Hooks + + llVariations := []struct { + name string + llReservationActive bool + matchThreadId bool + matchEffAddr bool + shouldSucceed bool + }{ + {name: "should succeed", llReservationActive: true, matchThreadId: true, matchEffAddr: true, shouldSucceed: true}, + {name: "mismatch addr", llReservationActive: true, matchThreadId: false, matchEffAddr: true, shouldSucceed: false}, + {name: "mismatched thread", llReservationActive: true, matchThreadId: true, matchEffAddr: false, shouldSucceed: false}, + {name: "mismatched addr & thread", llReservationActive: true, matchThreadId: false, matchEffAddr: false, shouldSucceed: false}, + {name: "no active reservation", llReservationActive: false, matchThreadId: true, matchEffAddr: true, shouldSucceed: false}, + } + + cases := []struct { + name string + base uint32 + offset int + value uint32 + effAddr uint32 + rtReg int + threadId uint32 + }{ + {name: "Aligned effAddr", base: 0x00_00_00_01, offset: 0x0133, value: 0xABCD, effAddr: 0x00_00_01_34, rtReg: 5, threadId: 4}, + {name: "Aligned effAddr, signed extended", base: 0x00_00_00_01, offset: 0xFF33, value: 0xABCD, effAddr: 0xFF_FF_FF_34, rtReg: 5, threadId: 4}, + {name: "Unaligned effAddr", base: 0xFF_12_00_01, offset: 0x3401, value: 0xABCD, effAddr: 0xFF_12_34_00, rtReg: 5, threadId: 4}, + {name: "Unaligned effAddr, sign extended w overflow", base: 0xFF_12_00_01, offset: 0x8401, value: 0xABCD, effAddr: 0xFF_11_84_00, rtReg: 5, threadId: 4}, + {name: "Return register set to 0", base: 0xFF_12_00_01, offset: 0x8401, value: 0xABCD, effAddr: 0xFF_11_84_00, rtReg: 0, threadId: 4}, + {name: "Zero valued ll args", base: 0x00_00_00_00, offset: 0x0, value: 0xABCD, effAddr: 0x00_00_00_00, rtReg: 5, threadId: 0}, + } + for i, c := range cases { + for _, v := range llVariations { + tName := fmt.Sprintf("%v (%v)", c.name, v.name) + t.Run(tName, func(t *testing.T) { + rtReg := c.rtReg + baseReg := 6 + pc := uint32(0x44) + insn := uint32((0b11_1000 << 26) | (baseReg & 0x1F << 21) | (rtReg & 0x1F << 16) | (0xFFFF & c.offset)) + goVm, state, contracts := setup(t, i, nil) + mttestutil.InitializeSingleThread(i*23456, state, i%2 == 1) + step := state.GetStep() + + // Define LL-related params + var llAddress, llOwnerThread uint32 + if v.matchEffAddr { + llAddress = c.effAddr + } else { + llAddress = c.effAddr + 4 + } + if v.matchThreadId { + llOwnerThread = c.threadId + } else { + llOwnerThread = c.threadId + 1 + } + + // Setup state + state.GetCurrentThread().ThreadId = c.threadId + state.GetCurrentThread().Cpu.PC = pc + state.GetCurrentThread().Cpu.NextPC = pc + 4 + state.GetMemory().SetMemory(pc, insn) + state.GetRegistersRef()[baseReg] = c.base + state.GetRegistersRef()[rtReg] = c.value + state.LLReservationActive = v.llReservationActive + state.LLAddress = llAddress + state.LLOwnerThread = llOwnerThread + + // Setup expectations + expected := mttestutil.NewExpectedMTState(state) + expected.ExpectStep() + var retVal uint32 + if v.shouldSucceed { + retVal = 1 + expected.ExpectMemoryWrite(c.effAddr, c.value) + expected.LLReservationActive = false + expected.LLAddress = 0 + expected.LLOwnerThread = 0 + } else { + retVal = 0 + } + if rtReg != 0 { + expected.ActiveThread().Registers[rtReg] = retVal + } + + stepWitness, err := goVm.Step(true) + require.NoError(t, err) + + // Check expectations + expected.Validate(t, state) + testutil.ValidateEVM(t, stepWitness, step, goVm, multithreaded.GetStateHashFn(), contracts, tracer) + }) + } + } +} + +func TestEVM_MT_SysRead_Preimage(t *testing.T) { + var tracer *tracing.Hooks + + preimageValue := make([]byte, 0, 8) + preimageValue = binary.BigEndian.AppendUint32(preimageValue, 0x12_34_56_78) + preimageValue = binary.BigEndian.AppendUint32(preimageValue, 0x98_76_54_32) + + llVariations := []struct { + name string + llReservationActive bool + matchThreadId bool + matchEffAddr bool + shouldClearReservation bool + }{ + {name: "matching reservation", llReservationActive: true, matchThreadId: true, matchEffAddr: true, shouldClearReservation: true}, + {name: "matching reservation, diff thread", llReservationActive: true, matchThreadId: false, matchEffAddr: true, shouldClearReservation: true}, + {name: "mismatched reservation", llReservationActive: true, matchThreadId: true, matchEffAddr: false, shouldClearReservation: false}, + {name: "mismatched reservation", llReservationActive: true, matchThreadId: false, matchEffAddr: false, shouldClearReservation: false}, + {name: "no reservation, matching addr", llReservationActive: false, matchThreadId: true, matchEffAddr: true, shouldClearReservation: true}, + {name: "no reservation, mismatched addr", llReservationActive: false, matchThreadId: true, matchEffAddr: false, shouldClearReservation: false}, + } + + cases := []struct { + name string + addr uint32 + count uint32 + writeLen uint32 + preimageOffset uint32 + prestateMem uint32 + postateMem uint32 + shouldPanic bool + }{ + {name: "Aligned addr, write 1 byte", addr: 0x00_00_FF_00, count: 1, writeLen: 1, preimageOffset: 8, prestateMem: 0xFF_FF_FF_FF, postateMem: 0x12_FF_FF_FF}, + {name: "Aligned addr, write 2 byte", addr: 0x00_00_FF_00, count: 2, writeLen: 2, preimageOffset: 8, prestateMem: 0xFF_FF_FF_FF, postateMem: 0x12_34_FF_FF}, + {name: "Aligned addr, write 3 byte", addr: 0x00_00_FF_00, count: 3, writeLen: 3, preimageOffset: 8, prestateMem: 0xFF_FF_FF_FF, postateMem: 0x12_34_56_FF}, + {name: "Aligned addr, write 4 byte", addr: 0x00_00_FF_00, count: 4, writeLen: 4, preimageOffset: 8, prestateMem: 0xFF_FF_FF_FF, postateMem: 0x12_34_56_78}, + {name: "1-byte misaligned addr, write 1 byte", addr: 0x00_00_FF_01, count: 1, writeLen: 1, preimageOffset: 8, prestateMem: 0xFF_FF_FF_FF, postateMem: 0xFF_12_FF_FF}, + {name: "1-byte misaligned addr, write 2 byte", addr: 0x00_00_FF_01, count: 2, writeLen: 2, preimageOffset: 9, prestateMem: 0xFF_FF_FF_FF, postateMem: 0xFF_34_56_FF}, + {name: "1-byte misaligned addr, write 3 byte", addr: 0x00_00_FF_01, count: 3, writeLen: 3, preimageOffset: 8, prestateMem: 0xFF_FF_FF_FF, postateMem: 0xFF_12_34_56}, + {name: "2-byte misaligned addr, write 1 byte", addr: 0x00_00_FF_02, count: 1, writeLen: 1, preimageOffset: 8, prestateMem: 0xFF_FF_FF_FF, postateMem: 0xFF_FF_12_FF}, + {name: "2-byte misaligned addr, write 2 byte", addr: 0x00_00_FF_02, count: 2, writeLen: 2, preimageOffset: 12, prestateMem: 0xFF_FF_FF_FF, postateMem: 0xFF_FF_98_76}, + {name: "3-byte misaligned addr, write 1 byte", addr: 0x00_00_FF_03, count: 1, writeLen: 1, preimageOffset: 8, prestateMem: 0xFF_FF_FF_FF, postateMem: 0xFF_FF_FF_12}, + {name: "Count of 0", addr: 0x00_00_FF_03, count: 0, writeLen: 0, preimageOffset: 8, prestateMem: 0xFF_FF_FF_FF, postateMem: 0xFF_FF_FF_FF}, + {name: "Count greater than 4", addr: 0x00_00_FF_00, count: 15, writeLen: 4, preimageOffset: 8, prestateMem: 0xFF_FF_FF_FF, postateMem: 0x12_34_56_78}, + {name: "Count greater than 4, unaligned", addr: 0x00_00_FF_01, count: 15, writeLen: 3, preimageOffset: 8, prestateMem: 0xFF_FF_FF_FF, postateMem: 0xFF_12_34_56}, + {name: "Offset at last byte", addr: 0x00_00_FF_00, count: 4, writeLen: 1, preimageOffset: 15, prestateMem: 0xFF_FF_FF_FF, postateMem: 0x32_FF_FF_FF}, + {name: "Offset just out of bounds", addr: 0x00_00_FF_00, count: 4, writeLen: 0, preimageOffset: 16, prestateMem: 0xFF_FF_FF_FF, postateMem: 0xFF_FF_FF_FF, shouldPanic: true}, + {name: "Offset out of bounds", addr: 0x00_00_FF_00, count: 4, writeLen: 0, preimageOffset: 17, prestateMem: 0xFF_FF_FF_FF, postateMem: 0xFF_FF_FF_FF, shouldPanic: true}, + } + for i, c := range cases { + for _, v := range llVariations { + tName := fmt.Sprintf("%v (%v)", c.name, v.name) + t.Run(tName, func(t *testing.T) { + effAddr := 0xFFffFFfc & c.addr + preimageKey := preimage.Keccak256Key(crypto.Keccak256Hash(preimageValue)).PreimageKey() + oracle := testutil.StaticOracle(t, preimageValue) + goVm, state, contracts := setup(t, i, oracle) + step := state.GetStep() + + // Define LL-related params + var llAddress, llOwnerThread uint32 + if v.matchEffAddr { + llAddress = effAddr + } else { + llAddress = effAddr + 4 + } + if v.matchThreadId { + llOwnerThread = state.GetCurrentThread().ThreadId + } else { + llOwnerThread = state.GetCurrentThread().ThreadId + 1 + } + + // Set up state + state.PreimageKey = preimageKey + state.PreimageOffset = c.preimageOffset + state.GetRegistersRef()[2] = exec.SysRead + state.GetRegistersRef()[4] = exec.FdPreimageRead + state.GetRegistersRef()[5] = c.addr + state.GetRegistersRef()[6] = c.count + state.GetMemory().SetMemory(state.GetPC(), syscallInsn) + state.LLReservationActive = v.llReservationActive + state.LLAddress = llAddress + state.LLOwnerThread = llOwnerThread + state.GetMemory().SetMemory(effAddr, c.prestateMem) + + // Setup expectations + expected := mttestutil.NewExpectedMTState(state) + expected.ExpectStep() + expected.ActiveThread().Registers[2] = c.writeLen + expected.ActiveThread().Registers[7] = 0 // no error + expected.PreimageOffset += c.writeLen + expected.ExpectMemoryWrite(effAddr, c.postateMem) + if v.shouldClearReservation { + expected.LLReservationActive = false + expected.LLAddress = 0 + expected.LLOwnerThread = 0 + } + + if c.shouldPanic { + require.Panics(t, func() { _, _ = goVm.Step(true) }) + testutil.AssertPreimageOracleReverts(t, preimageKey, preimageValue, c.preimageOffset, contracts, tracer) + } else { + stepWitness, err := goVm.Step(true) + require.NoError(t, err) + + // Check expectations + expected.Validate(t, state) + testutil.ValidateEVM(t, stepWitness, step, goVm, multithreaded.GetStateHashFn(), contracts, tracer) + } + }) + } + } +} + +func TestEVM_MT_StoreOpsClearMemReservation(t *testing.T) { + var tracer *tracing.Hooks + + llVariations := []struct { + name string + llReservationActive bool + matchThreadId bool + matchEffAddr bool + shouldClearReservation bool + }{ + {name: "matching reservation", llReservationActive: true, matchThreadId: true, matchEffAddr: true, shouldClearReservation: true}, + {name: "matching reservation, diff thread", llReservationActive: true, matchThreadId: false, matchEffAddr: true, shouldClearReservation: true}, + {name: "mismatched reservation", llReservationActive: true, matchThreadId: true, matchEffAddr: false, shouldClearReservation: false}, + {name: "mismatched reservation, diff thread", llReservationActive: true, matchThreadId: false, matchEffAddr: false, shouldClearReservation: false}, + {name: "no reservation, matching addr", llReservationActive: false, matchThreadId: true, matchEffAddr: true, shouldClearReservation: true}, + {name: "no reservation, mismatched addr", llReservationActive: false, matchThreadId: true, matchEffAddr: false, shouldClearReservation: false}, + } + + pc := uint32(0x04) + rt := uint32(0x12_34_56_78) + baseReg := 5 + rtReg := 6 + cases := []struct { + name string + opcode int + offset int + base uint32 + effAddr uint32 + preMem uint32 + postMem uint32 + }{ + {name: "Store byte", opcode: 0b10_1000, base: 0xFF_00_00_04, offset: 0xFF_00_00_08, effAddr: 0xFF_00_00_0C, preMem: 0xFF_FF_FF_FF, postMem: 0x78_FF_FF_FF}, + {name: "Store halfword", opcode: 0b10_1001, base: 0xFF_00_00_04, offset: 0xFF_00_00_08, effAddr: 0xFF_00_00_0C, preMem: 0xFF_FF_FF_FF, postMem: 0x56_78_FF_FF}, + {name: "Store word left", opcode: 0b10_1010, base: 0xFF_00_00_04, offset: 0xFF_00_00_08, effAddr: 0xFF_00_00_0C, preMem: 0xFF_FF_FF_FF, postMem: 0x12_34_56_78}, + {name: "Store word", opcode: 0b10_1011, base: 0xFF_00_00_04, offset: 0xFF_00_00_08, effAddr: 0xFF_00_00_0C, preMem: 0xFF_FF_FF_FF, postMem: 0x12_34_56_78}, + {name: "Store word right", opcode: 0b10_1110, base: 0xFF_00_00_04, offset: 0xFF_00_00_08, effAddr: 0xFF_00_00_0C, preMem: 0xFF_FF_FF_FF, postMem: 0x78_FF_FF_FF}, + } + for i, c := range cases { + for _, v := range llVariations { + tName := fmt.Sprintf("%v (%v)", c.name, v.name) + t.Run(tName, func(t *testing.T) { + insn := uint32((c.opcode << 26) | (baseReg & 0x1F << 21) | (rtReg & 0x1F << 16) | (0xFFFF & c.offset)) + goVm, state, contracts := setup(t, i, nil) + step := state.GetStep() + + // Define LL-related params + var llAddress, llOwnerThread uint32 + if v.matchEffAddr { + llAddress = c.effAddr + } else { + llAddress = c.effAddr + 4 + } + if v.matchThreadId { + llOwnerThread = state.GetCurrentThread().ThreadId + } else { + llOwnerThread = state.GetCurrentThread().ThreadId + 1 + } + + // Setup state + state.GetCurrentThread().Cpu.PC = pc + state.GetCurrentThread().Cpu.NextPC = pc + 4 + state.GetRegistersRef()[rtReg] = rt + state.GetRegistersRef()[baseReg] = c.base + state.GetMemory().SetMemory(state.GetPC(), insn) + state.GetMemory().SetMemory(c.effAddr, c.preMem) + state.LLReservationActive = v.llReservationActive + state.LLAddress = llAddress + state.LLOwnerThread = llOwnerThread + + // Setup expectations + expected := mttestutil.NewExpectedMTState(state) + expected.ExpectStep() + expected.ExpectMemoryWrite(c.effAddr, c.postMem) + if v.shouldClearReservation { + expected.LLReservationActive = false + expected.LLAddress = 0 + expected.LLOwnerThread = 0 + } + + stepWitness, err := goVm.Step(true) + require.NoError(t, err) + + // Check expectations + expected.Validate(t, state) + testutil.ValidateEVM(t, stepWitness, step, goVm, multithreaded.GetStateHashFn(), contracts, tracer) + }) + } + } +} + +func TestEVM_SysClone_FlagHandling(t *testing.T) { contracts := testutil.TestContractsSetup(t, testutil.MipsMultithreaded) var tracer *tracing.Hooks @@ -34,27 +407,32 @@ func TestEVM_CloneFlags(t *testing.T) { {"multiple unsupported flags", exec.CloneUntraced | exec.CloneParentSettid, false}, } - const insn = uint32(0x00_00_00_0C) // syscall instruction - for _, tt := range cases { - t.Run(tt.name, func(t *testing.T) { + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { state := multithreaded.CreateEmptyState() - state.Memory.SetMemory(state.GetPC(), insn) + state.Memory.SetMemory(state.GetPC(), syscallInsn) state.GetRegistersRef()[2] = exec.SysClone // Set syscall number - state.GetRegistersRef()[4] = tt.flags // Set first argument + state.GetRegistersRef()[4] = c.flags // Set first argument curStep := state.Step var err error var stepWitness *mipsevm.StepWitness - us := multithreaded.NewInstrumentedState(state, nil, os.Stdout, os.Stderr, nil) - if !tt.valid { + us := multithreaded.NewInstrumentedState(state, nil, os.Stdout, os.Stderr, nil, nil) + if !c.valid { // The VM should exit stepWitness, err = us.Step(true) require.NoError(t, err) + require.Equal(t, curStep+1, state.GetStep()) require.Equal(t, true, us.GetState().GetExited()) require.Equal(t, uint8(mipsevm.VMStatusPanic), us.GetState().GetExitCode()) + require.Equal(t, 1, state.ThreadCount()) } else { stepWitness, err = us.Step(true) require.NoError(t, err) + require.Equal(t, curStep+1, state.GetStep()) + require.Equal(t, false, us.GetState().GetExited()) + require.Equal(t, uint8(0), us.GetState().GetExitCode()) + require.Equal(t, 2, state.ThreadCount()) } evm := testutil.NewMIPSEVM(contracts) @@ -68,3 +446,1067 @@ func TestEVM_CloneFlags(t *testing.T) { }) } } + +func TestEVM_SysClone_Successful(t *testing.T) { + var tracer *tracing.Hooks + cases := []struct { + name string + traverseRight bool + }{ + {"traverse left", false}, + {"traverse right", true}, + } + + for i, c := range cases { + t.Run(c.name, func(t *testing.T) { + stackPtr := uint32(100) + + goVm, state, contracts := setup(t, i, nil) + mttestutil.InitializeSingleThread(i*333, state, c.traverseRight) + state.Memory.SetMemory(state.GetPC(), syscallInsn) + state.GetRegistersRef()[2] = exec.SysClone // the syscall number + state.GetRegistersRef()[4] = exec.ValidCloneFlags // a0 - first argument, clone flags + state.GetRegistersRef()[5] = stackPtr // a1 - the stack pointer + step := state.GetStep() + + // Sanity-check assumptions + require.Equal(t, uint32(1), state.NextThreadId) + + // Setup expectations + expected := mttestutil.NewExpectedMTState(state) + expected.Step += 1 + expectedNewThread := expected.ExpectNewThread() + expected.ActiveThreadId = expectedNewThread.ThreadId + expected.StepsSinceLastContextSwitch = 0 + if c.traverseRight { + expected.RightStackSize += 1 + } else { + expected.LeftStackSize += 1 + } + // Original thread expectations + expected.PrestateActiveThread().PC = state.GetCpu().NextPC + expected.PrestateActiveThread().NextPC = state.GetCpu().NextPC + 4 + expected.PrestateActiveThread().Registers[2] = 1 + expected.PrestateActiveThread().Registers[7] = 0 + // New thread expectations + expectedNewThread.PC = state.GetCpu().NextPC + expectedNewThread.NextPC = state.GetCpu().NextPC + 4 + expectedNewThread.ThreadId = 1 + expectedNewThread.Registers[2] = 0 + expectedNewThread.Registers[7] = 0 + expectedNewThread.Registers[29] = stackPtr + + var err error + var stepWitness *mipsevm.StepWitness + stepWitness, err = goVm.Step(true) + require.NoError(t, err) + + expected.Validate(t, state) + activeStack, inactiveStack := mttestutil.GetThreadStacks(state) + require.Equal(t, 2, len(activeStack)) + require.Equal(t, 0, len(inactiveStack)) + testutil.ValidateEVM(t, stepWitness, step, goVm, multithreaded.GetStateHashFn(), contracts, tracer) + }) + } +} + +func TestEVM_SysGetTID(t *testing.T) { + var tracer *tracing.Hooks + cases := []struct { + name string + threadId uint32 + }{ + {"zero", 0}, + {"non-zero", 11}, + } + + for i, c := range cases { + t.Run(c.name, func(t *testing.T) { + goVm, state, contracts := setup(t, i*789, nil) + mttestutil.InitializeSingleThread(i*789, state, false) + + state.GetCurrentThread().ThreadId = c.threadId + state.Memory.SetMemory(state.GetPC(), syscallInsn) + state.GetRegistersRef()[2] = exec.SysGetTID // Set syscall number + step := state.Step + + // Set up post-state expectations + expected := mttestutil.NewExpectedMTState(state) + expected.ExpectStep() + expected.ActiveThread().Registers[2] = c.threadId + expected.ActiveThread().Registers[7] = 0 + + // State transition + var err error + var stepWitness *mipsevm.StepWitness + stepWitness, err = goVm.Step(true) + require.NoError(t, err) + + // Validate post-state + expected.Validate(t, state) + testutil.ValidateEVM(t, stepWitness, step, goVm, multithreaded.GetStateHashFn(), contracts, tracer) + }) + } +} + +func TestEVM_SysExit(t *testing.T) { + var tracer *tracing.Hooks + cases := []struct { + name string + threadCount int + shouldExitGlobally bool + }{ + // If we exit the last thread, the whole process should exit + {name: "one thread", threadCount: 1, shouldExitGlobally: true}, + {name: "two threads ", threadCount: 2}, + {name: "three threads ", threadCount: 3}, + } + + for i, c := range cases { + t.Run(c.name, func(t *testing.T) { + exitCode := uint8(3) + + goVm, state, contracts := setup(t, i*133, nil) + mttestutil.SetupThreads(int64(i*1111), state, i%2 == 0, c.threadCount, 0) + + state.Memory.SetMemory(state.GetPC(), syscallInsn) + state.GetRegistersRef()[2] = exec.SysExit // Set syscall number + state.GetRegistersRef()[4] = uint32(exitCode) // The first argument (exit code) + step := state.Step + + // Set up expectations + expected := mttestutil.NewExpectedMTState(state) + expected.Step += 1 + expected.StepsSinceLastContextSwitch += 1 + expected.ActiveThread().Exited = true + expected.ActiveThread().ExitCode = exitCode + if c.shouldExitGlobally { + expected.Exited = true + expected.ExitCode = exitCode + } + + // State transition + var err error + var stepWitness *mipsevm.StepWitness + stepWitness, err = goVm.Step(true) + require.NoError(t, err) + + // Validate post-state + expected.Validate(t, state) + testutil.ValidateEVM(t, stepWitness, step, goVm, multithreaded.GetStateHashFn(), contracts, tracer) + }) + } +} + +func TestEVM_PopExitedThread(t *testing.T) { + var tracer *tracing.Hooks + cases := []struct { + name string + traverseRight bool + activeStackThreadCount int + expectTraverseRightPostState bool + }{ + {name: "traverse right", traverseRight: true, activeStackThreadCount: 2, expectTraverseRightPostState: true}, + {name: "traverse right, switch directions", traverseRight: true, activeStackThreadCount: 1, expectTraverseRightPostState: false}, + {name: "traverse left", traverseRight: false, activeStackThreadCount: 2, expectTraverseRightPostState: false}, + {name: "traverse left, switch directions", traverseRight: false, activeStackThreadCount: 1, expectTraverseRightPostState: true}, + } + + for i, c := range cases { + t.Run(c.name, func(t *testing.T) { + goVm, state, contracts := setup(t, i*133, nil) + mttestutil.SetupThreads(int64(i*222), state, c.traverseRight, c.activeStackThreadCount, 1) + step := state.Step + + // Setup thread to be dropped + threadToPop := state.GetCurrentThread() + threadToPop.Exited = true + threadToPop.ExitCode = 1 + + // Set up expectations + expected := mttestutil.NewExpectedMTState(state) + expected.Step += 1 + expected.ActiveThreadId = mttestutil.FindNextThreadExcluding(state, threadToPop.ThreadId).ThreadId + expected.StepsSinceLastContextSwitch = 0 + expected.ThreadCount -= 1 + expected.TraverseRight = c.expectTraverseRightPostState + expected.Thread(threadToPop.ThreadId).Dropped = true + if c.traverseRight { + expected.RightStackSize -= 1 + } else { + expected.LeftStackSize -= 1 + } + + // State transition + var err error + var stepWitness *mipsevm.StepWitness + stepWitness, err = goVm.Step(true) + require.NoError(t, err) + + // Validate post-state + expected.Validate(t, state) + testutil.ValidateEVM(t, stepWitness, step, goVm, multithreaded.GetStateHashFn(), contracts, tracer) + }) + } +} + +func TestEVM_SysFutex_WaitPrivate(t *testing.T) { + var tracer *tracing.Hooks + cases := []struct { + name string + addressParam uint32 + effAddr uint32 + targetValue uint32 + actualValue uint32 + timeout uint32 + shouldFail bool + shouldSetTimeout bool + }{ + {name: "successful wait, no timeout", addressParam: 0x1234, effAddr: 0x1234, targetValue: 0x01, actualValue: 0x01}, + {name: "successful wait, no timeout, unaligned addr", addressParam: 0x1235, effAddr: 0x1234, targetValue: 0x01, actualValue: 0x01}, + {name: "memory mismatch, no timeout", addressParam: 0x1200, effAddr: 0x1200, targetValue: 0x01, actualValue: 0x02, shouldFail: true}, + {name: "memory mismatch, no timeout, unaligned", addressParam: 0x1203, effAddr: 0x1200, targetValue: 0x01, actualValue: 0x02, shouldFail: true}, + {name: "successful wait w timeout", addressParam: 0x1234, effAddr: 0x1234, targetValue: 0x01, actualValue: 0x01, timeout: 1000000, shouldSetTimeout: true}, + {name: "successful wait w timeout, unaligned", addressParam: 0x1232, effAddr: 0x1230, targetValue: 0x01, actualValue: 0x01, timeout: 1000000, shouldSetTimeout: true}, + {name: "memory mismatch w timeout", addressParam: 0x1200, effAddr: 0x1200, targetValue: 0x01, actualValue: 0x02, timeout: 2000000, shouldFail: true}, + {name: "memory mismatch w timeout, unaligned", addressParam: 0x120F, effAddr: 0x120C, targetValue: 0x01, actualValue: 0x02, timeout: 2000000, shouldFail: true}, + } + + for i, c := range cases { + t.Run(c.name, func(t *testing.T) { + goVm, state, contracts := setup(t, i*1234, nil) + step := state.GetStep() + + state.Memory.SetMemory(state.GetPC(), syscallInsn) + state.Memory.SetMemory(c.effAddr, c.actualValue) + state.GetRegistersRef()[2] = exec.SysFutex // Set syscall number + state.GetRegistersRef()[4] = c.addressParam + state.GetRegistersRef()[5] = exec.FutexWaitPrivate + state.GetRegistersRef()[6] = c.targetValue + state.GetRegistersRef()[7] = c.timeout + + // Setup expectations + expected := mttestutil.NewExpectedMTState(state) + expected.Step += 1 + expected.StepsSinceLastContextSwitch += 1 + if c.shouldFail { + expected.ActiveThread().PC = state.GetCpu().NextPC + expected.ActiveThread().NextPC = state.GetCpu().NextPC + 4 + expected.ActiveThread().Registers[2] = exec.SysErrorSignal + expected.ActiveThread().Registers[7] = exec.MipsEAGAIN + } else { + // PC and return registers should not update on success, updates happen when wait completes + expected.ActiveThread().FutexAddr = c.effAddr + expected.ActiveThread().FutexVal = c.targetValue + expected.ActiveThread().FutexTimeoutStep = exec.FutexNoTimeout + if c.shouldSetTimeout { + expected.ActiveThread().FutexTimeoutStep = step + exec.FutexTimeoutSteps + 1 + } + } + + // State transition + var err error + var stepWitness *mipsevm.StepWitness + stepWitness, err = goVm.Step(true) + require.NoError(t, err) + + // Validate post-state + expected.Validate(t, state) + testutil.ValidateEVM(t, stepWitness, step, goVm, multithreaded.GetStateHashFn(), contracts, tracer) + }) + } +} + +func TestEVM_SysFutex_WakePrivate(t *testing.T) { + var tracer *tracing.Hooks + cases := []struct { + name string + addressParam uint32 + effAddr uint32 + activeThreadCount int + inactiveThreadCount int + traverseRight bool + expectTraverseRight bool + }{ + {name: "Traverse right", addressParam: 0x6700, effAddr: 0x6700, activeThreadCount: 2, inactiveThreadCount: 1, traverseRight: true}, + {name: "Traverse right, unaligned addr", addressParam: 0x6789, effAddr: 0x6788, activeThreadCount: 2, inactiveThreadCount: 1, traverseRight: true}, + {name: "Traverse right, no left threads", addressParam: 0x6784, effAddr: 0x6784, activeThreadCount: 2, inactiveThreadCount: 0, traverseRight: true}, + {name: "Traverse right, no left threads, unaligned addr", addressParam: 0x678E, effAddr: 0x678C, activeThreadCount: 2, inactiveThreadCount: 0, traverseRight: true}, + {name: "Traverse right, single thread", addressParam: 0x6788, effAddr: 0x6788, activeThreadCount: 1, inactiveThreadCount: 0, traverseRight: true}, + {name: "Traverse right, single thread, unaligned", addressParam: 0x6789, effAddr: 0x6788, activeThreadCount: 1, inactiveThreadCount: 0, traverseRight: true}, + {name: "Traverse left", addressParam: 0x6788, effAddr: 0x6788, activeThreadCount: 2, inactiveThreadCount: 1, traverseRight: false}, + {name: "Traverse left, unaliagned", addressParam: 0x6789, effAddr: 0x6788, activeThreadCount: 2, inactiveThreadCount: 1, traverseRight: false}, + {name: "Traverse left, switch directions", addressParam: 0x6788, effAddr: 0x6788, activeThreadCount: 1, inactiveThreadCount: 1, traverseRight: false, expectTraverseRight: true}, + {name: "Traverse left, switch directions, unaligned", addressParam: 0x6789, effAddr: 0x6788, activeThreadCount: 1, inactiveThreadCount: 1, traverseRight: false, expectTraverseRight: true}, + {name: "Traverse left, single thread", addressParam: 0x6788, effAddr: 0x6788, activeThreadCount: 1, inactiveThreadCount: 0, traverseRight: false, expectTraverseRight: true}, + {name: "Traverse left, single thread, unaligned", addressParam: 0x6789, effAddr: 0x6788, activeThreadCount: 1, inactiveThreadCount: 0, traverseRight: false, expectTraverseRight: true}, + } + + for i, c := range cases { + t.Run(c.name, func(t *testing.T) { + goVm, state, contracts := setup(t, i*1122, nil) + mttestutil.SetupThreads(int64(i*2244), state, c.traverseRight, c.activeThreadCount, c.inactiveThreadCount) + step := state.Step + + state.Memory.SetMemory(state.GetPC(), syscallInsn) + state.GetRegistersRef()[2] = exec.SysFutex // Set syscall number + state.GetRegistersRef()[4] = c.addressParam + state.GetRegistersRef()[5] = exec.FutexWakePrivate + + // Set up post-state expectations + expected := mttestutil.NewExpectedMTState(state) + expected.ExpectStep() + expected.ActiveThread().Registers[2] = 0 + expected.ActiveThread().Registers[7] = 0 + expected.Wakeup = c.effAddr + expected.ExpectPreemption(state) + expected.TraverseRight = c.expectTraverseRight + if c.traverseRight != c.expectTraverseRight { + // If we preempt the current thread and then switch directions, the same + // thread will remain active + expected.ActiveThreadId = state.GetCurrentThread().ThreadId + } + + // State transition + var err error + var stepWitness *mipsevm.StepWitness + stepWitness, err = goVm.Step(true) + require.NoError(t, err) + + // Validate post-state + expected.Validate(t, state) + testutil.ValidateEVM(t, stepWitness, step, goVm, multithreaded.GetStateHashFn(), contracts, tracer) + }) + } +} + +func TestEVM_SysFutex_UnsupportedOp(t *testing.T) { + var tracer *tracing.Hooks + + // From: https://github.com/torvalds/linux/blob/5be63fc19fcaa4c236b307420483578a56986a37/include/uapi/linux/futex.h + const FUTEX_PRIVATE_FLAG = 128 + const FUTEX_WAIT = 0 + const FUTEX_WAKE = 1 + const FUTEX_FD = 2 + const FUTEX_REQUEUE = 3 + const FUTEX_CMP_REQUEUE = 4 + const FUTEX_WAKE_OP = 5 + const FUTEX_LOCK_PI = 6 + const FUTEX_UNLOCK_PI = 7 + const FUTEX_TRYLOCK_PI = 8 + const FUTEX_WAIT_BITSET = 9 + const FUTEX_WAKE_BITSET = 10 + const FUTEX_WAIT_REQUEUE_PI = 11 + const FUTEX_CMP_REQUEUE_PI = 12 + const FUTEX_LOCK_PI2 = 13 + + unsupportedFutexOps := map[string]uint32{ + "FUTEX_WAIT": FUTEX_WAIT, + "FUTEX_WAKE": FUTEX_WAKE, + "FUTEX_FD": FUTEX_FD, + "FUTEX_REQUEUE": FUTEX_REQUEUE, + "FUTEX_CMP_REQUEUE": FUTEX_CMP_REQUEUE, + "FUTEX_WAKE_OP": FUTEX_WAKE_OP, + "FUTEX_LOCK_PI": FUTEX_LOCK_PI, + "FUTEX_UNLOCK_PI": FUTEX_UNLOCK_PI, + "FUTEX_TRYLOCK_PI": FUTEX_TRYLOCK_PI, + "FUTEX_WAIT_BITSET": FUTEX_WAIT_BITSET, + "FUTEX_WAKE_BITSET": FUTEX_WAKE_BITSET, + "FUTEX_WAIT_REQUEUE_PI": FUTEX_WAIT_REQUEUE_PI, + "FUTEX_CMP_REQUEUE_PI": FUTEX_CMP_REQUEUE_PI, + "FUTEX_LOCK_PI2": FUTEX_LOCK_PI2, + "FUTEX_REQUEUE_PRIVATE": (FUTEX_REQUEUE | FUTEX_PRIVATE_FLAG), + "FUTEX_CMP_REQUEUE_PRIVATE": (FUTEX_CMP_REQUEUE | FUTEX_PRIVATE_FLAG), + "FUTEX_WAKE_OP_PRIVATE": (FUTEX_WAKE_OP | FUTEX_PRIVATE_FLAG), + "FUTEX_LOCK_PI_PRIVATE": (FUTEX_LOCK_PI | FUTEX_PRIVATE_FLAG), + "FUTEX_LOCK_PI2_PRIVATE": (FUTEX_LOCK_PI2 | FUTEX_PRIVATE_FLAG), + "FUTEX_UNLOCK_PI_PRIVATE": (FUTEX_UNLOCK_PI | FUTEX_PRIVATE_FLAG), + "FUTEX_TRYLOCK_PI_PRIVATE": (FUTEX_TRYLOCK_PI | FUTEX_PRIVATE_FLAG), + "FUTEX_WAIT_BITSET_PRIVATE": (FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG), + "FUTEX_WAKE_BITSET_PRIVATE": (FUTEX_WAKE_BITSET | FUTEX_PRIVATE_FLAG), + "FUTEX_WAIT_REQUEUE_PI_PRIVATE": (FUTEX_WAIT_REQUEUE_PI | FUTEX_PRIVATE_FLAG), + "FUTEX_CMP_REQUEUE_PI_PRIVATE": (FUTEX_CMP_REQUEUE_PI | FUTEX_PRIVATE_FLAG), + } + + for name, op := range unsupportedFutexOps { + t.Run(name, func(t *testing.T) { + goVm, state, contracts := setup(t, int(op), nil) + step := state.GetStep() + + state.Memory.SetMemory(state.GetPC(), syscallInsn) + state.GetRegistersRef()[2] = exec.SysFutex // Set syscall number + state.GetRegistersRef()[5] = op + + // Setup expectations + expected := mttestutil.NewExpectedMTState(state) + expected.Step += 1 + expected.StepsSinceLastContextSwitch += 1 + expected.ActiveThread().PC = state.GetCpu().NextPC + expected.ActiveThread().NextPC = state.GetCpu().NextPC + 4 + expected.ActiveThread().Registers[2] = exec.SysErrorSignal + expected.ActiveThread().Registers[7] = exec.MipsEINVAL + + // State transition + var err error + var stepWitness *mipsevm.StepWitness + stepWitness, err = goVm.Step(true) + require.NoError(t, err) + + // Validate post-state + expected.Validate(t, state) + testutil.ValidateEVM(t, stepWitness, step, goVm, multithreaded.GetStateHashFn(), contracts, tracer) + }) + } +} + +func TestEVM_SysYield(t *testing.T) { + runPreemptSyscall(t, "SysSchedYield", exec.SysSchedYield) +} + +func TestEVM_SysNanosleep(t *testing.T) { + runPreemptSyscall(t, "SysNanosleep", exec.SysNanosleep) +} + +func runPreemptSyscall(t *testing.T, syscallName string, syscallNum uint32) { + var tracer *tracing.Hooks + cases := []struct { + name string + traverseRight bool + activeThreads int + inactiveThreads int + }{ + {name: "Last active thread", activeThreads: 1, inactiveThreads: 2}, + {name: "Only thread", activeThreads: 1, inactiveThreads: 0}, + {name: "Do not change directions", activeThreads: 2, inactiveThreads: 2}, + {name: "Do not change directions", activeThreads: 3, inactiveThreads: 0}, + } + + for i, c := range cases { + for _, traverseRight := range []bool{true, false} { + testName := fmt.Sprintf("%v: %v (traverseRight = %v)", syscallName, c.name, traverseRight) + t.Run(testName, func(t *testing.T) { + goVm, state, contracts := setup(t, i*789, nil) + mttestutil.SetupThreads(int64(i*3259), state, traverseRight, c.activeThreads, c.inactiveThreads) + + state.Memory.SetMemory(state.GetPC(), syscallInsn) + state.GetRegistersRef()[2] = syscallNum // Set syscall number + step := state.Step + + // Set up post-state expectations + expected := mttestutil.NewExpectedMTState(state) + expected.ExpectStep() + expected.ExpectPreemption(state) + expected.PrestateActiveThread().Registers[2] = 0 + expected.PrestateActiveThread().Registers[7] = 0 + + // State transition + var err error + var stepWitness *mipsevm.StepWitness + stepWitness, err = goVm.Step(true) + require.NoError(t, err) + + // Validate post-state + expected.Validate(t, state) + testutil.ValidateEVM(t, stepWitness, step, goVm, multithreaded.GetStateHashFn(), contracts, tracer) + }) + } + } +} + +func TestEVM_SysOpen(t *testing.T) { + var tracer *tracing.Hooks + + goVm, state, contracts := setup(t, 5512, nil) + + state.Memory.SetMemory(state.GetPC(), syscallInsn) + state.GetRegistersRef()[2] = exec.SysOpen // Set syscall number + step := state.Step + + // Set up post-state expectations + expected := mttestutil.NewExpectedMTState(state) + expected.ExpectStep() + expected.ActiveThread().Registers[2] = exec.SysErrorSignal + expected.ActiveThread().Registers[7] = exec.MipsEBADF + + // State transition + var err error + var stepWitness *mipsevm.StepWitness + stepWitness, err = goVm.Step(true) + require.NoError(t, err) + + // Validate post-state + expected.Validate(t, state) + testutil.ValidateEVM(t, stepWitness, step, goVm, multithreaded.GetStateHashFn(), contracts, tracer) +} + +func TestEVM_SysGetPID(t *testing.T) { + var tracer *tracing.Hooks + goVm, state, contracts := setup(t, 1929, nil) + + state.Memory.SetMemory(state.GetPC(), syscallInsn) + state.GetRegistersRef()[2] = exec.SysGetpid // Set syscall number + step := state.Step + + // Set up post-state expectations + expected := mttestutil.NewExpectedMTState(state) + expected.ExpectStep() + expected.ActiveThread().Registers[2] = 0 + expected.ActiveThread().Registers[7] = 0 + + // State transition + var err error + var stepWitness *mipsevm.StepWitness + stepWitness, err = goVm.Step(true) + require.NoError(t, err) + + // Validate post-state + expected.Validate(t, state) + testutil.ValidateEVM(t, stepWitness, step, goVm, multithreaded.GetStateHashFn(), contracts, tracer) +} + +func TestEVM_SysClockGettimeMonotonic(t *testing.T) { + testEVM_SysClockGettime(t, exec.ClockGettimeMonotonicFlag) +} + +func TestEVM_SysClockGettimeRealtime(t *testing.T) { + testEVM_SysClockGettime(t, exec.ClockGettimeRealtimeFlag) +} + +func testEVM_SysClockGettime(t *testing.T, clkid uint32) { + var tracer *tracing.Hooks + + llVariations := []struct { + name string + llReservationActive bool + matchThreadId bool + matchEffAddr bool + matchEffAddr2 bool + shouldClearReservation bool + }{ + {name: "matching reservation", llReservationActive: true, matchThreadId: true, matchEffAddr: true, shouldClearReservation: true}, + {name: "matching reservation, 2nd word", llReservationActive: true, matchThreadId: true, matchEffAddr2: true, shouldClearReservation: true}, + {name: "matching reservation, diff thread", llReservationActive: true, matchThreadId: false, matchEffAddr: true, shouldClearReservation: true}, + {name: "matching reservation, diff thread, 2nd word", llReservationActive: true, matchThreadId: false, matchEffAddr2: true, shouldClearReservation: true}, + {name: "mismatched reservation", llReservationActive: true, matchThreadId: true, matchEffAddr: false, shouldClearReservation: false}, + {name: "mismatched reservation, diff thread", llReservationActive: true, matchThreadId: false, matchEffAddr: false, shouldClearReservation: false}, + {name: "no reservation, matching addr", llReservationActive: false, matchThreadId: true, matchEffAddr: true, shouldClearReservation: true}, + {name: "no reservation, matching addr2", llReservationActive: false, matchThreadId: true, matchEffAddr2: true, shouldClearReservation: true}, + {name: "no reservation, mismatched addr", llReservationActive: false, matchThreadId: true, matchEffAddr: false, shouldClearReservation: false}, + } + + cases := []struct { + name string + timespecAddr uint32 + }{ + {"aligned timespec address", 0x1000}, + {"unaligned timespec address", 0x1003}, + } + for i, c := range cases { + for _, v := range llVariations { + tName := fmt.Sprintf("%v (%v)", c.name, v.name) + t.Run(tName, func(t *testing.T) { + goVm, state, contracts := setup(t, 2101, nil) + mttestutil.InitializeSingleThread(2101+i, state, i%2 == 1) + effAddr := c.timespecAddr & 0xFFffFFfc + effAddr2 := effAddr + 4 + step := state.Step + + // Define LL-related params + var llAddress, llOwnerThread uint32 + if v.matchEffAddr { + llAddress = effAddr + } else if v.matchEffAddr2 { + llAddress = effAddr2 + } else { + llAddress = effAddr2 + 8 + } + if v.matchThreadId { + llOwnerThread = state.GetCurrentThread().ThreadId + } else { + llOwnerThread = state.GetCurrentThread().ThreadId + 1 + } + + state.Memory.SetMemory(state.GetPC(), syscallInsn) + state.GetRegistersRef()[2] = exec.SysClockGetTime // Set syscall number + state.GetRegistersRef()[4] = clkid // a0 + state.GetRegistersRef()[5] = c.timespecAddr // a1 + state.LLReservationActive = v.llReservationActive + state.LLAddress = llAddress + state.LLOwnerThread = llOwnerThread + + expected := mttestutil.NewExpectedMTState(state) + expected.ExpectStep() + expected.ActiveThread().Registers[2] = 0 + expected.ActiveThread().Registers[7] = 0 + next := state.Step + 1 + var secs, nsecs uint32 + if clkid == exec.ClockGettimeMonotonicFlag { + secs = uint32(next / exec.HZ) + nsecs = uint32((next % exec.HZ) * (1_000_000_000 / exec.HZ)) + } + expected.ExpectMemoryWrite(effAddr, secs) + expected.ExpectMemoryWrite(effAddr2, nsecs) + if v.shouldClearReservation { + expected.LLReservationActive = false + expected.LLAddress = 0 + expected.LLOwnerThread = 0 + } + + var err error + var stepWitness *mipsevm.StepWitness + stepWitness, err = goVm.Step(true) + require.NoError(t, err) + + // Validate post-state + expected.Validate(t, state) + testutil.ValidateEVM(t, stepWitness, step, goVm, multithreaded.GetStateHashFn(), contracts, tracer) + }) + } + } +} + +func TestEVM_SysClockGettimeNonMonotonic(t *testing.T) { + var tracer *tracing.Hooks + goVm, state, contracts := setup(t, 2101, nil) + + timespecAddr := uint32(0x1000) + state.Memory.SetMemory(state.GetPC(), syscallInsn) + state.GetRegistersRef()[2] = exec.SysClockGetTime // Set syscall number + state.GetRegistersRef()[4] = 0xDEAD // a0 - invalid clockid + state.GetRegistersRef()[5] = timespecAddr // a1 + step := state.Step + + expected := mttestutil.NewExpectedMTState(state) + expected.ExpectStep() + expected.ActiveThread().Registers[2] = exec.SysErrorSignal + expected.ActiveThread().Registers[7] = exec.MipsEINVAL + + var err error + var stepWitness *mipsevm.StepWitness + stepWitness, err = goVm.Step(true) + require.NoError(t, err) + + // Validate post-state + expected.Validate(t, state) + testutil.ValidateEVM(t, stepWitness, step, goVm, multithreaded.GetStateHashFn(), contracts, tracer) +} + +var NoopSyscalls = map[string]uint32{ + "SysGetAffinity": 4240, + "SysMadvise": 4218, + "SysRtSigprocmask": 4195, + "SysSigaltstack": 4206, + "SysRtSigaction": 4194, + "SysPrlimit64": 4338, + "SysClose": 4006, + "SysPread64": 4200, + "SysFstat64": 4215, + "SysOpenAt": 4288, + "SysReadlink": 4085, + "SysReadlinkAt": 4298, + "SysIoctl": 4054, + "SysEpollCreate1": 4326, + "SysPipe2": 4328, + "SysEpollCtl": 4249, + "SysEpollPwait": 4313, + "SysGetRandom": 4353, + "SysUname": 4122, + "SysStat64": 4213, + "SysGetuid": 4024, + "SysGetgid": 4047, + "SysLlseek": 4140, + "SysMinCore": 4217, + "SysTgkill": 4266, + "SysMunmap": 4091, + "SysSetITimer": 4104, + "SysTimerCreate": 4257, + "SysTimerSetTime": 4258, + "SysTimerDelete": 4261, +} + +func TestEVM_NoopSyscall(t *testing.T) { + var tracer *tracing.Hooks + for noopName, noopVal := range NoopSyscalls { + t.Run(noopName, func(t *testing.T) { + goVm, state, contracts := setup(t, int(noopVal), nil) + + state.Memory.SetMemory(state.GetPC(), syscallInsn) + state.GetRegistersRef()[2] = noopVal // Set syscall number + step := state.Step + + // Set up post-state expectations + expected := mttestutil.NewExpectedMTState(state) + expected.ExpectStep() + expected.ActiveThread().Registers[2] = 0 + expected.ActiveThread().Registers[7] = 0 + + // State transition + var err error + var stepWitness *mipsevm.StepWitness + stepWitness, err = goVm.Step(true) + require.NoError(t, err) + + // Validate post-state + expected.Validate(t, state) + testutil.ValidateEVM(t, stepWitness, step, goVm, multithreaded.GetStateHashFn(), contracts, tracer) + }) + + } +} + +func TestEVM_UnsupportedSyscall(t *testing.T) { + t.Parallel() + var tracer *tracing.Hooks + + var NoopSyscallNums = maps.Values(NoopSyscalls) + var SupportedSyscalls = []uint32{exec.SysMmap, exec.SysBrk, exec.SysClone, exec.SysExitGroup, exec.SysRead, exec.SysWrite, exec.SysFcntl, exec.SysExit, exec.SysSchedYield, exec.SysGetTID, exec.SysFutex, exec.SysOpen, exec.SysNanosleep, exec.SysClockGetTime, exec.SysGetpid} + unsupportedSyscalls := make([]uint32, 0, 400) + for i := 4000; i < 4400; i++ { + candidate := uint32(i) + if slices.Contains(SupportedSyscalls, candidate) || slices.Contains(NoopSyscallNums, candidate) { + continue + } + unsupportedSyscalls = append(unsupportedSyscalls, candidate) + } + + for i, syscallNum := range unsupportedSyscalls { + testName := fmt.Sprintf("Unsupported syscallNum %v", syscallNum) + i := i + syscallNum := syscallNum + t.Run(testName, func(t *testing.T) { + t.Parallel() + goVm, state, contracts := setup(t, i*3434, nil) + // Setup basic getThreadId syscall instruction + state.Memory.SetMemory(state.GetPC(), syscallInsn) + state.GetRegistersRef()[2] = syscallNum + + // Set up post-state expectations + require.Panics(t, func() { _, _ = goVm.Step(true) }) + testutil.AssertEVMReverts(t, state, contracts, tracer) + }) + } +} + +func TestEVM_NormalTraversalStep_HandleWaitingThread(t *testing.T) { + var tracer *tracing.Hooks + cases := []struct { + name string + step uint64 + activeStackSize int + otherStackSize int + futexAddr uint32 + targetValue uint32 + actualValue uint32 + timeoutStep uint64 + shouldWakeup bool + shouldTimeout bool + }{ + {name: "Preempt, no timeout #1", step: 100, activeStackSize: 1, otherStackSize: 0, futexAddr: 0x100, targetValue: 0x01, actualValue: 0x01, timeoutStep: exec.FutexNoTimeout}, + {name: "Preempt, no timeout #2", step: 100, activeStackSize: 1, otherStackSize: 1, futexAddr: 0x100, targetValue: 0x01, actualValue: 0x01, timeoutStep: exec.FutexNoTimeout}, + {name: "Preempt, no timeout #3", step: 100, activeStackSize: 2, otherStackSize: 1, futexAddr: 0x100, targetValue: 0x01, actualValue: 0x01, timeoutStep: exec.FutexNoTimeout}, + {name: "Preempt, no timeout, unaligned", step: 100, activeStackSize: 2, otherStackSize: 1, futexAddr: 0x101, targetValue: 0x01, actualValue: 0x01, timeoutStep: exec.FutexNoTimeout}, + {name: "Preempt, with timeout #1", step: 100, activeStackSize: 2, otherStackSize: 1, futexAddr: 0x100, targetValue: 0x01, actualValue: 0x01, timeoutStep: 101}, + {name: "Preempt, with timeout #2", step: 100, activeStackSize: 1, otherStackSize: 1, futexAddr: 0x100, targetValue: 0x01, actualValue: 0x01, timeoutStep: 150}, + {name: "Preempt, with timeout, unaligned", step: 100, activeStackSize: 1, otherStackSize: 1, futexAddr: 0x101, targetValue: 0x01, actualValue: 0x01, timeoutStep: 150}, + {name: "Wakeup, no timeout #1", step: 100, activeStackSize: 1, otherStackSize: 0, futexAddr: 0x100, targetValue: 0x01, actualValue: 0x02, timeoutStep: exec.FutexNoTimeout, shouldWakeup: true}, + {name: "Wakeup, no timeout #2", step: 100, activeStackSize: 2, otherStackSize: 1, futexAddr: 0x100, targetValue: 0x01, actualValue: 0x02, timeoutStep: exec.FutexNoTimeout, shouldWakeup: true}, + {name: "Wakeup, no timeout, unaligned", step: 100, activeStackSize: 2, otherStackSize: 1, futexAddr: 0x102, targetValue: 0x01, actualValue: 0x02, timeoutStep: exec.FutexNoTimeout, shouldWakeup: true}, + {name: "Wakeup with timeout #1", step: 100, activeStackSize: 2, otherStackSize: 1, futexAddr: 0x100, targetValue: 0x01, actualValue: 0x02, timeoutStep: 100, shouldWakeup: true, shouldTimeout: true}, + {name: "Wakeup with timeout #2", step: 100, activeStackSize: 2, otherStackSize: 1, futexAddr: 0x100, targetValue: 0x02, actualValue: 0x02, timeoutStep: 100, shouldWakeup: true, shouldTimeout: true}, + {name: "Wakeup with timeout #3", step: 100, activeStackSize: 2, otherStackSize: 1, futexAddr: 0x100, targetValue: 0x02, actualValue: 0x02, timeoutStep: 50, shouldWakeup: true, shouldTimeout: true}, + {name: "Wakeup with timeout, unaligned", step: 100, activeStackSize: 2, otherStackSize: 1, futexAddr: 0x103, targetValue: 0x02, actualValue: 0x02, timeoutStep: 50, shouldWakeup: true, shouldTimeout: true}, + } + + for _, c := range cases { + for i, traverseRight := range []bool{true, false} { + testName := fmt.Sprintf("%v (traverseRight=%v)", c.name, traverseRight) + t.Run(testName, func(t *testing.T) { + // Sanity check + if !c.shouldWakeup && c.shouldTimeout { + require.Fail(t, "Invalid test case - cannot expect a timeout with no wakeup") + } + effAddr := c.futexAddr & 0xFF_FF_FF_Fc + goVm, state, contracts := setup(t, i, nil) + mttestutil.SetupThreads(int64(i*101), state, traverseRight, c.activeStackSize, c.otherStackSize) + state.Step = c.step + + activeThread := state.GetCurrentThread() + activeThread.FutexAddr = c.futexAddr + activeThread.FutexVal = c.targetValue + activeThread.FutexTimeoutStep = c.timeoutStep + state.GetMemory().SetMemory(effAddr, c.actualValue) + + // Set up post-state expectations + expected := mttestutil.NewExpectedMTState(state) + expected.Step += 1 + if c.shouldWakeup { + expected.ActiveThread().FutexAddr = exec.FutexEmptyAddr + expected.ActiveThread().FutexVal = 0 + expected.ActiveThread().FutexTimeoutStep = 0 + // PC and return registers are updated onWaitComplete + expected.ActiveThread().PC = state.GetCpu().NextPC + expected.ActiveThread().NextPC = state.GetCpu().NextPC + 4 + if c.shouldTimeout { + expected.ActiveThread().Registers[2] = exec.SysErrorSignal + expected.ActiveThread().Registers[7] = exec.MipsETIMEDOUT + } else { + expected.ActiveThread().Registers[2] = 0 + expected.ActiveThread().Registers[7] = 0 + } + } else { + expected.ExpectPreemption(state) + } + + // State transition + var err error + var stepWitness *mipsevm.StepWitness + stepWitness, err = goVm.Step(true) + require.NoError(t, err) + + // Validate post-state + expected.Validate(t, state) + testutil.ValidateEVM(t, stepWitness, c.step, goVm, multithreaded.GetStateHashFn(), contracts, tracer) + }) + + } + } +} + +func TestEVM_NormalTraversal_Full(t *testing.T) { + var tracer *tracing.Hooks + cases := []struct { + name string + threadCount int + }{ + {"1 thread", 1}, + {"2 threads", 2}, + {"3 threads", 3}, + } + + for i, c := range cases { + for _, traverseRight := range []bool{true, false} { + testName := fmt.Sprintf("%v (traverseRight = %v)", c.name, traverseRight) + t.Run(testName, func(t *testing.T) { + // Setup + goVm, state, contracts := setup(t, i*789, nil) + mttestutil.SetupThreads(int64(i*2947), state, traverseRight, c.threadCount, 0) + // Put threads into a waiting state so that we just traverse through them + for _, thread := range mttestutil.GetAllThreads(state) { + thread.FutexAddr = 0x04 + thread.FutexTimeoutStep = exec.FutexNoTimeout + } + step := state.Step + + initialState := mttestutil.NewExpectedMTState(state) + + // Loop through all the threads to get back to the starting state + iterations := c.threadCount * 2 + for i := 0; i < iterations; i++ { + // Set up post-state expectations + expected := mttestutil.NewExpectedMTState(state) + expected.Step += 1 + expected.ExpectPreemption(state) + + // State transition + var err error + var stepWitness *mipsevm.StepWitness + stepWitness, err = goVm.Step(true) + require.NoError(t, err) + + // Validate post-state + expected.Validate(t, state) + testutil.ValidateEVM(t, stepWitness, step, goVm, multithreaded.GetStateHashFn(), contracts, tracer) + } + + // We should be back to the original state with only a few modifications + initialState.Step += uint64(iterations) + initialState.StepsSinceLastContextSwitch = 0 + initialState.Validate(t, state) + }) + } + } +} + +func TestEVM_WakeupTraversalStep(t *testing.T) { + addr := uint32(0x1234) + wakeupVal := uint32(0x999) + var tracer *tracing.Hooks + cases := []struct { + name string + wakeupAddr uint32 + futexAddr uint32 + targetVal uint32 + traverseRight bool + activeStackSize int + otherStackSize int + shouldClearWakeup bool + shouldPreempt bool + }{ + {name: "Matching addr, not wakeable, first thread", wakeupAddr: addr, futexAddr: addr, targetVal: wakeupVal, traverseRight: false, activeStackSize: 3, otherStackSize: 0, shouldClearWakeup: true}, + {name: "Matching addr, wakeable, first thread", wakeupAddr: addr, futexAddr: addr, targetVal: wakeupVal + 1, traverseRight: false, activeStackSize: 3, otherStackSize: 0, shouldClearWakeup: true}, + {name: "Matching addr, not wakeable, last thread", wakeupAddr: addr, futexAddr: addr, targetVal: wakeupVal, traverseRight: true, activeStackSize: 1, otherStackSize: 2, shouldClearWakeup: true}, + {name: "Matching addr, wakeable, last thread", wakeupAddr: addr, futexAddr: addr, targetVal: wakeupVal + 1, traverseRight: true, activeStackSize: 1, otherStackSize: 2, shouldClearWakeup: true}, + {name: "Matching addr, not wakeable, intermediate thread", wakeupAddr: addr, futexAddr: addr, targetVal: wakeupVal, traverseRight: false, activeStackSize: 2, otherStackSize: 2, shouldClearWakeup: true}, + {name: "Matching addr, wakeable, intermediate thread", wakeupAddr: addr, futexAddr: addr, targetVal: wakeupVal + 1, traverseRight: true, activeStackSize: 2, otherStackSize: 2, shouldClearWakeup: true}, + {name: "Mismatched addr, last thread", wakeupAddr: addr, futexAddr: addr + 4, traverseRight: true, activeStackSize: 1, otherStackSize: 2, shouldPreempt: true, shouldClearWakeup: true}, + {name: "Mismatched addr", wakeupAddr: addr, futexAddr: addr + 4, traverseRight: true, activeStackSize: 2, otherStackSize: 2, shouldPreempt: true}, + {name: "Mismatched addr", wakeupAddr: addr, futexAddr: addr + 4, traverseRight: false, activeStackSize: 2, otherStackSize: 0, shouldPreempt: true}, + {name: "Mismatched addr", wakeupAddr: addr, futexAddr: addr + 4, traverseRight: false, activeStackSize: 1, otherStackSize: 0, shouldPreempt: true}, + {name: "Non-waiting thread", wakeupAddr: addr, futexAddr: exec.FutexEmptyAddr, traverseRight: false, activeStackSize: 1, otherStackSize: 0, shouldPreempt: true}, + {name: "Non-waiting thread", wakeupAddr: addr, futexAddr: exec.FutexEmptyAddr, traverseRight: true, activeStackSize: 2, otherStackSize: 1, shouldPreempt: true}, + {name: "Non-waiting thread, last thread", wakeupAddr: addr, futexAddr: exec.FutexEmptyAddr, traverseRight: true, activeStackSize: 1, otherStackSize: 1, shouldPreempt: true, shouldClearWakeup: true}, + // Check behavior of unaligned addresses - should be the same as aligned addresses (no memory access) + {name: "Matching addr, unaligned", wakeupAddr: addr + 1, futexAddr: addr + 1, targetVal: wakeupVal, traverseRight: false, activeStackSize: 3, otherStackSize: 0, shouldClearWakeup: true}, + {name: "Mismatched addr, last thread, wakeup unaligned", wakeupAddr: addr + 1, futexAddr: addr + 4, traverseRight: true, activeStackSize: 1, otherStackSize: 2, shouldPreempt: true, shouldClearWakeup: true}, + {name: "Mismatched addr, last thread, futex unaligned", wakeupAddr: addr, futexAddr: addr + 5, traverseRight: true, activeStackSize: 1, otherStackSize: 2, shouldPreempt: true, shouldClearWakeup: true}, + {name: "Mismatched addr, last thread, wake & futex unaligned", wakeupAddr: addr + 1, futexAddr: addr + 5, traverseRight: true, activeStackSize: 1, otherStackSize: 2, shouldPreempt: true, shouldClearWakeup: true}, + {name: "Mismatched addr, wakeup unaligned", wakeupAddr: addr + 3, futexAddr: addr + 4, traverseRight: true, activeStackSize: 2, otherStackSize: 2, shouldPreempt: true}, + {name: "Mismatched addr, futex unaligned", wakeupAddr: addr, futexAddr: addr + 6, traverseRight: true, activeStackSize: 2, otherStackSize: 2, shouldPreempt: true}, + {name: "Mismatched addr, wakeup & futex unaligned", wakeupAddr: addr + 2, futexAddr: addr + 6, traverseRight: true, activeStackSize: 2, otherStackSize: 2, shouldPreempt: true}, + {name: "Non-waiting thread, last thread, unaligned wakeup", wakeupAddr: addr + 3, futexAddr: exec.FutexEmptyAddr, traverseRight: true, activeStackSize: 1, otherStackSize: 1, shouldPreempt: true, shouldClearWakeup: true}, + } + + for i, c := range cases { + t.Run(c.name, func(t *testing.T) { + goVm, state, contracts := setup(t, i*2000, nil) + mttestutil.SetupThreads(int64(i*101), state, c.traverseRight, c.activeStackSize, c.otherStackSize) + step := state.Step + + state.Wakeup = c.wakeupAddr + state.GetMemory().SetMemory(c.wakeupAddr&0xFF_FF_FF_FC, wakeupVal) + activeThread := state.GetCurrentThread() + activeThread.FutexAddr = c.futexAddr + activeThread.FutexVal = c.targetVal + activeThread.FutexTimeoutStep = exec.FutexNoTimeout + + // Set up post-state expectations + expected := mttestutil.NewExpectedMTState(state) + expected.Step += 1 + if c.shouldClearWakeup { + expected.Wakeup = exec.FutexEmptyAddr + } + if c.shouldPreempt { + // Just preempt the current thread + expected.ExpectPreemption(state) + } + + // State transition + var err error + var stepWitness *mipsevm.StepWitness + stepWitness, err = goVm.Step(true) + require.NoError(t, err) + + // Validate post-state + expected.Validate(t, state) + testutil.ValidateEVM(t, stepWitness, step, goVm, multithreaded.GetStateHashFn(), contracts, tracer) + }) + } +} + +func TestEVM_WakeupTraversal_Full(t *testing.T) { + var tracer *tracing.Hooks + cases := []struct { + name string + threadCount int + }{ + {"1 thread", 1}, + {"2 threads", 2}, + {"3 threads", 3}, + } + for i, c := range cases { + t.Run(c.name, func(t *testing.T) { + // Setup + goVm, state, contracts := setup(t, i*789, nil) + mttestutil.SetupThreads(int64(i*2947), state, false, c.threadCount, 0) + state.Wakeup = 0x08 + step := state.Step + + initialState := mttestutil.NewExpectedMTState(state) + + // Loop through all the threads to get back to the starting state + iterations := c.threadCount * 2 + for i := 0; i < iterations; i++ { + // Set up post-state expectations + expected := mttestutil.NewExpectedMTState(state) + expected.Step += 1 + expected.ExpectPreemption(state) + + // State transition + var err error + var stepWitness *mipsevm.StepWitness + stepWitness, err = goVm.Step(true) + require.NoError(t, err) + + // We should clear the wakeup on the last step + if i == iterations-1 { + expected.Wakeup = exec.FutexEmptyAddr + } + + // Validate post-state + expected.Validate(t, state) + testutil.ValidateEVM(t, stepWitness, step, goVm, multithreaded.GetStateHashFn(), contracts, tracer) + } + + // We should be back to the original state with only a few modifications + initialState.Step += uint64(iterations) + initialState.StepsSinceLastContextSwitch = 0 + initialState.Wakeup = exec.FutexEmptyAddr + initialState.Validate(t, state) + }) + } +} + +func TestEVM_SchedQuantumThreshold(t *testing.T) { + var tracer *tracing.Hooks + cases := []struct { + name string + stepsSinceLastContextSwitch uint64 + shouldPreempt bool + }{ + {name: "just under threshold", stepsSinceLastContextSwitch: exec.SchedQuantum - 1}, + {name: "at threshold", stepsSinceLastContextSwitch: exec.SchedQuantum, shouldPreempt: true}, + {name: "beyond threshold", stepsSinceLastContextSwitch: exec.SchedQuantum + 1, shouldPreempt: true}, + } + + for i, c := range cases { + t.Run(c.name, func(t *testing.T) { + goVm, state, contracts := setup(t, i*789, nil) + // Setup basic getThreadId syscall instruction + state.Memory.SetMemory(state.GetPC(), syscallInsn) + state.GetRegistersRef()[2] = exec.SysGetTID // Set syscall number + state.StepsSinceLastContextSwitch = c.stepsSinceLastContextSwitch + step := state.Step + + // Set up post-state expectations + expected := mttestutil.NewExpectedMTState(state) + if c.shouldPreempt { + expected.Step += 1 + expected.ExpectPreemption(state) + } else { + // Otherwise just expect a normal step + expected.ExpectStep() + expected.ActiveThread().Registers[2] = state.GetCurrentThread().ThreadId + expected.ActiveThread().Registers[7] = 0 + } + + // State transition + var err error + var stepWitness *mipsevm.StepWitness + stepWitness, err = goVm.Step(true) + require.NoError(t, err) + + // Validate post-state + expected.Validate(t, state) + testutil.ValidateEVM(t, stepWitness, step, goVm, multithreaded.GetStateHashFn(), contracts, tracer) + }) + } +} + +func setup(t require.TestingT, randomSeed int, preimageOracle mipsevm.PreimageOracle) (mipsevm.FPVM, *multithreaded.State, *testutil.ContractMetadata) { + v := GetMultiThreadedTestCase(t) + vm := v.VMFactory(preimageOracle, os.Stdout, os.Stderr, testutil.CreateLogger(), testutil.WithRandomization(int64(randomSeed))) + state := mttestutil.GetMtState(t, vm) + + return vm, state, v.Contracts + +} diff --git a/cannon/mipsevm/tests/evm_singlethreaded_test.go b/cannon/mipsevm/tests/evm_singlethreaded_test.go new file mode 100644 index 0000000000000..32cad32cc00e2 --- /dev/null +++ b/cannon/mipsevm/tests/evm_singlethreaded_test.go @@ -0,0 +1,196 @@ +package tests + +import ( + "encoding/binary" + "os" + "testing" + + "github.com/ethereum/go-ethereum/core/tracing" + "github.com/ethereum/go-ethereum/crypto" + "github.com/stretchr/testify/require" + + "github.com/ethereum-optimism/optimism/cannon/mipsevm/exec" + "github.com/ethereum-optimism/optimism/cannon/mipsevm/memory" + "github.com/ethereum-optimism/optimism/cannon/mipsevm/testutil" + preimage "github.com/ethereum-optimism/optimism/op-preimage" +) + +func TestEVM_LL(t *testing.T) { + var tracer *tracing.Hooks + + cases := []struct { + name string + base uint32 + offset int + value uint32 + effAddr uint32 + rtReg int + }{ + {name: "Aligned effAddr", base: 0x00_00_00_01, offset: 0x0133, value: 0xABCD, effAddr: 0x00_00_01_34, rtReg: 5}, + {name: "Aligned effAddr, signed extended", base: 0x00_00_00_01, offset: 0xFF33, value: 0xABCD, effAddr: 0xFF_FF_FF_34, rtReg: 5}, + {name: "Unaligned effAddr", base: 0xFF_12_00_01, offset: 0x3401, value: 0xABCD, effAddr: 0xFF_12_34_00, rtReg: 5}, + {name: "Unaligned effAddr, sign extended w overflow", base: 0xFF_12_00_01, offset: 0x8401, value: 0xABCD, effAddr: 0xFF_11_84_00, rtReg: 5}, + {name: "Return register set to 0", base: 0x00_00_00_01, offset: 0x0133, value: 0xABCD, effAddr: 0x00_00_01_34, rtReg: 0}, + } + v := GetSingleThreadedTestCase(t) + for i, c := range cases { + t.Run(c.name, func(t *testing.T) { + rtReg := c.rtReg + baseReg := 6 + pc := uint32(0x44) + insn := uint32((0b11_0000 << 26) | (baseReg & 0x1F << 21) | (rtReg & 0x1F << 16) | (0xFFFF & c.offset)) + goVm := v.VMFactory(nil, os.Stdout, os.Stderr, testutil.CreateLogger(), testutil.WithRandomization(int64(i)), testutil.WithPC(pc), testutil.WithNextPC(pc+4)) + state := goVm.GetState() + state.GetMemory().SetMemory(pc, insn) + state.GetMemory().SetMemory(c.effAddr, c.value) + state.GetRegistersRef()[baseReg] = c.base + step := state.GetStep() + + // Setup expectations + expected := testutil.NewExpectedState(state) + expected.Step += 1 + expected.PC = pc + 4 + expected.NextPC = pc + 8 + if rtReg != 0 { + expected.Registers[rtReg] = c.value + } + + stepWitness, err := goVm.Step(true) + require.NoError(t, err) + + // Check expectations + expected.Validate(t, state) + testutil.ValidateEVM(t, stepWitness, step, goVm, v.StateHashFn, v.Contracts, tracer) + }) + } +} + +func TestEVM_SC(t *testing.T) { + var tracer *tracing.Hooks + + cases := []struct { + name string + base uint32 + offset int + value uint32 + effAddr uint32 + rtReg int + }{ + {name: "Aligned effAddr", base: 0x00_00_00_01, offset: 0x0133, value: 0xABCD, effAddr: 0x00_00_01_34, rtReg: 5}, + {name: "Aligned effAddr, signed extended", base: 0x00_00_00_01, offset: 0xFF33, value: 0xABCD, effAddr: 0xFF_FF_FF_34, rtReg: 5}, + {name: "Unaligned effAddr", base: 0xFF_12_00_01, offset: 0x3401, value: 0xABCD, effAddr: 0xFF_12_34_00, rtReg: 5}, + {name: "Unaligned effAddr, sign extended w overflow", base: 0xFF_12_00_01, offset: 0x8401, value: 0xABCD, effAddr: 0xFF_11_84_00, rtReg: 5}, + {name: "Return register set to 0", base: 0xFF_12_00_01, offset: 0x8401, value: 0xABCD, effAddr: 0xFF_11_84_00, rtReg: 0}, + } + v := GetSingleThreadedTestCase(t) + for i, c := range cases { + t.Run(c.name, func(t *testing.T) { + rtReg := c.rtReg + baseReg := 6 + pc := uint32(0x44) + insn := uint32((0b11_1000 << 26) | (baseReg & 0x1F << 21) | (rtReg & 0x1F << 16) | (0xFFFF & c.offset)) + goVm := v.VMFactory(nil, os.Stdout, os.Stderr, testutil.CreateLogger(), testutil.WithRandomization(int64(i)), testutil.WithPC(pc), testutil.WithNextPC(pc+4)) + state := goVm.GetState() + state.GetMemory().SetMemory(pc, insn) + state.GetRegistersRef()[baseReg] = c.base + state.GetRegistersRef()[rtReg] = c.value + step := state.GetStep() + + // Setup expectations + expected := testutil.NewExpectedState(state) + expected.Step += 1 + expected.PC = pc + 4 + expected.NextPC = pc + 8 + expectedMemory := memory.NewMemory() + expectedMemory.SetMemory(pc, insn) + expectedMemory.SetMemory(c.effAddr, c.value) + expected.MemoryRoot = expectedMemory.MerkleRoot() + if rtReg != 0 { + expected.Registers[rtReg] = 1 // 1 for success + } + + stepWitness, err := goVm.Step(true) + require.NoError(t, err) + + // Check expectations + expected.Validate(t, state) + testutil.ValidateEVM(t, stepWitness, step, goVm, v.StateHashFn, v.Contracts, tracer) + }) + } +} + +func TestEVM_SysRead_Preimage(t *testing.T) { + var tracer *tracing.Hooks + + preimageValue := make([]byte, 0, 8) + preimageValue = binary.BigEndian.AppendUint32(preimageValue, 0x12_34_56_78) + preimageValue = binary.BigEndian.AppendUint32(preimageValue, 0x98_76_54_32) + + v := GetSingleThreadedTestCase(t) + + cases := []struct { + name string + addr uint32 + count uint32 + writeLen uint32 + preimageOffset uint32 + prestateMem uint32 + postateMem uint32 + shouldPanic bool + }{ + {name: "Aligned addr, write 1 byte", addr: 0x00_00_FF_00, count: 1, writeLen: 1, preimageOffset: 8, prestateMem: 0xFF_FF_FF_FF, postateMem: 0x12_FF_FF_FF}, + {name: "Aligned addr, write 2 byte", addr: 0x00_00_FF_00, count: 2, writeLen: 2, preimageOffset: 8, prestateMem: 0xFF_FF_FF_FF, postateMem: 0x12_34_FF_FF}, + {name: "Aligned addr, write 3 byte", addr: 0x00_00_FF_00, count: 3, writeLen: 3, preimageOffset: 8, prestateMem: 0xFF_FF_FF_FF, postateMem: 0x12_34_56_FF}, + {name: "Aligned addr, write 4 byte", addr: 0x00_00_FF_00, count: 4, writeLen: 4, preimageOffset: 8, prestateMem: 0xFF_FF_FF_FF, postateMem: 0x12_34_56_78}, + {name: "1-byte misaligned addr, write 1 byte", addr: 0x00_00_FF_01, count: 1, writeLen: 1, preimageOffset: 8, prestateMem: 0xFF_FF_FF_FF, postateMem: 0xFF_12_FF_FF}, + {name: "1-byte misaligned addr, write 2 byte", addr: 0x00_00_FF_01, count: 2, writeLen: 2, preimageOffset: 9, prestateMem: 0xFF_FF_FF_FF, postateMem: 0xFF_34_56_FF}, + {name: "1-byte misaligned addr, write 3 byte", addr: 0x00_00_FF_01, count: 3, writeLen: 3, preimageOffset: 8, prestateMem: 0xFF_FF_FF_FF, postateMem: 0xFF_12_34_56}, + {name: "2-byte misaligned addr, write 1 byte", addr: 0x00_00_FF_02, count: 1, writeLen: 1, preimageOffset: 8, prestateMem: 0xFF_FF_FF_FF, postateMem: 0xFF_FF_12_FF}, + {name: "2-byte misaligned addr, write 2 byte", addr: 0x00_00_FF_02, count: 2, writeLen: 2, preimageOffset: 12, prestateMem: 0xFF_FF_FF_FF, postateMem: 0xFF_FF_98_76}, + {name: "3-byte misaligned addr, write 1 byte", addr: 0x00_00_FF_03, count: 1, writeLen: 1, preimageOffset: 8, prestateMem: 0xFF_FF_FF_FF, postateMem: 0xFF_FF_FF_12}, + {name: "Count of 0", addr: 0x00_00_FF_03, count: 0, writeLen: 0, preimageOffset: 8, prestateMem: 0xFF_FF_FF_FF, postateMem: 0xFF_FF_FF_FF}, + {name: "Count greater than 4", addr: 0x00_00_FF_00, count: 15, writeLen: 4, preimageOffset: 8, prestateMem: 0xFF_FF_FF_FF, postateMem: 0x12_34_56_78}, + {name: "Count greater than 4, unaligned", addr: 0x00_00_FF_01, count: 15, writeLen: 3, preimageOffset: 8, prestateMem: 0xFF_FF_FF_FF, postateMem: 0xFF_12_34_56}, + {name: "Offset at last byte", addr: 0x00_00_FF_00, count: 4, writeLen: 1, preimageOffset: 15, prestateMem: 0xFF_FF_FF_FF, postateMem: 0x32_FF_FF_FF}, + {name: "Offset just out of bounds", addr: 0x00_00_FF_00, count: 4, writeLen: 0, preimageOffset: 16, prestateMem: 0xFF_FF_FF_FF, postateMem: 0xFF_FF_FF_FF, shouldPanic: true}, + {name: "Offset out of bounds", addr: 0x00_00_FF_00, count: 4, writeLen: 0, preimageOffset: 17, prestateMem: 0xFF_FF_FF_FF, postateMem: 0xFF_FF_FF_FF, shouldPanic: true}, + } + for i, c := range cases { + t.Run(c.name, func(t *testing.T) { + effAddr := 0xFFffFFfc & c.addr + preimageKey := preimage.Keccak256Key(crypto.Keccak256Hash(preimageValue)).PreimageKey() + oracle := testutil.StaticOracle(t, preimageValue) + goVm := v.VMFactory(oracle, os.Stdout, os.Stderr, testutil.CreateLogger(), testutil.WithRandomization(int64(i)), testutil.WithPreimageKey(preimageKey), testutil.WithPreimageOffset(c.preimageOffset)) + state := goVm.GetState() + step := state.GetStep() + + // Set up state + state.GetRegistersRef()[2] = exec.SysRead + state.GetRegistersRef()[4] = exec.FdPreimageRead + state.GetRegistersRef()[5] = c.addr + state.GetRegistersRef()[6] = c.count + state.GetMemory().SetMemory(state.GetPC(), syscallInsn) + state.GetMemory().SetMemory(effAddr, c.prestateMem) + + // Setup expectations + expected := testutil.NewExpectedState(state) + expected.ExpectStep() + expected.Registers[2] = c.writeLen + expected.Registers[7] = 0 // no error + expected.PreimageOffset += c.writeLen + expected.ExpectMemoryWrite(effAddr, c.postateMem) + + if c.shouldPanic { + require.Panics(t, func() { _, _ = goVm.Step(true) }) + testutil.AssertPreimageOracleReverts(t, preimageKey, preimageValue, c.preimageOffset, v.Contracts, tracer) + } else { + stepWitness, err := goVm.Step(true) + require.NoError(t, err) + + // Check expectations + expected.Validate(t, state) + testutil.ValidateEVM(t, stepWitness, step, goVm, v.StateHashFn, v.Contracts, tracer) + } + }) + } +} diff --git a/cannon/mipsevm/tests/fuzz_evm_common_test.go b/cannon/mipsevm/tests/fuzz_evm_common_test.go index e96aa54d0aa44..2b85727679b17 100644 --- a/cannon/mipsevm/tests/fuzz_evm_common_test.go +++ b/cannon/mipsevm/tests/fuzz_evm_common_test.go @@ -2,11 +2,11 @@ package tests import ( "bytes" + "encoding/binary" + "math" "os" "testing" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/crypto" "github.com/stretchr/testify/require" @@ -30,7 +30,7 @@ func FuzzStateSyscallBrk(f *testing.F) { state.GetMemory().SetMemory(state.GetPC(), syscallInsn) step := state.GetStep() - expected := testutil.CreateExpectedState(state) + expected := testutil.NewExpectedState(state) expected.Step += 1 expected.PC = state.GetCpu().NextPC expected.NextPC = state.GetCpu().NextPC + 4 @@ -42,12 +42,7 @@ func FuzzStateSyscallBrk(f *testing.F) { require.False(t, stepWitness.HasPreimage()) expected.Validate(t, state) - - evm := testutil.NewMIPSEVM(v.Contracts) - evmPost := evm.Step(t, stepWitness, step, v.StateHashFn) - goPost, _ := goVm.GetState().EncodeWitness() - require.Equal(t, hexutil.Bytes(goPost).String(), hexutil.Bytes(evmPost).String(), - "mipsevm produced different state than EVM") + testutil.ValidateEVM(t, stepWitness, step, goVm, v.StateHashFn, v.Contracts, nil) }) } }) @@ -74,7 +69,7 @@ func FuzzStateSyscallMmap(f *testing.F) { state.GetRegistersRef()[5] = siz state.GetMemory().SetMemory(state.GetPC(), syscallInsn) - expected := testutil.CreateExpectedState(state) + expected := testutil.NewExpectedState(state) expected.Step += 1 expected.PC = state.GetCpu().NextPC expected.NextPC = state.GetCpu().NextPC + 4 @@ -102,12 +97,7 @@ func FuzzStateSyscallMmap(f *testing.F) { require.False(t, stepWitness.HasPreimage()) expected.Validate(t, state) - - evm := testutil.NewMIPSEVM(v.Contracts) - evmPost := evm.Step(t, stepWitness, step, v.StateHashFn) - goPost, _ := goVm.GetState().EncodeWitness() - require.Equal(t, hexutil.Bytes(goPost).String(), hexutil.Bytes(evmPost).String(), - "mipsevm produced different state than EVM") + testutil.ValidateEVM(t, stepWitness, step, goVm, v.StateHashFn, v.Contracts, nil) }) } }) @@ -126,7 +116,7 @@ func FuzzStateSyscallExitGroup(f *testing.F) { state.GetMemory().SetMemory(state.GetPC(), syscallInsn) step := state.GetStep() - expected := testutil.CreateExpectedState(state) + expected := testutil.NewExpectedState(state) expected.Step += 1 expected.Exited = true expected.ExitCode = exitCode @@ -136,12 +126,7 @@ func FuzzStateSyscallExitGroup(f *testing.F) { require.False(t, stepWitness.HasPreimage()) expected.Validate(t, state) - - evm := testutil.NewMIPSEVM(v.Contracts) - evmPost := evm.Step(t, stepWitness, step, v.StateHashFn) - goPost, _ := goVm.GetState().EncodeWitness() - require.Equal(t, hexutil.Bytes(goPost).String(), hexutil.Bytes(evmPost).String(), - "mipsevm produced different state than EVM") + testutil.ValidateEVM(t, stepWitness, step, goVm, v.StateHashFn, v.Contracts, nil) }) } }) @@ -161,7 +146,7 @@ func FuzzStateSyscallFcntl(f *testing.F) { state.GetMemory().SetMemory(state.GetPC(), syscallInsn) step := state.GetStep() - expected := testutil.CreateExpectedState(state) + expected := testutil.NewExpectedState(state) expected.Step += 1 expected.PC = state.GetCpu().NextPC expected.NextPC = state.GetCpu().NextPC + 4 @@ -187,12 +172,7 @@ func FuzzStateSyscallFcntl(f *testing.F) { require.False(t, stepWitness.HasPreimage()) expected.Validate(t, state) - - evm := testutil.NewMIPSEVM(v.Contracts) - evmPost := evm.Step(t, stepWitness, step, v.StateHashFn) - goPost, _ := goVm.GetState().EncodeWitness() - require.Equal(t, hexutil.Bytes(goPost).String(), hexutil.Bytes(evmPost).String(), - "mipsevm produced different state than EVM") + testutil.ValidateEVM(t, stepWitness, step, goVm, v.StateHashFn, v.Contracts, nil) }) } }) @@ -217,7 +197,7 @@ func FuzzStateHintRead(f *testing.F) { state.GetMemory().SetMemory(state.GetPC(), syscallInsn) step := state.GetStep() - expected := testutil.CreateExpectedState(state) + expected := testutil.NewExpectedState(state) expected.Step += 1 expected.PC = state.GetCpu().NextPC expected.NextPC = state.GetCpu().NextPC + 4 @@ -229,12 +209,7 @@ func FuzzStateHintRead(f *testing.F) { require.False(t, stepWitness.HasPreimage()) expected.Validate(t, state) - - evm := testutil.NewMIPSEVM(v.Contracts) - evmPost := evm.Step(t, stepWitness, step, v.StateHashFn) - goPost, _ := goVm.GetState().EncodeWitness() - require.Equal(t, hexutil.Bytes(goPost).String(), hexutil.Bytes(evmPost).String(), - "mipsevm produced different state than EVM") + testutil.ValidateEVM(t, stepWitness, step, goVm, v.StateHashFn, v.Contracts, nil) }) } }) @@ -242,24 +217,29 @@ func FuzzStateHintRead(f *testing.F) { func FuzzStatePreimageRead(f *testing.F) { versions := GetMipsVersionTestCases(f) - f.Fuzz(func(t *testing.T, addr uint32, count uint32, preimageOffset uint32, seed int64) { + f.Fuzz(func(t *testing.T, addr uint32, pc uint32, count uint32, preimageOffset uint32, seed int64) { for _, v := range versions { t.Run(v.Name, func(t *testing.T) { + effAddr := addr & 0xFF_FF_FF_FC + pc = pc & 0xFF_FF_FF_FC + preexistingMemoryVal := [4]byte{0xFF, 0xFF, 0xFF, 0xFF} preimageValue := []byte("hello world") - if preimageOffset >= uint32(len(preimageValue)) { + preimageData := testutil.AddPreimageLengthPrefix(preimageValue) + if preimageOffset >= uint32(len(preimageData)) || pc == effAddr { t.SkipNow() } preimageKey := preimage.Keccak256Key(crypto.Keccak256Hash(preimageValue)).PreimageKey() oracle := testutil.StaticOracle(t, preimageValue) goVm := v.VMFactory(oracle, os.Stdout, os.Stderr, testutil.CreateLogger(), - testutil.WithRandomization(seed), testutil.WithPreimageKey(preimageKey), testutil.WithPreimageOffset(preimageOffset)) + testutil.WithRandomization(seed), testutil.WithPreimageKey(preimageKey), testutil.WithPreimageOffset(preimageOffset), testutil.WithPCAndNextPC(pc)) state := goVm.GetState() state.GetRegistersRef()[2] = exec.SysRead state.GetRegistersRef()[4] = exec.FdPreimageRead state.GetRegistersRef()[5] = addr state.GetRegistersRef()[6] = count state.GetMemory().SetMemory(state.GetPC(), syscallInsn) + state.GetMemory().SetMemory(effAddr, binary.BigEndian.Uint32(preexistingMemoryVal[:])) step := state.GetStep() alignment := addr & 3 @@ -268,36 +248,31 @@ func FuzzStatePreimageRead(f *testing.F) { writeLen = count } // Cap write length to remaining bytes of the preimage - preimageDataLen := uint32(len(preimageValue) + 8) // Data len includes a length prefix + preimageDataLen := uint32(len(preimageData)) if preimageOffset+writeLen > preimageDataLen { writeLen = preimageDataLen - preimageOffset } - expected := testutil.CreateExpectedState(state) + expected := testutil.NewExpectedState(state) expected.Step += 1 expected.PC = state.GetCpu().NextPC expected.NextPC = state.GetCpu().NextPC + 4 expected.Registers[2] = writeLen expected.Registers[7] = 0 // no error expected.PreimageOffset += writeLen + if writeLen > 0 { + // Expect a memory write + expectedMemory := preexistingMemoryVal + copy(expectedMemory[alignment:], preimageData[preimageOffset:preimageOffset+writeLen]) + expected.ExpectMemoryWrite(effAddr, binary.BigEndian.Uint32(expectedMemory[:])) + } stepWitness, err := goVm.Step(true) require.NoError(t, err) require.True(t, stepWitness.HasPreimage()) - // TODO(cp-983) - Do stricter validation of expected memory - expected.Validate(t, state, testutil.SkipMemoryValidation) - if writeLen == 0 { - // Note: We are not asserting a memory root change when writeLen > 0 because we may not necessarily - // modify memory - it's possible we just write the leading zero bytes of the length prefix - require.Equal(t, expected.MemoryRoot, common.Hash(state.GetMemory().MerkleRoot())) - } - - evm := testutil.NewMIPSEVM(v.Contracts) - evmPost := evm.Step(t, stepWitness, step, v.StateHashFn) - goPost, _ := goVm.GetState().EncodeWitness() - require.Equal(t, hexutil.Bytes(goPost).String(), hexutil.Bytes(evmPost).String(), - "mipsevm produced different state than EVM") + expected.Validate(t, state) + testutil.ValidateEVM(t, stepWitness, step, goVm, v.StateHashFn, v.Contracts, nil) }) } }) @@ -305,49 +280,81 @@ func FuzzStatePreimageRead(f *testing.F) { func FuzzStateHintWrite(f *testing.F) { versions := GetMipsVersionTestCases(f) - f.Fuzz(func(t *testing.T, addr uint32, count uint32, randSeed int64) { + f.Fuzz(func(t *testing.T, addr uint32, count uint32, hint1, hint2, hint3 []byte, randSeed int64) { for _, v := range versions { t.Run(v.Name, func(t *testing.T) { - preimageData := []byte("hello world") - preimageKey := preimage.Keccak256Key(crypto.Keccak256Hash(preimageData)).PreimageKey() - // TODO(cp-983) - use testutil.HintTrackingOracle, validate expected hints - oracle := testutil.StaticOracle(t, preimageData) // only used for hinting + // Make sure pc does not overlap with hint data in memory + pc := uint32(0) + if addr <= 8 { + addr += 8 + } + // Set up hint data + r := testutil.NewRandHelper(randSeed) + hints := [][]byte{hint1, hint2, hint3} + hintData := make([]byte, 0) + for _, hint := range hints { + prefixedHint := testutil.AddHintLengthPrefix(hint) + hintData = append(hintData, prefixedHint...) + } + lastHintLen := math.Round(r.Fraction() * float64(len(hintData))) + lastHint := hintData[:int(lastHintLen)] + expectedBytesToProcess := int(count) + int(lastHintLen) + if expectedBytesToProcess > len(hintData) { + // Add an extra hint to span the rest of the hint data + randomHint := r.RandomBytes(t, expectedBytesToProcess) + prefixedHint := testutil.AddHintLengthPrefix(randomHint) + hintData = append(hintData, prefixedHint...) + hints = append(hints, randomHint) + } + + // Set up state + oracle := &testutil.HintTrackingOracle{} goVm := v.VMFactory(oracle, os.Stdout, os.Stderr, testutil.CreateLogger(), - testutil.WithRandomization(randSeed), testutil.WithPreimageKey(preimageKey)) + testutil.WithRandomization(randSeed), testutil.WithLastHint(lastHint), testutil.WithPCAndNextPC(pc)) state := goVm.GetState() state.GetRegistersRef()[2] = exec.SysWrite state.GetRegistersRef()[4] = exec.FdHintWrite state.GetRegistersRef()[5] = addr state.GetRegistersRef()[6] = count step := state.GetStep() - - // Set random data at the target memory range - randBytes := testutil.RandomBytes(t, randSeed, count) - err := state.GetMemory().SetMemoryRange(addr, bytes.NewReader(randBytes)) + err := state.GetMemory().SetMemoryRange(addr, bytes.NewReader(hintData[int(lastHintLen):])) require.NoError(t, err) - // Set instruction state.GetMemory().SetMemory(state.GetPC(), syscallInsn) - expected := testutil.CreateExpectedState(state) + // Set up expectations + expected := testutil.NewExpectedState(state) expected.Step += 1 expected.PC = state.GetCpu().NextPC expected.NextPC = state.GetCpu().NextPC + 4 expected.Registers[2] = count expected.Registers[7] = 0 // no error + // Figure out hint expectations + var expectedHints [][]byte + expectedLastHint := make([]byte, 0) + byteIndex := 0 + for _, hint := range hints { + hintDataLength := len(hint) + 4 // Hint data + prefix + hintLastByteIndex := hintDataLength + byteIndex - 1 + if hintLastByteIndex < expectedBytesToProcess { + expectedHints = append(expectedHints, hint) + } else { + expectedLastHint = hintData[byteIndex:expectedBytesToProcess] + break + } + byteIndex += hintDataLength + } + expected.LastHint = expectedLastHint + // Run state transition stepWitness, err := goVm.Step(true) require.NoError(t, err) require.False(t, stepWitness.HasPreimage()) - // TODO(cp-983) - validate expected hints - expected.Validate(t, state, testutil.SkipHintValidation) - - evm := testutil.NewMIPSEVM(v.Contracts) - evmPost := evm.Step(t, stepWitness, step, v.StateHashFn) - goPost, _ := goVm.GetState().EncodeWitness() - require.Equal(t, hexutil.Bytes(goPost).String(), hexutil.Bytes(evmPost).String(), - "mipsevm produced different state than EVM") + // Validate + require.Equal(t, expectedHints, oracle.Hints()) + expected.Validate(t, state) + testutil.ValidateEVM(t, stepWitness, step, goVm, v.StateHashFn, v.Contracts, nil) }) } }) @@ -358,45 +365,56 @@ func FuzzStatePreimageWrite(f *testing.F) { f.Fuzz(func(t *testing.T, addr uint32, count uint32, seed int64) { for _, v := range versions { t.Run(v.Name, func(t *testing.T) { + // Make sure pc does not overlap with preimage data in memory + pc := uint32(0) + if addr <= 8 { + addr += 8 + } + effAddr := addr & 0xFF_FF_FF_FC + preexistingMemoryVal := [4]byte{0x12, 0x34, 0x56, 0x78} preimageData := []byte("hello world") preimageKey := preimage.Keccak256Key(crypto.Keccak256Hash(preimageData)).PreimageKey() oracle := testutil.StaticOracle(t, preimageData) goVm := v.VMFactory(oracle, os.Stdout, os.Stderr, testutil.CreateLogger(), - testutil.WithRandomization(seed), testutil.WithPreimageKey(preimageKey), testutil.WithPreimageOffset(128)) + testutil.WithRandomization(seed), testutil.WithPreimageKey(preimageKey), testutil.WithPreimageOffset(128), testutil.WithPCAndNextPC(pc)) state := goVm.GetState() state.GetRegistersRef()[2] = exec.SysWrite state.GetRegistersRef()[4] = exec.FdPreimageWrite state.GetRegistersRef()[5] = addr state.GetRegistersRef()[6] = count state.GetMemory().SetMemory(state.GetPC(), syscallInsn) + state.GetMemory().SetMemory(effAddr, binary.BigEndian.Uint32(preexistingMemoryVal[:])) step := state.GetStep() - sz := 4 - (addr & 0x3) - if sz < count { - count = sz + expectBytesWritten := count + alignment := addr & 0x3 + sz := 4 - alignment + if sz < expectBytesWritten { + expectBytesWritten = sz } - expected := testutil.CreateExpectedState(state) + expected := testutil.NewExpectedState(state) expected.Step += 1 expected.PC = state.GetCpu().NextPC expected.NextPC = state.GetCpu().NextPC + 4 expected.PreimageOffset = 0 - expected.Registers[2] = count + expected.Registers[2] = expectBytesWritten expected.Registers[7] = 0 // No error + expected.PreimageKey = preimageKey + if expectBytesWritten > 0 { + // Copy original preimage key, but shift it left by expectBytesWritten + copy(expected.PreimageKey[:], preimageKey[expectBytesWritten:]) + // Copy memory data to rightmost expectedBytesWritten + copy(expected.PreimageKey[32-expectBytesWritten:], preexistingMemoryVal[alignment:]) + } stepWitness, err := goVm.Step(true) require.NoError(t, err) require.False(t, stepWitness.HasPreimage()) - // TODO(cp-983) - validate preimage key - expected.Validate(t, state, testutil.SkipPreimageKeyValidation) - - evm := testutil.NewMIPSEVM(v.Contracts) - evmPost := evm.Step(t, stepWitness, step, v.StateHashFn) - goPost, _ := goVm.GetState().EncodeWitness() - require.Equal(t, hexutil.Bytes(goPost).String(), hexutil.Bytes(evmPost).String(), - "mipsevm produced different state than EVM") + expected.Validate(t, state) + testutil.ValidateEVM(t, stepWitness, step, goVm, v.StateHashFn, v.Contracts, nil) }) } }) diff --git a/cannon/mipsevm/tests/fuzz_evm_multithreaded_test.go b/cannon/mipsevm/tests/fuzz_evm_multithreaded_test.go index 2b8224b10725c..828f9c5587399 100644 --- a/cannon/mipsevm/tests/fuzz_evm_multithreaded_test.go +++ b/cannon/mipsevm/tests/fuzz_evm_multithreaded_test.go @@ -4,44 +4,63 @@ import ( "os" "testing" - "github.com/ethereum/go-ethereum/common/hexutil" "github.com/stretchr/testify/require" "github.com/ethereum-optimism/optimism/cannon/mipsevm/exec" + "github.com/ethereum-optimism/optimism/cannon/mipsevm/multithreaded" + mttestutil "github.com/ethereum-optimism/optimism/cannon/mipsevm/multithreaded/testutil" "github.com/ethereum-optimism/optimism/cannon/mipsevm/testutil" ) -// TODO func FuzzStateSyscallCloneMT(f *testing.F) { v := GetMultiThreadedTestCase(f) - // t.Skip is causing linting check to fail, disable for now - //nolint:staticcheck - f.Fuzz(func(t *testing.T, seed int64) { - // TODO(cp-903) Customize test for multi-threaded vm - t.Skip("TODO - customize this test for MTCannon") + f.Fuzz(func(t *testing.T, nextThreadId, stackPtr uint32, seed int64) { goVm := v.VMFactory(nil, os.Stdout, os.Stderr, testutil.CreateLogger(), testutil.WithRandomization(seed)) - state := goVm.GetState() - state.GetRegistersRef()[2] = exec.SysClone + state := mttestutil.GetMtState(t, goVm) + // Update existing threads to avoid collision with nextThreadId + if mttestutil.FindThread(state, nextThreadId) != nil { + for i, t := range mttestutil.GetAllThreads(state) { + t.ThreadId = nextThreadId - uint32(i+1) + } + } + + // Setup + state.NextThreadId = nextThreadId state.GetMemory().SetMemory(state.GetPC(), syscallInsn) + state.GetRegistersRef()[2] = exec.SysClone + state.GetRegistersRef()[4] = exec.ValidCloneFlags + state.GetRegistersRef()[5] = stackPtr step := state.GetStep() - expected := testutil.CreateExpectedState(state) + // Set up expectations + expected := mttestutil.NewExpectedMTState(state) expected.Step += 1 - expected.PC = state.GetCpu().NextPC - expected.NextPC = state.GetCpu().NextPC + 4 - expected.Registers[2] = 0x1 - expected.Registers[7] = 0 + // Set original thread expectations + expected.PrestateActiveThread().PC = state.GetCpu().NextPC + expected.PrestateActiveThread().NextPC = state.GetCpu().NextPC + 4 + expected.PrestateActiveThread().Registers[2] = nextThreadId + expected.PrestateActiveThread().Registers[7] = 0 + // Set expectations for new, cloned thread + expected.ActiveThreadId = nextThreadId + epxectedNewThread := expected.ExpectNewThread() + epxectedNewThread.PC = state.GetCpu().NextPC + epxectedNewThread.NextPC = state.GetCpu().NextPC + 4 + epxectedNewThread.Registers[2] = 0 + epxectedNewThread.Registers[7] = 0 + epxectedNewThread.Registers[29] = stackPtr + expected.NextThreadId = nextThreadId + 1 + expected.StepsSinceLastContextSwitch = 0 + if state.TraverseRight { + expected.RightStackSize += 1 + } else { + expected.LeftStackSize += 1 + } stepWitness, err := goVm.Step(true) require.NoError(t, err) require.False(t, stepWitness.HasPreimage()) expected.Validate(t, state) - - evm := testutil.NewMIPSEVM(v.Contracts) - evmPost := evm.Step(t, stepWitness, step, v.StateHashFn) - goPost, _ := goVm.GetState().EncodeWitness() - require.Equal(t, hexutil.Bytes(goPost).String(), hexutil.Bytes(evmPost).String(), - "mipsevm produced different state than EVM") + testutil.ValidateEVM(t, stepWitness, step, goVm, multithreaded.GetStateHashFn(), v.Contracts, nil) }) } diff --git a/cannon/mipsevm/tests/fuzz_evm_singlethreaded_test.go b/cannon/mipsevm/tests/fuzz_evm_singlethreaded_test.go index be5c995d352cc..cc30c0040196d 100644 --- a/cannon/mipsevm/tests/fuzz_evm_singlethreaded_test.go +++ b/cannon/mipsevm/tests/fuzz_evm_singlethreaded_test.go @@ -20,7 +20,7 @@ func FuzzStateSyscallCloneST(f *testing.F) { state.GetMemory().SetMemory(state.GetPC(), syscallInsn) step := state.GetStep() - expected := testutil.CreateExpectedState(state) + expected := testutil.NewExpectedState(state) expected.Step += 1 expected.PC = state.GetCpu().NextPC expected.NextPC = state.GetCpu().NextPC + 4 diff --git a/cannon/mipsevm/tests/helpers.go b/cannon/mipsevm/tests/helpers.go index 5b75a03c6bc4b..d96940972a65e 100644 --- a/cannon/mipsevm/tests/helpers.go +++ b/cannon/mipsevm/tests/helpers.go @@ -31,7 +31,7 @@ func multiThreadedVmFactory(po mipsevm.PreimageOracle, stdOut, stdErr io.Writer, for _, opt := range opts { opt(mutator) } - return multithreaded.NewInstrumentedState(state, po, stdOut, stdErr, log) + return multithreaded.NewInstrumentedState(state, po, stdOut, stdErr, log, nil) } type ElfVMFactory func(t require.TestingT, elfFile string, po mipsevm.PreimageOracle, stdOut, stdErr io.Writer, log log.Logger) mipsevm.FPVM @@ -45,8 +45,8 @@ func singleThreadElfVmFactory(t require.TestingT, elfFile string, po mipsevm.Pre func multiThreadElfVmFactory(t require.TestingT, elfFile string, po mipsevm.PreimageOracle, stdOut, stdErr io.Writer, log log.Logger) mipsevm.FPVM { state, meta := testutil.LoadELFProgram(t, elfFile, multithreaded.CreateInitialState, false) - fpvm := multithreaded.NewInstrumentedState(state, po, stdOut, stdErr, log) - require.NoError(t, fpvm.InitDebug(meta)) + fpvm := multithreaded.NewInstrumentedState(state, po, stdOut, stdErr, log, meta) + require.NoError(t, fpvm.InitDebug()) return fpvm } diff --git a/cannon/mipsevm/testutil/elf.go b/cannon/mipsevm/testutil/elf.go index 683f987026537..b5b63cdeb1d39 100644 --- a/cannon/mipsevm/testutil/elf.go +++ b/cannon/mipsevm/testutil/elf.go @@ -9,7 +9,7 @@ import ( "github.com/ethereum-optimism/optimism/cannon/mipsevm/program" ) -func LoadELFProgram[T mipsevm.FPVMState](t require.TestingT, name string, initState program.CreateInitialFPVMState[T], doPatchGo bool) (T, *program.Metadata) { +func LoadELFProgram[T mipsevm.FPVMState](t require.TestingT, name string, initState program.CreateInitialFPVMState[T], doPatchGoGC bool) (T, *program.Metadata) { elfProgram, err := elf.Open(name) require.NoError(t, err, "open ELF file") meta, err := program.MakeMetadata(elfProgram) @@ -18,8 +18,8 @@ func LoadELFProgram[T mipsevm.FPVMState](t require.TestingT, name string, initSt state, err := program.LoadELF(elfProgram, initState) require.NoError(t, err, "load ELF into state") - if doPatchGo { - err = program.PatchGo(elfProgram, state) + if doPatchGoGC { + err = program.PatchGoGC(elfProgram, state) require.NoError(t, err, "apply Go runtime patches") } diff --git a/cannon/mipsevm/testutil/mips.go b/cannon/mipsevm/testutil/mips.go index 39d8fbed0b46f..33ada41869d76 100644 --- a/cannon/mipsevm/testutil/mips.go +++ b/cannon/mipsevm/testutil/mips.go @@ -9,6 +9,7 @@ import ( "testing" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/tracing" "github.com/ethereum/go-ethereum/core/vm" @@ -20,19 +21,24 @@ import ( ) type MIPSEVM struct { + sender vm.AccountRef + startingGas uint64 env *vm.EVM evmState *state.StateDB addrs *Addresses localOracle mipsevm.PreimageOracle artifacts *Artifacts // Track step execution for logging purposes - lastStep uint64 - lastStepInput []byte + lastStep uint64 + lastStepInput []byte + lastPreimageOracleInput []byte } func NewMIPSEVM(contracts *ContractMetadata) *MIPSEVM { env, evmState := NewEVMEnv(contracts) - return &MIPSEVM{env, evmState, contracts.Addresses, nil, contracts.Artifacts, math.MaxUint64, nil} + sender := vm.AccountRef{0x13, 0x37} + startingGas := uint64(30_000_000) + return &MIPSEVM{sender, startingGas, env, evmState, contracts.Addresses, nil, contracts.Artifacts, math.MaxUint64, nil, nil} } func (m *MIPSEVM) SetTracer(tracer *tracing.Hooks) { @@ -51,23 +57,23 @@ func (m *MIPSEVM) SetSourceMapTracer(t *testing.T, version MipsVersion) { func (m *MIPSEVM) Step(t *testing.T, stepWitness *mipsevm.StepWitness, step uint64, stateHashFn mipsevm.HashFn) []byte { m.lastStep = step m.lastStepInput = nil - sender := common.Address{0x13, 0x37} - startingGas := uint64(30_000_000) + m.lastPreimageOracleInput = nil // we take a snapshot so we can clean up the state, and isolate the logs of this instruction run. snap := m.env.StateDB.Snapshot() if stepWitness.HasPreimage() { t.Logf("reading preimage key %x at offset %d", stepWitness.PreimageKey, stepWitness.PreimageOffset) - poInput, err := EncodePreimageOracleInput(t, stepWitness, mipsevm.LocalContext{}, m.localOracle, m.artifacts.Oracle) + poInput, err := m.encodePreimageOracleInput(t, stepWitness.PreimageKey, stepWitness.PreimageValue, stepWitness.PreimageOffset, mipsevm.LocalContext{}) + m.lastPreimageOracleInput = poInput require.NoError(t, err, "encode preimage oracle input") - _, leftOverGas, err := m.env.Call(vm.AccountRef(sender), m.addrs.Oracle, poInput, startingGas, common.U2560) - require.NoErrorf(t, err, "evm should not fail, took %d gas", startingGas-leftOverGas) + _, leftOverGas, err := m.env.Call(m.sender, m.addrs.Oracle, poInput, m.startingGas, common.U2560) + require.NoErrorf(t, err, "evm should not fail, took %d gas", m.startingGas-leftOverGas) } input := EncodeStepInput(t, stepWitness, mipsevm.LocalContext{}, m.artifacts.MIPS) m.lastStepInput = input - ret, leftOverGas, err := m.env.Call(vm.AccountRef(sender), m.addrs.MIPS, input, startingGas, common.U2560) + ret, leftOverGas, err := m.env.Call(m.sender, m.addrs.MIPS, input, m.startingGas, common.U2560) require.NoError(t, err, "evm should not fail") require.Len(t, ret, 32, "expecting 32-byte state hash") // remember state hash, to check it against state @@ -81,7 +87,7 @@ func (m *MIPSEVM) Step(t *testing.T, stepWitness *mipsevm.StepWitness, step uint require.Equal(t, stateHash, postHash, "logged state must be accurate") m.env.StateDB.RevertToSnapshot(snap) - t.Logf("EVM step %d took %d gas, and returned stateHash %s", step, startingGas-leftOverGas, postHash) + t.Logf("EVM step %d took %d gas, and returned stateHash %s", step, m.startingGas-leftOverGas, postHash) return evmPost } @@ -91,46 +97,48 @@ func EncodeStepInput(t *testing.T, wit *mipsevm.StepWitness, localContext mipsev return input } -func EncodePreimageOracleInput(t *testing.T, wit *mipsevm.StepWitness, localContext mipsevm.LocalContext, localOracle mipsevm.PreimageOracle, oracle *foundry.Artifact) ([]byte, error) { - if wit.PreimageKey == ([32]byte{}) { +func (m *MIPSEVM) encodePreimageOracleInput(t *testing.T, preimageKey [32]byte, preimageValue []byte, preimageOffset uint32, localContext mipsevm.LocalContext) ([]byte, error) { + if preimageKey == ([32]byte{}) { return nil, errors.New("cannot encode pre-image oracle input, witness has no pre-image to proof") } + localOracle := m.localOracle + oracle := m.artifacts.Oracle - switch preimage.KeyType(wit.PreimageKey[0]) { + switch preimage.KeyType(preimageKey[0]) { case preimage.LocalKeyType: - if len(wit.PreimageValue) > 32+8 { - return nil, fmt.Errorf("local pre-image exceeds maximum size of 32 bytes with key 0x%x", wit.PreimageKey) + if len(preimageValue) > 32+8 { + return nil, fmt.Errorf("local pre-image exceeds maximum size of 32 bytes with key 0x%x", preimageKey) } - preimagePart := wit.PreimageValue[8:] + preimagePart := preimageValue[8:] var tmp [32]byte copy(tmp[:], preimagePart) input, err := oracle.ABI.Pack("loadLocalData", - new(big.Int).SetBytes(wit.PreimageKey[1:]), + new(big.Int).SetBytes(preimageKey[1:]), localContext, tmp, new(big.Int).SetUint64(uint64(len(preimagePart))), - new(big.Int).SetUint64(uint64(wit.PreimageOffset)), + new(big.Int).SetUint64(uint64(preimageOffset)), ) require.NoError(t, err) return input, nil case preimage.Keccak256KeyType: input, err := oracle.ABI.Pack( "loadKeccak256PreimagePart", - new(big.Int).SetUint64(uint64(wit.PreimageOffset)), - wit.PreimageValue[8:]) + new(big.Int).SetUint64(uint64(preimageOffset)), + 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") + return nil, errors.New("local oracle is required for precompile preimages") } - preimage := localOracle.GetPreimage(preimage.Keccak256Key(wit.PreimageKey).PreimageKey()) + preimage := localOracle.GetPreimage(preimage.Keccak256Key(preimageKey).PreimageKey()) precompile := common.BytesToAddress(preimage[:20]) requiredGas := binary.BigEndian.Uint64(preimage[20:28]) callInput := preimage[28:] input, err := oracle.ABI.Pack( "loadPrecompilePreimagePart", - new(big.Int).SetUint64(uint64(wit.PreimageOffset)), + new(big.Int).SetUint64(uint64(preimageOffset)), precompile, requiredGas, callInput, @@ -139,15 +147,63 @@ func EncodePreimageOracleInput(t *testing.T, wit *mipsevm.StepWitness, localCont 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) + preimageKey[0], preimageKey, preimageOffset) } } +func (m *MIPSEVM) assertPreimageOracleReverts(t *testing.T, preimageKey [32]byte, preimageValue []byte, preimageOffset uint32) { + poInput, err := m.encodePreimageOracleInput(t, preimageKey, preimageValue, preimageOffset, mipsevm.LocalContext{}) + require.NoError(t, err, "encode preimage oracle input") + _, _, evmErr := m.env.Call(m.sender, m.addrs.Oracle, poInput, m.startingGas, common.U2560) + + require.ErrorContains(t, evmErr, "execution reverted") +} + func LogStepFailureAtCleanup(t *testing.T, mipsEvm *MIPSEVM) { t.Cleanup(func() { if t.Failed() { // Note: For easier debugging of a failing step, see MIPS.t.sol#test_step_debug_succeeds() - t.Logf("Failed while executing step %d with input: %x", mipsEvm.lastStep, mipsEvm.lastStepInput) + t.Logf("Failed while executing step %d with\n\tstep input: %x\n\tpreimageOracle input: %x", mipsEvm.lastStep, mipsEvm.lastStepInput, mipsEvm.lastPreimageOracleInput) } }) } + +// ValidateEVM runs a single evm step and validates against an FPVM poststate +func ValidateEVM(t *testing.T, stepWitness *mipsevm.StepWitness, step uint64, goVm mipsevm.FPVM, hashFn mipsevm.HashFn, contracts *ContractMetadata, tracer *tracing.Hooks) { + evm := NewMIPSEVM(contracts) + evm.SetTracer(tracer) + LogStepFailureAtCleanup(t, evm) + + evmPost := evm.Step(t, stepWitness, step, hashFn) + goPost, _ := goVm.GetState().EncodeWitness() + require.Equal(t, hexutil.Bytes(goPost).String(), hexutil.Bytes(evmPost).String(), + "mipsevm produced different state than EVM") +} + +// AssertEVMReverts runs a single evm step from an FPVM prestate and asserts that the VM panics +func AssertEVMReverts(t *testing.T, state mipsevm.FPVMState, contracts *ContractMetadata, tracer *tracing.Hooks) { + insnProof := state.GetMemory().MerkleProof(state.GetPC()) + encodedWitness, _ := state.EncodeWitness() + stepWitness := &mipsevm.StepWitness{ + State: encodedWitness, + ProofData: insnProof[:], + } + input := EncodeStepInput(t, stepWitness, mipsevm.LocalContext{}, contracts.Artifacts.MIPS) + startingGas := uint64(30_000_000) + + env, evmState := NewEVMEnv(contracts) + env.Config.Tracer = tracer + sender := common.Address{0x13, 0x37} + _, _, err := env.Call(vm.AccountRef(sender), contracts.Addresses.MIPS, input, startingGas, common.U2560) + require.EqualValues(t, err, vm.ErrExecutionReverted) + logs := evmState.Logs() + require.Equal(t, 0, len(logs)) +} + +func AssertPreimageOracleReverts(t *testing.T, preimageKey [32]byte, preimageValue []byte, preimageOffset uint32, contracts *ContractMetadata, tracer *tracing.Hooks) { + evm := NewMIPSEVM(contracts) + evm.SetTracer(tracer) + LogStepFailureAtCleanup(t, evm) + + evm.assertPreimageOracleReverts(t, preimageKey, preimageValue, preimageOffset) +} diff --git a/cannon/mipsevm/testutil/oracle.go b/cannon/mipsevm/testutil/oracle.go index e0cd9baf6dff5..64b0f31a897c9 100644 --- a/cannon/mipsevm/testutil/oracle.go +++ b/cannon/mipsevm/testutil/oracle.go @@ -120,14 +120,19 @@ func ClaimTestOracle(t *testing.T) (po mipsevm.PreimageOracle, stdOut string, st return oracle, fmt.Sprintf("computing %d * %d + %d\nclaim %d is good!\n", s, a, b, s*a+b), "started!" } -func AllocOracle(t *testing.T, numAllocs int) *TestOracle { +func AllocOracle(t *testing.T, numAllocs int, allocSize int) *TestOracle { return &TestOracle{ hint: func(v []byte) {}, getPreimage: func(k [32]byte) []byte { - if k != preimage.LocalIndexKey(0).PreimageKey() { + switch k { + case preimage.LocalIndexKey(0).PreimageKey(): + return binary.LittleEndian.AppendUint64(nil, uint64(numAllocs)) + case preimage.LocalIndexKey(1).PreimageKey(): + return binary.LittleEndian.AppendUint64(nil, uint64(allocSize)) + default: t.Fatalf("invalid preimage request for %x", k) } - return binary.LittleEndian.AppendUint64(nil, uint64(numAllocs)) + panic("unreachable") }, } } diff --git a/cannon/mipsevm/testutil/rand.go b/cannon/mipsevm/testutil/rand.go new file mode 100644 index 0000000000000..96ff0eb6318b9 --- /dev/null +++ b/cannon/mipsevm/testutil/rand.go @@ -0,0 +1,82 @@ +package testutil + +import ( + "encoding/binary" + "math/rand" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" +) + +type RandHelper struct { + r *rand.Rand +} + +func NewRandHelper(seed int64) *RandHelper { + r := rand.New(rand.NewSource(seed)) + return &RandHelper{r: r} +} + +func (h *RandHelper) Uint32() uint32 { + return h.r.Uint32() +} + +func (h *RandHelper) Fraction() float64 { + return h.r.Float64() +} + +func (h *RandHelper) Intn(n int) int { + return h.r.Intn(n) +} + +func (h *RandHelper) RandHash() common.Hash { + var bytes [32]byte + _, err := h.r.Read(bytes[:]) + if err != nil { + panic(err) + } + return bytes +} + +func (h *RandHelper) RandHint() []byte { + + bytesCount := h.r.Intn(24) + bytes := make([]byte, bytesCount) + + if bytesCount >= 8 { + // Set up a reasonable length prefix + nextHintLen := uint64(h.r.Intn(30)) + binary.BigEndian.PutUint64(bytes, nextHintLen) + + _, err := h.r.Read(bytes[8:]) + if err != nil { + panic(err) + } + } + + return bytes +} + +func (h *RandHelper) RandRegisters() *[32]uint32 { + registers := new([32]uint32) + for i := 0; i < 32; i++ { + registers[i] = h.r.Uint32() + } + return registers +} + +func (h *RandHelper) RandomBytes(t require.TestingT, length int) []byte { + randBytes := make([]byte, length) + if _, err := h.r.Read(randBytes); err != nil { + require.NoError(t, err) + } + return randBytes +} + +func (h *RandHelper) RandPC() uint32 { + return AlignPC(h.r.Uint32()) +} + +func (h *RandHelper) RandStep() uint64 { + return BoundStep(h.r.Uint64()) +} diff --git a/cannon/mipsevm/testutil/state.go b/cannon/mipsevm/testutil/state.go index da0c9d1657eed..86d5cfb2b6adf 100644 --- a/cannon/mipsevm/testutil/state.go +++ b/cannon/mipsevm/testutil/state.go @@ -1,9 +1,8 @@ package testutil import ( + "encoding/binary" "fmt" - "math/rand" - "slices" "testing" "github.com/ethereum/go-ethereum/common" @@ -11,12 +10,25 @@ import ( "github.com/stretchr/testify/require" "github.com/ethereum-optimism/optimism/cannon/mipsevm" + "github.com/ethereum-optimism/optimism/cannon/mipsevm/memory" ) -func CopyRegisters(state mipsevm.FPVMState) *[32]uint32 { - copy := new([32]uint32) - *copy = *state.GetRegistersRef() - return copy +func AddHintLengthPrefix(data []byte) []byte { + dataLen := len(data) + prefixed := make([]byte, 0, dataLen+4) + prefixed = binary.BigEndian.AppendUint32(prefixed, uint32(dataLen)) + prefixed = append(prefixed, data...) + + return prefixed +} + +func AddPreimageLengthPrefix(data []byte) []byte { + dataLen := len(data) + prefixed := make([]byte, 0, dataLen+8) + prefixed = binary.BigEndian.AppendUint64(prefixed, uint64(dataLen)) + prefixed = append(prefixed, data...) + + return prefixed } type StateMutator interface { @@ -31,7 +43,7 @@ type StateMutator interface { SetExited(val bool) SetStep(val uint64) SetLastHint(val hexutil.Bytes) - GetRegistersRef() *[32]uint32 + Randomize(randSeed int64) } type StateOption func(state StateMutator) @@ -48,6 +60,13 @@ func WithNextPC(nextPC uint32) StateOption { } } +func WithPCAndNextPC(pc uint32) StateOption { + return func(state StateMutator) { + state.SetPC(pc) + state.SetNextPC(pc + 4) + } +} + func WithHeap(addr uint32) StateOption { return func(state StateMutator) { state.SetHeap(addr) @@ -80,36 +99,26 @@ func WithStep(step uint64) StateOption { func WithRandomization(seed int64) StateOption { return func(mut StateMutator) { - RandomizeState(seed, mut) + mut.Randomize(seed) } } -func RandomizeState(seed int64, mut StateMutator) { - r := rand.New(rand.NewSource(seed)) - +func AlignPC(pc uint32) uint32 { // Memory-align random pc and leave room for nextPC - pc := r.Uint32() & 0xFF_FF_FF_FC // Align address + pc = pc & 0xFF_FF_FF_FC // Align address if pc >= 0xFF_FF_FF_FC { // Leave room to set and then increment nextPC pc = 0xFF_FF_FF_FC - 8 } + return pc +} - // Set random step, but leave room to increment - step := r.Uint64() +func BoundStep(step uint64) uint64 { + // Leave room to increment step at least once if step == ^uint64(0) { step -= 1 } - - mut.SetPreimageKey(randHash(r)) - mut.SetPreimageOffset(r.Uint32()) - mut.SetPC(pc) - mut.SetNextPC(pc + 4) - mut.SetHI(r.Uint32()) - mut.SetLO(r.Uint32()) - mut.SetHeap(r.Uint32()) - mut.SetStep(step) - mut.SetLastHint(randHint(r)) - *mut.GetRegistersRef() = *randRegisters(r) + return step } type ExpectedState struct { @@ -126,9 +135,10 @@ type ExpectedState struct { LastHint hexutil.Bytes Registers [32]uint32 MemoryRoot common.Hash + expectedMemory *memory.Memory } -func CreateExpectedState(fromState mipsevm.FPVMState) *ExpectedState { +func NewExpectedState(fromState mipsevm.FPVMState) *ExpectedState { return &ExpectedState{ PreimageKey: fromState.GetPreimageKey(), PreimageOffset: fromState.GetPreimageOffset(), @@ -143,22 +153,24 @@ func CreateExpectedState(fromState mipsevm.FPVMState) *ExpectedState { LastHint: fromState.GetLastHint(), Registers: *fromState.GetRegistersRef(), MemoryRoot: fromState.GetMemory().MerkleRoot(), + expectedMemory: fromState.GetMemory().Copy(), } } -type StateValidationFlags int +func (e *ExpectedState) ExpectStep() { + // Set some standard expectations for a normal step + e.Step += 1 + e.PC += 4 + e.NextPC += 4 +} -// TODO(cp-983) - Remove these validation hacks -const ( - SkipMemoryValidation StateValidationFlags = iota - SkipHintValidation - SkipPreimageKeyValidation -) +func (e *ExpectedState) ExpectMemoryWrite(addr uint32, val uint32) { + e.expectedMemory.SetMemory(addr, val) + e.MemoryRoot = e.expectedMemory.MerkleRoot() +} -func (e *ExpectedState) Validate(t testing.TB, actualState mipsevm.FPVMState, flags ...StateValidationFlags) { - if !slices.Contains(flags, SkipPreimageKeyValidation) { - require.Equal(t, e.PreimageKey, actualState.GetPreimageKey(), fmt.Sprintf("Expect preimageKey = %v", e.PreimageKey)) - } +func (e *ExpectedState) Validate(t testing.TB, actualState mipsevm.FPVMState) { + require.Equal(t, e.PreimageKey, actualState.GetPreimageKey(), fmt.Sprintf("Expect preimageKey = %v", e.PreimageKey)) require.Equal(t, e.PreimageOffset, actualState.GetPreimageOffset(), fmt.Sprintf("Expect preimageOffset = %v", e.PreimageOffset)) require.Equal(t, e.PC, actualState.GetCpu().PC, fmt.Sprintf("Expect PC = 0x%x", e.PC)) require.Equal(t, e.NextPC, actualState.GetCpu().NextPC, fmt.Sprintf("Expect nextPC = 0x%x", e.NextPC)) @@ -168,48 +180,7 @@ func (e *ExpectedState) Validate(t testing.TB, actualState mipsevm.FPVMState, fl require.Equal(t, e.ExitCode, actualState.GetExitCode(), fmt.Sprintf("Expect exitCode = 0x%x", e.ExitCode)) require.Equal(t, e.Exited, actualState.GetExited(), fmt.Sprintf("Expect exited = %v", e.Exited)) require.Equal(t, e.Step, actualState.GetStep(), fmt.Sprintf("Expect step = %d", e.Step)) - if !slices.Contains(flags, SkipHintValidation) { - require.Equal(t, e.LastHint, actualState.GetLastHint(), fmt.Sprintf("Expect lastHint = %v", e.LastHint)) - } + require.Equal(t, e.LastHint, actualState.GetLastHint(), fmt.Sprintf("Expect lastHint = %v", e.LastHint)) require.Equal(t, e.Registers, *actualState.GetRegistersRef(), fmt.Sprintf("Expect registers = %v", e.Registers)) - if !slices.Contains(flags, SkipMemoryValidation) { - require.Equal(t, e.MemoryRoot, common.Hash(actualState.GetMemory().MerkleRoot()), fmt.Sprintf("Expect memory root = %v", e.MemoryRoot)) - } -} - -func randHash(r *rand.Rand) common.Hash { - var bytes [32]byte - _, err := r.Read(bytes[:]) - if err != nil { - panic(err) - } - return bytes -} - -func randHint(r *rand.Rand) []byte { - count := r.Intn(10) - - bytes := make([]byte, count) - _, err := r.Read(bytes[:]) - if err != nil { - panic(err) - } - return bytes -} - -func randRegisters(r *rand.Rand) *[32]uint32 { - registers := new([32]uint32) - for i := 0; i < 32; i++ { - registers[i] = r.Uint32() - } - return registers -} - -func RandomBytes(t require.TestingT, seed int64, length uint32) []byte { - r := rand.New(rand.NewSource(seed)) - randBytes := make([]byte, length) - if _, err := r.Read(randBytes); err != nil { - require.NoError(t, err) - } - return randBytes + require.Equal(t, e.MemoryRoot, common.Hash(actualState.GetMemory().MerkleRoot()), fmt.Sprintf("Expect memory root = %v", e.MemoryRoot)) } diff --git a/cannon/mipsevm/versions/detect.go b/cannon/mipsevm/versions/detect.go new file mode 100644 index 0000000000000..ca4b9be9c51d5 --- /dev/null +++ b/cannon/mipsevm/versions/detect.go @@ -0,0 +1,35 @@ +package versions + +import ( + "fmt" + "io" + + "github.com/ethereum-optimism/optimism/cannon/serialize" + "github.com/ethereum-optimism/optimism/op-service/ioutil" +) + +func DetectVersion(path string) (StateVersion, error) { + if !serialize.IsBinaryFile(path) { + return VersionSingleThreaded, nil + } + + var f io.ReadCloser + f, err := ioutil.OpenDecompressed(path) + if err != nil { + return 0, fmt.Errorf("failed to open file %q: %w", path, err) + } + defer f.Close() + + var ver StateVersion + bin := serialize.NewBinaryReader(f) + if err := bin.ReadUInt(&ver); err != nil { + return 0, err + } + + switch ver { + case VersionSingleThreaded, VersionMultiThreaded: + return ver, nil + default: + return 0, fmt.Errorf("%w: %d", ErrUnknownVersion, ver) + } +} diff --git a/cannon/mipsevm/versions/detect_test.go b/cannon/mipsevm/versions/detect_test.go new file mode 100644 index 0000000000000..38a90f1786948 --- /dev/null +++ b/cannon/mipsevm/versions/detect_test.go @@ -0,0 +1,65 @@ +package versions + +import ( + "os" + "path/filepath" + "testing" + + "github.com/ethereum-optimism/optimism/cannon/mipsevm/multithreaded" + "github.com/ethereum-optimism/optimism/cannon/mipsevm/singlethreaded" + "github.com/ethereum-optimism/optimism/op-service/ioutil" + "github.com/stretchr/testify/require" +) + +func TestDetectVersion(t *testing.T) { + t.Run("SingleThreadedJSON", func(t *testing.T) { + state, err := NewFromState(singlethreaded.CreateEmptyState()) + require.NoError(t, err) + path := writeToFile(t, "state.json", state) + version, err := DetectVersion(path) + require.NoError(t, err) + require.Equal(t, VersionSingleThreaded, version) + }) + + t.Run("SingleThreadedBinary", func(t *testing.T) { + state, err := NewFromState(singlethreaded.CreateEmptyState()) + require.NoError(t, err) + path := writeToFile(t, "state.bin.gz", state) + version, err := DetectVersion(path) + require.NoError(t, err) + require.Equal(t, VersionSingleThreaded, version) + }) + + t.Run("MultiThreadedBinary", func(t *testing.T) { + state, err := NewFromState(multithreaded.CreateEmptyState()) + require.NoError(t, err) + path := writeToFile(t, "state.bin.gz", state) + version, err := DetectVersion(path) + require.NoError(t, err) + require.Equal(t, VersionMultiThreaded, version) + }) +} + +func TestDetectVersionInvalid(t *testing.T) { + t.Run("bad gzip", func(t *testing.T) { + dir := t.TempDir() + filename := "state.bin.gz" + path := filepath.Join(dir, filename) + require.NoError(t, os.WriteFile(path, []byte("ekans"), 0o644)) + + _, err := DetectVersion(path) + require.ErrorContains(t, err, "failed to open file") + }) + + t.Run("unknown version", func(t *testing.T) { + dir := t.TempDir() + filename := "state.bin.gz" + path := filepath.Join(dir, filename) + const badVersion = 0xFF + err := ioutil.WriteCompressedBytes(path, []byte{badVersion}, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0o644) + require.NoError(t, err) + + _, err = DetectVersion(path) + require.ErrorIs(t, err, ErrUnknownVersion) + }) +} diff --git a/cannon/mipsevm/versions/state.go b/cannon/mipsevm/versions/state.go new file mode 100644 index 0000000000000..afd2a94204b39 --- /dev/null +++ b/cannon/mipsevm/versions/state.go @@ -0,0 +1,130 @@ +package versions + +import ( + "encoding/json" + "errors" + "fmt" + "io" + + "github.com/ethereum-optimism/optimism/cannon/mipsevm" + "github.com/ethereum-optimism/optimism/cannon/mipsevm/multithreaded" + "github.com/ethereum-optimism/optimism/cannon/mipsevm/singlethreaded" + "github.com/ethereum-optimism/optimism/cannon/serialize" + "github.com/ethereum-optimism/optimism/op-service/jsonutil" +) + +type StateVersion uint8 + +const ( + // VersionSingleThreaded is the version of the Cannon STF found in op-contracts/v1.6.0 - https://github.com/ethereum-optimism/optimism/blob/op-contracts/v1.6.0/packages/contracts-bedrock/src/cannon/MIPS.sol + VersionSingleThreaded StateVersion = iota + VersionMultiThreaded +) + +var ( + ErrUnknownVersion = errors.New("unknown version") + ErrJsonNotSupported = errors.New("json not supported") +) + +var StateVersionTypes = []StateVersion{VersionSingleThreaded, VersionMultiThreaded} + +func LoadStateFromFile(path string) (*VersionedState, error) { + if !serialize.IsBinaryFile(path) { + // Always use singlethreaded for JSON states + state, err := jsonutil.LoadJSON[singlethreaded.State](path) + if err != nil { + return nil, err + } + return NewFromState(state) + } + return serialize.LoadSerializedBinary[VersionedState](path) +} + +func NewFromState(state mipsevm.FPVMState) (*VersionedState, error) { + switch state := state.(type) { + case *singlethreaded.State: + return &VersionedState{ + Version: VersionSingleThreaded, + FPVMState: state, + }, nil + case *multithreaded.State: + return &VersionedState{ + Version: VersionMultiThreaded, + FPVMState: state, + }, nil + default: + return nil, fmt.Errorf("%w: %T", ErrUnknownVersion, state) + } +} + +// VersionedState deserializes a FPVMState and implements VersionedState based on the version of that state. +// It does this based on the version byte read in Deserialize +type VersionedState struct { + Version StateVersion + mipsevm.FPVMState +} + +func (s *VersionedState) Serialize(w io.Writer) error { + bout := serialize.NewBinaryWriter(w) + if err := bout.WriteUInt(s.Version); err != nil { + return err + } + return s.FPVMState.Serialize(w) +} + +func (s *VersionedState) Deserialize(in io.Reader) error { + bin := serialize.NewBinaryReader(in) + if err := bin.ReadUInt(&s.Version); err != nil { + return err + } + + switch s.Version { + case VersionSingleThreaded: + state := &singlethreaded.State{} + if err := state.Deserialize(in); err != nil { + return err + } + s.FPVMState = state + return nil + case VersionMultiThreaded: + state := &multithreaded.State{} + if err := state.Deserialize(in); err != nil { + return err + } + s.FPVMState = state + return nil + default: + return fmt.Errorf("%w: %d", ErrUnknownVersion, s.Version) + } +} + +// MarshalJSON marshals the underlying state without adding version prefix. +// JSON states are always assumed to be single threaded +func (s *VersionedState) MarshalJSON() ([]byte, error) { + if s.Version != VersionSingleThreaded { + return nil, fmt.Errorf("%w for type %T", ErrJsonNotSupported, s.FPVMState) + } + return json.Marshal(s.FPVMState) +} + +func (s StateVersion) String() string { + switch s { + case VersionSingleThreaded: + return "singlethreaded" + case VersionMultiThreaded: + return "multithreaded" + default: + return "unknown" + } +} + +func ParseStateVersion(ver string) (StateVersion, error) { + switch ver { + case "singlethreaded": + return VersionSingleThreaded, nil + case "multithreaded": + return VersionMultiThreaded, nil + default: + return StateVersion(0), errors.New("unknown state version") + } +} diff --git a/cannon/mipsevm/versions/state_test.go b/cannon/mipsevm/versions/state_test.go new file mode 100644 index 0000000000000..7fb36cd5734c1 --- /dev/null +++ b/cannon/mipsevm/versions/state_test.go @@ -0,0 +1,76 @@ +package versions + +import ( + "path/filepath" + "testing" + + "github.com/ethereum-optimism/optimism/cannon/mipsevm/multithreaded" + "github.com/ethereum-optimism/optimism/cannon/mipsevm/singlethreaded" + "github.com/ethereum-optimism/optimism/cannon/serialize" + "github.com/stretchr/testify/require" +) + +func TestNewFromState(t *testing.T) { + t.Run("singlethreaded", func(t *testing.T) { + actual, err := NewFromState(singlethreaded.CreateEmptyState()) + require.NoError(t, err) + require.IsType(t, &singlethreaded.State{}, actual.FPVMState) + require.Equal(t, VersionSingleThreaded, actual.Version) + }) + + t.Run("multithreaded", func(t *testing.T) { + actual, err := NewFromState(multithreaded.CreateEmptyState()) + require.NoError(t, err) + require.IsType(t, &multithreaded.State{}, actual.FPVMState) + require.Equal(t, VersionMultiThreaded, actual.Version) + }) +} + +func TestLoadStateFromFile(t *testing.T) { + t.Run("SinglethreadedFromJSON", func(t *testing.T) { + expected, err := NewFromState(singlethreaded.CreateEmptyState()) + require.NoError(t, err) + + path := writeToFile(t, "state.json", expected) + actual, err := LoadStateFromFile(path) + require.NoError(t, err) + require.Equal(t, expected, actual) + }) + + t.Run("SinglethreadedFromBinary", func(t *testing.T) { + expected, err := NewFromState(singlethreaded.CreateEmptyState()) + require.NoError(t, err) + + path := writeToFile(t, "state.bin.gz", expected) + actual, err := LoadStateFromFile(path) + require.NoError(t, err) + require.Equal(t, expected, actual) + }) + + t.Run("MultithreadedFromBinary", func(t *testing.T) { + expected, err := NewFromState(multithreaded.CreateEmptyState()) + require.NoError(t, err) + + path := writeToFile(t, "state.bin.gz", expected) + actual, err := LoadStateFromFile(path) + require.NoError(t, err) + require.Equal(t, expected, actual) + }) +} + +func TestMultithreadedDoesNotSupportJSON(t *testing.T) { + state, err := NewFromState(multithreaded.CreateEmptyState()) + require.NoError(t, err) + + dir := t.TempDir() + path := filepath.Join(dir, "test.json") + err = serialize.Write(path, state, 0o644) + require.ErrorIs(t, err, ErrJsonNotSupported) +} + +func writeToFile(t *testing.T, filename string, data serialize.Serializable) string { + dir := t.TempDir() + path := filepath.Join(dir, filename) + require.NoError(t, serialize.Write(path, data, 0o644)) + return path +} diff --git a/cannon/multicannon/embeds/.gitkeep b/cannon/multicannon/embeds/.gitkeep new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/cannon/multicannon/exec.go b/cannon/multicannon/exec.go new file mode 100644 index 0000000000000..1372c035f5604 --- /dev/null +++ b/cannon/multicannon/exec.go @@ -0,0 +1,83 @@ +package main + +import ( + "context" + "embed" + "errors" + "fmt" + "os" + "os/exec" + "path/filepath" + + "github.com/ethereum-optimism/optimism/cannon/mipsevm/versions" +) + +// use the all directive to ensure the .gitkeep file is retained and avoid compiler errors + +//go:embed all:embeds +var vmFS embed.FS + +const baseDir = "embeds" + +func ExecuteCannon(ctx context.Context, args []string, ver versions.StateVersion) error { + switch ver { + case versions.VersionSingleThreaded, versions.VersionMultiThreaded: + default: + return errors.New("unsupported version") + } + + cannonProgramName := vmFilename(ver) + cannonProgramBin, err := vmFS.ReadFile(cannonProgramName) + if err != nil { + return err + } + cannonProgramPath, err := extractTempFile(filepath.Base(cannonProgramName), cannonProgramBin) + if err != nil { + fmt.Fprintf(os.Stderr, "Error extracting %s: %v\n", cannonProgramName, err) + os.Exit(1) + } + defer os.Remove(cannonProgramPath) + + if err := os.Chmod(cannonProgramPath, 0755); err != nil { + fmt.Fprintf(os.Stderr, "Error setting execute permission for %s: %v\n", cannonProgramName, err) + os.Exit(1) + } + + // nosemgrep: go.lang.security.audit.dangerous-exec-command.dangerous-exec-command + cmd := exec.CommandContext(ctx, cannonProgramPath, args...) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + err = cmd.Start() + if err != nil { + return fmt.Errorf("unable to launch cannon-impl program: %w", err) + } + if err := cmd.Wait(); err != nil { + var exitErr *exec.ExitError + if errors.As(err, &exitErr) { + // relay exit code to the parent process + os.Exit(exitErr.ExitCode()) + } else { + return fmt.Errorf("failed to wait for cannon-impl program: %w", err) + } + } + return nil +} + +func extractTempFile(name string, data []byte) (string, error) { + tempDir := os.TempDir() + tempFile, err := os.CreateTemp(tempDir, name+"-*") + if err != nil { + return "", err + } + defer tempFile.Close() + + if _, err := tempFile.Write(data); err != nil { + return "", err + } + + return tempFile.Name(), nil +} + +func vmFilename(ver versions.StateVersion) string { + return fmt.Sprintf("%s/cannon-%d", baseDir, ver) +} diff --git a/cannon/multicannon/list.go b/cannon/multicannon/list.go new file mode 100644 index 0000000000000..6e9e8a68b65a9 --- /dev/null +++ b/cannon/multicannon/list.go @@ -0,0 +1,73 @@ +package main + +import ( + "fmt" + "math" + "strconv" + "strings" + + "github.com/urfave/cli/v2" + + "github.com/ethereum-optimism/optimism/cannon/mipsevm/versions" +) + +func List(ctx *cli.Context) error { + return list() +} + +func list() error { + fmt.Println("Available cannon versions:") + artifacts, err := getArtifacts() + if err != nil { + return err + } + for _, art := range artifacts { + if art.isValid() { + fmt.Printf("filename: %s\tversion: %s (%d)\n", art.filename, versions.StateVersion(art.ver), art.ver) + } else { + fmt.Printf("filename: %s\tversion: %s\n", art.filename, "unknown") + } + } + return nil +} + +func getArtifacts() ([]artifact, error) { + var ret []artifact + entries, err := vmFS.ReadDir(baseDir) + if err != nil { + return nil, err + } + for _, entry := range entries { + filename := entry.Name() + toks := strings.Split(filename, "-") + if len(toks) != 2 { + continue + } + if toks[0] != "cannon" { + continue + } + ver, err := strconv.ParseUint(toks[1], 10, 8) + if err != nil { + ret = append(ret, artifact{filename, math.MaxUint64}) + continue + } + ret = append(ret, artifact{filename, ver}) + } + return ret, nil +} + +type artifact struct { + filename string + ver uint64 +} + +func (a artifact) isValid() bool { + return a.ver != math.MaxUint64 +} + +var ListCommand = &cli.Command{ + Name: "list", + Usage: "List embedded Cannon VM implementations", + Description: "List embedded Cannon VM implementations", + Action: List, +} diff --git a/cannon/multicannon/load_elf.go b/cannon/multicannon/load_elf.go new file mode 100644 index 0000000000000..cbe1fda463039 --- /dev/null +++ b/cannon/multicannon/load_elf.go @@ -0,0 +1,31 @@ +package main + +import ( + "fmt" + "os" + + "github.com/ethereum-optimism/optimism/cannon/cmd" + "github.com/ethereum-optimism/optimism/cannon/mipsevm/versions" + "github.com/urfave/cli/v2" +) + +func LoadELF(ctx *cli.Context) error { + if len(os.Args) == 2 && os.Args[2] == "--help" { + if err := list(); err != nil { + return err + } + fmt.Println("use `--type --help` to get more detailed help") + } + + typ, err := parseFlag(os.Args[1:], "--type") + if err != nil { + return err + } + ver, err := versions.ParseStateVersion(typ) + if err != nil { + return err + } + return ExecuteCannon(ctx.Context, os.Args[1:], ver) +} + +var LoadELFCommand = cmd.CreateLoadELFCommand(LoadELF) diff --git a/cannon/multicannon/main.go b/cannon/multicannon/main.go new file mode 100644 index 0000000000000..e496eba880ba7 --- /dev/null +++ b/cannon/multicannon/main.go @@ -0,0 +1,46 @@ +package main + +import ( + "context" + "errors" + "fmt" + "os" + + "github.com/ethereum-optimism/optimism/cannon/multicannon/version" + opservice "github.com/ethereum-optimism/optimism/op-service" + "github.com/ethereum-optimism/optimism/op-service/ctxinterrupt" + "github.com/urfave/cli/v2" +) + +var ( + GitCommit = "" + GitDate = "" +) + +// VersionWithMeta holds the textual version string including the metadata. +var VersionWithMeta = opservice.FormatVersion(version.Version, GitCommit, GitDate, version.Meta) + +func main() { + app := cli.NewApp() + app.Name = "multicannon" + app.Usage = "MIPS Fault Proof tool" + app.Description = "MIPS Fault Proof tool" + app.Version = VersionWithMeta + app.Commands = []*cli.Command{ + LoadELFCommand, + WitnessCommand, + RunCommand, + ListCommand, + } + ctx := ctxinterrupt.WithCancelOnInterrupt(context.Background()) + err := app.RunContext(ctx, os.Args) + if err != nil { + if errors.Is(err, ctx.Err()) { + _, _ = fmt.Fprintf(os.Stderr, "command interrupted") + os.Exit(130) + } else { + _, _ = fmt.Fprintf(os.Stderr, "error: %v", err) + os.Exit(1) + } + } +} diff --git a/cannon/multicannon/run.go b/cannon/multicannon/run.go new file mode 100644 index 0000000000000..532cf317fb21c --- /dev/null +++ b/cannon/multicannon/run.go @@ -0,0 +1,39 @@ +package main + +import ( + "fmt" + "os" + + "github.com/urfave/cli/v2" + + "github.com/ethereum-optimism/optimism/cannon/mipsevm/versions" +) + +func Run(ctx *cli.Context) error { + fmt.Printf("args %v\n", os.Args[:]) + if len(os.Args) == 3 && os.Args[2] == "--help" { + if err := list(); err != nil { + return err + } + fmt.Println("use `--input --help` to get more detailed help") + } + + inputPath, err := parsePathFlag(os.Args[1:], "--input") + if err != nil { + return err + } + version, err := versions.DetectVersion(inputPath) + if err != nil { + return err + } + return ExecuteCannon(ctx.Context, os.Args[1:], version) +} + +// var RunCommand = cmd.CreateRunCommand(Run) +var RunCommand = &cli.Command{ + Name: "run", + Usage: "Run VM step(s) and generate proof data to replicate onchain.", + Description: "Run VM step(s) and generate proof data to replicate onchain. See flags to match when to output a proof, a snapshot, or to stop early.", + Action: Run, + SkipFlagParsing: true, +} diff --git a/cannon/multicannon/util.go b/cannon/multicannon/util.go new file mode 100644 index 0000000000000..ea484c6ce2d2f --- /dev/null +++ b/cannon/multicannon/util.go @@ -0,0 +1,37 @@ +package main + +import ( + "errors" + "fmt" + "os" + "strings" +) + +// parseFlag reads a flag argument. It assumes the flag has an argument +func parseFlag(args []string, flag string) (string, error) { + for i := 0; i < len(args); i++ { + arg := args[i] + if strings.HasPrefix(arg, flag) { + toks := strings.Split(arg, "=") + if len(toks) == 2 { + return toks[1], nil + } else if i+1 == len(args) { + return "", fmt.Errorf("flag needs an argument: %s", flag) + } else { + return args[i+1], nil + } + } + } + return "", fmt.Errorf("missing flag: %s", flag) +} + +func parsePathFlag(args []string, flag string) (string, error) { + path, err := parseFlag(args, flag) + if err != nil { + return "", err + } + if _, err := os.Stat(path); errors.Is(err, os.ErrNotExist) { + return "", fmt.Errorf("file `%s` does not exist", path) + } + return path, nil +} diff --git a/cannon/multicannon/util_test.go b/cannon/multicannon/util_test.go new file mode 100644 index 0000000000000..9997b1315a8f1 --- /dev/null +++ b/cannon/multicannon/util_test.go @@ -0,0 +1,68 @@ +package main + +import ( + "strings" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestParseFlag(t *testing.T) { + cases := []struct { + name string + args string + flag string + expect string + expectErr string + }{ + { + name: "bar=one", + args: "--foo --bar=one --baz", + flag: "--bar", + expect: "one", + }, + { + name: "bar one", + args: "--foo --bar one --baz", + flag: "--bar", + expect: "one", + }, + { + name: "bar one first flag", + args: "--bar one --foo two --baz three", + flag: "--bar", + expect: "one", + }, + { + name: "bar one last flag", + args: "--foo --baz --bar one", + flag: "--bar", + expect: "one", + }, + { + name: "non-existent flag", + args: "--foo one", + flag: "--bar", + expectErr: "missing flag", + }, + { + name: "empty args", + args: "", + flag: "--foo", + expectErr: "missing flag", + }, + } + for _, tt := range cases { + tt := tt + t.Run(tt.name, func(t *testing.T) { + args := strings.Split(tt.args, " ") + result, err := parseFlag(args, tt.flag) + if tt.expectErr != "" { + require.ErrorContains(t, err, tt.expectErr) + } else { + require.NoError(t, err) + require.Equal(t, tt.expect, result) + } + }) + } +} diff --git a/cannon/multicannon/version/version.go b/cannon/multicannon/version/version.go new file mode 100644 index 0000000000000..2456f656d45c1 --- /dev/null +++ b/cannon/multicannon/version/version.go @@ -0,0 +1,6 @@ +package version + +var ( + Version = "v0.0.0" + Meta = "dev" +) diff --git a/cannon/multicannon/witness.go b/cannon/multicannon/witness.go new file mode 100644 index 0000000000000..077d0d3f1aed5 --- /dev/null +++ b/cannon/multicannon/witness.go @@ -0,0 +1,32 @@ +package main + +import ( + "fmt" + "os" + + "github.com/urfave/cli/v2" + + "github.com/ethereum-optimism/optimism/cannon/cmd" + "github.com/ethereum-optimism/optimism/cannon/mipsevm/versions" +) + +func Witness(ctx *cli.Context) error { + if len(os.Args) == 3 && os.Args[2] == "--help" { + if err := list(); err != nil { + return err + } + fmt.Println("use `--input --help` to get more detailed help") + } + + inputPath, err := parsePathFlag(os.Args[1:], "--input") + if err != nil { + return err + } + version, err := versions.DetectVersion(inputPath) + if err != nil { + return err + } + return ExecuteCannon(ctx.Context, os.Args[1:], version) +} + +var WitnessCommand = cmd.CreateWitnessCommand(Witness) diff --git a/cannon/serialize/binary.go b/cannon/serialize/binary.go new file mode 100644 index 0000000000000..aeaf14c5b4930 --- /dev/null +++ b/cannon/serialize/binary.go @@ -0,0 +1,64 @@ +package serialize + +import ( + "errors" + "fmt" + "io" + "reflect" + + "github.com/ethereum-optimism/optimism/op-service/ioutil" +) + +// Deserializable defines functionality for a type that may be deserialized from raw bytes. +type Deserializable interface { + // Deserialize decodes raw bytes into the type. + Deserialize(in io.Reader) error +} + +// Serializable defines functionality for a type that may be serialized to raw bytes. +type Serializable interface { + // Serialize encodes the type as raw bytes. + Serialize(out io.Writer) error +} + +func LoadSerializedBinary[X any](inputPath string) (*X, error) { + if inputPath == "" { + return nil, errors.New("no path specified") + } + var f io.ReadCloser + f, err := ioutil.OpenDecompressed(inputPath) + if err != nil { + return nil, fmt.Errorf("failed to open file %q: %w", inputPath, err) + } + defer f.Close() + + var x X + serializable, ok := reflect.ValueOf(&x).Interface().(Deserializable) + if !ok { + return nil, fmt.Errorf("%T is not a Serializable", x) + } + err = serializable.Deserialize(f) + if err != nil { + return nil, err + } + return &x, nil +} + +func WriteSerializedBinary(value Serializable, target ioutil.OutputTarget) error { + out, closer, abort, err := target() + if err != nil { + return err + } + if out == nil { + return nil // Nothing to write to so skip generating content entirely + } + defer abort() + err = value.Serialize(out) + if err != nil { + return fmt.Errorf("failed to write binary: %w", err) + } + if err := closer.Close(); err != nil { + return fmt.Errorf("failed to finish write: %w", err) + } + return nil +} diff --git a/cannon/serialize/binary_test.go b/cannon/serialize/binary_test.go new file mode 100644 index 0000000000000..95700b537c405 --- /dev/null +++ b/cannon/serialize/binary_test.go @@ -0,0 +1,94 @@ +package serialize + +import ( + "encoding/binary" + "io" + "os" + "path/filepath" + "testing" + + "github.com/ethereum-optimism/optimism/op-service/ioutil" + "github.com/stretchr/testify/require" +) + +func TestRoundTripBinary(t *testing.T) { + dir := t.TempDir() + file := filepath.Join(dir, "test.bin") + data := &serializableTestData{A: []byte{0xde, 0xad}, B: 3} + err := WriteSerializedBinary(data, ioutil.ToAtomicFile(file, 0644)) + require.NoError(t, err) + + hasGzip, err := hasGzipHeader(file) + require.NoError(t, err) + require.False(t, hasGzip) + + result, err := LoadSerializedBinary[serializableTestData](file) + require.NoError(t, err) + require.EqualValues(t, data, result) +} + +func TestRoundTripBinaryWithGzip(t *testing.T) { + dir := t.TempDir() + file := filepath.Join(dir, "test.bin.gz") + data := &serializableTestData{A: []byte{0xde, 0xad}, B: 3} + err := WriteSerializedBinary(data, ioutil.ToAtomicFile(file, 0644)) + require.NoError(t, err) + + hasGzip, err := hasGzipHeader(file) + require.NoError(t, err) + require.True(t, hasGzip) + + result, err := LoadSerializedBinary[serializableTestData](file) + require.NoError(t, err) + require.EqualValues(t, data, result) +} + +func hasGzipHeader(filename string) (bool, error) { + file, err := os.Open(filename) + if err != nil { + return false, err + } + defer file.Close() + + header := make([]byte, 2) + _, err = file.Read(header) + if err != nil { + return false, err + } + + // Gzip header magic numbers: 1F 8B + return header[0] == 0x1F && header[1] == 0x8B, nil +} + +type serializableTestData struct { + A []byte + B uint8 +} + +func (s *serializableTestData) Serialize(w io.Writer) error { + if err := binary.Write(w, binary.BigEndian, uint64(len(s.A))); err != nil { + return err + } + if _, err := w.Write(s.A); err != nil { + return err + } + if err := binary.Write(w, binary.BigEndian, s.B); err != nil { + return err + } + return nil +} + +func (s *serializableTestData) Deserialize(in io.Reader) error { + var lenA uint64 + if err := binary.Read(in, binary.BigEndian, &lenA); err != nil { + return err + } + s.A = make([]byte, lenA) + if _, err := io.ReadFull(in, s.A); err != nil { + return err + } + if err := binary.Read(in, binary.BigEndian, &s.B); err != nil { + return err + } + return nil +} diff --git a/cannon/serialize/detect.go b/cannon/serialize/detect.go new file mode 100644 index 0000000000000..13cf3aef849ea --- /dev/null +++ b/cannon/serialize/detect.go @@ -0,0 +1,20 @@ +package serialize + +import ( + "os" + "strings" + + "github.com/ethereum-optimism/optimism/op-service/ioutil" + "github.com/ethereum-optimism/optimism/op-service/jsonutil" +) + +func Write[X Serializable](outputPath string, x X, perm os.FileMode) error { + if IsBinaryFile(outputPath) { + return WriteSerializedBinary(x, ioutil.ToStdOutOrFileOrNoop(outputPath, perm)) + } + return jsonutil.WriteJSON[X](x, ioutil.ToStdOutOrFileOrNoop(outputPath, perm)) +} + +func IsBinaryFile(path string) bool { + return strings.HasSuffix(path, ".bin") || strings.HasSuffix(path, ".bin.gz") +} diff --git a/cannon/serialize/detect_test.go b/cannon/serialize/detect_test.go new file mode 100644 index 0000000000000..22ac747a10447 --- /dev/null +++ b/cannon/serialize/detect_test.go @@ -0,0 +1,60 @@ +package serialize + +import ( + "io" + "path/filepath" + "testing" + + "github.com/ethereum-optimism/optimism/op-service/ioutil" + "github.com/ethereum-optimism/optimism/op-service/jsonutil" + "github.com/stretchr/testify/require" +) + +func TestRoundtrip(t *testing.T) { + tests := []struct { + filename string + expectJSON bool + expectGzip bool + }{ + {filename: "test.json", expectJSON: true, expectGzip: false}, + {filename: "test.json.gz", expectJSON: true, expectGzip: true}, + {filename: "test.foo", expectJSON: true, expectGzip: false}, + {filename: "test.foo.gz", expectJSON: true, expectGzip: true}, + {filename: "test.bin", expectJSON: false, expectGzip: false}, + {filename: "test.bin.gz", expectJSON: false, expectGzip: true}, + } + + for _, test := range tests { + test := test + t.Run(test.filename, func(t *testing.T) { + path := filepath.Join(t.TempDir(), test.filename) + + data := &serializableTestData{A: []byte{0xde, 0xad}, B: 3} + err := Write[*serializableTestData](path, data, 0644) + require.NoError(t, err) + + hasGzip, err := hasGzipHeader(path) + require.NoError(t, err) + require.Equal(t, test.expectGzip, hasGzip) + + decompressed, err := ioutil.OpenDecompressed(path) + require.NoError(t, err) + defer decompressed.Close() + start := make([]byte, 1) + _, err = io.ReadFull(decompressed, start) + require.NoError(t, err) + var load func(path string) (*serializableTestData, error) + if test.expectJSON { + load = jsonutil.LoadJSON[serializableTestData] + require.Equal(t, "{", string(start)) + } else { + load = LoadSerializedBinary[serializableTestData] + require.NotEqual(t, "{", string(start)) + } + + result, err := load(path) + require.NoError(t, err) + require.EqualValues(t, data, result) + }) + } +} diff --git a/cannon/serialize/reader.go b/cannon/serialize/reader.go new file mode 100644 index 0000000000000..53f4440659a41 --- /dev/null +++ b/cannon/serialize/reader.go @@ -0,0 +1,60 @@ +package serialize + +import ( + "encoding/binary" + "fmt" + "io" + + "github.com/ethereum/go-ethereum/common" +) + +// BinaryReader provides methods to decode content written by BinaryWriter. +type BinaryReader struct { + in io.Reader +} + +func NewBinaryReader(in io.Reader) *BinaryReader { + return &BinaryReader{in: in} +} + +func (r *BinaryReader) ReadUInt(target any) error { + return binary.Read(r.in, binary.BigEndian, target) +} + +func (r *BinaryReader) ReadHash(target *common.Hash) error { + _, err := io.ReadFull(r.in, target[:]) + return err +} + +func (r *BinaryReader) ReadBool(target *bool) error { + var v uint8 + if err := r.ReadUInt(&v); err != nil { + return err + } + switch v { + case 0: + *target = false + case 1: + *target = true + default: + return fmt.Errorf("invalid boolean value: %v", v) + } + return nil +} + +func (r *BinaryReader) ReadBytes(target *[]byte) error { + var size uint32 + if err := r.ReadUInt(&size); err != nil { + return err + } + if size == 0 { + *target = nil + return nil + } + data := make([]byte, size) + if _, err := io.ReadFull(r.in, data); err != nil { + return err + } + *target = data + return nil +} diff --git a/cannon/serialize/reader_test.go b/cannon/serialize/reader_test.go new file mode 100644 index 0000000000000..0d6b8678c5926 --- /dev/null +++ b/cannon/serialize/reader_test.go @@ -0,0 +1,48 @@ +package serialize + +import ( + "bytes" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" +) + +func TestRoundTripWithReader(t *testing.T) { + // Test that reader can read the data written by BinaryWriter. + // The writer tests check that the generated data is what is expected, so simply check that the reader correctly + // parses a range of data here rather than duplicating the expected binary serialization. + buf := new(bytes.Buffer) + out := NewBinaryWriter(buf) + require.NoError(t, out.WriteBool(true)) + require.NoError(t, out.WriteBool(false)) + require.NoError(t, out.WriteUInt(uint8(5))) + require.NoError(t, out.WriteUInt(uint32(76))) + require.NoError(t, out.WriteUInt(uint64(24824424))) + expectedHash := common.HexToHash("0x5a8f75b8e1c1529d1d1c596464d17b99763604f4c00b280436fc0dffacc60efd") + require.NoError(t, out.WriteHash(expectedHash)) + expectedBytes := []byte{1, 2, 3, 4, 5, 6, 7, 8, 9} + require.NoError(t, out.WriteBytes(expectedBytes)) + + in := NewBinaryReader(buf) + var b bool + require.NoError(t, in.ReadBool(&b)) + require.True(t, b) + require.NoError(t, in.ReadBool(&b)) + require.False(t, b) + var vUInt8 uint8 + require.NoError(t, in.ReadUInt(&vUInt8)) + require.Equal(t, uint8(5), vUInt8) + var vUInt32 uint32 + require.NoError(t, in.ReadUInt(&vUInt32)) + require.Equal(t, uint32(76), vUInt32) + var vUInt64 uint64 + require.NoError(t, in.ReadUInt(&vUInt64)) + require.Equal(t, uint64(24824424), vUInt64) + var hash common.Hash + require.NoError(t, in.ReadHash(&hash)) + require.Equal(t, expectedHash, hash) + var data []byte + require.NoError(t, in.ReadBytes(&data)) + require.Equal(t, expectedBytes, data) +} diff --git a/cannon/serialize/writer.go b/cannon/serialize/writer.go new file mode 100644 index 0000000000000..a8790115a11c3 --- /dev/null +++ b/cannon/serialize/writer.go @@ -0,0 +1,44 @@ +package serialize + +import ( + "encoding/binary" + "io" + + "github.com/ethereum/go-ethereum/common" +) + +// BinaryWriter writes a simple binary format which can be read again using BinaryReader. +// The format is a simple concatenation of values, with prefixed length for variable length items. +// All numbers are encoded using big endian. +type BinaryWriter struct { + out io.Writer +} + +func NewBinaryWriter(out io.Writer) *BinaryWriter { + return &BinaryWriter{out: out} +} + +func (w *BinaryWriter) WriteUInt(v any) error { + return binary.Write(w.out, binary.BigEndian, v) +} + +func (w *BinaryWriter) WriteHash(v common.Hash) error { + _, err := w.out.Write(v[:]) + return err +} + +func (w *BinaryWriter) WriteBool(v bool) error { + if v { + return w.WriteUInt(uint8(1)) + } else { + return w.WriteUInt(uint8(0)) + } +} + +func (w *BinaryWriter) WriteBytes(v []byte) error { + if err := w.WriteUInt(uint32(len(v))); err != nil { + return err + } + _, err := w.out.Write(v) + return err +} diff --git a/cannon/serialize/writer_test.go b/cannon/serialize/writer_test.go new file mode 100644 index 0000000000000..d37b18da094f2 --- /dev/null +++ b/cannon/serialize/writer_test.go @@ -0,0 +1,102 @@ +package serialize + +import ( + "bytes" + "fmt" + "math" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" +) + +func TestUInt(t *testing.T) { + tests := []struct { + name string + val any + expected []byte + }{ + {name: "uint8-zero", val: uint8(0), expected: []byte{0}}, + {name: "uint8-one", val: uint8(1), expected: []byte{1}}, + {name: "uint8-big", val: uint8(156), expected: []byte{156}}, + {name: "uint8-max", val: uint8(math.MaxUint8), expected: []byte{255}}, + + {name: "uint16-zero", val: uint16(0), expected: []byte{0, 0}}, + {name: "uint16-one", val: uint16(1), expected: []byte{0, 1}}, + {name: "uint16-big", val: uint16(1283), expected: []byte{5, 3}}, + {name: "uint16-max", val: uint16(math.MaxUint16), expected: []byte{255, 255}}, + + {name: "uint32-zero", val: uint32(0), expected: []byte{0, 0, 0, 0}}, + {name: "uint32-one", val: uint32(1), expected: []byte{0, 0, 0, 1}}, + {name: "uint32-big", val: uint32(1283424245), expected: []byte{0x4c, 0x7f, 0x7f, 0xf5}}, + {name: "uint32-max", val: uint32(math.MaxUint32), expected: []byte{255, 255, 255, 255}}, + + {name: "uint64-zero", val: uint64(0), expected: []byte{0, 0, 0, 0, 0, 0, 0, 0}}, + {name: "uint64-one", val: uint64(1), expected: []byte{0, 0, 0, 0, 0, 0, 0, 1}}, + {name: "uint64-big", val: uint64(1283424245242429284), expected: []byte{0x11, 0xcf, 0xa3, 0x8d, 0x19, 0xcc, 0x7f, 0x64}}, + {name: "uint64-max", val: uint64(math.MaxUint64), expected: []byte{255, 255, 255, 255, 255, 255, 255, 255}}, + } + + for _, test := range tests { + test := test + t.Run(test.name, func(t *testing.T) { + out := new(bytes.Buffer) + bout := NewBinaryWriter(out) + require.NoError(t, bout.WriteUInt(test.val)) + result := out.Bytes() + require.Equal(t, test.expected, result) + }) + } +} + +func TestWriteHash(t *testing.T) { + out := new(bytes.Buffer) + bout := NewBinaryWriter(out) + hash := common.HexToHash("0x5a8f75b8e1c1529d1d1c596464d17b99763604f4c00b280436fc0dffacc60efd") + require.NoError(t, bout.WriteHash(hash)) + + result := out.Bytes() + require.Equal(t, hash[:], result) +} + +func TestWriteBool(t *testing.T) { + for _, val := range []bool{true, false} { + val := val + t.Run(fmt.Sprintf("%t", val), func(t *testing.T) { + out := new(bytes.Buffer) + bout := NewBinaryWriter(out) + require.NoError(t, bout.WriteBool(val)) + + result := out.Bytes() + require.Len(t, result, 1) + if val { + require.Equal(t, result[0], uint8(1)) + } else { + require.Equal(t, result[0], uint8(0)) + } + }) + } +} + +func TestWriteBytes(t *testing.T) { + tests := []struct { + name string + val []byte + expected []byte + }{ + {name: "nil", val: nil, expected: []byte{0, 0, 0, 0}}, + {name: "empty", val: []byte{}, expected: []byte{0, 0, 0, 0}}, + {name: "non-empty", val: []byte{1, 2, 3, 4, 5}, expected: []byte{0, 0, 0, 5, 1, 2, 3, 4, 5}}, + } + for _, test := range tests { + test := test + t.Run(test.name, func(t *testing.T) { + out := new(bytes.Buffer) + bout := NewBinaryWriter(out) + require.NoError(t, bout.WriteBytes(test.val)) + + result := out.Bytes() + require.Equal(t, test.expected, result) + }) + } +} diff --git a/cannon/testdata/example/alloc/go.mod b/cannon/testdata/example/alloc/go.mod index 4068cbf1ddf61..d4d3c23faf2d9 100644 --- a/cannon/testdata/example/alloc/go.mod +++ b/cannon/testdata/example/alloc/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.26.0 // indirect - golang.org/x/sys v0.24.0 // indirect + golang.org/x/crypto v0.27.0 // indirect + golang.org/x/sys v0.25.0 // indirect ) replace github.com/ethereum-optimism/optimism v0.0.0 => ../../../.. diff --git a/cannon/testdata/example/alloc/go.sum b/cannon/testdata/example/alloc/go.sum index 7fb6c4a685ae2..c319c56516338 100644 --- a/cannon/testdata/example/alloc/go.sum +++ b/cannon/testdata/example/alloc/go.sum @@ -4,9 +4,9 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 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.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= -golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= -golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= -golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= +golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.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/testdata/example/alloc/main.go b/cannon/testdata/example/alloc/main.go index 41bc67000d2bb..3c7af2f165f50 100644 --- a/cannon/testdata/example/alloc/main.go +++ b/cannon/testdata/example/alloc/main.go @@ -12,20 +12,27 @@ func main() { var mem []byte po := preimage.NewOracleClient(preimage.ClientPreimageChannel()) numAllocs := binary.LittleEndian.Uint64(po.Get(preimage.LocalIndexKey(0))) + allocSize := binary.LittleEndian.Uint64(po.Get(preimage.LocalIndexKey(1))) - fmt.Printf("alloc program. numAllocs=%d\n", numAllocs) + fmt.Printf("alloc program. numAllocs=%d allocSize=%d\n", numAllocs, allocSize) var alloc int for i := 0; i < int(numAllocs); i++ { - mem = make([]byte, 32*1024*1024) + mem = make([]byte, allocSize) alloc += len(mem) // touch a couple pages to prevent the runtime from overcommitting memory for j := 0; j < len(mem); j += 1024 { mem[j] = 0xFF } - fmt.Printf("allocated %d bytes\n", alloc) + printGCStats(alloc) } + fmt.Println("alloc program exit") + printGCStats(alloc) +} + +func printGCStats(alloc int) { var m runtime.MemStats runtime.ReadMemStats(&m) - fmt.Printf("alloc program exit. memstats: heap_alloc=%d frees=%d mallocs=%d\n", m.HeapAlloc, m.Frees, m.Mallocs) + fmt.Printf("allocated %d bytes. memstats: heap_alloc=%d next_gc=%d frees=%d mallocs=%d num_gc=%d\n", + alloc, m.HeapAlloc, m.NextGC, m.Frees, m.Mallocs, m.NumGC) } diff --git a/cannon/testdata/example/claim/go.mod b/cannon/testdata/example/claim/go.mod index 8b88d2cf5c32e..c70d9906f06ca 100644 --- a/cannon/testdata/example/claim/go.mod +++ b/cannon/testdata/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.26.0 // indirect - golang.org/x/sys v0.24.0 // indirect + golang.org/x/crypto v0.27.0 // indirect + golang.org/x/sys v0.25.0 // indirect ) replace github.com/ethereum-optimism/optimism v0.0.0 => ../../../.. diff --git a/cannon/testdata/example/claim/go.sum b/cannon/testdata/example/claim/go.sum index 7fb6c4a685ae2..c319c56516338 100644 --- a/cannon/testdata/example/claim/go.sum +++ b/cannon/testdata/example/claim/go.sum @@ -4,9 +4,9 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 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.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= -golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= -golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= -golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= +golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.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/testdata/example/entry/go.mod b/cannon/testdata/example/entry/go.mod new file mode 100644 index 0000000000000..2e4d29124f548 --- /dev/null +++ b/cannon/testdata/example/entry/go.mod @@ -0,0 +1,3 @@ +module entry + +go 1.21 diff --git a/cannon/testdata/example/entry/main.go b/cannon/testdata/example/entry/main.go new file mode 100644 index 0000000000000..78866f88abebf --- /dev/null +++ b/cannon/testdata/example/entry/main.go @@ -0,0 +1,30 @@ +package main + +import ( + "os" + "runtime" +) + +func main() { + if len(os.Args) != 1 { + panic("expected 1 arg") + } + if os.Args[0] != "op-program" { + panic("unexpected arg0") + } + + var memProfileRate bool + env := os.Environ() + for _, env := range env { + if env != "GODEBUG=memprofilerate=0" { + panic("invalid envar") + } + memProfileRate = true + } + if !memProfileRate { + panic("memProfileRate env is not set") + } + if runtime.MemProfileRate != 0 { + panic("runtime.MemProfileRate is non-zero") + } +} diff --git a/docker-bake.hcl b/docker-bake.hcl index d57ab76e7e62f..b094959487458 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -69,6 +69,9 @@ variable "OP_CONDUCTOR_VERSION" { default = "${GIT_VERSION}" } +variable "OP_DEPLOYER_VERSION" { + default = "${GIT_VERSION}" +} target "op-node" { dockerfile = "ops/docker/op-stack-go/Dockerfile" @@ -199,6 +202,19 @@ target "cannon" { tags = [for tag in split(",", IMAGE_TAGS) : "${REGISTRY}/${REPOSITORY}/cannon:${tag}"] } +target "proofs-tools" { + dockerfile = "./ops/docker/proofs-tools/Dockerfile" + context = "." + args = { + CHALLENGER_VERSION="90700b9bb37080961747420882b14578577d47cc" + KONA_VERSION="kona-client-v0.1.0-alpha.3" + ASTERISC_VERSION="v1.0.2" + } + target="proofs-tools" + platforms = split(",", PLATFORMS) + tags = [for tag in split(",", IMAGE_TAGS) : "${REGISTRY}/${REPOSITORY}/proofs-tools:${tag}"] +} + target "ci-builder" { dockerfile = "./ops/docker/ci-builder/Dockerfile" context = "." @@ -219,6 +235,20 @@ target "contracts-bedrock" { dockerfile = "./ops/docker/Dockerfile.packages" context = "." target = "contracts-bedrock" - platforms = split(",", PLATFORMS) + # See comment in Dockerfile.packages for why we only build for linux/amd64. + platforms = ["linux/amd64"] tags = [for tag in split(",", IMAGE_TAGS) : "${REGISTRY}/${REPOSITORY}/contracts-bedrock:${tag}"] } + +target "op-deployer" { + dockerfile = "ops/docker/op-stack-go/Dockerfile" + context = "." + args = { + GIT_COMMIT = "${GIT_COMMIT}" + GIT_DATE = "${GIT_DATE}" + OP_DEPLOYER_VERSION = "${OP_DEPLOYER_VERSION}" + } + target = "op-deployer-target" + platforms = split(",", PLATFORMS) + tags = [for tag in split(",", IMAGE_TAGS) : "${REGISTRY}/${REPOSITORY}/op-deployer:${tag}"] +} diff --git a/docs/README.md b/docs/README.md index da82e0a7f6aa6..cabb2506b084f 100644 --- a/docs/README.md +++ b/docs/README.md @@ -6,4 +6,3 @@ The directory layout is divided into the following sub-directories. - [`postmortems/`](./postmortems/): Timestamped post-mortem documents. - [`security-reviews`](./security-reviews/): Audit summaries and other security review documents. -- [`fault-proof-alpha`](./fault-proof-alpha): Information on the alpha version of the fault proof system. diff --git a/go.mod b/go.mod index e8a150cb6a1d6..4681c720ba8ca 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/crate-crypto/go-kzg-4844 v1.0.0 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3 - github.com/ethereum-optimism/superchain-registry/superchain v0.0.0-20240821192748-42bd03ba8313 + github.com/ethereum-optimism/superchain-registry/superchain v0.0.0-20240910145426-b3905c89e8ac github.com/ethereum/go-ethereum v1.14.8 github.com/fsnotify/fsnotify v1.7.0 github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb @@ -20,12 +20,13 @@ require ( github.com/google/gofuzz v1.2.1-0.20220503160820-4a35382e8fc8 github.com/hashicorp/go-multierror v1.1.1 github.com/hashicorp/golang-lru/v2 v2.0.7 - github.com/hashicorp/raft v1.7.0 + github.com/hashicorp/raft v1.7.1 github.com/hashicorp/raft-boltdb/v2 v2.3.0 github.com/holiman/uint256 v1.3.1 github.com/ipfs/go-datastore v0.6.0 github.com/ipfs/go-ds-leveldb v0.5.0 github.com/klauspost/compress v1.17.9 + github.com/kurtosis-tech/kurtosis/api/golang v1.3.0 github.com/libp2p/go-libp2p v0.36.2 github.com/libp2p/go-libp2p-mplex v0.9.0 github.com/libp2p/go-libp2p-pubsub v0.12.0 @@ -35,25 +36,28 @@ require ( github.com/multiformats/go-base32 v0.1.0 github.com/multiformats/go-multiaddr v0.13.0 github.com/multiformats/go-multiaddr-dns v0.3.1 + github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416 github.com/olekukonko/tablewriter v0.0.5 github.com/onsi/gomega v1.34.1 github.com/pkg/errors v0.9.1 github.com/pkg/profile v1.7.0 - github.com/prometheus/client_golang v1.20.2 + github.com/prometheus/client_golang v1.20.4 github.com/protolambda/ctxlock v0.1.0 github.com/stretchr/testify v1.9.0 github.com/urfave/cli/v2 v2.27.4 - golang.org/x/crypto v0.26.0 + golang.org/x/crypto v0.27.0 golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa golang.org/x/sync v0.8.0 - golang.org/x/term v0.23.0 + golang.org/x/term v0.24.0 golang.org/x/time v0.6.0 ) require ( github.com/DataDog/zstd v1.5.6-0.20230824185856-869dae002e5e // indirect + github.com/Masterminds/semver/v3 v3.1.1 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect github.com/VictoriaMetrics/fastcache v1.12.2 // indirect + github.com/adrg/xdg v0.4.0 // indirect github.com/allegro/bigcache v1.2.1 // indirect github.com/armon/go-metrics v0.4.1 // indirect github.com/benbjohnson/clock v1.3.5 // indirect @@ -84,6 +88,7 @@ require ( github.com/docker/go-units v0.5.0 // indirect github.com/donovanhide/eventsource v0.0.0-20210830082556-c59027999da0 // indirect github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127 // indirect + github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/elastic/gosigar v0.14.3 // indirect github.com/ethereum/c-kzg-4844 v1.0.0 // indirect @@ -95,15 +100,18 @@ require ( github.com/francoispqt/gojay v1.2.13 // indirect github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect github.com/getsentry/sentry-go v0.27.0 // indirect + github.com/ghodss/yaml v1.0.0 // indirect github.com/go-ini/ini v1.67.0 // indirect github.com/go-ole/go-ole v1.3.0 // indirect github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect + github.com/go-yaml/yaml v2.1.0+incompatible // indirect github.com/goccy/go-json v0.10.3 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/gofrs/flock v0.8.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt/v4 v4.5.0 // indirect + github.com/golang/protobuf v1.5.4 // indirect github.com/google/gopacket v1.1.19 // indirect github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 // indirect github.com/google/uuid v1.6.0 // indirect @@ -113,7 +121,7 @@ require ( github.com/hashicorp/go-bexpr v0.1.11 // 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/v2 v2.1.1 // indirect + github.com/hashicorp/go-msgpack/v2 v2.1.2 // indirect github.com/hashicorp/golang-lru v0.5.0 // indirect github.com/hashicorp/golang-lru/arc/v2 v2.0.7 // indirect github.com/hashicorp/raft-boltdb v0.0.0-20231211162105-6c830fa4535e // indirect @@ -135,6 +143,11 @@ require ( github.com/koron/go-ssdp v0.0.4 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect + github.com/kurtosis-tech/kurtosis-portal/api/golang v0.0.0-20230818182330-1a86869414d2 // indirect + github.com/kurtosis-tech/kurtosis/contexts-config-store v0.0.0-20230818184218-f4e3e773463b // indirect + github.com/kurtosis-tech/kurtosis/grpc-file-transfer/golang v0.0.0-20230803130419-099ee7a4e3dc // indirect + github.com/kurtosis-tech/kurtosis/path-compression v0.0.0-20240307154559-64d2929cd265 // indirect + github.com/kurtosis-tech/stacktrace v0.0.0-20211028211901-1c67a77b5409 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect github.com/libp2p/go-flow-metrics v0.1.0 // indirect github.com/libp2p/go-libp2p-asn-util v0.4.1 // indirect @@ -147,6 +160,7 @@ 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/mholt/archiver v3.1.1+incompatible // indirect github.com/miekg/dns v1.1.62 // indirect github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect @@ -165,12 +179,13 @@ require ( github.com/multiformats/go-varint v0.0.7 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/naoina/go-stringutil v0.1.0 // indirect - github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416 // indirect + github.com/nwaples/rardecode v1.1.3 // indirect github.com/onsi/ginkgo/v2 v2.20.0 // indirect github.com/opencontainers/runtime-spec v1.2.0 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 // indirect + github.com/pierrec/lz4 v2.6.1+incompatible // indirect github.com/pion/datachannel v1.5.8 // indirect github.com/pion/dtls/v2 v2.2.12 // indirect github.com/pion/ice/v2 v2.3.34 // indirect @@ -199,11 +214,12 @@ require ( github.com/quic-go/webtransport-go v0.8.0 // indirect github.com/raulk/go-watchdog v1.3.0 // indirect github.com/rivo/uniseg v0.4.4 // indirect - github.com/rogpeppe/go-internal v1.10.0 // indirect + github.com/rogpeppe/go-internal v1.11.0 // indirect github.com/rs/cors v1.11.0 // indirect github.com/rs/xid v1.6.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/shirou/gopsutil v3.21.11+incompatible // indirect + github.com/sirupsen/logrus v1.9.3 // 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.2 // indirect @@ -212,7 +228,9 @@ require ( github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/numcpus v0.6.1 // indirect github.com/tyler-smith/go-bip39 v1.1.0 // indirect + github.com/ulikunitz/xz v0.5.11 // indirect github.com/wlynxg/anet v0.0.4 // indirect + github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect github.com/yusufpapurcu/wmi v1.2.3 // indirect go.etcd.io/bbolt v1.3.5 // indirect @@ -224,9 +242,13 @@ require ( go.uber.org/zap v1.27.0 // indirect golang.org/x/mod v0.20.0 // indirect golang.org/x/net v0.28.0 // indirect - golang.org/x/sys v0.24.0 // indirect - golang.org/x/text v0.17.0 // indirect + golang.org/x/sys v0.25.0 // indirect + golang.org/x/text v0.18.0 // indirect golang.org/x/tools v0.24.0 // indirect + google.golang.org/genproto v0.0.0-20230726155614-23370e0ffb3e // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20230803162519-f966b187b2e5 // indirect + google.golang.org/grpc v1.57.1 // indirect google.golang.org/protobuf v1.34.2 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index 0c661e610830e..a92b17d143eb7 100644 --- a/go.sum +++ b/go.sum @@ -16,11 +16,15 @@ 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.6-0.20230824185856-869dae002e5e h1:ZIWapoIRN1VqT8GR8jAwb1Ie9GyehWjVcGh32Y2MznE= github.com/DataDog/zstd v1.5.6-0.20230824185856-869dae002e5e/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= +github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= +github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/VictoriaMetrics/fastcache v1.12.2 h1:N0y9ASrJ0F6h0QaC3o6uJb3NIZ9VKLjCM7NQbSmF7WI= github.com/VictoriaMetrics/fastcache v1.12.2/go.mod h1:AmC+Nzz1+3G2eCPapF6UcsnkThDcMsQicp4xDukwJYI= +github.com/adrg/xdg v0.4.0 h1:RzRqFcjH4nE5C6oTAxhBtoE2IRyjBSa62SCbyPidvls= +github.com/adrg/xdg v0.4.0/go.mod h1:N6ag73EX4wyxeaoeHctc1mas01KZgsj5tYiAIwqJE/E= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -168,6 +172,9 @@ github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127 h1:qwcF+vdFrvPSEUDSX5R github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM= +github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 h1:iFaUwBSo5Svw6L7HYpRu/0lE3e0BaElwnNO1qkNQxBY= +github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s= +github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= @@ -178,8 +185,8 @@ github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3 h1:RWHKLhCrQThMfch+QJ1Z github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3/go.mod h1:QziizLAiF0KqyLdNJYD7O5cpDlaFMNZzlxYNcWsJUxs= github.com/ethereum-optimism/op-geth v1.101408.0-rc.4.0.20240827042333-110c433a2469 h1:sGqlBjx0+z/ExU6VNo5OHSXS/5nc6BfkEQJvSdVbWp0= github.com/ethereum-optimism/op-geth v1.101408.0-rc.4.0.20240827042333-110c433a2469/go.mod h1:Mk8AhvlqFbjI9oW2ymThSSoqc6kiEH0/tCmHGMEu6ac= -github.com/ethereum-optimism/superchain-registry/superchain v0.0.0-20240821192748-42bd03ba8313 h1:SVSFg8ccdRBJxOdRS1pK8oIHvMufiPAQz1gkQsEPnZc= -github.com/ethereum-optimism/superchain-registry/superchain v0.0.0-20240821192748-42bd03ba8313/go.mod h1:XaVXL9jg8BcyOeugECgIUGa9Y3DjYJj71RHmb5qon6M= +github.com/ethereum-optimism/superchain-registry/superchain v0.0.0-20240910145426-b3905c89e8ac h1:hCIrLuOPV3FJfMDvXeOhCC3uQNvFoMIIlkT2mN2cfeg= +github.com/ethereum-optimism/superchain-registry/superchain v0.0.0-20240910145426-b3905c89e8ac/go.mod h1:XaVXL9jg8BcyOeugECgIUGa9Y3DjYJj71RHmb5qon6M= github.com/ethereum/c-kzg-4844 v1.0.0 h1:0X1LBXxaEtYD9xsyj9B9ctQEZIpnvVDeoBx8aHEwTNA= github.com/ethereum/c-kzg-4844 v1.0.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= github.com/ethereum/go-verkle v0.1.1-0.20240306133620-7d920df305f0 h1:KrE8I4reeVvf7C1tm8elRjj4BdscTYzz/WAbYyf/JI4= @@ -196,6 +203,8 @@ github.com/flynn/noise v1.1.0 h1:KjPQoQCEFdZDiP03phOvGi11+SVVhBG2wOWAorLsstg= github.com/flynn/noise v1.1.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag= github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk= github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= 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= @@ -207,6 +216,7 @@ github.com/getkin/kin-openapi v0.53.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW github.com/getkin/kin-openapi v0.61.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4= github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps= github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= +github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs= @@ -232,6 +242,8 @@ github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/me github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= +github.com/go-yaml/yaml v2.1.0+incompatible h1:RYi2hDdss1u4YE7GwixGzWwVo47T8UQwnTLB6vQiq+o= +github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0= github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA= github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= @@ -321,8 +333,8 @@ github.com/hashicorp/go-immutable-radix v1.0.0 h1:AKDB1HM5PWEA7i4nhcpwOrO2byshxB 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= github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-msgpack/v2 v2.1.1 h1:xQEY9yB2wnHitoSzk/B9UjXWRQ67QKu5AOm8aFp8N3I= -github.com/hashicorp/go-msgpack/v2 v2.1.1/go.mod h1:upybraOAblm4S7rx0+jeNy+CWWhzywQsSRV5033mMu4= +github.com/hashicorp/go-msgpack/v2 v2.1.2 h1:4Ee8FTp834e+ewB71RDrQ0VKpyFdrKOjvYtnQ/ltVj0= +github.com/hashicorp/go-msgpack/v2 v2.1.2/go.mod h1:upybraOAblm4S7rx0+jeNy+CWWhzywQsSRV5033mMu4= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= @@ -335,8 +347,8 @@ github.com/hashicorp/golang-lru/arc/v2 v2.0.7/go.mod h1:Pe7gBlGdc8clY5LJ0LpJXMt5 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.7.0 h1:4u24Qn6lQ6uwziM++UgsyiT64Q8GyRn43CV41qPiz1o= -github.com/hashicorp/raft v1.7.0/go.mod h1:N1sKh6Vn47mrWvEArQgILTyng8GoDRNYlgKyK7PMjs0= +github.com/hashicorp/raft v1.7.1 h1:ytxsNx4baHsRZrhUcbt3+79zc4ly8qm7pi0393pSchY= +github.com/hashicorp/raft v1.7.1/go.mod h1:hUeiEwQQR/Nk2iKDD0dkEhklSsu3jcAcqvPzPoZSAEM= 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/hashicorp/raft-boltdb/v2 v2.3.0 h1:fPpQR1iGEVYjZ2OELvUHX600VAK5qmdnDEv3eXOwZUA= @@ -400,8 +412,10 @@ github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQL github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM= github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= @@ -420,6 +434,18 @@ github.com/kr/pty v1.1.3/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/kurtosis-tech/kurtosis-portal/api/golang v0.0.0-20230818182330-1a86869414d2 h1:izciXrFyFR+ihJ7nLTOkoIX5GzBPIp8gVKlw94gIc98= +github.com/kurtosis-tech/kurtosis-portal/api/golang v0.0.0-20230818182330-1a86869414d2/go.mod h1:bWSMQK3WHVTGHX9CjxPAb/LtzcmfOxID2wdzakSWQxo= +github.com/kurtosis-tech/kurtosis/api/golang v1.3.0 h1:6r+ER69AgIyoHM48DLcP6r+f6dKDeU+65U8Uiibj46w= +github.com/kurtosis-tech/kurtosis/api/golang v1.3.0/go.mod h1:9T22P7Vv3j5g6sbm78DxHQ4s9C4Cj3s9JjFQ7DFyYpM= +github.com/kurtosis-tech/kurtosis/contexts-config-store v0.0.0-20230818184218-f4e3e773463b h1:hMoIM99QKcYQqsnK4AF7Lovi9ZD9ac6lZLZ5D/jx2x8= +github.com/kurtosis-tech/kurtosis/contexts-config-store v0.0.0-20230818184218-f4e3e773463b/go.mod h1:4pFdrRwDz5R+Fov2ZuTaPhAVgjA2jhGh1Izf832sX7A= +github.com/kurtosis-tech/kurtosis/grpc-file-transfer/golang v0.0.0-20230803130419-099ee7a4e3dc h1:7IlEpSehmWcNXOFpNP24Cu5HQI3af7GCBQw//m+LnvQ= +github.com/kurtosis-tech/kurtosis/grpc-file-transfer/golang v0.0.0-20230803130419-099ee7a4e3dc/go.mod h1:TOWMQgvAJH/NiWWERGXg/plT9lS7aFcXFxCa0M5sfHo= +github.com/kurtosis-tech/kurtosis/path-compression v0.0.0-20240307154559-64d2929cd265 h1:uSDftcGStwuAjHv8fV2TleNCKSWPvUKe7EaplFG3yBI= +github.com/kurtosis-tech/kurtosis/path-compression v0.0.0-20240307154559-64d2929cd265/go.mod h1:aDMrPeS7Gii8W6SDKSKyrBNgEQAUYidriyeKGf+Ml3I= +github.com/kurtosis-tech/stacktrace v0.0.0-20211028211901-1c67a77b5409 h1:YQTATifMUwZEtZYb0LVA7DK2pj8s71iY8rzweuUQ5+g= +github.com/kurtosis-tech/stacktrace v0.0.0-20211028211901-1c67a77b5409/go.mod h1:y5weVs5d9wXXHcDA1awRxkIhhHC1xxYJN8a7aXnE6S8= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/labstack/echo/v4 v4.2.1/go.mod h1:AA49e0DZ8kk5jTOOCKNuPR6oTnBS0dYiM4FW1e6jwpg= @@ -478,6 +504,8 @@ 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/mholt/archiver v3.1.1+incompatible h1:1dCVxuqs0dJseYEhi5pl7MYPH9zDa1wBi7mF09cbNkU= +github.com/mholt/archiver v3.1.1+incompatible/go.mod h1:Dh2dOXnSdiLxRiPoVfIr/fI1TwETms9B8CTWfeh7ROU= 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.62 h1:cN8OuEF1/x5Rq6Np+h1epln8OiyPWV+lROx9LxcGgIQ= @@ -544,6 +572,8 @@ github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416 h1:shk/vn9oCoOTmwcou github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E= github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= +github.com/nwaples/rardecode v1.1.3 h1:cWCaZwfM5H7nAD6PyEdcVnczzV8i/JtotnyW/dD9lEc= +github.com/nwaples/rardecode v1.1.3/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY= @@ -581,6 +611,8 @@ github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2D github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y= github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 h1:oYW+YCJ1pachXTQmzR3rNLYGGz4g/UgFcjb28p/viDM= github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= +github.com/pierrec/lz4 v2.6.1+incompatible h1:9UY3+iC23yxF0UfGaYrGplQ+79Rg+h/q9FV9ix19jjM= +github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= github.com/pion/datachannel v1.5.8 h1:ph1P1NsGkazkjrvyMfhRBUAWMxugJjq2HfQifaOoSNo= @@ -642,8 +674,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.20.2 h1:5ctymQzZlyOON1666svgwn3s6IKWgfbjsejTMiXIyjg= -github.com/prometheus/client_golang v1.20.2/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI= +github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= 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= @@ -686,8 +718,8 @@ github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUc github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/rs/cors v1.11.0 h1:0B9GE/r9Bc2UxRMMtymBkHTenPkHDv0CW4Y98GBY+po= github.com/rs/cors v1.11.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU= @@ -725,6 +757,8 @@ github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5k github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= @@ -764,6 +798,9 @@ github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9f github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= 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/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8= +github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli/v2 v2.27.4 h1:o1owoI+02Eb+K107p27wEX9Bb8eqIoZCfLXloLUSWJ8= github.com/urfave/cli/v2 v2.27.4/go.mod h1:m4QzxcD2qpra4z7WhzEGn74WZLViBnMpb1ToCAKdGRQ= @@ -775,6 +812,8 @@ github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMI github.com/wlynxg/anet v0.0.3/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA= github.com/wlynxg/anet v0.0.4 h1:0de1OFQxnNqAu+x2FAKKCVIrnfGKQbs7FQz++tB0+Uw= github.com/wlynxg/anet v0.0.4/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA= +github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo= +github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -826,8 +865,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= -golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= -golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= +golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= +golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa h1:ELnwvuAXPNtPk1TJRuGkI9fDTwym6AYBu0qzT8AcHdI= golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ= @@ -937,11 +976,13 @@ 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-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/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-20220715151400-c0bba94af5f8/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= @@ -953,8 +994,8 @@ golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= -golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.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= @@ -963,8 +1004,8 @@ golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= -golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU= -golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= +golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= +golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= 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= @@ -977,8 +1018,8 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= -golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= +golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1023,10 +1064,18 @@ 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 v0.0.0-20230726155614-23370e0ffb3e h1:xIXmWJ303kJCuogpj0bHq+dcjcZHU+XFyc1I0Yl9cRg= +google.golang.org/genproto v0.0.0-20230726155614-23370e0ffb3e/go.mod h1:0ggbjUrZYpy1q+ANUS30SEoGZ53cdfwtbuG7Ptgy108= +google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 h1:FmF5cCW94Ij59cfpoLiwTgodWmm60eEV0CjlsVg2fuw= +google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98/go.mod h1:rsr7RhLuwsDKL7RmgDDCUc6yaGr1iqceVb5Wv6f6YvQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230803162519-f966b187b2e5 h1:eSaPbMR4T7WfH9FvABk36NBMacoTUKdWCvV0dx+KfOg= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230803162519-f966b187b2e5/go.mod h1:zBEcrKX2ZOcEkHWxBPAIvYUWOKKMIhYcmNiUIu2ji3I= 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.57.1 h1:upNTNqv0ES+2ZOOqACwVtS3Il8M12/+Hz41RCPzAjQg= +google.golang.org/grpc v1.57.1/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= 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= diff --git a/op-alt-da/cli.go b/op-alt-da/cli.go index e931707b67f50..30ce2168f5702 100644 --- a/op-alt-da/cli.go +++ b/op-alt-da/cli.go @@ -3,15 +3,19 @@ package altda import ( "fmt" "net/url" + "time" "github.com/urfave/cli/v2" ) var ( - EnabledFlagName = altDAFlags("enabled") - DaServerAddressFlagName = altDAFlags("da-server") - VerifyOnReadFlagName = altDAFlags("verify-on-read") - DaServiceFlag = altDAFlags("da-service") + EnabledFlagName = altDAFlags("enabled") + DaServerAddressFlagName = altDAFlags("da-server") + VerifyOnReadFlagName = altDAFlags("verify-on-read") + DaServiceFlagName = altDAFlags("da-service") + PutTimeoutFlagName = altDAFlags("put-timeout") + GetTimeoutFlagName = altDAFlags("get-timeout") + MaxConcurrentRequestsFlagName = altDAFlags("max-concurrent-da-requests") ) // altDAFlags returns the flag names for altDA @@ -46,20 +50,41 @@ func CLIFlags(envPrefix string, category string) []cli.Flag { Category: category, }, &cli.BoolFlag{ - Name: DaServiceFlag, + Name: DaServiceFlagName, Usage: "Use DA service type where commitments are generated by Alt-DA server", Value: false, EnvVars: altDAEnvs(envPrefix, "DA_SERVICE"), Category: category, }, + &cli.DurationFlag{ + Name: PutTimeoutFlagName, + Usage: "Timeout for put requests. 0 means no timeout.", + Value: time.Duration(0), + EnvVars: altDAEnvs(envPrefix, "PUT_TIMEOUT"), + }, + &cli.DurationFlag{ + Name: GetTimeoutFlagName, + Usage: "Timeout for get requests. 0 means no timeout.", + Value: time.Duration(0), + EnvVars: altDAEnvs(envPrefix, "GET_TIMEOUT"), + }, + &cli.Uint64Flag{ + Name: MaxConcurrentRequestsFlagName, + Usage: "Maximum number of concurrent requests to the DA server", + Value: 1, + EnvVars: altDAEnvs(envPrefix, "MAX_CONCURRENT_DA_REQUESTS"), + }, } } type CLIConfig struct { - Enabled bool - DAServerURL string - VerifyOnRead bool - GenericDA bool + Enabled bool + DAServerURL string + VerifyOnRead bool + GenericDA bool + PutTimeout time.Duration + GetTimeout time.Duration + MaxConcurrentRequests uint64 } func (c CLIConfig) Check() error { @@ -75,14 +100,17 @@ func (c CLIConfig) Check() error { } func (c CLIConfig) NewDAClient() *DAClient { - return &DAClient{url: c.DAServerURL, verify: c.VerifyOnRead, precompute: !c.GenericDA} + return &DAClient{url: c.DAServerURL, verify: c.VerifyOnRead, precompute: !c.GenericDA, getTimeout: c.GetTimeout, putTimeout: c.PutTimeout} } func ReadCLIConfig(c *cli.Context) CLIConfig { return CLIConfig{ - Enabled: c.Bool(EnabledFlagName), - DAServerURL: c.String(DaServerAddressFlagName), - VerifyOnRead: c.Bool(VerifyOnReadFlagName), - GenericDA: c.Bool(DaServiceFlag), + Enabled: c.Bool(EnabledFlagName), + DAServerURL: c.String(DaServerAddressFlagName), + VerifyOnRead: c.Bool(VerifyOnReadFlagName), + GenericDA: c.Bool(DaServiceFlagName), + PutTimeout: c.Duration(PutTimeoutFlagName), + GetTimeout: c.Duration(GetTimeoutFlagName), + MaxConcurrentRequests: c.Uint64(MaxConcurrentRequestsFlagName), } } diff --git a/op-alt-da/cmd/daserver/entrypoint.go b/op-alt-da/cmd/daserver/entrypoint.go index 96cc9fe48db12..32ff7d29f651d 100644 --- a/op-alt-da/cmd/daserver/entrypoint.go +++ b/op-alt-da/cmd/daserver/entrypoint.go @@ -6,8 +6,8 @@ import ( "github.com/urfave/cli/v2" altda "github.com/ethereum-optimism/optimism/op-alt-da" + "github.com/ethereum-optimism/optimism/op-service/ctxinterrupt" oplog "github.com/ethereum-optimism/optimism/op-service/log" - "github.com/ethereum-optimism/optimism/op-service/opio" ) func StartDAServer(cliCtx *cli.Context) error { @@ -55,7 +55,5 @@ func StartDAServer(cliCtx *cli.Context) error { } }() - opio.BlockOnInterrupts() - - return nil + return ctxinterrupt.Wait(cliCtx.Context) } diff --git a/op-alt-da/cmd/daserver/main.go b/op-alt-da/cmd/daserver/main.go index f45c63ffebef9..3ed37bd053218 100644 --- a/op-alt-da/cmd/daserver/main.go +++ b/op-alt-da/cmd/daserver/main.go @@ -9,8 +9,8 @@ import ( opservice "github.com/ethereum-optimism/optimism/op-service" "github.com/ethereum-optimism/optimism/op-service/cliapp" + "github.com/ethereum-optimism/optimism/op-service/ctxinterrupt" oplog "github.com/ethereum-optimism/optimism/op-service/log" - "github.com/ethereum-optimism/optimism/op-service/opio" ) var Version = "v0.0.1" @@ -26,7 +26,7 @@ func main() { app.Description = "Service for storing AltDA inputs" app.Action = StartDAServer - ctx := opio.WithInterruptBlocker(context.Background()) + ctx := ctxinterrupt.WithSignalWaiterMain(context.Background()) err := app.RunContext(ctx, os.Args) if err != nil { log.Crit("Application failed", "message", err) diff --git a/op-alt-da/daclient.go b/op-alt-da/daclient.go index db9c66ce5c216..269b71f3c1043 100644 --- a/op-alt-da/daclient.go +++ b/op-alt-da/daclient.go @@ -7,6 +7,7 @@ import ( "fmt" "io" "net/http" + "time" ) // ErrNotFound is returned when the server could not find the input. @@ -23,10 +24,16 @@ type DAClient struct { verify bool // whether commitment is precomputable (only applicable to keccak256) precompute bool + getTimeout time.Duration + putTimeout time.Duration } func NewDAClient(url string, verify bool, pc bool) *DAClient { - return &DAClient{url, verify, pc} + return &DAClient{ + url: url, + verify: verify, + precompute: pc, + } } // GetInput returns the input data for the given encoded commitment bytes. @@ -35,7 +42,8 @@ func (c *DAClient) GetInput(ctx context.Context, comm CommitmentData) ([]byte, e if err != nil { return nil, fmt.Errorf("failed to create HTTP request: %w", err) } - resp, err := http.DefaultClient.Do(req) + client := &http.Client{Timeout: c.getTimeout} + resp, err := client.Do(req) if err != nil { return nil, err } @@ -91,7 +99,8 @@ func (c *DAClient) setInputWithCommit(ctx context.Context, comm CommitmentData, return fmt.Errorf("failed to create HTTP request: %w", err) } req.Header.Set("Content-Type", "application/octet-stream") - resp, err := http.DefaultClient.Do(req) + client := &http.Client{Timeout: c.putTimeout} + resp, err := client.Do(req) if err != nil { return err } @@ -116,7 +125,8 @@ func (c *DAClient) setInput(ctx context.Context, img []byte) (CommitmentData, er 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) + client := &http.Client{Timeout: c.putTimeout} + resp, err := client.Do(req) if err != nil { return nil, err } diff --git a/op-alt-da/daclient_test.go b/op-alt-da/daclient_test.go index 02a9611ae276d..d9f7902aadee1 100644 --- a/op-alt-da/daclient_test.go +++ b/op-alt-da/daclient_test.go @@ -2,48 +2,14 @@ package altda import ( "context" - "fmt" "math/rand" - "sync" "testing" "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" ) -type MemStore struct { - db map[string][]byte - lock sync.RWMutex -} - -func NewMemStore() *MemStore { - return &MemStore{ - db: make(map[string][]byte), - } -} - -// Get retrieves the given key if it's present in the key-value store. -func (s *MemStore) Get(ctx context.Context, key []byte) ([]byte, error) { - s.lock.RLock() - defer s.lock.RUnlock() - - if entry, ok := s.db[string(key)]; ok { - return common.CopyBytes(entry), nil - } - return nil, ErrNotFound -} - -// Put inserts the given value into the key-value store. -func (s *MemStore) Put(ctx context.Context, key []byte, value []byte) error { - s.lock.Lock() - defer s.lock.Unlock() - - s.db[string(key)] = common.CopyBytes(value) - return nil -} - func TestDAClientPrecomputed(t *testing.T) { store := NewMemStore() logger := testlog.Logger(t, log.LevelDebug) @@ -56,7 +22,7 @@ func TestDAClientPrecomputed(t *testing.T) { cfg := CLIConfig{ Enabled: true, - DAServerURL: fmt.Sprintf("http://%s", server.Endpoint()), + DAServerURL: server.HttpEndpoint(), VerifyOnRead: true, } require.NoError(t, cfg.Check()) @@ -113,7 +79,7 @@ func TestDAClientService(t *testing.T) { cfg := CLIConfig{ Enabled: true, - DAServerURL: fmt.Sprintf("http://%s", server.Endpoint()), + DAServerURL: server.HttpEndpoint(), VerifyOnRead: false, GenericDA: false, } diff --git a/op-alt-da/damock.go b/op-alt-da/damock.go index b56b73fdfcc90..0db129171a822 100644 --- a/op-alt-da/damock.go +++ b/op-alt-da/damock.go @@ -4,8 +4,12 @@ import ( "context" "errors" "io" + "net/http" + "sync" + "time" "github.com/ethereum-optimism/optimism/op-service/eth" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb/memorydb" "github.com/ethereum/go-ethereum/log" @@ -99,3 +103,84 @@ func (d *AltDADisabled) OnFinalizedHeadSignal(f HeadSignalFn) { func (d *AltDADisabled) AdvanceL1Origin(ctx context.Context, l1 L1Fetcher, blockId eth.BlockID) error { return ErrNotEnabled } + +// FakeDAServer is a fake DA server for e2e tests. +// It is a small wrapper around DAServer that allows for setting request latencies, +// to mimic a DA service with slow responses (eg. eigenDA with 10 min batching interval). +type FakeDAServer struct { + *DAServer + putRequestLatency time.Duration + getRequestLatency time.Duration +} + +func NewFakeDAServer(host string, port int, log log.Logger) *FakeDAServer { + store := NewMemStore() + fakeDAServer := &FakeDAServer{ + DAServer: NewDAServer(host, port, store, log, true), + putRequestLatency: 0, + getRequestLatency: 0, + } + return fakeDAServer +} + +func (s *FakeDAServer) HandleGet(w http.ResponseWriter, r *http.Request) { + time.Sleep(s.getRequestLatency) + s.DAServer.HandleGet(w, r) +} + +func (s *FakeDAServer) HandlePut(w http.ResponseWriter, r *http.Request) { + time.Sleep(s.putRequestLatency) + s.DAServer.HandlePut(w, r) +} + +func (s *FakeDAServer) Start() error { + err := s.DAServer.Start() + if err != nil { + return err + } + // Override the HandleGet/Put method registrations + mux := http.NewServeMux() + mux.HandleFunc("/get/", s.HandleGet) + mux.HandleFunc("/put/", s.HandlePut) + s.httpServer.Handler = mux + return nil +} + +func (s *FakeDAServer) SetPutRequestLatency(latency time.Duration) { + s.putRequestLatency = latency +} + +func (s *FakeDAServer) SetGetRequestLatency(latency time.Duration) { + s.getRequestLatency = latency +} + +type MemStore struct { + db map[string][]byte + lock sync.RWMutex +} + +func NewMemStore() *MemStore { + return &MemStore{ + db: make(map[string][]byte), + } +} + +// Get retrieves the given key if it's present in the key-value store. +func (s *MemStore) Get(ctx context.Context, key []byte) ([]byte, error) { + s.lock.RLock() + defer s.lock.RUnlock() + + if entry, ok := s.db[string(key)]; ok { + return common.CopyBytes(entry), nil + } + return nil, ErrNotFound +} + +// Put inserts the given value into the key-value store. +func (s *MemStore) Put(ctx context.Context, key []byte, value []byte) error { + s.lock.Lock() + defer s.lock.Unlock() + + s.db[string(key)] = common.CopyBytes(value) + return nil +} diff --git a/op-alt-da/daserver.go b/op-alt-da/daserver.go index ef43fd27fef3c..94446944b5430 100644 --- a/op-alt-da/daserver.go +++ b/op-alt-da/daserver.go @@ -187,8 +187,8 @@ func (d *DAServer) HandlePut(w http.ResponseWriter, r *http.Request) { } } -func (b *DAServer) Endpoint() string { - return b.listener.Addr().String() +func (b *DAServer) HttpEndpoint() string { + return fmt.Sprintf("http://%s", b.listener.Addr().String()) } func (b *DAServer) Stop() error { diff --git a/op-alt-da/params.go b/op-alt-da/params.go index 86339200f7fc2..4cd515354dfb6 100644 --- a/op-alt-da/params.go +++ b/op-alt-da/params.go @@ -3,7 +3,7 @@ package altda // MaxInputSize 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 +const MaxInputSize = 4000000 // TxDataVersion1 is the version number for batcher transactions containing // altDA commitments. It should not collide with DerivationVersion which is still diff --git a/op-batcher/batcher/channel.go b/op-batcher/batcher/channel.go index 9a5e6b4c6a2eb..de68fa588a0a6 100644 --- a/op-batcher/batcher/channel.go +++ b/op-batcher/batcher/channel.go @@ -35,7 +35,7 @@ type channel struct { } func newChannel(log log.Logger, metr metrics.Metricer, cfg ChannelConfig, rollupCfg *rollup.Config, latestL1OriginBlockNum uint64) (*channel, error) { - cb, err := NewChannelBuilder(cfg, *rollupCfg, latestL1OriginBlockNum) + cb, err := NewChannelBuilder(cfg, rollupCfg, latestL1OriginBlockNum) if err != nil { return nil, fmt.Errorf("creating new channel: %w", err) } @@ -155,9 +155,9 @@ 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 +// NextTxData dequeues the next frames from the channel and returns them encoded in a tx data packet. +// If cfg.UseBlobs is false, it returns txData with a single frame. +// If cfg.UseBlobs 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. @@ -177,10 +177,11 @@ func (s *channel) NextTxData() txData { } func (s *channel) HasTxData() bool { - if s.IsFull() || !s.cfg.UseBlobs { + if s.IsFull() || // If the channel is full, we should start to submit it + !s.cfg.UseBlobs { // If using calldata, we only send one frame per tx return s.channelBuilder.HasFrame() } - // collect enough frames if channel is not full yet + // Collect enough frames if channel is not full yet return s.channelBuilder.PendingFrames() >= int(s.cfg.MaxFramesPerTx()) } diff --git a/op-batcher/batcher/channel_builder.go b/op-batcher/batcher/channel_builder.go index 4cdcba8325c22..0c16f3156d9b7 100644 --- a/op-batcher/batcher/channel_builder.go +++ b/op-batcher/batcher/channel_builder.go @@ -48,7 +48,7 @@ type frameData struct { // size approximation. type ChannelBuilder struct { cfg ChannelConfig - rollupCfg rollup.Config + rollupCfg *rollup.Config // L1 block number timeout of combined // - channel duration timeout, @@ -85,22 +85,8 @@ type ChannelBuilder struct { // NewChannelBuilder creates a new channel builder or returns an error if the // channel out could not be created. // it acts as a factory for either a span or singular channel out -func NewChannelBuilder(cfg ChannelConfig, rollupCfg rollup.Config, latestL1OriginBlockNum uint64) (*ChannelBuilder, error) { - c, err := cfg.CompressorConfig.NewCompressor() - if err != nil { - return nil, err - } - - chainSpec := rollup.NewChainSpec(&rollupCfg) - var co derive.ChannelOut - if cfg.BatchType == derive.SpanBatchType { - co, err = derive.NewSpanChannelOut( - rollupCfg.Genesis.L2Time, rollupCfg.L2ChainID, - cfg.CompressorConfig.TargetOutputSize, cfg.CompressorConfig.CompressionAlgo, - chainSpec, derive.WithMaxBlocksPerSpanBatch(cfg.MaxBlocksPerSpanBatch)) - } else { - co, err = derive.NewSingularChannelOut(c, chainSpec) - } +func NewChannelBuilder(cfg ChannelConfig, rollupCfg *rollup.Config, latestL1OriginBlockNum uint64) (*ChannelBuilder, error) { + co, err := newChannelOut(cfg, rollupCfg) if err != nil { return nil, fmt.Errorf("creating channel out: %w", err) } @@ -116,6 +102,21 @@ func NewChannelBuilder(cfg ChannelConfig, rollupCfg rollup.Config, latestL1Origi return cb, nil } +// newChannelOut creates a new channel out based on the given configuration. +func newChannelOut(cfg ChannelConfig, rollupCfg *rollup.Config) (derive.ChannelOut, error) { + spec := rollup.NewChainSpec(rollupCfg) + if cfg.BatchType == derive.SpanBatchType { + return derive.NewSpanChannelOut( + cfg.CompressorConfig.TargetOutputSize, cfg.CompressorConfig.CompressionAlgo, + spec, derive.WithMaxBlocksPerSpanBatch(cfg.MaxBlocksPerSpanBatch)) + } + comp, err := cfg.CompressorConfig.NewCompressor() + if err != nil { + return nil, err + } + return derive.NewSingularChannelOut(comp, spec) +} + func (c *ChannelBuilder) ID() derive.ChannelID { return c.co.ID() } @@ -177,7 +178,7 @@ func (c *ChannelBuilder) AddBlock(block *types.Block) (*derive.L1BlockInfo, erro return nil, c.FullErr() } - batch, l1info, err := derive.BlockToSingularBatch(&c.rollupCfg, block) + batch, l1info, err := derive.BlockToSingularBatch(c.rollupCfg, block) if err != nil { return l1info, fmt.Errorf("converting block to batch: %w", err) } @@ -416,12 +417,12 @@ func (c *ChannelBuilder) HasFrame() bool { } // PendingFrames returns the number of pending frames in the frames queue. -// It is larger zero iff HasFrames() returns true. +// It is larger zero iff HasFrame() returns true. func (c *ChannelBuilder) PendingFrames() int { return len(c.frames) } -// NextFrame returns the next available frame. +// NextFrame dequeues 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 { diff --git a/op-batcher/batcher/channel_builder_test.go b/op-batcher/batcher/channel_builder_test.go index 85edbef5def5d..1c25f06d81c05 100644 --- a/op-batcher/batcher/channel_builder_test.go +++ b/op-batcher/batcher/channel_builder_test.go @@ -22,7 +22,7 @@ import ( const latestL1BlockOrigin = 10 -var defaultTestRollupConfig = rollup.Config{ +var defaultTestRollupConfig = &rollup.Config{ Genesis: rollup.Genesis{L2: eth.BlockID{Number: 0}}, L2ChainID: big.NewInt(1234), } @@ -63,7 +63,7 @@ func newMiniL2BlockWithNumberParentAndL1Information(numTx int, l2Number *big.Int Number: big.NewInt(l1Number), Time: blockTime, }, nil, nil, trie.NewStackTrie(nil)) - l1InfoTx, err := derive.L1InfoDeposit(&defaultTestRollupConfig, eth.SystemConfig{}, 0, eth.BlockToInfo(l1Block), blockTime) + l1InfoTx, err := derive.L1InfoDeposit(defaultTestRollupConfig, eth.SystemConfig{}, 0, eth.BlockToInfo(l1Block), blockTime) if err != nil { panic(err) } @@ -369,7 +369,7 @@ func ChannelBuilder_OutputWrongFramePanic(t *testing.T, batchType uint) { // the type of batch does not matter here because we are using it to construct a broken frame c, err := channelConfig.CompressorConfig.NewCompressor() require.NoError(t, err) - co, err := derive.NewSingularChannelOut(c, rollup.NewChainSpec(&defaultTestRollupConfig)) + co, err := derive.NewSingularChannelOut(c, rollup.NewChainSpec(defaultTestRollupConfig)) require.NoError(t, err) var buf bytes.Buffer fn, err := co.OutputFrame(&buf, channelConfig.MaxFrameSize) @@ -503,7 +503,7 @@ func ChannelBuilder_OutputFrames_SpanBatch(t *testing.T, algo derive.Compression func ChannelBuilder_MaxRLPBytesPerChannel(t *testing.T, batchType uint) { t.Parallel() channelConfig := defaultTestChannelConfig() - chainSpec := rollup.NewChainSpec(&defaultTestRollupConfig) + chainSpec := rollup.NewChainSpec(defaultTestRollupConfig) channelConfig.MaxFrameSize = chainSpec.MaxRLPBytesPerChannel(latestL1BlockOrigin) * 2 channelConfig.InitNoneCompressor() channelConfig.BatchType = batchType @@ -525,7 +525,7 @@ func ChannelBuilder_MaxRLPBytesPerChannel(t *testing.T, batchType uint) { func ChannelBuilder_MaxRLPBytesPerChannelFjord(t *testing.T, batchType uint) { t.Parallel() channelConfig := defaultTestChannelConfig() - chainSpec := rollup.NewChainSpec(&defaultTestRollupConfig) + chainSpec := rollup.NewChainSpec(defaultTestRollupConfig) channelConfig.MaxFrameSize = chainSpec.MaxRLPBytesPerChannel(latestL1BlockOrigin) * 2 channelConfig.InitNoneCompressor() channelConfig.BatchType = batchType @@ -541,13 +541,13 @@ func ChannelBuilder_MaxRLPBytesPerChannelFjord(t *testing.T, batchType uint) { // Create a new channel builder with fjord fork now := time.Now() fjordTime := uint64(now.Add(-1 * time.Second).Unix()) - rollupConfig := rollup.Config{ + rollupConfig := &rollup.Config{ Genesis: rollup.Genesis{L2: eth.BlockID{Number: 0}}, L2ChainID: big.NewInt(1234), FjordTime: &fjordTime, } - chainSpec = rollup.NewChainSpec(&rollupConfig) + chainSpec = rollup.NewChainSpec(rollupConfig) channelConfig.MaxFrameSize = chainSpec.MaxRLPBytesPerChannel(uint64(now.Unix())) * 2 channelConfig.InitNoneCompressor() channelConfig.BatchType = batchType @@ -887,7 +887,7 @@ func ChannelBuilder_InputBytes(t *testing.T, batchType uint) { if batchType == derive.SingularBatchType { l += blockBatchRlpSize(t, block) } else { - singularBatch, l1Info, err := derive.BlockToSingularBatch(&defaultTestRollupConfig, block) + singularBatch, l1Info, err := derive.BlockToSingularBatch(defaultTestRollupConfig, block) require.NoError(err) err = spanBatch.AppendSingularBatch(singularBatch, l1Info.SequenceNumber) require.NoError(err) @@ -942,7 +942,7 @@ func ChannelBuilder_OutputBytes(t *testing.T, batchType uint) { func blockBatchRlpSize(t *testing.T, b *types.Block) int { t.Helper() - singularBatch, _, err := derive.BlockToSingularBatch(&defaultTestRollupConfig, b) + singularBatch, _, err := derive.BlockToSingularBatch(defaultTestRollupConfig, b) batch := derive.NewBatchData(singularBatch) require.NoError(t, err) var buf bytes.Buffer diff --git a/op-batcher/batcher/channel_config.go b/op-batcher/batcher/channel_config.go index 63e0d5d5deef0..45dc1d4dcfa4a 100644 --- a/op-batcher/batcher/channel_config.go +++ b/op-batcher/batcher/channel_config.go @@ -51,8 +51,8 @@ type ChannelConfig struct { UseBlobs bool } -// ChannelConfig returns a copy of itself. This makes a ChannelConfig a static -// ChannelConfigProvider of itself. +// ChannelConfig returns a copy of the receiver. +// This allows the receiver to be a static ChannelConfigProvider of itself. func (cc ChannelConfig) ChannelConfig() ChannelConfig { return cc } diff --git a/op-batcher/batcher/channel_config_provider.go b/op-batcher/batcher/channel_config_provider.go index c65e83b8289fa..6cf5b0db68633 100644 --- a/op-batcher/batcher/channel_config_provider.go +++ b/op-batcher/batcher/channel_config_provider.go @@ -48,6 +48,10 @@ func NewDynamicEthChannelConfig(lgr log.Logger, return dec } +// ChannelConfig will perform an estimate of the cost per byte for +// calldata and for blobs, given current market conditions: it will return +// the appropriate ChannelConfig depending on which is cheaper. It makes +// assumptions about the typical makeup of channel data. func (dec *DynamicEthChannelConfig) ChannelConfig() ChannelConfig { ctx, cancel := context.WithTimeout(context.Background(), dec.timeout) defer cancel() diff --git a/op-batcher/batcher/channel_manager.go b/op-batcher/batcher/channel_manager.go index 1f22565c94c50..23e8f7843696f 100644 --- a/op-batcher/batcher/channel_manager.go +++ b/op-batcher/batcher/channel_manager.go @@ -35,6 +35,8 @@ type channelManager struct { blocks []*types.Block // The latest L1 block from all the L2 blocks in the most recently closed channel l1OriginLastClosedChannel eth.BlockID + // The default ChannelConfig to use for the next channel + defaultCfg ChannelConfig // last block hash - for reorg detection tip common.Hash @@ -54,6 +56,7 @@ func NewChannelManager(log log.Logger, metr metrics.Metricer, cfgProvider Channe log: log, metr: metr, cfgProvider: cfgProvider, + defaultCfg: cfgProvider.ChannelConfig(), rollupCfg: rollupCfg, txChannels: make(map[string]*channel), } @@ -133,7 +136,8 @@ func (s *channelManager) removePendingChannel(channel *channel) { s.channelQueue = append(s.channelQueue[:index], s.channelQueue[index+1:]...) } -// nextTxData pops off s.datas & handles updating the internal state +// nextTxData dequeues frames from the channel and returns them encoded in a transaction. +// It also updates the internal tx -> channels mapping func (s *channelManager) nextTxData(channel *channel) (txData, error) { if channel == nil || !channel.HasTxData() { s.log.Trace("no next tx data") @@ -146,12 +150,55 @@ func (s *channelManager) nextTxData(channel *channel) (txData, error) { // TxData returns the next tx data that should be submitted to L1. // -// If the pending channel is +// If the current 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 tx data. +// +// It will decide whether to switch DA type automatically. +// When switching DA type, the channelManager state will be rebuilt +// with a new ChannelConfig. func (s *channelManager) TxData(l1Head eth.BlockID) (txData, error) { s.mu.Lock() defer s.mu.Unlock() + channel, err := s.getReadyChannel(l1Head) + if err != nil { + return emptyTxData, err + } + // If the channel has already started being submitted, + // return now and ensure no requeueing happens + if !channel.NoneSubmitted() { + return s.nextTxData(channel) + } + + // Call provider method to reassess optimal DA type + newCfg := s.cfgProvider.ChannelConfig() + + // No change: + if newCfg.UseBlobs == s.defaultCfg.UseBlobs { + s.log.Debug("Recomputing optimal ChannelConfig: no need to switch DA type", + "useBlobs", s.defaultCfg.UseBlobs) + return s.nextTxData(channel) + } + + // Change: + s.log.Info("Recomputing optimal ChannelConfig: changing DA type and requeing blocks...", + "useBlobsBefore", s.defaultCfg.UseBlobs, + "useBlobsAfter", newCfg.UseBlobs) + s.Requeue(newCfg) + channel, err = s.getReadyChannel(l1Head) + if err != nil { + return emptyTxData, err + } + return s.nextTxData(channel) +} + +// getReadyChannel returns the next channel ready to submit data, or an error. +// It will create a new channel if necessary. +// If there is no data ready to send, it adds blocks from the block queue +// to the current channel and generates frames for it. +// Always returns nil and the io.EOF sentinel error when +// there is no channel with txData +func (s *channelManager) getReadyChannel(l1Head eth.BlockID) (*channel, error) { var firstWithTxData *channel for _, ch := range s.channelQueue { if ch.HasTxData() { @@ -160,27 +207,31 @@ func (s *channelManager) TxData(l1Head eth.BlockID) (txData, error) { } } - dataPending := firstWithTxData != nil && firstWithTxData.HasTxData() + dataPending := firstWithTxData != nil s.log.Debug("Requested tx data", "l1Head", l1Head, "txdata_pending", dataPending, "blocks_pending", len(s.blocks)) - // Short circuit if there is pending tx data or the channel manager is closed. - if dataPending || s.closed { - return s.nextTxData(firstWithTxData) + // Short circuit if there is pending tx data or the channel manager is closed + if dataPending { + return firstWithTxData, nil + } + + if s.closed { + return nil, io.EOF } // 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 { - return txData{}, io.EOF + return nil, io.EOF } if err := s.ensureChannelWithSpace(l1Head); err != nil { - return txData{}, err + return nil, err } if err := s.processBlocks(); err != nil { - return txData{}, err + return nil, err } // Register current L1 head only after all pending blocks have been @@ -189,10 +240,14 @@ func (s *channelManager) TxData(l1Head eth.BlockID) (txData, error) { s.registerL1Block(l1Head) if err := s.outputFrames(); err != nil { - return txData{}, err + return nil, err + } + + if s.currentChannel.HasTxData() { + return s.currentChannel, nil } - return s.nextTxData(s.currentChannel) + return nil, io.EOF } // ensureChannelWithSpace ensures currentChannel is populated with a channel that has @@ -203,7 +258,10 @@ func (s *channelManager) ensureChannelWithSpace(l1Head eth.BlockID) error { return nil } - cfg := s.cfgProvider.ChannelConfig() + // We reuse the ChannelConfig from the last channel. + // This will be reassessed at channel submission-time, + // but this is our best guess at the appropriate values for now. + cfg := s.defaultCfg pc, err := newChannel(s.log, s.metr, cfg, s.rollupCfg, s.l1OriginLastClosedChannel.Number) if err != nil { return fmt.Errorf("creating new channel: %w", err) @@ -228,7 +286,7 @@ func (s *channelManager) ensureChannelWithSpace(l1Head eth.BlockID) error { return nil } -// registerL1Block registers the given block at the pending channel. +// registerL1Block registers the given block at the current channel. func (s *channelManager) registerL1Block(l1Head eth.BlockID) { s.currentChannel.CheckTimeout(l1Head.Number) s.log.Debug("new L1-block registered at channel builder", @@ -238,7 +296,7 @@ func (s *channelManager) registerL1Block(l1Head eth.BlockID) { ) } -// processBlocks adds blocks from the blocks queue to the pending channel until +// processBlocks adds blocks from the blocks queue to the current channel until // either the queue got exhausted or the channel is full. func (s *channelManager) processBlocks() error { var ( @@ -288,6 +346,7 @@ func (s *channelManager) processBlocks() error { return nil } +// outputFrames generates frames for the current channel, and computes and logs the compression ratio func (s *channelManager) outputFrames() error { if err := s.currentChannel.OutputFrames(); err != nil { return fmt.Errorf("creating frames with channel builder: %w", err) @@ -339,6 +398,7 @@ func (s *channelManager) outputFrames() error { func (s *channelManager) AddL2Block(block *types.Block) error { s.mu.Lock() defer s.mu.Unlock() + if s.tip != (common.Hash{}) && s.tip != block.ParentHash() { return ErrReorg } @@ -414,3 +474,26 @@ func (s *channelManager) Close() error { } return nil } + +// Requeue rebuilds the channel manager state by +// rewinding blocks back from the channel queue, and setting the defaultCfg. +func (s *channelManager) Requeue(newCfg ChannelConfig) { + newChannelQueue := []*channel{} + blocksToRequeue := []*types.Block{} + for _, channel := range s.channelQueue { + if !channel.NoneSubmitted() { + newChannelQueue = append(newChannelQueue, channel) + continue + } + blocksToRequeue = append(blocksToRequeue, channel.channelBuilder.Blocks()...) + } + + // We put the blocks back at the front of the queue: + s.blocks = append(blocksToRequeue, s.blocks...) + // Channels which where already being submitted are put back + s.channelQueue = newChannelQueue + s.currentChannel = nil + // Setting the defaultCfg will cause new channels + // to pick up the new ChannelConfig + s.defaultCfg = newCfg +} diff --git a/op-batcher/batcher/channel_manager_test.go b/op-batcher/batcher/channel_manager_test.go index 474942ce5e879..c129cd9cde991 100644 --- a/op-batcher/batcher/channel_manager_test.go +++ b/op-batcher/batcher/channel_manager_test.go @@ -1,6 +1,7 @@ package batcher import ( + "errors" "io" "math/big" "math/rand" @@ -124,7 +125,7 @@ func ChannelManager_Clear(t *testing.T, batchType uint) { // clearing confirmed transactions, and resetting the pendingChannels map cfg.ChannelTimeout = 10 cfg.InitRatioCompressor(1, derive.Zlib) - m := NewChannelManager(log, metrics.NoopMetrics, cfg, &defaultTestRollupConfig) + m := NewChannelManager(log, metrics.NoopMetrics, cfg, defaultTestRollupConfig) // Channel Manager state should be empty by default require.Empty(m.blocks) @@ -195,7 +196,7 @@ func ChannelManager_TxResend(t *testing.T, batchType uint) { 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 := NewChannelManager(log, metrics.NoopMetrics, cfg, defaultTestRollupConfig) m.Clear(eth.BlockID{}) a := derivetest.RandomL2BlockWithChainId(rng, 4, defaultTestRollupConfig.L2ChainID) @@ -234,7 +235,7 @@ func ChannelManagerCloseBeforeFirstUse(t *testing.T, batchType uint) { log := testlog.Logger(t, log.LevelCrit) m := NewChannelManager(log, metrics.NoopMetrics, channelManagerTestConfig(10000, batchType), - &defaultTestRollupConfig, + defaultTestRollupConfig, ) m.Clear(eth.BlockID{}) @@ -258,7 +259,7 @@ func ChannelManagerCloseNoPendingChannel(t *testing.T, batchType uint) { cfg := channelManagerTestConfig(10000, batchType) cfg.CompressorConfig.TargetOutputSize = 1 // full on first block cfg.ChannelTimeout = 1000 - m := NewChannelManager(log, metrics.NoopMetrics, cfg, &defaultTestRollupConfig) + m := NewChannelManager(log, metrics.NoopMetrics, cfg, defaultTestRollupConfig) m.Clear(eth.BlockID{}) a := newMiniL2Block(0) b := newMiniL2BlockWithNumberParent(0, big.NewInt(1), a.Hash()) @@ -294,7 +295,7 @@ func ChannelManagerClosePendingChannel(t *testing.T, batchType uint) { log := testlog.Logger(t, log.LevelError) cfg := channelManagerTestConfig(10_000, batchType) cfg.ChannelTimeout = 1000 - m := NewChannelManager(log, metrics.NoopMetrics, cfg, &defaultTestRollupConfig) + m := NewChannelManager(log, metrics.NoopMetrics, cfg, defaultTestRollupConfig) m.Clear(eth.BlockID{}) numTx := 20 // Adjust number of txs to make 2 frames @@ -346,7 +347,7 @@ func TestChannelManager_Close_PartiallyPendingChannel(t *testing.T) { TargetNumFrames: 100, } cfg.InitNoneCompressor() - m := NewChannelManager(log, metrics.NoopMetrics, cfg, &defaultTestRollupConfig) + m := NewChannelManager(log, metrics.NoopMetrics, cfg, defaultTestRollupConfig) m.Clear(eth.BlockID{}) numTx := 3 // Adjust number of txs to make 2 frames @@ -398,7 +399,7 @@ func ChannelManagerCloseAllTxsFailed(t *testing.T, batchType uint) { cfg := channelManagerTestConfig(100, batchType) cfg.TargetNumFrames = 1000 cfg.InitNoneCompressor() - m := NewChannelManager(log, metrics.NoopMetrics, cfg, &defaultTestRollupConfig) + m := NewChannelManager(log, metrics.NoopMetrics, cfg, defaultTestRollupConfig) m.Clear(eth.BlockID{}) a := derivetest.RandomL2BlockWithChainId(rng, 1000, defaultTestRollupConfig.L2ChainID) @@ -471,7 +472,7 @@ func TestChannelManager_ChannelCreation(t *testing.T) { } { test := tt t.Run(test.name, func(t *testing.T) { - m := NewChannelManager(l, metrics.NoopMetrics, cfg, &defaultTestRollupConfig) + m := NewChannelManager(l, metrics.NoopMetrics, cfg, defaultTestRollupConfig) m.l1OriginLastClosedChannel = test.safeL1Block require.Nil(t, m.currentChannel) @@ -483,3 +484,185 @@ func TestChannelManager_ChannelCreation(t *testing.T) { }) } } + +// FakeDynamicEthChannelConfig is a ChannelConfigProvider which always returns +// either a blob- or calldata-based config depending on its internal chooseBlob +// switch. +type FakeDynamicEthChannelConfig struct { + DynamicEthChannelConfig + chooseBlobs bool + assessments int +} + +func (f *FakeDynamicEthChannelConfig) ChannelConfig() ChannelConfig { + f.assessments++ + if f.chooseBlobs { + return f.blobConfig + } + return f.calldataConfig +} + +func newFakeDynamicEthChannelConfig(lgr log.Logger, + reqTimeout time.Duration) *FakeDynamicEthChannelConfig { + + calldataCfg := ChannelConfig{ + MaxFrameSize: 120_000 - 1, + TargetNumFrames: 1, + } + blobCfg := ChannelConfig{ + MaxFrameSize: eth.MaxBlobDataSize - 1, + TargetNumFrames: 3, // gets closest to amortized fixed tx costs + UseBlobs: true, + } + calldataCfg.InitNoneCompressor() + blobCfg.InitNoneCompressor() + + return &FakeDynamicEthChannelConfig{ + chooseBlobs: false, + DynamicEthChannelConfig: *NewDynamicEthChannelConfig( + lgr, + reqTimeout, + &mockGasPricer{}, + blobCfg, + calldataCfg), + } +} + +// TestChannelManager_TxData seeds the channel manager with blocks and triggers the +// blocks->channels pipeline multiple times. Values are chosen such that a channel +// is created under one set of market conditions, and then submitted under a different +// set of market conditions. The test asserts that the DA type is changed at channel +// submission time. +func TestChannelManager_TxData(t *testing.T) { + + type TestCase struct { + name string + chooseBlobsWhenChannelCreated bool + chooseBlobsWhenChannelSubmitted bool + + // * One when the channelManager was created + // * One when the channel is about to be submitted + // * Potentially one more if the replacement channel is about to be submitted, + // this only happens when going from calldata->blobs because + // the channel is no longer ready to send until more data + // is added. + numExpectedAssessments int + } + + tt := []TestCase{ + {"blobs->blobs", true, true, 2}, + {"calldata->calldata", false, false, 2}, + {"blobs->calldata", true, false, 2}, + {"calldata->blobs", false, true, 3}, + } + + for _, tc := range tt { + t.Run(tc.name, func(t *testing.T) { + l := testlog.Logger(t, log.LevelCrit) + + cfg := newFakeDynamicEthChannelConfig(l, 1000) + + cfg.chooseBlobs = tc.chooseBlobsWhenChannelCreated + m := NewChannelManager(l, metrics.NoopMetrics, cfg, defaultTestRollupConfig) + require.Equal(t, tc.chooseBlobsWhenChannelCreated, m.defaultCfg.UseBlobs) + + // Seed channel manager with a block + rng := rand.New(rand.NewSource(time.Now().UnixNano())) + blockA := derivetest.RandomL2BlockWithChainId(rng, 200, defaultTestRollupConfig.L2ChainID) + m.blocks = []*types.Block{blockA} + + // Call TxData a first time to trigger blocks->channels pipeline + _, err := m.TxData(eth.BlockID{}) + require.ErrorIs(t, err, io.EOF) + + // The test requires us to have something in the channel queue + // at this point, but not yet ready to send and not full + require.NotEmpty(t, m.channelQueue) + require.False(t, m.channelQueue[0].IsFull()) + + // Simulate updated market conditions + // by possibly flipping the state of the + // fake channel provider + l.Info("updating market conditions", "chooseBlobs", tc.chooseBlobsWhenChannelSubmitted) + cfg.chooseBlobs = tc.chooseBlobsWhenChannelSubmitted + + // Add a block and call TxData until + // we get some data to submit + var data txData + for { + m.blocks = []*types.Block{blockA} + data, err = m.TxData(eth.BlockID{}) + if err == nil && data.Len() > 0 { + break + } + if !errors.Is(err, io.EOF) { + require.NoError(t, err) + } + } + + require.Equal(t, tc.numExpectedAssessments, cfg.assessments) + require.Equal(t, tc.chooseBlobsWhenChannelSubmitted, data.asBlob) + require.Equal(t, tc.chooseBlobsWhenChannelSubmitted, m.defaultCfg.UseBlobs) + }) + } + +} + +// TestChannelManager_Requeue seeds the channel manager with blocks, +// takes a state snapshot, triggers the blocks->channels pipeline, +// and then calls Requeue. Finally, it asserts the channel manager's +// state is equal to the snapshot. It repeats this for a channel +// which has a pending transaction and verifies that Requeue is then +// a noop. +func TestChannelManager_Requeue(t *testing.T) { + l := testlog.Logger(t, log.LevelCrit) + cfg := channelManagerTestConfig(100, derive.SingularBatchType) + m := NewChannelManager(l, metrics.NoopMetrics, cfg, defaultTestRollupConfig) + + // Seed channel manager with blocks + rng := rand.New(rand.NewSource(99)) + blockA := derivetest.RandomL2BlockWithChainId(rng, 10, defaultTestRollupConfig.L2ChainID) + blockB := derivetest.RandomL2BlockWithChainId(rng, 10, defaultTestRollupConfig.L2ChainID) + + // This is the snapshot of channel manager state we want to reinstate + // when we requeue + stateSnapshot := []*types.Block{blockA, blockB} + m.blocks = stateSnapshot + require.Empty(t, m.channelQueue) + + // Trigger the blocks -> channelQueue data pipelining + require.NoError(t, m.ensureChannelWithSpace(eth.BlockID{})) + require.NotEmpty(t, m.channelQueue) + require.NoError(t, m.processBlocks()) + + // Assert that at least one block was processed into the channel + require.NotContains(t, m.blocks, blockA) + + // Call the function we are testing + m.Requeue(m.defaultCfg) + + // Ensure we got back to the state above + require.Equal(t, m.blocks, stateSnapshot) + require.Empty(t, m.channelQueue) + + // Trigger the blocks -> channelQueue data pipelining again + require.NoError(t, m.ensureChannelWithSpace(eth.BlockID{})) + require.NotEmpty(t, m.channelQueue) + require.NoError(t, m.processBlocks()) + + // Assert that at least one block was processed into the channel + require.NotContains(t, m.blocks, blockA) + + // Now mark the 0th channel in the queue as already + // starting to send on chain + channel0 := m.channelQueue[0] + channel0.pendingTransactions["foo"] = txData{} + require.False(t, channel0.NoneSubmitted()) + + // Call the function we are testing + m.Requeue(m.defaultCfg) + + // The requeue shouldn't affect the pending channel + require.Contains(t, m.channelQueue, channel0) + require.NotContains(t, m.blocks, blockA) +} diff --git a/op-batcher/batcher/channel_test.go b/op-batcher/batcher/channel_test.go index 7fa8030e771e6..8dec9d9e108be 100644 --- a/op-batcher/batcher/channel_test.go +++ b/op-batcher/batcher/channel_test.go @@ -86,8 +86,8 @@ func TestChannelManager_NextTxData(t *testing.T) { require.Equal(t, txData{}, returnedTxData) // Set the pending channel - // The nextTxData function should still return EOF - // since the pending channel has no frames + // The nextTxData function should still return io.EOF + // since the current channel has no frames require.NoError(t, m.ensureChannelWithSpace(eth.BlockID{})) channel := m.currentChannel require.NotNil(t, channel) diff --git a/op-batcher/batcher/driver.go b/op-batcher/batcher/driver.go index 431f442a39346..968e6de3e71ae 100644 --- a/op-batcher/batcher/driver.go +++ b/op-batcher/batcher/driver.go @@ -8,7 +8,6 @@ import ( "math/big" _ "net/http/pprof" "sync" - "sync/atomic" "time" altda "github.com/ethereum-optimism/optimism/op-alt-da" @@ -23,6 +22,7 @@ import ( "github.com/ethereum/go-ethereum/core/txpool" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" + "golang.org/x/sync/errgroup" ) var ( @@ -42,6 +42,25 @@ type txRef struct { isBlob bool } +func (r txRef) String() string { + return r.string(func(id txID) string { return id.String() }) +} + +func (r txRef) TerminalString() string { + return r.string(func(id txID) string { return id.TerminalString() }) +} + +func (r txRef) string(txIDStringer func(txID) string) string { + if r.isCancel { + if r.isBlob { + return "blob-cancellation" + } else { + return "calldata-cancellation" + } + } + return txIDStringer(r.id) +} + type L1Client interface { HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) NonceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (uint64, error) @@ -61,7 +80,7 @@ type DriverSetup struct { Metr metrics.Metricer RollupConfig *rollup.Config Config BatcherConfig - Txmgr *txmgr.SimpleTxManager + Txmgr txmgr.TxManager L1Client L1Client EndpointProvider dial.L2EndpointProvider ChannelConfig ChannelConfigProvider @@ -83,6 +102,10 @@ type BatchSubmitter struct { mutex sync.Mutex running bool + txpoolMutex sync.Mutex // guards txpoolState and txpoolBlockedBlob + txpoolState int + txpoolBlockedBlob bool + // lastStoredBlock is the last block loaded into `state`. If it is empty it should be set to the l2 safe head. lastStoredBlock eth.BlockID lastL1Tip eth.L1BlockRef @@ -167,10 +190,11 @@ func (l *BatchSubmitter) StopBatchSubmitting(ctx context.Context) error { // loadBlocksIntoState loads all blocks since the previous stored block // It does the following: -// 1. Fetch the sync status of the sequencer -// 2. Check if the sync status is valid or if we are all the way up to date -// 3. Check if it needs to initialize state OR it is lagging (todo: lagging just means race condition?) -// 4. Load all new blocks into the local state. +// 1. Fetch the sync status of the sequencer +// 2. Check if the sync status is valid or if we are all the way up to date +// 3. Check if it needs to initialize state OR it is lagging (todo: lagging just means race condition?) +// 4. Load all new blocks into the local state. +// // If there is a reorg, it will reset the last stored block but not clear the internal state so // the state can be flushed to L1. func (l *BatchSubmitter) loadBlocksIntoState(ctx context.Context) error { @@ -263,7 +287,7 @@ func (l *BatchSubmitter) calculateL2BlockRangeToStore(ctx context.Context) (eth. // Check if we should even attempt to load any blocks. TODO: May not need this check if syncStatus.SafeL2.Number >= syncStatus.UnsafeL2.Number { - return eth.BlockID{}, eth.BlockID{}, errors.New("L2 safe head ahead of L2 unsafe head") + return eth.BlockID{}, eth.BlockID{}, fmt.Errorf("L2 safe head(%d) ahead of L2 unsafe head(%d)", syncStatus.SafeL2.Number, syncStatus.UnsafeL2.Number) } return l.lastStoredBlock, syncStatus.UnsafeL2.ID(), nil @@ -289,7 +313,7 @@ const ( // send a cancellation transaction. // TxpoolCancelPending -> TxpoolGood: // happens once the cancel transaction completes, whether successfully or in error. - TxpoolGood int32 = iota + TxpoolGood int = iota TxpoolBlocked TxpoolCancelPending ) @@ -299,29 +323,36 @@ func (l *BatchSubmitter) loop() { receiptsCh := make(chan txmgr.TxReceipt[txRef]) queue := txmgr.NewQueue[txRef](l.killCtx, l.Txmgr, l.Config.MaxPendingTransactions) - var daWaitGroup sync.WaitGroup + daGroup := &errgroup.Group{} + // errgroup with limit of 0 means no goroutine is able to run concurrently, + // so we only set the limit if it is greater than 0. + if l.Config.MaxConcurrentDARequests > 0 { + daGroup.SetLimit(int(l.Config.MaxConcurrentDARequests)) + } // start the receipt/result processing loop receiptLoopDone := make(chan struct{}) defer close(receiptLoopDone) // shut down receipt loop - var ( - txpoolState atomic.Int32 - txpoolBlockedBlob bool - ) - txpoolState.Store(TxpoolGood) + l.txpoolMutex.Lock() + l.txpoolState = TxpoolGood + l.txpoolMutex.Unlock() go func() { for { select { case r := <-receiptsCh: - if errors.Is(r.Err, txpool.ErrAlreadyReserved) && txpoolState.CompareAndSwap(TxpoolGood, TxpoolBlocked) { - txpoolBlockedBlob = r.ID.isBlob - l.Log.Info("incompatible tx in txpool") - } else if r.ID.isCancel && txpoolState.CompareAndSwap(TxpoolCancelPending, TxpoolGood) { + l.txpoolMutex.Lock() + if errors.Is(r.Err, txpool.ErrAlreadyReserved) && l.txpoolState == TxpoolGood { + l.txpoolState = TxpoolBlocked + l.txpoolBlockedBlob = r.ID.isBlob + l.Log.Info("incompatible tx in txpool", "is_blob", r.ID.isBlob) + } else if r.ID.isCancel && l.txpoolState == TxpoolCancelPending { // Set state to TxpoolGood even if the cancellation transaction ended in error // since the stuck transaction could have cleared while we were waiting. + l.txpoolState = TxpoolGood l.Log.Info("txpool may no longer be blocked", "err", r.Err) } + l.txpoolMutex.Unlock() l.Log.Info("Handling receipt", "id", r.ID) l.handleReceipt(r) case <-receiptLoopDone: @@ -335,11 +366,20 @@ func (l *BatchSubmitter) loop() { defer ticker.Stop() publishAndWait := func() { - l.publishStateToL1(queue, receiptsCh, &daWaitGroup) + l.publishStateToL1(queue, receiptsCh, daGroup) if !l.Txmgr.IsClosed() { - l.Log.Info("Wait for pure DA writes, not L1 txs") - daWaitGroup.Wait() - l.Log.Info("Wait for L1 writes (blobs or DA commitments)") + if l.Config.UseAltDA { + l.Log.Info("Waiting for altDA writes to complete...") + err := daGroup.Wait() + if err != nil { + l.Log.Error("Error returned by one of the altda goroutines waited on", "err", err) + } + } + l.Log.Info("Waiting for L1 txs to be confirmed...") + err := queue.Wait() + if err != nil { + l.Log.Error("Error returned by one of the txmgr goroutines waited on", "err", err) + } } else { l.Log.Info("Txmgr is closed, remaining channel data won't be sent") } @@ -348,13 +388,7 @@ func (l *BatchSubmitter) loop() { for { select { case <-ticker.C: - if txpoolState.CompareAndSwap(TxpoolBlocked, TxpoolCancelPending) { - // txpoolState is set to Blocked only if Send() is returning - // ErrAlreadyReserved. In this case, the TxMgr nonce should be reset to nil, - // allowing us to send a cancellation transaction. - l.cancelBlockingTx(queue, receiptsCh, txpoolBlockedBlob) - } - if txpoolState.Load() != TxpoolGood { + if !l.checkTxpool(queue, receiptsCh) { continue } if err := l.loadBlocksIntoState(l.shutdownCtx); errors.Is(err, ErrReorg) { @@ -372,7 +406,7 @@ func (l *BatchSubmitter) loop() { l.clearState(l.shutdownCtx) continue } - l.publishStateToL1(queue, receiptsCh, &daWaitGroup) + l.publishStateToL1(queue, receiptsCh, daGroup) case <-l.shutdownCtx.Done(): if l.Txmgr.IsClosed() { l.Log.Info("Txmgr is closed, remaining channel data won't be sent") @@ -429,14 +463,18 @@ func (l *BatchSubmitter) waitNodeSync() error { // 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[txRef], receiptsCh chan txmgr.TxReceipt[txRef], daWaitGroup *sync.WaitGroup) { +func (l *BatchSubmitter) publishStateToL1(queue *txmgr.Queue[txRef], receiptsCh chan txmgr.TxReceipt[txRef], daGroup *errgroup.Group) { 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, daWaitGroup) + if !l.checkTxpool(queue, receiptsCh) { + l.Log.Info("txpool state is not good, aborting state publishing") + return + } + err := l.publishTxToL1(l.killCtx, queue, receiptsCh, daGroup) if err != nil { if err != io.EOF { l.Log.Error("Error publishing tx to l1", "err", err) @@ -486,7 +524,7 @@ func (l *BatchSubmitter) clearState(ctx context.Context) { } // publishTxToL1 submits a single state tx to the L1 -func (l *BatchSubmitter) publishTxToL1(ctx context.Context, queue *txmgr.Queue[txRef], receiptsCh chan txmgr.TxReceipt[txRef], waitGroup *sync.WaitGroup) error { +func (l *BatchSubmitter) publishTxToL1(ctx context.Context, queue *txmgr.Queue[txRef], receiptsCh chan txmgr.TxReceipt[txRef], daGroup *errgroup.Group) error { // send all available transactions l1tip, err := l.l1Tip(ctx) if err != nil { @@ -495,7 +533,8 @@ func (l *BatchSubmitter) publishTxToL1(ctx context.Context, queue *txmgr.Queue[t } l.recordL1Tip(l1tip) - // Collect next transaction data + // Collect next transaction data. This pulls data out of the channel, so we need to make sure + // to put it back if ever da or txmgr requests fail, by calling l.recordFailedDARequest/recordFailedTx. txdata, err := l.state.TxData(l1tip.ID()) if err == io.EOF { @@ -506,14 +545,9 @@ func (l *BatchSubmitter) publishTxToL1(ctx context.Context, queue *txmgr.Queue[t return err } - waitGroup.Add(1) - go func() { - defer waitGroup.Done() - err := l.sendTransaction(ctx, txdata, queue, receiptsCh) - if err != nil { - l.Log.Warn("BatchSubmitter.sendTransaction failed: %w", "err", err) - } - }() + if err = l.sendTransaction(txdata, queue, receiptsCh, daGroup); err != nil { + return fmt.Errorf("BatchSubmitter.sendTransaction failed: %w", err) + } return nil } @@ -553,14 +587,59 @@ func (l *BatchSubmitter) cancelBlockingTx(queue *txmgr.Queue[txRef], receiptsCh panic(err) // this error should not happen } l.Log.Warn("sending a cancellation transaction to unblock txpool", "blocked_blob", isBlockedBlob) - l.queueTx(txData{}, true, candidate, queue, receiptsCh) + l.sendTx(txData{}, true, candidate, queue, receiptsCh) +} + +// publishToAltDAAndL1 posts the txdata to the DA Provider and then sends the commitment to L1. +func (l *BatchSubmitter) publishToAltDAAndL1(txdata txData, queue *txmgr.Queue[txRef], receiptsCh chan txmgr.TxReceipt[txRef], daGroup *errgroup.Group) { + // sanity checks + if nf := len(txdata.frames); nf != 1 { + l.Log.Crit("Unexpected number of frames in calldata tx", "num_frames", nf) + } + if txdata.asBlob { + l.Log.Crit("Unexpected blob txdata with AltDA enabled") + } + + // when posting txdata to an external DA Provider, we use a goroutine to avoid blocking the main loop + // since it may take a while for the request to return. + goroutineSpawned := daGroup.TryGo(func() error { + // TODO: probably shouldn't be using the global shutdownCtx here, see https://go.dev/blog/context-and-structs + // but sendTransaction receives l.killCtx as an argument, which currently is only canceled after waiting for the main loop + // to exit, which would wait on this DA call to finish, which would take a long time. + // So we prefer to mimic the behavior of txmgr and cancel all pending DA/txmgr requests when the batcher is stopped. + comm, err := l.AltDA.SetInput(l.shutdownCtx, txdata.CallData()) + if err != nil { + l.Log.Error("Failed to post input to Alt DA", "error", err) + // requeue frame if we fail to post to the DA Provider so it can be retried + // note: this assumes that the da server caches requests, otherwise it might lead to resubmissions of the blobs + l.recordFailedDARequest(txdata.ID(), err) + return nil + } + l.Log.Info("Set altda input", "commitment", comm, "tx", txdata.ID()) + candidate := l.calldataTxCandidate(comm.TxData()) + l.sendTx(txdata, false, candidate, queue, receiptsCh) + return nil + }) + if !goroutineSpawned { + // We couldn't start the goroutine because the errgroup.Group limit + // is already reached. Since we can't send the txdata, we have to + // return it for later processing. We use nil error to skip error logging. + l.recordFailedDARequest(txdata.ID(), nil) + } } // sendTransaction creates & queues for sending a transaction to the batch inbox address with the given `txData`. +// This call will block if the txmgr queue is at the max-pending limit. // The method will block if the queue's MaxPendingTransactions is exceeded. -func (l *BatchSubmitter) sendTransaction(ctx context.Context, txdata txData, queue *txmgr.Queue[txRef], receiptsCh chan txmgr.TxReceipt[txRef]) error { +func (l *BatchSubmitter) sendTransaction(txdata txData, queue *txmgr.Queue[txRef], receiptsCh chan txmgr.TxReceipt[txRef], daGroup *errgroup.Group) error { var err error - // Do the gas estimation offline. A value of 0 will cause the [txmgr] to estimate the gas limit. + + // if Alt DA is enabled we post the txdata to the DA Provider and replace it with the commitment. + if l.Config.UseAltDA { + l.publishToAltDAAndL1(txdata, queue, receiptsCh, daGroup) + // we return nil to allow publishStateToL1 to keep processing the next txdata + return nil + } var candidate *txmgr.TxCandidate if txdata.asBlob { @@ -576,28 +655,16 @@ func (l *BatchSubmitter) sendTransaction(ctx context.Context, txdata txData, que if nf := len(txdata.frames); nf != 1 { l.Log.Crit("Unexpected number of frames in calldata tx", "num_frames", nf) } - data := txdata.CallData() - // if AltDA is enabled we post the txdata to the DA Provider and replace it with the commitment. - if l.Config.UseAltDA { - comm, err := l.AltDA.SetInput(ctx, data) - if err != nil { - l.Log.Error("Failed to post input to Alt 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 - } - l.Log.Info("Set AltDA input", "commitment", comm, "tx", txdata.ID()) - // signal AltDA commitment tx with TxDataVersion1 - data = comm.TxData() - } - candidate = l.calldataTxCandidate(data) + candidate = l.calldataTxCandidate(txdata.CallData()) } - l.queueTx(txdata, false, candidate, queue, receiptsCh) + l.sendTx(txdata, false, candidate, queue, receiptsCh) return nil } -func (l *BatchSubmitter) queueTx(txdata txData, isCancel bool, candidate *txmgr.TxCandidate, queue *txmgr.Queue[txRef], receiptsCh chan txmgr.TxReceipt[txRef]) { +// sendTx uses the txmgr queue to send the given transaction candidate after setting its +// gaslimit. It will block if the txmgr queue has reached its MaxPendingTransactions limit. +func (l *BatchSubmitter) sendTx(txdata txData, isCancel bool, candidate *txmgr.TxCandidate, queue *txmgr.Queue[txRef], receiptsCh chan txmgr.TxReceipt[txRef]) { intrinsicGas, err := core.IntrinsicGas(candidate.TxData, nil, false, true, true, false) if err != nil { // we log instead of return an error here because txmgr can do its own gas estimation @@ -650,6 +717,13 @@ func (l *BatchSubmitter) recordL1Tip(l1tip eth.L1BlockRef) { l.Metr.RecordLatestL1Block(l1tip) } +func (l *BatchSubmitter) recordFailedDARequest(id txID, err error) { + if err != nil { + l.Log.Warn("DA request failed", logFields(id, err)...) + } + l.state.TxFailed(id) +} + func (l *BatchSubmitter) recordFailedTx(id txID, err error) { l.Log.Warn("Transaction failed to send", logFields(id, err)...) l.state.TxFailed(id) @@ -673,6 +747,23 @@ func (l *BatchSubmitter) l1Tip(ctx context.Context) (eth.L1BlockRef, error) { return eth.InfoToL1BlockRef(eth.HeaderBlockInfo(head)), nil } +func (l *BatchSubmitter) checkTxpool(queue *txmgr.Queue[txRef], receiptsCh chan txmgr.TxReceipt[txRef]) bool { + l.txpoolMutex.Lock() + if l.txpoolState == TxpoolBlocked { + // txpoolState is set to Blocked only if Send() is returning + // ErrAlreadyReserved. In this case, the TxMgr nonce should be reset to nil, + // allowing us to send a cancellation transaction. + l.txpoolState = TxpoolCancelPending + isBlob := l.txpoolBlockedBlob + l.txpoolMutex.Unlock() + l.cancelBlockingTx(queue, receiptsCh, isBlob) + return false + } + r := l.txpoolState == TxpoolGood + l.txpoolMutex.Unlock() + return r +} + func logFields(xs ...any) (fs []any) { for _, x := range xs { switch v := x.(type) { diff --git a/op-batcher/batcher/driver_test.go b/op-batcher/batcher/driver_test.go index df72fa28d49ac..5ce0983bfe1a7 100644 --- a/op-batcher/batcher/driver_test.go +++ b/op-batcher/batcher/driver_test.go @@ -49,7 +49,8 @@ func setup(t *testing.T) (*BatchSubmitter, *mockL2EndpointProvider) { return NewBatchSubmitter(DriverSetup{ Log: testlog.Logger(t, log.LevelDebug), Metr: metrics.NoopMetrics, - RollupConfig: &cfg, + RollupConfig: cfg, + ChannelConfig: defaultTestChannelConfig(), EndpointProvider: ep, }), ep } diff --git a/op-batcher/batcher/service.go b/op-batcher/batcher/service.go index 00d3d32071f7f..6ed906af15aa1 100644 --- a/op-batcher/batcher/service.go +++ b/op-batcher/batcher/service.go @@ -39,6 +39,8 @@ type BatcherConfig struct { // UseAltDA is true if the rollup config has a DA challenge address so the batcher // will post inputs to the DA server and post commitments to blobs or calldata. UseAltDA bool + // maximum number of concurrent blob put requests to the DA server + MaxConcurrentDARequests uint64 WaitNodeSync bool CheckRecentTxsDepth int @@ -51,7 +53,7 @@ type BatcherService struct { Metrics metrics.Metricer L1Client *ethclient.Client EndpointProvider dial.L2EndpointProvider - TxManager *txmgr.SimpleTxManager + TxManager txmgr.TxManager AltDA *altda.DAClient BatcherConfig @@ -93,6 +95,7 @@ func (bs *BatcherService) initFromCLIConfig(ctx context.Context, version string, bs.PollInterval = cfg.PollInterval bs.MaxPendingTransactions = cfg.MaxPendingTransactions + bs.MaxConcurrentDARequests = cfg.AltDA.MaxConcurrentRequests bs.NetworkTimeout = cfg.TxMgrConfig.NetworkTimeout bs.CheckRecentTxsDepth = cfg.CheckRecentTxsDepth bs.WaitNodeSync = cfg.WaitNodeSync @@ -105,6 +108,10 @@ func (bs *BatcherService) initFromCLIConfig(ctx context.Context, version string, if err := bs.initTxManager(cfg); err != nil { return fmt.Errorf("failed to init Tx manager: %w", err) } + // must be init before driver and channel config + if err := bs.initAltDA(cfg); err != nil { + return fmt.Errorf("failed to init AltDA: %w", err) + } if err := bs.initChannelConfig(cfg); err != nil { return fmt.Errorf("failed to init channel config: %w", err) } @@ -115,10 +122,6 @@ 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.initAltDA(cfg); err != nil { - return fmt.Errorf("failed to init AltDA: %w", err) - } bs.initDriver() if err := bs.initRPCServer(cfg); err != nil { return fmt.Errorf("failed to start RPC server: %w", err) diff --git a/op-batcher/batcher/test_batch_submitter.go b/op-batcher/batcher/test_batch_submitter.go index 8814400f06ca7..9ff5ca69796fe 100644 --- a/op-batcher/batcher/test_batch_submitter.go +++ b/op-batcher/batcher/test_batch_submitter.go @@ -37,8 +37,12 @@ func (l *TestBatchSubmitter) JamTxPool(ctx context.Context) error { return err } + simpleTxMgr, ok := l.Txmgr.(*txmgr.SimpleTxManager) + if !ok { + return errors.New("txmgr is not a SimpleTxManager") + } l.ttm = &txmgr.TestTxManager{ - SimpleTxManager: l.Txmgr, + SimpleTxManager: simpleTxMgr, } l.Log.Info("sending txpool blocking test tx") if err := l.ttm.JamTxPool(ctx, *candidate); err != nil { diff --git a/op-batcher/cmd/main.go b/op-batcher/cmd/main.go index 91e032ff36b4a..82472006da279 100644 --- a/op-batcher/cmd/main.go +++ b/op-batcher/cmd/main.go @@ -11,9 +11,9 @@ import ( "github.com/ethereum-optimism/optimism/op-batcher/metrics" opservice "github.com/ethereum-optimism/optimism/op-service" "github.com/ethereum-optimism/optimism/op-service/cliapp" + "github.com/ethereum-optimism/optimism/op-service/ctxinterrupt" oplog "github.com/ethereum-optimism/optimism/op-service/log" "github.com/ethereum-optimism/optimism/op-service/metrics/doc" - "github.com/ethereum-optimism/optimism/op-service/opio" "github.com/ethereum/go-ethereum/log" ) @@ -40,7 +40,7 @@ func main() { }, } - ctx := opio.WithInterruptBlocker(context.Background()) + ctx := ctxinterrupt.WithSignalWaiterMain(context.Background()) err := app.RunContext(ctx, os.Args) if err != nil { log.Crit("Application failed", "message", err) diff --git a/op-bootnode/bootnode/entrypoint.go b/op-bootnode/bootnode/entrypoint.go index 0dcf356fa1f30..0c33383c70c7b 100644 --- a/op-bootnode/bootnode/entrypoint.go +++ b/op-bootnode/bootnode/entrypoint.go @@ -17,10 +17,10 @@ import ( "github.com/ethereum-optimism/optimism/op-node/p2p" p2pcli "github.com/ethereum-optimism/optimism/op-node/p2p/cli" "github.com/ethereum-optimism/optimism/op-node/rollup" + "github.com/ethereum-optimism/optimism/op-service/ctxinterrupt" "github.com/ethereum-optimism/optimism/op-service/eth" 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" ) @@ -116,9 +116,7 @@ func Main(cliCtx *cli.Context) error { m.RecordUp() } - opio.BlockOnInterrupts() - - return nil + return ctxinterrupt.Wait(ctx) } // validateConfig ensures the minimal config required to run a bootnode diff --git a/op-chain-ops/.gitignore b/op-chain-ops/.gitignore index ba077a4031add..2d94eb56a7db0 100644 --- a/op-chain-ops/.gitignore +++ b/op-chain-ops/.gitignore @@ -1 +1,3 @@ bin +intent.toml +state.json \ No newline at end of file diff --git a/op-chain-ops/Makefile b/op-chain-ops/Makefile index 1f119a95f62dc..fd3cc9ad67b34 100644 --- a/op-chain-ops/Makefile +++ b/op-chain-ops/Makefile @@ -1,3 +1,26 @@ +GITCOMMIT ?= $(shell git rev-parse HEAD) +GITDATE ?= $(shell git show -s --format='%ct') + +# Find the github tag that points to this commit. If none are found, set the version string to "untagged" +# Prioritizes release tag, if one exists, over tags suffixed with "-rc" +VERSION ?= $(shell tags=$$(git tag --points-at $(GITCOMMIT) | grep '^op-deployer/' | sed 's/op-deployer\///' | sort -V); \ + preferred_tag=$$(echo "$$tags" | grep -v -- '-rc' | tail -n 1); \ + if [ -z "$$preferred_tag" ]; then \ + if [ -z "$$tags" ]; then \ + echo "untagged"; \ + else \ + echo "$$tags" | tail -n 1; \ + fi \ + else \ + echo $$preferred_tag; \ + fi) + +LDFLAGSSTRING +=-X main.GitCommit=$(GITCOMMIT) +LDFLAGSSTRING +=-X main.GitDate=$(GITDATE) +LDFLAGSSTRING +=-X github.com/ethereum-optimism/optimism/op-chain-ops/deployer/version.Version=$(VERSION) +LDFLAGSSTRING +=-X github.com/ethereum-optimism/optimism/op-chain-ops/deployer/version.Meta=$(VERSION_META) +LDFLAGS := -ldflags "$(LDFLAGSSTRING)" + # Use the old Apple linker to workaround broken xcode - https://github.com/golang/go/issues/65169 ifeq ($(shell uname),Darwin) FUZZLDFLAGS := -ldflags=-extldflags=-Wl,-ld_classic @@ -12,10 +35,17 @@ receipt-reference-builder: test: go test ./... +op-deployer: + GOOS=$(TARGETOS) GOARCH=$(TARGETARCH) CGO_ENABLED=0 go build -v $(LDFLAGS) -o ./bin/op-deployer ./cmd/op-deployer/main.go + fuzz: go test $(FUZZLDFLAGS) -run NOTAREALTEST -v -fuzztime 10s -fuzz=FuzzEncodeDecodeWithdrawal ./crossdomain go test $(FUZZLDFLAGS) -run NOTAREALTEST -v -fuzztime 10s -fuzz=FuzzEncodeDecodeLegacyWithdrawal ./crossdomain go test $(FUZZLDFLAGS) -run NOTAREALTEST -v -fuzztime 10s -fuzz=FuzzAliasing ./crossdomain go test $(FUZZLDFLAGS) -run NOTAREALTEST -v -fuzztime 10s -fuzz=FuzzVersionedNonce ./crossdomain -.PHONY: test fuzz + +sync-standard-version: + curl -Lo ./deployer/opcm/standard-versions.toml https://raw.githubusercontent.com/ethereum-optimism/superchain-registry/refs/heads/main/validation/standard/standard-versions.toml + +.PHONY: test fuzz op-deployer sync-standard-version \ No newline at end of file diff --git a/op-chain-ops/cmd/check-ecotone/main.go b/op-chain-ops/cmd/check-ecotone/main.go index 2f46f03d29d03..58a11e9ce1ad0 100644 --- a/op-chain-ops/cmd/check-ecotone/main.go +++ b/op-chain-ops/cmd/check-ecotone/main.go @@ -32,10 +32,10 @@ import ( 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/ctxinterrupt" "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/predeploys" "github.com/ethereum-optimism/optimism/op-service/retry" "github.com/ethereum-optimism/optimism/op-service/sources" @@ -168,7 +168,7 @@ func makeCommandAction(fn CheckAction) func(c *cli.Context) error { logCfg := oplog.ReadCLIConfig(c) logger := oplog.NewLogger(c.App.Writer, logCfg) - c.Context = opio.CancelOnInterrupt(c.Context) + c.Context = ctxinterrupt.WithCancelOnInterrupt(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) diff --git a/op-chain-ops/cmd/check-fjord/main.go b/op-chain-ops/cmd/check-fjord/main.go index 5a2ef66fbcb9d..c63cc43493f54 100644 --- a/op-chain-ops/cmd/check-fjord/main.go +++ b/op-chain-ops/cmd/check-fjord/main.go @@ -9,8 +9,8 @@ import ( "github.com/ethereum-optimism/optimism/op-chain-ops/cmd/check-fjord/checks" op_service "github.com/ethereum-optimism/optimism/op-service" "github.com/ethereum-optimism/optimism/op-service/cliapp" + "github.com/ethereum-optimism/optimism/op-service/ctxinterrupt" oplog "github.com/ethereum-optimism/optimism/op-service/log" - "github.com/ethereum-optimism/optimism/op-service/opio" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethclient" "github.com/urfave/cli/v2" @@ -54,7 +54,7 @@ func makeCommandAction(fn CheckAction) func(c *cli.Context) error { logCfg := oplog.ReadCLIConfig(c) logger := oplog.NewLogger(c.App.Writer, logCfg) - c.Context = opio.CancelOnInterrupt(c.Context) + c.Context = ctxinterrupt.WithCancelOnInterrupt(c.Context) l2Cl, err := ethclient.DialContext(c.Context, c.String(EndpointL2.Name)) if err != nil { return fmt.Errorf("failed to dial L2 RPC: %w", err) diff --git a/op-chain-ops/cmd/op-deployer/main.go b/op-chain-ops/cmd/op-deployer/main.go new file mode 100644 index 0000000000000..023d8adca39d1 --- /dev/null +++ b/op-chain-ops/cmd/op-deployer/main.go @@ -0,0 +1,57 @@ +package main + +import ( + "fmt" + "os" + + "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/version" + opservice "github.com/ethereum-optimism/optimism/op-service" + + "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/inspect" + + "github.com/ethereum-optimism/optimism/op-chain-ops/deployer" + "github.com/ethereum-optimism/optimism/op-service/cliapp" + "github.com/urfave/cli/v2" +) + +var ( + GitCommit = "" + GitDate = "" +) + +// VersionWithMeta holds the textual version string including the metadata. +var VersionWithMeta = opservice.FormatVersion(version.Version, GitCommit, GitDate, version.Meta) + +func main() { + app := cli.NewApp() + app.Version = VersionWithMeta + app.Name = "op-deployer" + app.Usage = "Tool to configure and deploy OP Chains." + app.Flags = cliapp.ProtectFlags(deployer.GlobalFlags) + app.Commands = []*cli.Command{ + { + Name: "init", + Usage: "initializes a chain intent and state file", + Flags: cliapp.ProtectFlags(deployer.InitFlags), + Action: deployer.InitCLI(), + }, + { + Name: "apply", + Usage: "applies a chain intent to the chain", + Flags: cliapp.ProtectFlags(deployer.ApplyFlags), + Action: deployer.ApplyCLI(), + }, + { + Name: "inspect", + Usage: "inspects the state of a deployment", + Subcommands: inspect.Commands, + }, + } + app.Writer = os.Stdout + app.ErrWriter = os.Stderr + err := app.Run(os.Args) + if err != nil { + _, _ = fmt.Fprintf(os.Stderr, "Application failed: %v\n", err) + os.Exit(1) + } +} diff --git a/op-chain-ops/cmd/op-simulate/main.go b/op-chain-ops/cmd/op-simulate/main.go index 83aab87142182..8b0986e4554ff 100644 --- a/op-chain-ops/cmd/op-simulate/main.go +++ b/op-chain-ops/cmd/op-simulate/main.go @@ -33,8 +33,8 @@ import ( op_service "github.com/ethereum-optimism/optimism/op-service" "github.com/ethereum-optimism/optimism/op-service/cliapp" + "github.com/ethereum-optimism/optimism/op-service/ctxinterrupt" oplog "github.com/ethereum-optimism/optimism/op-service/log" - "github.com/ethereum-optimism/optimism/op-service/opio" ) var EnvPrefix = "OP_SIMULATE" @@ -82,7 +82,7 @@ func main() { } func mainAction(c *cli.Context) error { - ctx := opio.CancelOnInterrupt(c.Context) + ctx := ctxinterrupt.WithCancelOnInterrupt(c.Context) logCfg := oplog.ReadCLIConfig(c) logger := oplog.NewLogger(c.App.Writer, logCfg) diff --git a/op-chain-ops/deployer/apply.go b/op-chain-ops/deployer/apply.go new file mode 100644 index 0000000000000..ca34d4266df79 --- /dev/null +++ b/op-chain-ops/deployer/apply.go @@ -0,0 +1,189 @@ +package deployer + +import ( + "context" + "crypto/ecdsa" + "fmt" + "strings" + + "github.com/ethereum-optimism/optimism/op-chain-ops/foundry" + + "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/state" + + "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/pipeline" + opcrypto "github.com/ethereum-optimism/optimism/op-service/crypto" + "github.com/ethereum-optimism/optimism/op-service/ctxinterrupt" + oplog "github.com/ethereum-optimism/optimism/op-service/log" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/log" + "github.com/urfave/cli/v2" +) + +type ApplyConfig struct { + L1RPCUrl string + Workdir string + PrivateKey string + Logger log.Logger + + privateKeyECDSA *ecdsa.PrivateKey +} + +func (a *ApplyConfig) Check() error { + if a.L1RPCUrl == "" { + return fmt.Errorf("l1RPCUrl must be specified") + } + + if a.Workdir == "" { + return fmt.Errorf("workdir must be specified") + } + + if a.PrivateKey == "" { + return fmt.Errorf("private key must be specified") + } + + privECDSA, err := crypto.HexToECDSA(strings.TrimPrefix(a.PrivateKey, "0x")) + if err != nil { + return fmt.Errorf("failed to parse private key: %w", err) + } + a.privateKeyECDSA = privECDSA + + if a.Logger == nil { + return fmt.Errorf("logger must be specified") + } + + return nil +} + +func ApplyCLI() func(cliCtx *cli.Context) error { + return func(cliCtx *cli.Context) error { + logCfg := oplog.ReadCLIConfig(cliCtx) + l := oplog.NewLogger(oplog.AppOut(cliCtx), logCfg) + oplog.SetGlobalLogHandler(l.Handler()) + + l1RPCUrl := cliCtx.String(L1RPCURLFlagName) + workdir := cliCtx.String(WorkdirFlagName) + privateKey := cliCtx.String(PrivateKeyFlagName) + + ctx := ctxinterrupt.WithCancelOnInterrupt(cliCtx.Context) + + return Apply(ctx, ApplyConfig{ + L1RPCUrl: l1RPCUrl, + Workdir: workdir, + PrivateKey: privateKey, + Logger: l, + }) + } +} + +func Apply(ctx context.Context, cfg ApplyConfig) error { + if err := cfg.Check(); err != nil { + return fmt.Errorf("invalid config for apply: %w", err) + } + + l1Client, err := ethclient.Dial(cfg.L1RPCUrl) + if err != nil { + return fmt.Errorf("failed to connect to L1 RPC: %w", err) + } + + chainID, err := l1Client.ChainID(ctx) + if err != nil { + return fmt.Errorf("failed to get chain ID: %w", err) + } + + signer := opcrypto.SignerFnFromBind(opcrypto.PrivateKeySignerFn(cfg.privateKeyECDSA, chainID)) + deployer := crypto.PubkeyToAddress(cfg.privateKeyECDSA.PublicKey) + + env := &pipeline.Env{ + Workdir: cfg.Workdir, + L1Client: l1Client, + Logger: cfg.Logger, + Signer: signer, + Deployer: deployer, + } + + intent, err := env.ReadIntent() + if err != nil { + return err + } + + if err := intent.Check(); err != nil { + return fmt.Errorf("invalid intent: %w", err) + } + + st, err := env.ReadState() + if err != nil { + return err + } + + if err := ApplyPipeline(ctx, env, intent, st); err != nil { + return err + } + + st.AppliedIntent = intent + if err := env.WriteState(st); err != nil { + return err + } + + return nil +} + +type pipelineStage struct { + name string + apply pipeline.Stage +} + +func ApplyPipeline( + ctx context.Context, + env *pipeline.Env, + intent *state.Intent, + st *state.State, +) error { + progressor := func(curr, total int64) { + env.Logger.Info("artifacts download progress", "current", curr, "total", total) + } + + artifactsFS, cleanup, err := pipeline.DownloadArtifacts(ctx, intent.ContractArtifactsURL, progressor) + if err != nil { + return fmt.Errorf("failed to download artifacts: %w", err) + } + defer func() { + if err := cleanup(); err != nil { + env.Logger.Warn("failed to clean up artifacts", "err", err) + } + }() + + pline := []pipelineStage{ + {"init", pipeline.Init}, + {"deploy-superchain", pipeline.DeploySuperchain}, + {"deploy-implementations", pipeline.DeployImplementations}, + } + + for _, chain := range intent.Chains { + chainID := chain.ID + pline = append(pline, pipelineStage{ + fmt.Sprintf("deploy-opchain-%s", chainID.Hex()), + func(ctx context.Context, env *pipeline.Env, artifactsFS foundry.StatDirFs, intent *state.Intent, st *state.State) error { + return pipeline.DeployOPChain(ctx, env, artifactsFS, intent, st, chainID) + }, + }, pipelineStage{ + fmt.Sprintf("generate-l2-genesis-%s", chainID.Hex()), + func(ctx context.Context, env *pipeline.Env, artifactsFS foundry.StatDirFs, intent *state.Intent, st *state.State) error { + return pipeline.GenerateL2Genesis(ctx, env, artifactsFS, intent, st, chainID) + }, + }) + } + + for _, stage := range pline { + if err := stage.apply(ctx, env, artifactsFS, intent, st); err != nil { + return fmt.Errorf("error in pipeline stage apply: %w", err) + } + } + + st.AppliedIntent = intent + if err := env.WriteState(st); err != nil { + return fmt.Errorf("failed to write state: %w", err) + } + + return nil +} diff --git a/op-chain-ops/deployer/broadcaster/broadcaster.go b/op-chain-ops/deployer/broadcaster/broadcaster.go new file mode 100644 index 0000000000000..641d1f73dfb5d --- /dev/null +++ b/op-chain-ops/deployer/broadcaster/broadcaster.go @@ -0,0 +1,21 @@ +package broadcaster + +import ( + "context" + + "github.com/ethereum-optimism/optimism/op-chain-ops/script" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" +) + +type Broadcaster interface { + Broadcast(ctx context.Context) ([]BroadcastResult, error) + Hook(bcast script.Broadcast) +} + +type BroadcastResult struct { + Broadcast script.Broadcast `json:"broadcast"` + TxHash common.Hash `json:"txHash"` + Receipt *types.Receipt `json:"receipt"` + Err error `json:"-"` +} diff --git a/op-chain-ops/deployer/broadcaster/discard.go b/op-chain-ops/deployer/broadcaster/discard.go new file mode 100644 index 0000000000000..42f5b1b0a9642 --- /dev/null +++ b/op-chain-ops/deployer/broadcaster/discard.go @@ -0,0 +1,20 @@ +package broadcaster + +import ( + "context" + + "github.com/ethereum-optimism/optimism/op-chain-ops/script" +) + +type discardBroadcaster struct { +} + +func DiscardBroadcaster() Broadcaster { + return &discardBroadcaster{} +} + +func (d *discardBroadcaster) Broadcast(ctx context.Context) ([]BroadcastResult, error) { + return nil, nil +} + +func (d *discardBroadcaster) Hook(bcast script.Broadcast) {} diff --git a/op-chain-ops/deployer/broadcaster/keyed.go b/op-chain-ops/deployer/broadcaster/keyed.go new file mode 100644 index 0000000000000..63b72010042b6 --- /dev/null +++ b/op-chain-ops/deployer/broadcaster/keyed.go @@ -0,0 +1,224 @@ +package broadcaster + +import ( + "context" + "fmt" + "math/big" + "time" + + "github.com/ethereum-optimism/optimism/op-chain-ops/script" + opcrypto "github.com/ethereum-optimism/optimism/op-service/crypto" + "github.com/ethereum-optimism/optimism/op-service/eth" + "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/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/log" + "github.com/hashicorp/go-multierror" + "github.com/holiman/uint256" +) + +const ( + GasPadFactor = 2.0 +) + +type KeyedBroadcaster struct { + lgr log.Logger + mgr txmgr.TxManager + bcasts []script.Broadcast + client *ethclient.Client +} + +type KeyedBroadcasterOpts struct { + Logger log.Logger + ChainID *big.Int + Client *ethclient.Client + Signer opcrypto.SignerFn + From common.Address + TXManagerLogger log.Logger +} + +func NewKeyedBroadcaster(cfg KeyedBroadcasterOpts) (*KeyedBroadcaster, error) { + mgrCfg := &txmgr.Config{ + Backend: cfg.Client, + ChainID: cfg.ChainID, + TxSendTimeout: 5 * time.Minute, + TxNotInMempoolTimeout: time.Minute, + NetworkTimeout: 10 * time.Second, + ReceiptQueryInterval: time.Second, + NumConfirmations: 1, + SafeAbortNonceTooLowCount: 3, + Signer: cfg.Signer, + From: cfg.From, + } + + minTipCap, err := eth.GweiToWei(1.0) + if err != nil { + panic(err) + } + minBaseFee, err := eth.GweiToWei(1.0) + if err != nil { + panic(err) + } + + mgrCfg.ResubmissionTimeout.Store(int64(48 * time.Second)) + mgrCfg.FeeLimitMultiplier.Store(5) + mgrCfg.FeeLimitThreshold.Store(big.NewInt(100)) + mgrCfg.MinTipCap.Store(minTipCap) + mgrCfg.MinTipCap.Store(minBaseFee) + + txmLogger := log.NewLogger(log.DiscardHandler()) + if cfg.TXManagerLogger != nil { + txmLogger = cfg.TXManagerLogger + } + + mgr, err := txmgr.NewSimpleTxManagerFromConfig( + "transactor", + txmLogger, + &metrics.NoopTxMetrics{}, + mgrCfg, + ) + + if err != nil { + return nil, fmt.Errorf("failed to create tx manager: %w", err) + } + + return &KeyedBroadcaster{ + lgr: cfg.Logger, + mgr: mgr, + client: cfg.Client, + }, nil +} + +func (t *KeyedBroadcaster) Hook(bcast script.Broadcast) { + t.bcasts = append(t.bcasts, bcast) +} + +func (t *KeyedBroadcaster) Broadcast(ctx context.Context) ([]BroadcastResult, error) { + results := make([]BroadcastResult, len(t.bcasts)) + futures := make([]<-chan txmgr.SendResponse, len(t.bcasts)) + ids := make([]common.Hash, len(t.bcasts)) + + latestBlock, err := t.client.BlockByNumber(ctx, nil) + if err != nil { + return nil, fmt.Errorf("failed to get latest block: %w", err) + } + + for i, bcast := range t.bcasts { + futures[i], ids[i] = t.broadcast(ctx, bcast, latestBlock.GasLimit()) + t.lgr.Info( + "transaction broadcasted", + "id", ids[i], + "nonce", bcast.Nonce, + ) + } + + var txErr *multierror.Error + var completed int + for i, fut := range futures { + bcastRes := <-fut + completed++ + outRes := BroadcastResult{ + Broadcast: t.bcasts[i], + } + + if bcastRes.Err == nil { + outRes.Receipt = bcastRes.Receipt + outRes.TxHash = bcastRes.Receipt.TxHash + + if bcastRes.Receipt.Status == 0 { + failErr := fmt.Errorf("transaction failed: %s", outRes.Receipt.TxHash.String()) + txErr = multierror.Append(txErr, failErr) + outRes.Err = failErr + t.lgr.Error( + "transaction failed on chain", + "id", ids[i], + "completed", completed, + "total", len(t.bcasts), + "hash", outRes.Receipt.TxHash.String(), + "nonce", outRes.Broadcast.Nonce, + ) + } else { + t.lgr.Info( + "transaction confirmed", + "id", ids[i], + "completed", completed, + "total", len(t.bcasts), + "hash", outRes.Receipt.TxHash.String(), + "nonce", outRes.Broadcast.Nonce, + "creation", outRes.Receipt.ContractAddress, + ) + } + } else { + txErr = multierror.Append(txErr, bcastRes.Err) + outRes.Err = bcastRes.Err + t.lgr.Error( + "transaction failed", + "id", ids[i], + "completed", completed, + "total", len(t.bcasts), + "err", bcastRes.Err, + ) + } + + results[i] = outRes + } + return results, txErr.ErrorOrNil() +} + +func (t *KeyedBroadcaster) broadcast(ctx context.Context, bcast script.Broadcast, blockGasLimit uint64) (<-chan txmgr.SendResponse, common.Hash) { + ch := make(chan txmgr.SendResponse, 1) + + id := bcast.ID() + value := ((*uint256.Int)(bcast.Value)).ToBig() + var candidate txmgr.TxCandidate + switch bcast.Type { + case script.BroadcastCall: + to := &bcast.To + candidate = txmgr.TxCandidate{ + TxData: bcast.Input, + To: to, + Value: value, + GasLimit: padGasLimit(bcast.Input, bcast.GasUsed, false, blockGasLimit), + } + case script.BroadcastCreate: + candidate = txmgr.TxCandidate{ + TxData: bcast.Input, + To: nil, + GasLimit: padGasLimit(bcast.Input, bcast.GasUsed, true, blockGasLimit), + } + case script.BroadcastCreate2: + txData := make([]byte, len(bcast.Salt)+len(bcast.Input)) + copy(txData, bcast.Salt[:]) + copy(txData[len(bcast.Salt):], bcast.Input) + + candidate = txmgr.TxCandidate{ + TxData: txData, + To: &script.DeterministicDeployerAddress, + Value: value, + GasLimit: padGasLimit(bcast.Input, bcast.GasUsed, true, blockGasLimit), + } + } + + t.mgr.SendAsync(ctx, candidate, ch) + return ch, id +} + +// padGasLimit calculates the gas limit for a transaction based on the intrinsic gas and the gas used by +// the underlying call. Values are multiplied by a pad factor to account for any discrepancies. The output +// is clamped to the block gas limit since Geth will reject transactions that exceed it before letting them +// into the mempool. +func padGasLimit(data []byte, gasUsed uint64, creation bool, blockGasLimit uint64) uint64 { + intrinsicGas, err := core.IntrinsicGas(data, nil, creation, true, true, false) + // This method never errors - we should look into it if it does. + if err != nil { + panic(err) + } + + limit := uint64(float64(intrinsicGas+gasUsed) * GasPadFactor) + if limit > blockGasLimit { + return blockGasLimit + } + return limit +} diff --git a/op-chain-ops/deployer/flags.go b/op-chain-ops/deployer/flags.go new file mode 100644 index 0000000000000..e0ab864bdada2 --- /dev/null +++ b/op-chain-ops/deployer/flags.go @@ -0,0 +1,82 @@ +package deployer + +import ( + "os" + + op_service "github.com/ethereum-optimism/optimism/op-service" + oplog "github.com/ethereum-optimism/optimism/op-service/log" + "github.com/urfave/cli/v2" +) + +const ( + EnvVarPrefix = "DEPLOYER" + L1RPCURLFlagName = "l1-rpc-url" + L1ChainIDFlagName = "l1-chain-id" + L2ChainIDsFlagName = "l2-chain-ids" + WorkdirFlagName = "workdir" + OutdirFlagName = "outdir" + PrivateKeyFlagName = "private-key" +) + +var ( + L1RPCURLFlag = &cli.StringFlag{ + Name: L1RPCURLFlagName, + Usage: "RPC URL for the L1 chain. Can be set to 'genesis' for deployments " + + "that will be deployed at the launch of the L1.", + EnvVars: []string{ + "L1_RPC_URL", + }, + } + L1ChainIDFlag = &cli.Uint64Flag{ + Name: L1ChainIDFlagName, + Usage: "Chain ID of the L1 chain.", + EnvVars: prefixEnvVar("L1_CHAIN_ID"), + Value: 900, + } + L2ChainIDsFlag = &cli.StringFlag{ + Name: L2ChainIDsFlagName, + Usage: "Comma-separated list of L2 chain IDs to deploy.", + EnvVars: prefixEnvVar("L2_CHAIN_IDS"), + } + WorkdirFlag = &cli.StringFlag{ + Name: WorkdirFlagName, + Usage: "Directory storing intent and stage. Defaults to the current directory.", + EnvVars: prefixEnvVar("WORKDIR"), + Value: cwd(), + Aliases: []string{ + OutdirFlagName, + }, + } + + PrivateKeyFlag = &cli.StringFlag{ + Name: PrivateKeyFlagName, + Usage: "Private key of the deployer account.", + EnvVars: prefixEnvVar("PRIVATE_KEY"), + } +) + +var GlobalFlags = append([]cli.Flag{}, oplog.CLIFlags(EnvVarPrefix)...) + +var InitFlags = []cli.Flag{ + L1ChainIDFlag, + L2ChainIDsFlag, + WorkdirFlag, +} + +var ApplyFlags = []cli.Flag{ + L1RPCURLFlag, + WorkdirFlag, + PrivateKeyFlag, +} + +func prefixEnvVar(name string) []string { + return op_service.PrefixEnvVar(EnvVarPrefix, name) +} + +func cwd() string { + dir, err := os.Getwd() + if err != nil { + return "" + } + return dir +} diff --git a/op-chain-ops/deployer/init.go b/op-chain-ops/deployer/init.go new file mode 100644 index 0000000000000..bd79f980cdffb --- /dev/null +++ b/op-chain-ops/deployer/init.go @@ -0,0 +1,122 @@ +package deployer + +import ( + "fmt" + "path" + "strings" + + op_service "github.com/ethereum-optimism/optimism/op-service" + + "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/state" + "github.com/ethereum-optimism/optimism/op-chain-ops/devkeys" + "github.com/ethereum/go-ethereum/common" + "github.com/urfave/cli/v2" +) + +type InitConfig struct { + L1ChainID uint64 + Outdir string + L2ChainIDs []common.Hash +} + +func (c *InitConfig) Check() error { + if c.L1ChainID == 0 { + return fmt.Errorf("l1ChainID must be specified") + } + + if c.Outdir == "" { + return fmt.Errorf("outdir must be specified") + } + + if len(c.L2ChainIDs) == 0 { + return fmt.Errorf("must specify at least one L2 chain ID") + } + + return nil +} + +func InitCLI() func(ctx *cli.Context) error { + return func(ctx *cli.Context) error { + l1ChainID := ctx.Uint64(L1ChainIDFlagName) + outdir := ctx.String(OutdirFlagName) + + l2ChainIDsRaw := ctx.String(L2ChainIDsFlagName) + l2ChainIDsStr := strings.Split(l2ChainIDsRaw, ",") + l2ChainIDs := make([]common.Hash, 0, len(l2ChainIDsStr)) + for _, idStr := range l2ChainIDsStr { + id, err := op_service.Parse256BitChainID(idStr) + if err != nil { + return fmt.Errorf("invalid chain ID: %w", err) + } + l2ChainIDs = append(l2ChainIDs, id) + } + + return Init(InitConfig{ + L1ChainID: l1ChainID, + Outdir: outdir, + L2ChainIDs: l2ChainIDs, + }) + } +} + +func Init(cfg InitConfig) error { + if err := cfg.Check(); err != nil { + return fmt.Errorf("invalid config for init: %w", err) + } + + intent := &state.Intent{ + L1ChainID: cfg.L1ChainID, + UseFaultProofs: true, + FundDevAccounts: true, + ContractsRelease: "dev", + } + + l1ChainIDBig := intent.L1ChainIDBig() + + dk, err := devkeys.NewMnemonicDevKeys(devkeys.TestMnemonic) + if err != nil { + return fmt.Errorf("failed to create dev keys: %w", err) + } + + addrFor := func(key devkeys.Key) common.Address { + // The error below should never happen, so panic if it does. + addr, err := dk.Address(key) + if err != nil { + panic(err) + } + return addr + } + intent.SuperchainRoles = state.SuperchainRoles{ + ProxyAdminOwner: addrFor(devkeys.L1ProxyAdminOwnerRole.Key(l1ChainIDBig)), + ProtocolVersionsOwner: addrFor(devkeys.SuperchainProtocolVersionsOwner.Key(l1ChainIDBig)), + Guardian: addrFor(devkeys.SuperchainConfigGuardianKey.Key(l1ChainIDBig)), + } + + for _, l2ChainID := range cfg.L2ChainIDs { + l2ChainIDBig := l2ChainID.Big() + intent.Chains = append(intent.Chains, &state.ChainIntent{ + ID: l2ChainID, + Roles: state.ChainRoles{ + ProxyAdminOwner: addrFor(devkeys.L2ProxyAdminOwnerRole.Key(l2ChainIDBig)), + SystemConfigOwner: addrFor(devkeys.SystemConfigOwner.Key(l2ChainIDBig)), + GovernanceTokenOwner: addrFor(devkeys.L2ProxyAdminOwnerRole.Key(l2ChainIDBig)), + UnsafeBlockSigner: addrFor(devkeys.SequencerP2PRole.Key(l2ChainIDBig)), + Batcher: addrFor(devkeys.BatcherRole.Key(l2ChainIDBig)), + Proposer: addrFor(devkeys.ProposerRole.Key(l2ChainIDBig)), + Challenger: addrFor(devkeys.ChallengerRole.Key(l2ChainIDBig)), + }, + }) + } + + st := &state.State{ + Version: 1, + } + + if err := intent.WriteToFile(path.Join(cfg.Outdir, "intent.toml")); err != nil { + return fmt.Errorf("failed to write intent to file: %w", err) + } + if err := st.WriteToFile(path.Join(cfg.Outdir, "state.json")); err != nil { + return fmt.Errorf("failed to write state to file: %w", err) + } + return nil +} diff --git a/op-chain-ops/deployer/inspect/flags.go b/op-chain-ops/deployer/inspect/flags.go new file mode 100644 index 0000000000000..601e28ba85a5e --- /dev/null +++ b/op-chain-ops/deployer/inspect/flags.go @@ -0,0 +1,83 @@ +package inspect + +import ( + "fmt" + + op_service "github.com/ethereum-optimism/optimism/op-service" + + "github.com/ethereum-optimism/optimism/op-chain-ops/deployer" + "github.com/ethereum/go-ethereum/common" + "github.com/urfave/cli/v2" +) + +const ( + OutfileFlagName = "outfile" +) + +var ( + FlagOutfile = &cli.StringFlag{ + Name: OutfileFlagName, + Usage: "output file. set to - to use stdout", + Value: "-", + } +) + +var Flags = []cli.Flag{ + deployer.WorkdirFlag, + FlagOutfile, +} + +var Commands = []*cli.Command{ + { + Name: "genesis", + Usage: "outputs the genesis for an L2 chain", + Args: true, + ArgsUsage: "", + Action: GenesisCLI, + Flags: Flags, + }, + { + Name: "rollup", + Usage: "outputs the rollup config for an L2 chain", + Args: true, + ArgsUsage: "", + Action: RollupCLI, + Flags: Flags, + }, +} + +type cliConfig struct { + Workdir string + Outfile string + ChainID common.Hash +} + +func readConfig(cliCtx *cli.Context) (cliConfig, error) { + var cfg cliConfig + + outfile := cliCtx.String(OutfileFlagName) + if outfile == "" { + return cfg, fmt.Errorf("outfile flag is required") + } + + workdir := cliCtx.String(deployer.WorkdirFlagName) + if workdir == "" { + return cfg, fmt.Errorf("workdir flag is required") + } + + chainIDStr := cliCtx.Args().First() + if chainIDStr == "" { + return cfg, fmt.Errorf("chain-id argument is required") + } + + chainID, err := op_service.Parse256BitChainID(chainIDStr) + if err != nil { + return cfg, fmt.Errorf("failed to parse chain ID: %w", err) + } + + return cliConfig{ + Workdir: cliCtx.String(deployer.WorkdirFlagName), + Outfile: cliCtx.String(OutfileFlagName), + ChainID: chainID, + }, nil +} diff --git a/op-chain-ops/deployer/inspect/genesis.go b/op-chain-ops/deployer/inspect/genesis.go new file mode 100644 index 0000000000000..4c2fbad010929 --- /dev/null +++ b/op-chain-ops/deployer/inspect/genesis.go @@ -0,0 +1,92 @@ +package inspect + +import ( + "fmt" + + "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/pipeline" + "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/state" + "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" + "github.com/ethereum-optimism/optimism/op-node/rollup" + "github.com/ethereum/go-ethereum/core" + + "github.com/ethereum-optimism/optimism/op-service/ioutil" + "github.com/ethereum-optimism/optimism/op-service/jsonutil" + "github.com/ethereum/go-ethereum/common" + "github.com/urfave/cli/v2" +) + +func GenesisCLI(cliCtx *cli.Context) error { + cfg, err := readConfig(cliCtx) + if err != nil { + return err + } + + env := &pipeline.Env{Workdir: cfg.Workdir} + globalState, err := env.ReadState() + if err != nil { + return fmt.Errorf("failed to read intent: %w", err) + } + + l2Genesis, _, err := GenesisAndRollup(globalState, cfg.ChainID) + if err != nil { + return fmt.Errorf("failed to generate genesis block: %w", err) + } + + if err := jsonutil.WriteJSON(l2Genesis, ioutil.ToStdOutOrFileOrNoop(cfg.Outfile, 0o666)); err != nil { + return fmt.Errorf("failed to write genesis: %w", err) + } + + return nil +} + +func GenesisAndRollup(globalState *state.State, chainID common.Hash) (*core.Genesis, *rollup.Config, error) { + if globalState.AppliedIntent == nil { + return nil, nil, fmt.Errorf("chain state is not applied - run op-deployer apply") + } + + chainIntent, err := globalState.AppliedIntent.Chain(chainID) + if err != nil { + return nil, nil, fmt.Errorf("failed to get applied chain intent: %w", err) + } + + chainState, err := globalState.Chain(chainID) + if err != nil { + return nil, nil, fmt.Errorf("failed to get chain ID %s: %w", chainID.String(), err) + } + + l2Allocs, err := chainState.UnmarshalAllocs() + if err != nil { + return nil, nil, fmt.Errorf("failed to unmarshal genesis: %w", err) + } + + config, err := state.CombineDeployConfig( + globalState.AppliedIntent, + chainIntent, + globalState, + chainState, + ) + if err != nil { + return nil, nil, fmt.Errorf("failed to combine L2 init config: %w", err) + } + + l2GenesisBuilt, err := genesis.BuildL2Genesis(&config, l2Allocs, chainState.StartBlock) + if err != nil { + return nil, nil, fmt.Errorf("failed to build L2 genesis: %w", err) + } + l2GenesisBlock := l2GenesisBuilt.ToBlock() + + rollupConfig, err := config.RollupConfig( + chainState.StartBlock, + l2GenesisBlock.Hash(), + l2GenesisBlock.Number().Uint64(), + ) + if err != nil { + return nil, nil, fmt.Errorf("failed to build rollup config: %w", err) + } + + if err := rollupConfig.Check(); err != nil { + return nil, nil, fmt.Errorf("generated rollup config does not pass validation: %w", err) + } + + return l2GenesisBuilt, rollupConfig, nil +} diff --git a/op-chain-ops/deployer/inspect/rollup.go b/op-chain-ops/deployer/inspect/rollup.go new file mode 100644 index 0000000000000..60cbf4f5c46c5 --- /dev/null +++ b/op-chain-ops/deployer/inspect/rollup.go @@ -0,0 +1,34 @@ +package inspect + +import ( + "fmt" + + "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/pipeline" + "github.com/ethereum-optimism/optimism/op-service/ioutil" + "github.com/ethereum-optimism/optimism/op-service/jsonutil" + "github.com/urfave/cli/v2" +) + +func RollupCLI(cliCtx *cli.Context) error { + cfg, err := readConfig(cliCtx) + if err != nil { + return err + } + + env := &pipeline.Env{Workdir: cfg.Workdir} + globalState, err := env.ReadState() + if err != nil { + return fmt.Errorf("failed to read intent: %w", err) + } + + _, rollupConfig, err := GenesisAndRollup(globalState, cfg.ChainID) + if err != nil { + return fmt.Errorf("failed to generate rollup config: %w", err) + } + + if err := jsonutil.WriteJSON(rollupConfig, ioutil.ToStdOutOrFileOrNoop(cfg.Outfile, 0o666)); err != nil { + return fmt.Errorf("failed to write rollup config: %w", err) + } + + return nil +} diff --git a/op-chain-ops/deployer/integration_test/apply_test.go b/op-chain-ops/deployer/integration_test/apply_test.go new file mode 100644 index 0000000000000..ad22651fa36ed --- /dev/null +++ b/op-chain-ops/deployer/integration_test/apply_test.go @@ -0,0 +1,264 @@ +package integration_test + +import ( + "context" + "fmt" + "log/slog" + "math/big" + "net/url" + "path" + "runtime" + "testing" + + "github.com/ethereum-optimism/optimism/op-chain-ops/deployer" + "github.com/holiman/uint256" + + "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/pipeline" + "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/state" + "github.com/ethereum-optimism/optimism/op-chain-ops/devkeys" + opcrypto "github.com/ethereum-optimism/optimism/op-service/crypto" + "github.com/ethereum-optimism/optimism/op-service/testlog" + "github.com/ethereum-optimism/optimism/op-service/testutils/kurtosisutil" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/stretchr/testify/require" +) + +const TestParams = ` +participants: + - el_type: geth + el_extra_params: + - "--gcmode=archive" + cl_type: lighthouse +network_params: + prefunded_accounts: '{ "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266": { "balance": "1000000ETH" } }' + additional_preloaded_contracts: '{ + "0x4e59b44847b379578588920cA78FbF26c0B4956C": { + balance: "0ETH", + code: "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3", + storage: {}, + nonce: 0, + secretKey: "0x" + } + }' + network_id: "77799777" + seconds_per_slot: 3 + genesis_delay: 0 +` + +type deployerKey struct{} + +func (d *deployerKey) HDPath() string { + return "m/44'/60'/0'/0/0" +} + +func (d *deployerKey) String() string { + return "deployer-key" +} + +func TestEndToEndApply(t *testing.T) { + kurtosisutil.Test(t) + + lgr := testlog.Logger(t, slog.LevelDebug) + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + _, testFilename, _, ok := runtime.Caller(0) + require.Truef(t, ok, "failed to get test filename") + monorepoDir := path.Join(path.Dir(testFilename), "..", "..", "..") + artifactsDir := path.Join(monorepoDir, "packages", "contracts-bedrock", "forge-artifacts") + + enclaveCtx := kurtosisutil.StartEnclave(t, ctx, lgr, "github.com/ethpandaops/ethereum-package", TestParams) + + service, err := enclaveCtx.GetServiceContext("el-1-geth-lighthouse") + require.NoError(t, err) + + ip := service.GetMaybePublicIPAddress() + ports := service.GetPublicPorts() + rpcURL := fmt.Sprintf("http://%s:%d", ip, ports["rpc"].GetNumber()) + l1Client, err := ethclient.Dial(rpcURL) + require.NoError(t, err) + + artifactsURL, err := url.Parse(fmt.Sprintf("file://%s", artifactsDir)) + require.NoError(t, err) + + depKey := new(deployerKey) + l1ChainID := big.NewInt(77799777) + dk, err := devkeys.NewMnemonicDevKeys(devkeys.TestMnemonic) + require.NoError(t, err) + pk, err := dk.Secret(depKey) + require.NoError(t, err) + signer := opcrypto.SignerFnFromBind(opcrypto.PrivateKeySignerFn(pk, l1ChainID)) + + id := uint256.NewInt(1) + + deployerAddr, err := dk.Address(depKey) + require.NoError(t, err) + + env := &pipeline.Env{ + Workdir: t.TempDir(), + L1Client: l1Client, + Signer: signer, + Deployer: deployerAddr, + Logger: lgr, + } + + t.Run("initial chain", func(t *testing.T) { + intent, st := makeIntent(t, l1ChainID, artifactsURL, dk, id) + + require.NoError(t, deployer.ApplyPipeline( + ctx, + env, + intent, + st, + )) + + addrs := []struct { + name string + addr common.Address + }{ + {"SuperchainProxyAdmin", st.SuperchainDeployment.ProxyAdminAddress}, + {"SuperchainConfigProxy", st.SuperchainDeployment.SuperchainConfigProxyAddress}, + {"SuperchainConfigImpl", st.SuperchainDeployment.SuperchainConfigImplAddress}, + {"ProtocolVersionsProxy", st.SuperchainDeployment.ProtocolVersionsProxyAddress}, + {"ProtocolVersionsImpl", st.SuperchainDeployment.ProtocolVersionsImplAddress}, + {"OpcmProxy", st.ImplementationsDeployment.OpcmProxyAddress}, + {"DelayedWETHImpl", st.ImplementationsDeployment.DelayedWETHImplAddress}, + {"OptimismPortalImpl", st.ImplementationsDeployment.OptimismPortalImplAddress}, + {"PreimageOracleSingleton", st.ImplementationsDeployment.PreimageOracleSingletonAddress}, + {"MipsSingleton", st.ImplementationsDeployment.MipsSingletonAddress}, + {"SystemConfigImpl", st.ImplementationsDeployment.SystemConfigImplAddress}, + {"L1CrossDomainMessengerImpl", st.ImplementationsDeployment.L1CrossDomainMessengerImplAddress}, + {"L1ERC721BridgeImpl", st.ImplementationsDeployment.L1ERC721BridgeImplAddress}, + {"L1StandardBridgeImpl", st.ImplementationsDeployment.L1StandardBridgeImplAddress}, + {"OptimismMintableERC20FactoryImpl", st.ImplementationsDeployment.OptimismMintableERC20FactoryImplAddress}, + {"DisputeGameFactoryImpl", st.ImplementationsDeployment.DisputeGameFactoryImplAddress}, + } + for _, addr := range addrs { + t.Run(addr.name, func(t *testing.T) { + code, err := l1Client.CodeAt(ctx, addr.addr, nil) + require.NoError(t, err) + require.NotEmpty(t, code, "contracts %s at %s has no code", addr.name, addr.addr) + }) + } + + validateOPChainDeployment(t, ctx, l1Client, st) + }) + + t.Run("subsequent chain", func(t *testing.T) { + newID := uint256.NewInt(2) + intent, st := makeIntent(t, l1ChainID, artifactsURL, dk, newID) + env.Workdir = t.TempDir() + + require.NoError(t, deployer.ApplyPipeline( + ctx, + env, + intent, + st, + )) + + addrs := []struct { + name string + addr common.Address + }{ + {"SuperchainConfigProxy", st.SuperchainDeployment.SuperchainConfigProxyAddress}, + {"ProtocolVersionsProxy", st.SuperchainDeployment.ProtocolVersionsProxyAddress}, + {"OpcmProxy", st.ImplementationsDeployment.OpcmProxyAddress}, + } + for _, addr := range addrs { + t.Run(addr.name, func(t *testing.T) { + code, err := l1Client.CodeAt(ctx, addr.addr, nil) + require.NoError(t, err) + require.NotEmpty(t, code, "contracts %s at %s has no code", addr.name, addr.addr) + }) + } + + validateOPChainDeployment(t, ctx, l1Client, st) + }) +} + +func makeIntent( + t *testing.T, + l1ChainID *big.Int, + artifactsURL *url.URL, + dk *devkeys.MnemonicDevKeys, + l2ChainID *uint256.Int, +) (*state.Intent, *state.State) { + addrFor := func(key devkeys.Key) common.Address { + addr, err := dk.Address(key) + require.NoError(t, err) + return addr + } + + intent := &state.Intent{ + L1ChainID: l1ChainID.Uint64(), + SuperchainRoles: state.SuperchainRoles{ + ProxyAdminOwner: addrFor(devkeys.L1ProxyAdminOwnerRole.Key(l1ChainID)), + ProtocolVersionsOwner: addrFor(devkeys.SuperchainDeployerKey.Key(l1ChainID)), + Guardian: addrFor(devkeys.SuperchainConfigGuardianKey.Key(l1ChainID)), + }, + UseFaultProofs: true, + FundDevAccounts: true, + ContractArtifactsURL: (*state.ArtifactsURL)(artifactsURL), + ContractsRelease: "dev", + Chains: []*state.ChainIntent{ + { + ID: l2ChainID.Bytes32(), + Roles: state.ChainRoles{ + ProxyAdminOwner: addrFor(devkeys.L2ProxyAdminOwnerRole.Key(l1ChainID)), + SystemConfigOwner: addrFor(devkeys.SystemConfigOwner.Key(l1ChainID)), + GovernanceTokenOwner: addrFor(devkeys.L2ProxyAdminOwnerRole.Key(l1ChainID)), + UnsafeBlockSigner: addrFor(devkeys.SequencerP2PRole.Key(l1ChainID)), + Batcher: addrFor(devkeys.BatcherRole.Key(l1ChainID)), + Proposer: addrFor(devkeys.ProposerRole.Key(l1ChainID)), + Challenger: addrFor(devkeys.ChallengerRole.Key(l1ChainID)), + }, + }, + }, + } + st := &state.State{ + Version: 1, + } + return intent, st +} + +func validateOPChainDeployment(t *testing.T, ctx context.Context, l1Client *ethclient.Client, st *state.State) { + for _, chainState := range st.Chains { + chainAddrs := []struct { + name string + addr common.Address + }{ + {"ProxyAdminAddress", chainState.ProxyAdminAddress}, + {"AddressManagerAddress", chainState.AddressManagerAddress}, + {"L1ERC721BridgeProxyAddress", chainState.L1ERC721BridgeProxyAddress}, + {"SystemConfigProxyAddress", chainState.SystemConfigProxyAddress}, + {"OptimismMintableERC20FactoryProxyAddress", chainState.OptimismMintableERC20FactoryProxyAddress}, + {"L1StandardBridgeProxyAddress", chainState.L1StandardBridgeProxyAddress}, + {"L1CrossDomainMessengerProxyAddress", chainState.L1CrossDomainMessengerProxyAddress}, + {"OptimismPortalProxyAddress", chainState.OptimismPortalProxyAddress}, + {"DisputeGameFactoryProxyAddress", chainState.DisputeGameFactoryProxyAddress}, + {"AnchorStateRegistryProxyAddress", chainState.AnchorStateRegistryProxyAddress}, + {"AnchorStateRegistryImplAddress", chainState.AnchorStateRegistryImplAddress}, + {"FaultDisputeGameAddress", chainState.FaultDisputeGameAddress}, + {"PermissionedDisputeGameAddress", chainState.PermissionedDisputeGameAddress}, + {"DelayedWETHPermissionedGameProxyAddress", chainState.DelayedWETHPermissionedGameProxyAddress}, + {"DelayedWETHPermissionlessGameProxyAddress", chainState.DelayedWETHPermissionlessGameProxyAddress}, + } + for _, addr := range chainAddrs { + // TODO Delete this `if`` block once FaultDisputeGameAddress is deployed. + if addr.name == "FaultDisputeGameAddress" { + continue + } + t.Run(addr.name, func(t *testing.T) { + code, err := l1Client.CodeAt(ctx, addr.addr, nil) + require.NoError(t, err) + require.NotEmpty(t, code, "contracts %s at %s for chain %s has no code", addr.name, addr.addr, chainState.ID) + }) + } + + t.Run("l2 genesis", func(t *testing.T) { + require.Greater(t, len(chainState.Allocs), 0) + }) + } +} diff --git a/op-chain-ops/deployer/opcm/contract.go b/op-chain-ops/deployer/opcm/contract.go new file mode 100644 index 0000000000000..c81222aafe888 --- /dev/null +++ b/op-chain-ops/deployer/opcm/contract.go @@ -0,0 +1,83 @@ +package opcm + +import ( + "bytes" + "context" + "fmt" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" +) + +type Contract struct { + addr common.Address + client *ethclient.Client +} + +func NewContract(addr common.Address, client *ethclient.Client) *Contract { + return &Contract{addr: addr, client: client} +} + +func (c *Contract) SuperchainConfig(ctx context.Context) (common.Address, error) { + return c.getAddress(ctx, "superchainConfig") +} + +func (c *Contract) ProtocolVersions(ctx context.Context) (common.Address, error) { + return c.getAddress(ctx, "protocolVersions") +} + +func (c *Contract) getAddress(ctx context.Context, name string) (common.Address, error) { + method := abi.NewMethod( + name, + name, + abi.Function, + "view", + true, + false, + abi.Arguments{}, + abi.Arguments{ + abi.Argument{ + Name: "address", + Type: mustType("address"), + Indexed: false, + }, + }, + ) + + calldata, err := method.Inputs.Pack() + if err != nil { + return common.Address{}, fmt.Errorf("failed to pack inputs: %w", err) + } + + msg := ethereum.CallMsg{ + To: &c.addr, + Data: append(bytes.Clone(method.ID), calldata...), + } + result, err := c.client.CallContract(ctx, msg, nil) + if err != nil { + return common.Address{}, fmt.Errorf("failed to call contract: %w", err) + } + + out, err := method.Outputs.Unpack(result) + if err != nil { + return common.Address{}, fmt.Errorf("failed to unpack result: %w", err) + } + if len(out) != 1 { + return common.Address{}, fmt.Errorf("unexpected output length: %d", len(out)) + } + addr, ok := out[0].(common.Address) + if !ok { + return common.Address{}, fmt.Errorf("unexpected type: %T", out[0]) + } + return addr, nil +} + +func mustType(t string) abi.Type { + typ, err := abi.NewType(t, "", nil) + if err != nil { + panic(err) + } + return typ +} diff --git a/op-chain-ops/deployer/opcm/implementations.go b/op-chain-ops/deployer/opcm/implementations.go new file mode 100644 index 0000000000000..fec30d94cbd55 --- /dev/null +++ b/op-chain-ops/deployer/opcm/implementations.go @@ -0,0 +1,109 @@ +package opcm + +import ( + "fmt" + "math/big" + + "github.com/ethereum/go-ethereum/common" + + "github.com/ethereum-optimism/optimism/op-chain-ops/script" +) + +type DeployImplementationsInput struct { + Salt common.Hash + WithdrawalDelaySeconds *big.Int + MinProposalSizeBytes *big.Int + ChallengePeriodSeconds *big.Int + ProofMaturityDelaySeconds *big.Int + DisputeGameFinalityDelaySeconds *big.Int + // Release version to set OPCM implementations for, of the format `op-contracts/vX.Y.Z`. + Release string + SuperchainConfigProxy common.Address + ProtocolVersionsProxy common.Address + UseInterop bool // if true, deploy Interop implementations + + SuperchainProxyAdmin common.Address + StandardVersionsToml string // contents of 'standard-versions.toml' file +} + +func (input *DeployImplementationsInput) InputSet() bool { + return true +} + +type DeployImplementationsOutput struct { + OpcmProxy common.Address + OpcmImpl common.Address + DelayedWETHImpl common.Address + OptimismPortalImpl common.Address + PreimageOracleSingleton common.Address + MipsSingleton common.Address + SystemConfigImpl common.Address + L1CrossDomainMessengerImpl common.Address + L1ERC721BridgeImpl common.Address + L1StandardBridgeImpl common.Address + OptimismMintableERC20FactoryImpl common.Address + DisputeGameFactoryImpl common.Address +} + +func (output *DeployImplementationsOutput) CheckOutput(input common.Address) error { + return nil +} + +type DeployImplementationsScript struct { + Run func(input, output common.Address) error +} + +func DeployImplementations( + host *script.Host, + input DeployImplementationsInput, +) (DeployImplementationsOutput, error) { + var output DeployImplementationsOutput + inputAddr := host.NewScriptAddress() + outputAddr := host.NewScriptAddress() + + cleanupInput, err := script.WithPrecompileAtAddress[*DeployImplementationsInput](host, inputAddr, &input) + if err != nil { + return output, fmt.Errorf("failed to insert DeployImplementationsInput precompile: %w", err) + } + defer cleanupInput() + + cleanupOutput, err := script.WithPrecompileAtAddress[*DeployImplementationsOutput](host, outputAddr, &output, + script.WithFieldSetter[*DeployImplementationsOutput]) + if err != nil { + return output, fmt.Errorf("failed to insert DeployImplementationsOutput precompile: %w", err) + } + defer cleanupOutput() + + implContract := "DeployImplementations" + if input.UseInterop { + implContract = "DeployImplementationsInterop" + } + deployScript, cleanupDeploy, err := script.WithScript[DeployImplementationsScript](host, "DeployImplementations.s.sol", implContract) + if err != nil { + return output, fmt.Errorf("failed to load %s script: %w", implContract, err) + } + defer cleanupDeploy() + + opcmContract := "OPContractsManager" + if input.UseInterop { + opcmContract = "OPContractsManagerInterop" + } + if err := host.RememberOnLabel("OPContractsManager", opcmContract+".sol", opcmContract); err != nil { + return output, fmt.Errorf("failed to link OPContractsManager label: %w", err) + } + + // So we can see in detail where the SystemConfig interop initializer fails + sysConfig := "SystemConfig" + if input.UseInterop { + sysConfig = "SystemConfigInterop" + } + if err := host.RememberOnLabel("SystemConfigImpl", sysConfig+".sol", sysConfig); err != nil { + return output, fmt.Errorf("failed to link SystemConfig label: %w", err) + } + + if err := deployScript.Run(inputAddr, outputAddr); err != nil { + return output, fmt.Errorf("failed to run %s script: %w", implContract, err) + } + + return output, nil +} diff --git a/op-chain-ops/deployer/opcm/l2genesis.go b/op-chain-ops/deployer/opcm/l2genesis.go new file mode 100644 index 0000000000000..8b6e123dad3fc --- /dev/null +++ b/op-chain-ops/deployer/opcm/l2genesis.go @@ -0,0 +1,55 @@ +package opcm + +import ( + "fmt" + + "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" + "github.com/ethereum-optimism/optimism/op-chain-ops/script" + "github.com/ethereum/go-ethereum/common" +) + +var ( + // address(uint160(uint256(keccak256(abi.encode("optimism.deployconfig"))))) - not a simple hash, due to ABI encode + deployConfigAddr = common.HexToAddress("0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c") +) + +type L1Deployments struct { + L1CrossDomainMessengerProxy common.Address + L1StandardBridgeProxy common.Address + L1ERC721BridgeProxy common.Address +} + +type L2GenesisInput struct { + L1Deployments L1Deployments + L2Config genesis.L2InitializationConfig +} + +type L2GenesisScript struct { + RunWithEnv func() error +} + +func L2Genesis(l2Host *script.Host, input *L2GenesisInput) error { + l2Host.SetEnvVar("L2GENESIS_L1CrossDomainMessengerProxy", input.L1Deployments.L1CrossDomainMessengerProxy.String()) + l2Host.SetEnvVar("L2GENESIS_L1StandardBridgeProxy", input.L1Deployments.L1StandardBridgeProxy.String()) + l2Host.SetEnvVar("L2GENESIS_L1ERC721BridgeProxy", input.L1Deployments.L1ERC721BridgeProxy.String()) + + deployConfig := &genesis.DeployConfig{ + L2InitializationConfig: input.L2Config, + } + cleanupDeployConfig, err := script.WithPrecompileAtAddress[*genesis.DeployConfig](l2Host, deployConfigAddr, deployConfig, script.WithFieldsOnly[*genesis.DeployConfig]) + if err != nil { + return fmt.Errorf("failed to insert DeployConfig precompile: %w", err) + } + defer cleanupDeployConfig() + + l2GenesisScript, cleanupL2Genesis, err := script.WithScript[L2GenesisScript](l2Host, "L2Genesis.s.sol", "L2Genesis") + if err != nil { + return fmt.Errorf("failed to load L2Genesis script: %w", err) + } + defer cleanupL2Genesis() + + if err := l2GenesisScript.RunWithEnv(); err != nil { + return fmt.Errorf("failed to run L2 genesis script: %w", err) + } + return nil +} diff --git a/op-chain-ops/deployer/opcm/opchain.go b/op-chain-ops/deployer/opcm/opchain.go new file mode 100644 index 0000000000000..c204c1a57ec3d --- /dev/null +++ b/op-chain-ops/deployer/opcm/opchain.go @@ -0,0 +1,305 @@ +package opcm + +import ( + "context" + "fmt" + "math/big" + "strings" + + "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/broadcaster" + "github.com/ethereum-optimism/optimism/op-chain-ops/foundry" + "github.com/ethereum-optimism/optimism/op-chain-ops/script" + "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/ethclient" + "github.com/holiman/uint256" +) + +// PermissionedGameStartingAnchorRoots is a root of bytes32(hex"dead") for the permissioned game at block 0, +// and no root for the permissionless game. +var PermissionedGameStartingAnchorRoots = []byte{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xde, 0xad, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +} + +type DeployOPChainInput struct { + OpChainProxyAdminOwner common.Address + SystemConfigOwner common.Address + Batcher common.Address + UnsafeBlockSigner common.Address + Proposer common.Address + Challenger common.Address + + BasefeeScalar uint32 + BlobBaseFeeScalar uint32 + L2ChainId *big.Int + OpcmProxy common.Address +} + +func (input *DeployOPChainInput) InputSet() bool { + return true +} + +func (input *DeployOPChainInput) StartingAnchorRoots() []byte { + return PermissionedGameStartingAnchorRoots +} + +type DeployOPChainOutput struct { + OpChainProxyAdmin common.Address + AddressManager common.Address + L1ERC721BridgeProxy common.Address + SystemConfigProxy common.Address + OptimismMintableERC20FactoryProxy common.Address + L1StandardBridgeProxy common.Address + L1CrossDomainMessengerProxy common.Address + // Fault proof contracts below. + OptimismPortalProxy common.Address + DisputeGameFactoryProxy common.Address + AnchorStateRegistryProxy common.Address + AnchorStateRegistryImpl common.Address + FaultDisputeGame common.Address + PermissionedDisputeGame common.Address + DelayedWETHPermissionedGameProxy common.Address + DelayedWETHPermissionlessGameProxy common.Address +} + +func (output *DeployOPChainOutput) CheckOutput(input common.Address) error { + return nil +} + +type DeployOPChainScript struct { + Run func(input, output common.Address) error +} + +func DeployOPChain(host *script.Host, input DeployOPChainInput) (DeployOPChainOutput, error) { + var dco DeployOPChainOutput + inputAddr := host.NewScriptAddress() + outputAddr := host.NewScriptAddress() + + cleanupInput, err := script.WithPrecompileAtAddress[*DeployOPChainInput](host, inputAddr, &input) + if err != nil { + return dco, fmt.Errorf("failed to insert DeployOPChainInput precompile: %w", err) + } + defer cleanupInput() + host.Label(inputAddr, "DeployOPChainInput") + + cleanupOutput, err := script.WithPrecompileAtAddress[*DeployOPChainOutput](host, outputAddr, &dco, + script.WithFieldSetter[*DeployOPChainOutput]) + if err != nil { + return dco, fmt.Errorf("failed to insert DeployOPChainOutput precompile: %w", err) + } + defer cleanupOutput() + host.Label(outputAddr, "DeployOPChainOutput") + + deployScript, cleanupDeploy, err := script.WithScript[DeployOPChainScript](host, "DeployOPChain.s.sol", "DeployOPChain") + if err != nil { + return dco, fmt.Errorf("failed to load DeployOPChain script: %w", err) + } + defer cleanupDeploy() + + if err := deployScript.Run(inputAddr, outputAddr); err != nil { + return dco, fmt.Errorf("failed to run DeployOPChain script: %w", err) + } + + return dco, nil +} + +// opcmRoles is an internal struct used to pass the roles to OPSM. See opcmDeployInput for more info. +type opcmRoles struct { + OpChainProxyAdminOwner common.Address + SystemConfigOwner common.Address + Batcher common.Address + UnsafeBlockSigner common.Address + Proposer common.Address + Challenger common.Address +} + +// opcmDeployInput is the input struct for the deploy method of the OPStackManager contract. We +// define a separate struct here to match what the OPSM contract expects. +type opcmDeployInput struct { + Roles opcmRoles + BasefeeScalar uint32 + BlobBasefeeScalar uint32 + L2ChainId *big.Int + StartingAnchorRoots []byte +} + +// decodeOutputABIJSON defines an ABI for a fake method called "decodeOutput" that returns the +// DeployOutput struct. This allows the code in the deployer to decode directly into a struct +// using Geth's ABI library. +const decodeOutputABIJSON = ` +[ + { + "type": "function", + "name": "decodeOutput", + "inputs": [], + "outputs": [ + { + "name": "output", + "indexed": false, + "type": "tuple", + "components": [ + { + "name": "opChainProxyAdmin", + "type": "address" + }, + { + "name": "addressManager", + "type": "address" + }, + { + "name": "l1ERC721BridgeProxy", + "type": "address" + }, + { + "name": "systemConfigProxy", + "type": "address" + }, + { + "name": "optimismMintableERC20FactoryProxy", + "type": "address" + }, + { + "name": "l1StandardBridgeProxy", + "type": "address" + }, + { + "name": "l1CrossDomainMessengerProxy", + "type": "address" + }, + { + "name": "optimismPortalProxy", + "type": "address" + }, + { + "name": "disputeGameFactoryProxy", + "type": "address" + }, + { + "name": "anchorStateRegistryProxy", + "type": "address" + }, + { + "name": "anchorStateRegistryImpl", + "type": "address" + }, + { + "name": "faultDisputeGame", + "type": "address", + "internalType": "contract FaultDisputeGame" + }, + { + "name": "permissionedDisputeGame", + "type": "address" + }, + { + "name": "delayedWETHPermissionedGameProxy", + "type": "address" + }, + { + "name": "delayedWETHPermissionlessGameProxy", + "type": "address" + } + ] + } + ] + } +] +` + +var decodeOutputABI abi.ABI + +// DeployOPChainRaw deploys an OP Chain using a raw call to a pre-deployed OPSM contract. +func DeployOPChainRaw( + ctx context.Context, + l1 *ethclient.Client, + bcast broadcaster.Broadcaster, + deployer common.Address, + artifacts foundry.StatDirFs, + input DeployOPChainInput, +) (DeployOPChainOutput, error) { + var out DeployOPChainOutput + + artifactsFS := &foundry.ArtifactsFS{FS: artifacts} + opcmArtifacts, err := artifactsFS.ReadArtifact("OPContractsManager.sol", "OPContractsManager") + if err != nil { + return out, fmt.Errorf("failed to read OPStackManager artifact: %w", err) + } + + opcmABI := opcmArtifacts.ABI + calldata, err := opcmABI.Pack("deploy", opcmDeployInput{ + Roles: opcmRoles{ + OpChainProxyAdminOwner: input.OpChainProxyAdminOwner, + SystemConfigOwner: input.SystemConfigOwner, + Batcher: input.Batcher, + UnsafeBlockSigner: input.UnsafeBlockSigner, + Proposer: input.Proposer, + Challenger: input.Challenger, + }, + BasefeeScalar: input.BasefeeScalar, + BlobBasefeeScalar: input.BlobBaseFeeScalar, + L2ChainId: input.L2ChainId, + StartingAnchorRoots: input.StartingAnchorRoots(), + }) + if err != nil { + return out, fmt.Errorf("failed to pack deploy input: %w", err) + } + + nonce, err := l1.NonceAt(ctx, deployer, nil) + if err != nil { + return out, fmt.Errorf("failed to read nonce: %w", err) + } + + bcast.Hook(script.Broadcast{ + From: deployer, + To: input.OpcmProxy, + Input: calldata, + Value: (*hexutil.U256)(uint256.NewInt(0)), + // use hardcoded 19MM gas for now since this is roughly what we've seen this deployment cost. + GasUsed: 19_000_000, + Type: script.BroadcastCall, + Nonce: nonce, + }) + + results, err := bcast.Broadcast(ctx) + if err != nil { + return out, fmt.Errorf("failed to broadcast OP chain deployment: %w", err) + } + + deployedEvent := opcmABI.Events["Deployed"] + res := results[0] + + for _, log := range res.Receipt.Logs { + if log.Topics[0] != deployedEvent.ID { + continue + } + + type EventData struct { + DeployOutput []byte + } + var data EventData + if err := opcmABI.UnpackIntoInterface(&data, "Deployed", log.Data); err != nil { + return out, fmt.Errorf("failed to unpack Deployed event: %w", err) + } + + type OutputData struct { + Output DeployOPChainOutput + } + var outData OutputData + if err := decodeOutputABI.UnpackIntoInterface(&outData, "decodeOutput", data.DeployOutput); err != nil { + return out, fmt.Errorf("failed to unpack DeployOutput: %w", err) + } + + return outData.Output, nil + } + + return out, fmt.Errorf("failed to find Deployed event") +} + +func init() { + var err error + decodeOutputABI, err = abi.JSON(strings.NewReader(decodeOutputABIJSON)) + if err != nil { + panic(fmt.Sprintf("failed to parse decodeOutput ABI: %v", err)) + } +} diff --git a/op-chain-ops/deployer/opcm/standard-versions.toml b/op-chain-ops/deployer/opcm/standard-versions.toml new file mode 100644 index 0000000000000..cb4d336a73364 --- /dev/null +++ b/op-chain-ops/deployer/opcm/standard-versions.toml @@ -0,0 +1,47 @@ +standard_release = "op-contracts/v1.6.0" + +[releases] + +# Contracts which are +# * unproxied singletons: specify a standard "address" +# * proxied : specify a standard "implementation_address" +# * neither : specify neither a standard "address" nor "implementation_address" + +# Fault Proofs https://github.com/ethereum-optimism/optimism/releases/tag/op-contracts%2Fv1.6.0 +[releases."op-contracts/v1.6.0"] +optimism_portal = { version = "3.10.0", implementation_address = "0xe2F826324b2faf99E513D16D266c3F80aE87832B" } +system_config = { version = "2.2.0", implementation_address = "0xF56D96B2535B932656d3c04Ebf51baBff241D886" } +anchor_state_registry = { version = "2.0.0" } +delayed_weth = { version = "1.1.0", implementation_address = "0x71e966Ae981d1ce531a7b6d23DC0f27B38409087" } +dispute_game_factory = { version = "1.0.0", implementation_address = "0xc641A33cab81C559F2bd4b21EA34C290E2440C2B" } +fault_dispute_game = { version = "1.3.0" } +permissioned_dispute_game = { version = "1.3.0" } +mips = { version = "1.1.0", address = "0x16e83cE5Ce29BF90AD9Da06D2fE6a15d5f344ce4" } +preimage_oracle = { version = "1.1.2", address = "0x9c065e11870B891D214Bc2Da7EF1f9DDFA1BE277" } +l1_cross_domain_messenger = { version = "2.3.0", implementation_address = "0xD3494713A5cfaD3F5359379DfA074E2Ac8C6Fd65" } +l1_erc721_bridge = { version = "2.1.0", implementation_address = "0xAE2AF01232a6c4a4d3012C5eC5b1b35059caF10d" } +l1_standard_bridge = { version = "2.1.0", implementation_address = "0x64B5a5Ed26DCb17370Ff4d33a8D503f0fbD06CfF" } +# l2_output_oracle -- This contract not used in fault proofs +optimism_mintable_erc20_factory = { version = "1.9.0", implementation_address = "0xE01efbeb1089D1d1dB9c6c8b135C934C0734c846" } + +# Fault Proofs https://github.com/ethereum-optimism/optimism/releases/tag/op-contracts%2Fv1.4.0 +[releases."op-contracts/v1.4.0"] +optimism_portal = { version = "3.10.0", implementation_address = "0xe2F826324b2faf99E513D16D266c3F80aE87832B" } +system_config = { version = "2.2.0", implementation_address = "0xF56D96B2535B932656d3c04Ebf51baBff241D886" } +anchor_state_registry = { version = "1.0.0" } +delayed_weth = { version = "1.0.0", implementation_address = "0x97988d5624F1ba266E1da305117BCf20713bee08" } +dispute_game_factory = { version = "1.0.0", implementation_address = "0xc641A33cab81C559F2bd4b21EA34C290E2440C2B" } +fault_dispute_game = { version = "1.2.0" } +permissioned_dispute_game = { version = "1.2.0" } +mips = { version = "1.0.1", address = "0x0f8EdFbDdD3c0256A80AD8C0F2560B1807873C9c" } +preimage_oracle = { version = "1.0.0", address = "0xD326E10B8186e90F4E2adc5c13a2d0C137ee8b34" } + +# MCP https://github.com/ethereum-optimism/optimism/releases/tag/op-contracts%2Fv1.3.0 +[releases."op-contracts/v1.3.0"] +l1_cross_domain_messenger = { version = "2.3.0", implementation_address = "0xD3494713A5cfaD3F5359379DfA074E2Ac8C6Fd65" } +l1_erc721_bridge = { version = "2.1.0", implementation_address = "0xAE2AF01232a6c4a4d3012C5eC5b1b35059caF10d" } +l1_standard_bridge = { version = "2.1.0", implementation_address = "0x64B5a5Ed26DCb17370Ff4d33a8D503f0fbD06CfF" } +l2_output_oracle = { version = "1.8.0", implementation_address = "0xF243BEd163251380e78068d317ae10f26042B292" } +optimism_mintable_erc20_factory = { version = "1.9.0", implementation_address = "0xE01efbeb1089D1d1dB9c6c8b135C934C0734c846" } +optimism_portal = { version = "2.5.0", implementation_address = "0x2D778797049FE9259d947D1ED8e5442226dFB589" } +system_config = { version = "1.12.0", implementation_address = "0xba2492e52F45651B60B8B38d4Ea5E2390C64Ffb1" } diff --git a/op-chain-ops/deployer/opcm/standard.go b/op-chain-ops/deployer/opcm/standard.go new file mode 100644 index 0000000000000..9f182ca4685c9 --- /dev/null +++ b/op-chain-ops/deployer/opcm/standard.go @@ -0,0 +1,8 @@ +package opcm + +import "embed" + +//go:embed standard-versions.toml +var StandardVersionsData string + +var _ embed.FS diff --git a/op-chain-ops/deployer/opcm/superchain.go b/op-chain-ops/deployer/opcm/superchain.go new file mode 100644 index 0000000000000..4f648bbfa8a36 --- /dev/null +++ b/op-chain-ops/deployer/opcm/superchain.go @@ -0,0 +1,89 @@ +package opcm + +import ( + "fmt" + "math/big" + + "github.com/ethereum-optimism/optimism/op-chain-ops/foundry" + "github.com/ethereum-optimism/optimism/op-chain-ops/script" + opcrypto "github.com/ethereum-optimism/optimism/op-service/crypto" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/params" +) + +type DeploySuperchainInput struct { + SuperchainProxyAdminOwner common.Address `toml:"superchainProxyAdminOwner"` + ProtocolVersionsOwner common.Address `toml:"protocolVersionsOwner"` + Guardian common.Address `toml:"guardian"` + Paused bool `toml:"paused"` + RequiredProtocolVersion params.ProtocolVersion `toml:"requiredProtocolVersion"` + RecommendedProtocolVersion params.ProtocolVersion `toml:"recommendedProtocolVersion"` +} + +func (dsi *DeploySuperchainInput) InputSet() bool { + return true +} + +type DeploySuperchainOutput struct { + SuperchainProxyAdmin common.Address + SuperchainConfigImpl common.Address + SuperchainConfigProxy common.Address + ProtocolVersionsImpl common.Address + ProtocolVersionsProxy common.Address +} + +func (output *DeploySuperchainOutput) CheckOutput(input common.Address) error { + return nil +} + +type DeploySuperchainScript struct { + Run func(in common.Address, out common.Address) error +} + +type DeploySuperchainOpts struct { + ChainID *big.Int + ArtifactsFS foundry.StatDirFs + Deployer common.Address + Signer opcrypto.SignerFn + Input DeploySuperchainInput + Client *ethclient.Client + Logger log.Logger +} + +func DeploySuperchain(h *script.Host, input DeploySuperchainInput) (DeploySuperchainOutput, error) { + var dso DeploySuperchainOutput + + inputAddr := h.NewScriptAddress() + outputAddr := h.NewScriptAddress() + + cleanupInput, err := script.WithPrecompileAtAddress[*DeploySuperchainInput](h, inputAddr, &input) + if err != nil { + return dso, fmt.Errorf("failed to insert DeploySuperchainInput precompile: %w", err) + } + defer cleanupInput() + + cleanupOutput, err := script.WithPrecompileAtAddress[*DeploySuperchainOutput]( + h, + outputAddr, + &dso, + script.WithFieldSetter[*DeploySuperchainOutput], + ) + if err != nil { + return dso, fmt.Errorf("failed to insert DeploySuperchainOutput precompile: %w", err) + } + defer cleanupOutput() + + deployScript, cleanupDeploy, err := script.WithScript[DeploySuperchainScript](h, "DeploySuperchain.s.sol", "DeploySuperchain") + if err != nil { + return dso, fmt.Errorf("failed to load DeploySuperchain script: %w", err) + } + defer cleanupDeploy() + + if err := deployScript.Run(inputAddr, outputAddr); err != nil { + return dso, fmt.Errorf("failed to run DeploySuperchain script: %w", err) + } + + return dso, nil +} diff --git a/op-chain-ops/deployer/pipeline/downloader.go b/op-chain-ops/deployer/pipeline/downloader.go new file mode 100644 index 0000000000000..8932792f822ff --- /dev/null +++ b/op-chain-ops/deployer/pipeline/downloader.go @@ -0,0 +1,138 @@ +package pipeline + +import ( + "archive/tar" + "bufio" + "compress/gzip" + "context" + "errors" + "fmt" + "io" + "net/http" + "net/url" + "os" + "path" + "strings" + "time" + + "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/state" + "github.com/ethereum-optimism/optimism/op-chain-ops/foundry" +) + +var ErrUnsupportedArtifactsScheme = errors.New("unsupported artifacts URL scheme") + +type DownloadProgressor func(current, total int64) + +type CleanupFunc func() error + +var noopCleanup = func() error { return nil } + +func DownloadArtifacts(ctx context.Context, artifactsURL *state.ArtifactsURL, progress DownloadProgressor) (foundry.StatDirFs, CleanupFunc, error) { + switch artifactsURL.Scheme { + case "http", "https": + req, err := http.NewRequestWithContext(ctx, http.MethodGet, (*url.URL)(artifactsURL).String(), nil) + if err != nil { + return nil, nil, fmt.Errorf("failed to create request: %w", err) + } + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return nil, nil, fmt.Errorf("failed to download artifacts: %w", err) + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return nil, nil, fmt.Errorf("failed to download artifacts: invalid status code %s", resp.Status) + } + + tmpDir, err := os.MkdirTemp("", "op-deployer-artifacts-*") + if err != nil { + return nil, nil, fmt.Errorf("failed to create temp dir: %w", err) + } + + pr := &progressReader{ + r: resp.Body, + progress: progress, + total: resp.ContentLength, + } + + gr, err := gzip.NewReader(pr) + if err != nil { + return nil, nil, fmt.Errorf("failed to create gzip reader: %w", err) + } + defer gr.Close() + + tr := tar.NewReader(gr) + if err := untar(tmpDir, tr); err != nil { + return nil, nil, fmt.Errorf("failed to untar: %w", err) + } + + fs := os.DirFS(path.Join(tmpDir, "forge-artifacts")) + cleanup := func() error { + return os.RemoveAll(tmpDir) + } + return fs.(foundry.StatDirFs), cleanup, nil + case "file": + fs := os.DirFS(artifactsURL.Path) + return fs.(foundry.StatDirFs), noopCleanup, nil + default: + return nil, nil, ErrUnsupportedArtifactsScheme + } +} + +type progressReader struct { + r io.Reader + progress DownloadProgressor + curr int64 + total int64 + lastPrint time.Time +} + +func (pr *progressReader) Read(p []byte) (int, error) { + + n, err := pr.r.Read(p) + pr.curr += int64(n) + if pr.progress != nil && time.Since(pr.lastPrint) > 1*time.Second { + pr.progress(pr.curr, pr.total) + pr.lastPrint = time.Now() + } + return n, err +} + +func untar(dir string, tr *tar.Reader) error { + for { + hdr, err := tr.Next() + if err == io.EOF { + return nil + } + if err != nil { + return fmt.Errorf("failed to read tar header: %w", err) + } + + cleanedName := path.Clean(hdr.Name) + if strings.Contains(cleanedName, "..") { + return fmt.Errorf("invalid file path: %s", hdr.Name) + } + dst := path.Join(dir, cleanedName) + if hdr.FileInfo().IsDir() { + if err := os.MkdirAll(dst, 0o755); err != nil { + return fmt.Errorf("failed to create directory: %w", err) + } + continue + } + + f, err := os.Create(dst) + buf := bufio.NewWriter(f) + if err != nil { + return fmt.Errorf("failed to create file: %w", err) + } + if _, err := io.Copy(buf, tr); err != nil { + _ = f.Close() + return fmt.Errorf("failed to write file: %w", err) + } + if err := buf.Flush(); err != nil { + return fmt.Errorf("failed to flush buffer: %w", err) + } + _ = f.Close() + } +} diff --git a/op-chain-ops/deployer/pipeline/downloader_test.go b/op-chain-ops/deployer/pipeline/downloader_test.go new file mode 100644 index 0000000000000..277409461a41e --- /dev/null +++ b/op-chain-ops/deployer/pipeline/downloader_test.go @@ -0,0 +1,42 @@ +package pipeline + +import ( + "context" + "io" + "net/http" + "net/http/httptest" + "net/url" + "os" + "testing" + + "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/state" + "github.com/stretchr/testify/require" +) + +func TestDownloadArtifacts(t *testing.T) { + f, err := os.OpenFile("testdata/artifacts.tar.gz", os.O_RDONLY, 0o644) + require.NoError(t, err) + defer f.Close() + + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + _, err := io.Copy(w, f) + require.NoError(t, err) + })) + defer ts.Close() + + ctx := context.Background() + artifactsURL, err := url.Parse(ts.URL) + require.NoError(t, err) + + fs, cleanup, err := DownloadArtifacts(ctx, (*state.ArtifactsURL)(artifactsURL), nil) + require.NoError(t, err) + require.NotNil(t, fs) + defer func() { + require.NoError(t, cleanup()) + }() + + info, err := fs.Stat("WETH98.sol/WETH98.json") + require.NoError(t, err) + require.Greater(t, info.Size(), int64(0)) +} diff --git a/op-chain-ops/deployer/pipeline/env.go b/op-chain-ops/deployer/pipeline/env.go new file mode 100644 index 0000000000000..d0778122d27a1 --- /dev/null +++ b/op-chain-ops/deployer/pipeline/env.go @@ -0,0 +1,49 @@ +package pipeline + +import ( + "context" + "fmt" + "path" + + "github.com/ethereum-optimism/optimism/op-chain-ops/foundry" + + "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/state" + opcrypto "github.com/ethereum-optimism/optimism/op-service/crypto" + "github.com/ethereum-optimism/optimism/op-service/jsonutil" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/log" +) + +type Env struct { + Workdir string + L1Client *ethclient.Client + Signer opcrypto.SignerFn + Deployer common.Address + Logger log.Logger +} + +func (e *Env) ReadIntent() (*state.Intent, error) { + intentPath := path.Join(e.Workdir, "intent.toml") + intent, err := jsonutil.LoadTOML[state.Intent](intentPath) + if err != nil { + return nil, fmt.Errorf("failed to read intent file: %w", err) + } + return intent, nil +} + +func (e *Env) ReadState() (*state.State, error) { + statePath := path.Join(e.Workdir, "state.json") + st, err := jsonutil.LoadJSON[state.State](statePath) + if err != nil { + return nil, fmt.Errorf("failed to read state file: %w", err) + } + return st, nil +} + +func (e *Env) WriteState(st *state.State) error { + statePath := path.Join(e.Workdir, "state.json") + return st.WriteToFile(statePath) +} + +type Stage func(ctx context.Context, env *Env, artifactsFS foundry.StatDirFs, intent *state.Intent, state2 *state.State) error diff --git a/op-chain-ops/deployer/pipeline/host.go b/op-chain-ops/deployer/pipeline/host.go new file mode 100644 index 0000000000000..71bc9e29e05c3 --- /dev/null +++ b/op-chain-ops/deployer/pipeline/host.go @@ -0,0 +1,87 @@ +package pipeline + +import ( + "context" + "fmt" + "math/big" + + "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/broadcaster" + "github.com/ethereum-optimism/optimism/op-chain-ops/foundry" + "github.com/ethereum-optimism/optimism/op-chain-ops/script" + opcrypto "github.com/ethereum-optimism/optimism/op-service/crypto" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/log" +) + +type BroadcasterFactory func(opts CallScriptBroadcastOpts) (broadcaster.Broadcaster, error) + +func KeyedBroadcaster(opts CallScriptBroadcastOpts) (broadcaster.Broadcaster, error) { + return broadcaster.NewKeyedBroadcaster(broadcaster.KeyedBroadcasterOpts{ + Logger: opts.Logger, + ChainID: opts.L1ChainID, + Client: opts.Client, + Signer: opts.Signer, + From: opts.Deployer, + }) +} + +func DiscardBroadcaster(opts CallScriptBroadcastOpts) (broadcaster.Broadcaster, error) { + return broadcaster.DiscardBroadcaster(), nil +} + +type CallScriptBroadcastOpts struct { + L1ChainID *big.Int + Logger log.Logger + ArtifactsFS foundry.StatDirFs + Deployer common.Address + Signer opcrypto.SignerFn + Client *ethclient.Client + Handler func(host *script.Host) error + Broadcaster BroadcasterFactory +} + +func CallScriptBroadcast( + ctx context.Context, + opts CallScriptBroadcastOpts, +) error { + bcaster, err := opts.Broadcaster(opts) + if err != nil { + return fmt.Errorf("failed to create broadcaster: %w", err) + } + + scriptCtx := script.DefaultContext + scriptCtx.Sender = opts.Deployer + scriptCtx.Origin = opts.Deployer + artifacts := &foundry.ArtifactsFS{FS: opts.ArtifactsFS} + h := script.NewHost( + opts.Logger, + artifacts, + nil, + scriptCtx, + script.WithBroadcastHook(bcaster.Hook), + script.WithIsolatedBroadcasts(), + script.WithCreate2Deployer(), + ) + + if err := h.EnableCheats(); err != nil { + return fmt.Errorf("failed to enable cheats: %w", err) + } + + nonce, err := opts.Client.NonceAt(ctx, opts.Deployer, nil) + if err != nil { + return fmt.Errorf("failed to fetch nonce: %w", err) + } + h.SetNonce(opts.Deployer, nonce) + + err = opts.Handler(h) + if err != nil { + return fmt.Errorf("failed to run handler: %w", err) + } + + if _, err := bcaster.Broadcast(ctx); err != nil { + return fmt.Errorf("failed to broadcast: %w", err) + } + + return nil +} diff --git a/op-chain-ops/deployer/pipeline/implementations.go b/op-chain-ops/deployer/pipeline/implementations.go new file mode 100644 index 0000000000000..5c5a1e99287cc --- /dev/null +++ b/op-chain-ops/deployer/pipeline/implementations.go @@ -0,0 +1,95 @@ +package pipeline + +import ( + "context" + "fmt" + "math/big" + + "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/opcm" + "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/state" + "github.com/ethereum-optimism/optimism/op-chain-ops/foundry" + "github.com/ethereum-optimism/optimism/op-chain-ops/script" +) + +func DeployImplementations(ctx context.Context, env *Env, artifactsFS foundry.StatDirFs, intent *state.Intent, st *state.State) error { + lgr := env.Logger.New("stage", "deploy-implementations") + + if !shouldDeployImplementations(intent, st) { + lgr.Info("implementations deployment not needed") + return nil + } + + lgr.Info("deploying implementations") + + var dump *foundry.ForgeAllocs + var dio opcm.DeployImplementationsOutput + var err error + err = CallScriptBroadcast( + ctx, + CallScriptBroadcastOpts{ + L1ChainID: big.NewInt(int64(intent.L1ChainID)), + Logger: lgr, + ArtifactsFS: artifactsFS, + Deployer: env.Deployer, + Signer: env.Signer, + Client: env.L1Client, + Broadcaster: KeyedBroadcaster, + Handler: func(host *script.Host) error { + host.SetEnvVar("IMPL_SALT", st.Create2Salt.Hex()[2:]) + host.ImportState(st.SuperchainDeployment.StateDump) + dio, err = opcm.DeployImplementations( + host, + opcm.DeployImplementationsInput{ + Salt: st.Create2Salt, + WithdrawalDelaySeconds: big.NewInt(604800), + MinProposalSizeBytes: big.NewInt(126000), + ChallengePeriodSeconds: big.NewInt(86400), + ProofMaturityDelaySeconds: big.NewInt(604800), + DisputeGameFinalityDelaySeconds: big.NewInt(302400), + Release: intent.ContractsRelease, + SuperchainConfigProxy: st.SuperchainDeployment.SuperchainConfigProxyAddress, + ProtocolVersionsProxy: st.SuperchainDeployment.ProtocolVersionsProxyAddress, + SuperchainProxyAdmin: st.SuperchainDeployment.ProxyAdminAddress, + StandardVersionsToml: opcm.StandardVersionsData, + UseInterop: false, + }, + ) + if err != nil { + return fmt.Errorf("error deploying implementations: %w", err) + } + dump, err = host.StateDump() + if err != nil { + return fmt.Errorf("error dumping state: %w", err) + } + return nil + }, + }, + ) + if err != nil { + return fmt.Errorf("error deploying implementations: %w", err) + } + + st.ImplementationsDeployment = &state.ImplementationsDeployment{ + OpcmProxyAddress: dio.OpcmProxy, + DelayedWETHImplAddress: dio.DelayedWETHImpl, + OptimismPortalImplAddress: dio.OptimismPortalImpl, + PreimageOracleSingletonAddress: dio.PreimageOracleSingleton, + MipsSingletonAddress: dio.MipsSingleton, + SystemConfigImplAddress: dio.SystemConfigImpl, + L1CrossDomainMessengerImplAddress: dio.L1CrossDomainMessengerImpl, + L1ERC721BridgeImplAddress: dio.L1ERC721BridgeImpl, + L1StandardBridgeImplAddress: dio.L1StandardBridgeImpl, + OptimismMintableERC20FactoryImplAddress: dio.OptimismMintableERC20FactoryImpl, + DisputeGameFactoryImplAddress: dio.DisputeGameFactoryImpl, + StateDump: dump, + } + if err := env.WriteState(st); err != nil { + return err + } + + return nil +} + +func shouldDeployImplementations(intent *state.Intent, st *state.State) bool { + return st.ImplementationsDeployment == nil +} diff --git a/op-chain-ops/deployer/pipeline/init.go b/op-chain-ops/deployer/pipeline/init.go new file mode 100644 index 0000000000000..a680c7fdb48f8 --- /dev/null +++ b/op-chain-ops/deployer/pipeline/init.go @@ -0,0 +1,120 @@ +package pipeline + +import ( + "context" + "crypto/rand" + "fmt" + + "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/opcm" + "github.com/ethereum-optimism/optimism/op-chain-ops/foundry" + + "github.com/ethereum-optimism/optimism/op-chain-ops/script" + + "github.com/ethereum/go-ethereum/common" + + "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/state" +) + +func IsSupportedStateVersion(version int) bool { + return version == 1 +} + +func Init(ctx context.Context, env *Env, artifactsFS foundry.StatDirFs, intent *state.Intent, st *state.State) error { + lgr := env.Logger.New("stage", "init") + lgr.Info("initializing pipeline") + + // Ensure the state version is supported. + if !IsSupportedStateVersion(st.Version) { + return fmt.Errorf("unsupported state version: %d", st.Version) + } + + if st.Create2Salt == (common.Hash{}) { + _, err := rand.Read(st.Create2Salt[:]) + if err != nil { + return fmt.Errorf("failed to generate CREATE2 salt: %w", err) + } + } + + if intent.OPCMAddress != (common.Address{}) { + env.Logger.Info("using provided OPCM address, populating state", "address", intent.OPCMAddress.Hex()) + + if intent.ContractsRelease == "dev" { + env.Logger.Warn("using dev release with existing OPCM, this field will be ignored") + } + + opcmContract := opcm.NewContract(intent.OPCMAddress, env.L1Client) + protocolVersions, err := opcmContract.ProtocolVersions(ctx) + if err != nil { + return fmt.Errorf("error getting protocol versions address: %w", err) + } + superchainConfig, err := opcmContract.SuperchainConfig(ctx) + if err != nil { + return fmt.Errorf("error getting superchain config address: %w", err) + } + env.Logger.Debug( + "populating protocol versions and superchain config addresses", + "protocolVersions", protocolVersions.Hex(), + "superchainConfig", superchainConfig.Hex(), + ) + + // The below fields are the only ones required to perform an OP Chain + // deployment via an existing OPCM contract. All the others are used + // for deploying the OPCM itself, which isn't necessary in this case. + st.SuperchainDeployment = &state.SuperchainDeployment{ + ProtocolVersionsProxyAddress: protocolVersions, + SuperchainConfigProxyAddress: superchainConfig, + } + st.ImplementationsDeployment = &state.ImplementationsDeployment{ + OpcmProxyAddress: intent.OPCMAddress, + } + } + + // If the state has never been applied, we don't need to perform + // any additional checks. + if st.AppliedIntent == nil { + return nil + } + + // If the state has been applied, we need to check if any immutable + // fields have changed. + if st.AppliedIntent.L1ChainID != intent.L1ChainID { + return immutableErr("L1ChainID", st.AppliedIntent.L1ChainID, intent.L1ChainID) + } + + if st.AppliedIntent.UseFaultProofs != intent.UseFaultProofs { + return immutableErr("useFaultProofs", st.AppliedIntent.UseFaultProofs, intent.UseFaultProofs) + } + + if st.AppliedIntent.UseAltDA != intent.UseAltDA { + return immutableErr("useAltDA", st.AppliedIntent.UseAltDA, intent.UseAltDA) + } + + if st.AppliedIntent.FundDevAccounts != intent.FundDevAccounts { + return immutableErr("fundDevAccounts", st.AppliedIntent.FundDevAccounts, intent.FundDevAccounts) + } + + l1ChainID, err := env.L1Client.ChainID(ctx) + if err != nil { + return fmt.Errorf("failed to get L1 chain ID: %w", err) + } + + if l1ChainID.Cmp(intent.L1ChainIDBig()) != 0 { + return fmt.Errorf("L1 chain ID mismatch: got %d, expected %d", l1ChainID, intent.L1ChainID) + } + + deployerCode, err := env.L1Client.CodeAt(ctx, script.DeterministicDeployerAddress, nil) + if err != nil { + return fmt.Errorf("failed to get deployer code: %w", err) + } + if len(deployerCode) == 0 { + return fmt.Errorf("deterministic deployer is not deployed on this chain - please deploy it first") + } + + // TODO: validate individual + + return nil +} + +func immutableErr(field string, was, is any) error { + return fmt.Errorf("%s is immutable: was %v, is %v", field, was, is) +} diff --git a/op-chain-ops/deployer/pipeline/l2genesis.go b/op-chain-ops/deployer/pipeline/l2genesis.go new file mode 100644 index 0000000000000..25aa316c78a50 --- /dev/null +++ b/op-chain-ops/deployer/pipeline/l2genesis.go @@ -0,0 +1,97 @@ +package pipeline + +import ( + "bytes" + "compress/gzip" + "context" + "encoding/json" + "fmt" + "math/big" + + "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/opcm" + "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/state" + "github.com/ethereum-optimism/optimism/op-chain-ops/foundry" + "github.com/ethereum-optimism/optimism/op-chain-ops/script" + "github.com/ethereum/go-ethereum/common" +) + +func GenerateL2Genesis(ctx context.Context, env *Env, artifactsFS foundry.StatDirFs, intent *state.Intent, st *state.State, chainID common.Hash) error { + lgr := env.Logger.New("stage", "generate-l2-genesis") + + lgr.Info("generating L2 genesis", "id", chainID.Hex()) + + thisIntent, err := intent.Chain(chainID) + if err != nil { + return fmt.Errorf("failed to get chain intent: %w", err) + } + + thisChainState, err := st.Chain(chainID) + if err != nil { + return fmt.Errorf("failed to get chain state: %w", err) + } + + initCfg, err := state.CombineDeployConfig(intent, thisIntent, st, thisChainState) + if err != nil { + return fmt.Errorf("failed to combine L2 init config: %w", err) + } + + var dump *foundry.ForgeAllocs + err = CallScriptBroadcast( + ctx, + CallScriptBroadcastOpts{ + L1ChainID: big.NewInt(int64(intent.L1ChainID)), + Logger: lgr, + ArtifactsFS: artifactsFS, + Deployer: env.Deployer, + Signer: env.Signer, + Client: env.L1Client, + Broadcaster: DiscardBroadcaster, + Handler: func(host *script.Host) error { + err := opcm.L2Genesis(host, &opcm.L2GenesisInput{ + L1Deployments: opcm.L1Deployments{ + L1CrossDomainMessengerProxy: thisChainState.L1CrossDomainMessengerProxyAddress, + L1StandardBridgeProxy: thisChainState.L1StandardBridgeProxyAddress, + L1ERC721BridgeProxy: thisChainState.L1ERC721BridgeProxyAddress, + }, + L2Config: initCfg.L2InitializationConfig, + }) + if err != nil { + return fmt.Errorf("failed to call L2Genesis script: %w", err) + } + + host.Wipe(env.Deployer) + + dump, err = host.StateDump() + if err != nil { + return fmt.Errorf("failed to dump state: %w", err) + } + + return nil + }, + }, + ) + if err != nil { + return fmt.Errorf("failed to call L2Genesis script: %w", err) + } + + var buf bytes.Buffer + gw := gzip.NewWriter(&buf) + if err := json.NewEncoder(gw).Encode(dump); err != nil { + return fmt.Errorf("failed to encode state dump: %w", err) + } + if err := gw.Close(); err != nil { + return fmt.Errorf("failed to close gzip writer: %w", err) + } + thisChainState.Allocs = buf.Bytes() + startHeader, err := env.L1Client.HeaderByNumber(ctx, nil) + if err != nil { + return fmt.Errorf("failed to get start block: %w", err) + } + thisChainState.StartBlock = startHeader + + if err := env.WriteState(st); err != nil { + return fmt.Errorf("failed to write state: %w", err) + } + + return nil +} diff --git a/op-chain-ops/deployer/pipeline/opchain.go b/op-chain-ops/deployer/pipeline/opchain.go new file mode 100644 index 0000000000000..27919fb8b1357 --- /dev/null +++ b/op-chain-ops/deployer/pipeline/opchain.go @@ -0,0 +1,130 @@ +package pipeline + +import ( + "context" + "fmt" + "math/big" + + "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/broadcaster" + + "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/opcm" + "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/state" + "github.com/ethereum-optimism/optimism/op-chain-ops/foundry" + "github.com/ethereum-optimism/optimism/op-chain-ops/script" + "github.com/ethereum/go-ethereum/common" +) + +func DeployOPChain(ctx context.Context, env *Env, artifactsFS foundry.StatDirFs, intent *state.Intent, st *state.State, chainID common.Hash) error { + lgr := env.Logger.New("stage", "deploy-opchain") + + if !shouldDeployOPChain(intent, st, chainID) { + lgr.Info("opchain deployment not needed") + return nil + } + + lgr.Info("deploying OP chain", "id", chainID.Hex()) + + thisIntent, err := intent.Chain(chainID) + if err != nil { + return fmt.Errorf("failed to get chain intent: %w", err) + } + + input := opcm.DeployOPChainInput{ + OpChainProxyAdminOwner: thisIntent.Roles.ProxyAdminOwner, + SystemConfigOwner: thisIntent.Roles.SystemConfigOwner, + Batcher: thisIntent.Roles.Batcher, + UnsafeBlockSigner: thisIntent.Roles.UnsafeBlockSigner, + Proposer: thisIntent.Roles.Proposer, + Challenger: thisIntent.Roles.Challenger, + BasefeeScalar: 1368, + BlobBaseFeeScalar: 801949, + L2ChainId: chainID.Big(), + OpcmProxy: st.ImplementationsDeployment.OpcmProxyAddress, + } + + var dco opcm.DeployOPChainOutput + if intent.OPCMAddress == (common.Address{}) { + err = CallScriptBroadcast( + ctx, + CallScriptBroadcastOpts{ + L1ChainID: big.NewInt(int64(intent.L1ChainID)), + Logger: lgr, + ArtifactsFS: artifactsFS, + Deployer: env.Deployer, + Signer: env.Signer, + Client: env.L1Client, + Broadcaster: KeyedBroadcaster, + Handler: func(host *script.Host) error { + host.ImportState(st.ImplementationsDeployment.StateDump) + + dco, err = opcm.DeployOPChain( + host, + input, + ) + return err + }, + }, + ) + if err != nil { + return fmt.Errorf("error deploying OP chain: %w", err) + } + } else { + lgr.Info("deploying using existing OPCM", "address", intent.OPCMAddress.Hex()) + + bcaster, err := broadcaster.NewKeyedBroadcaster(broadcaster.KeyedBroadcasterOpts{ + Logger: lgr, + ChainID: big.NewInt(int64(intent.L1ChainID)), + Client: env.L1Client, + Signer: env.Signer, + From: env.Deployer, + }) + if err != nil { + return fmt.Errorf("failed to create broadcaster: %w", err) + } + dco, err = opcm.DeployOPChainRaw( + ctx, + env.L1Client, + bcaster, + env.Deployer, + artifactsFS, + input, + ) + if err != nil { + return fmt.Errorf("error deploying OP chain: %w", err) + } + } + + st.Chains = append(st.Chains, &state.ChainState{ + ID: chainID, + ProxyAdminAddress: dco.OpChainProxyAdmin, + AddressManagerAddress: dco.AddressManager, + L1ERC721BridgeProxyAddress: dco.L1ERC721BridgeProxy, + SystemConfigProxyAddress: dco.SystemConfigProxy, + OptimismMintableERC20FactoryProxyAddress: dco.OptimismMintableERC20FactoryProxy, + L1StandardBridgeProxyAddress: dco.L1StandardBridgeProxy, + L1CrossDomainMessengerProxyAddress: dco.L1CrossDomainMessengerProxy, + OptimismPortalProxyAddress: dco.OptimismPortalProxy, + DisputeGameFactoryProxyAddress: dco.DisputeGameFactoryProxy, + AnchorStateRegistryProxyAddress: dco.AnchorStateRegistryProxy, + AnchorStateRegistryImplAddress: dco.AnchorStateRegistryImpl, + FaultDisputeGameAddress: dco.FaultDisputeGame, + PermissionedDisputeGameAddress: dco.PermissionedDisputeGame, + DelayedWETHPermissionedGameProxyAddress: dco.DelayedWETHPermissionedGameProxy, + DelayedWETHPermissionlessGameProxyAddress: dco.DelayedWETHPermissionlessGameProxy, + }) + if err := env.WriteState(st); err != nil { + return err + } + + return nil +} + +func shouldDeployOPChain(intent *state.Intent, st *state.State, chainID common.Hash) bool { + for _, chain := range st.Chains { + if chain.ID == chainID { + return false + } + } + + return true +} diff --git a/op-chain-ops/deployer/pipeline/superchain.go b/op-chain-ops/deployer/pipeline/superchain.go new file mode 100644 index 0000000000000..13737475c916b --- /dev/null +++ b/op-chain-ops/deployer/pipeline/superchain.go @@ -0,0 +1,83 @@ +package pipeline + +import ( + "context" + "fmt" + "math/big" + + "github.com/ethereum-optimism/optimism/op-chain-ops/script" + + "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/opcm" + "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/state" + "github.com/ethereum-optimism/optimism/op-chain-ops/foundry" + "github.com/ethereum-optimism/optimism/op-node/rollup" +) + +func DeploySuperchain(ctx context.Context, env *Env, artifactsFS foundry.StatDirFs, intent *state.Intent, st *state.State) error { + lgr := env.Logger.New("stage", "deploy-superchain") + + if !shouldDeploySuperchain(intent, st) { + lgr.Info("superchain deployment not needed") + return nil + } + + lgr.Info("deploying superchain") + + var dump *foundry.ForgeAllocs + var dso opcm.DeploySuperchainOutput + var err error + err = CallScriptBroadcast( + ctx, + CallScriptBroadcastOpts{ + L1ChainID: big.NewInt(int64(intent.L1ChainID)), + Logger: lgr, + ArtifactsFS: artifactsFS, + Deployer: env.Deployer, + Signer: env.Signer, + Client: env.L1Client, + Broadcaster: KeyedBroadcaster, + Handler: func(host *script.Host) error { + dso, err = opcm.DeploySuperchain( + host, + opcm.DeploySuperchainInput{ + SuperchainProxyAdminOwner: intent.SuperchainRoles.ProxyAdminOwner, + ProtocolVersionsOwner: intent.SuperchainRoles.ProtocolVersionsOwner, + Guardian: intent.SuperchainRoles.Guardian, + Paused: false, + RequiredProtocolVersion: rollup.OPStackSupport, + RecommendedProtocolVersion: rollup.OPStackSupport, + }, + ) + if err != nil { + return fmt.Errorf("failed to deploy superchain: %w", err) + } + dump, err = host.StateDump() + if err != nil { + return fmt.Errorf("error dumping state: %w", err) + } + return nil + }, + }, + ) + if err != nil { + return fmt.Errorf("error deploying superchain: %w", err) + } + + st.SuperchainDeployment = &state.SuperchainDeployment{ + ProxyAdminAddress: dso.SuperchainProxyAdmin, + SuperchainConfigProxyAddress: dso.SuperchainConfigProxy, + SuperchainConfigImplAddress: dso.SuperchainConfigImpl, + ProtocolVersionsProxyAddress: dso.ProtocolVersionsProxy, + ProtocolVersionsImplAddress: dso.ProtocolVersionsImpl, + StateDump: dump, + } + if err := env.WriteState(st); err != nil { + return err + } + + return nil +} + +func shouldDeploySuperchain(intent *state.Intent, st *state.State) bool { + return st.SuperchainDeployment == nil +} diff --git a/op-chain-ops/deployer/pipeline/testdata/artifacts.tar.gz b/op-chain-ops/deployer/pipeline/testdata/artifacts.tar.gz new file mode 100644 index 0000000000000..58f034254f46a Binary files /dev/null and b/op-chain-ops/deployer/pipeline/testdata/artifacts.tar.gz differ diff --git a/op-chain-ops/deployer/state/artifacts_url.go b/op-chain-ops/deployer/state/artifacts_url.go new file mode 100644 index 0000000000000..5ea576d79eecb --- /dev/null +++ b/op-chain-ops/deployer/state/artifacts_url.go @@ -0,0 +1,18 @@ +package state + +import "net/url" + +type ArtifactsURL url.URL + +func (a *ArtifactsURL) MarshalText() ([]byte, error) { + return []byte((*url.URL)(a).String()), nil +} + +func (a *ArtifactsURL) UnmarshalText(text []byte) error { + u, err := url.Parse(string(text)) + if err != nil { + return err + } + *a = ArtifactsURL(*u) + return nil +} diff --git a/op-chain-ops/deployer/state/base64.go b/op-chain-ops/deployer/state/base64.go new file mode 100644 index 0000000000000..23e4379fe5fa9 --- /dev/null +++ b/op-chain-ops/deployer/state/base64.go @@ -0,0 +1,30 @@ +package state + +import ( + "encoding/base64" + "encoding/json" +) + +type Base64Bytes []byte + +func (b Base64Bytes) MarshalJSON() ([]byte, error) { + if len(b) == 0 { + return []byte(`null`), nil + } + + encoded := base64.StdEncoding.EncodeToString(b) + return []byte(`"` + encoded + `"`), nil +} + +func (b *Base64Bytes) UnmarshalJSON(data []byte) error { + var dataStr string + if err := json.Unmarshal(data, &dataStr); err != nil { + return err + } + decoded, err := base64.StdEncoding.DecodeString(dataStr) + if err != nil { + return err + } + *b = decoded + return nil +} diff --git a/op-chain-ops/deployer/state/base64_test.go b/op-chain-ops/deployer/state/base64_test.go new file mode 100644 index 0000000000000..abfa6654cee5d --- /dev/null +++ b/op-chain-ops/deployer/state/base64_test.go @@ -0,0 +1,38 @@ +package state + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestBase64BytesMarshaling(t *testing.T) { + tests := []struct { + name string + in Base64Bytes + out string + }{ + { + name: "empty", + in: Base64Bytes{}, + out: "null", + }, + { + name: "non-empty", + in: Base64Bytes{0x01, 0x02, 0x03}, + out: `"AQID"`, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + data, err := tt.in.MarshalJSON() + require.NoError(t, err) + require.Equal(t, tt.out, string(data)) + + var b Base64Bytes + err = b.UnmarshalJSON(data) + require.NoError(t, err) + require.Equal(t, tt.in, b) + }) + } +} diff --git a/op-chain-ops/deployer/state/deploy_config.go b/op-chain-ops/deployer/state/deploy_config.go new file mode 100644 index 0000000000000..81801e5865cb1 --- /dev/null +++ b/op-chain-ops/deployer/state/deploy_config.go @@ -0,0 +1,158 @@ +package state + +import ( + "encoding/json" + "fmt" + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + + "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" + "github.com/ethereum/go-ethereum/common/hexutil" +) + +var ( + l2GenesisBlockBaseFeePerGas = hexutil.Big(*(big.NewInt(1000000000))) + + vaultMinWithdrawalAmount = mustHexBigFromHex("0x8ac7230489e80000") +) + +func DefaultDeployConfig() genesis.DeployConfig { + return genesis.DeployConfig{ + L2InitializationConfig: genesis.L2InitializationConfig{ + L2GenesisBlockDeployConfig: genesis.L2GenesisBlockDeployConfig{ + L2GenesisBlockGasLimit: 30_000_000, + L2GenesisBlockBaseFeePerGas: &l2GenesisBlockBaseFeePerGas, + }, + L2VaultsDeployConfig: genesis.L2VaultsDeployConfig{ + BaseFeeVaultWithdrawalNetwork: "local", + L1FeeVaultWithdrawalNetwork: "local", + SequencerFeeVaultWithdrawalNetwork: "local", + SequencerFeeVaultMinimumWithdrawalAmount: vaultMinWithdrawalAmount, + BaseFeeVaultMinimumWithdrawalAmount: vaultMinWithdrawalAmount, + L1FeeVaultMinimumWithdrawalAmount: vaultMinWithdrawalAmount, + }, + GovernanceDeployConfig: genesis.GovernanceDeployConfig{ + EnableGovernance: true, + GovernanceTokenSymbol: "OP", + GovernanceTokenName: "Optimism", + }, + GasPriceOracleDeployConfig: genesis.GasPriceOracleDeployConfig{ + GasPriceOracleBaseFeeScalar: 1368, + GasPriceOracleBlobBaseFeeScalar: 810949, + }, + EIP1559DeployConfig: genesis.EIP1559DeployConfig{ + EIP1559Denominator: 50, + EIP1559DenominatorCanyon: 250, + EIP1559Elasticity: 6, + }, + UpgradeScheduleDeployConfig: genesis.UpgradeScheduleDeployConfig{ + L2GenesisRegolithTimeOffset: u64UtilPtr(0), + L2GenesisCanyonTimeOffset: u64UtilPtr(0), + L2GenesisDeltaTimeOffset: u64UtilPtr(0), + L2GenesisEcotoneTimeOffset: u64UtilPtr(0), + L2GenesisFjordTimeOffset: u64UtilPtr(0), + L2GenesisGraniteTimeOffset: u64UtilPtr(0), + UseInterop: false, + }, + L2CoreDeployConfig: genesis.L2CoreDeployConfig{ + L2BlockTime: 2, + FinalizationPeriodSeconds: 12, + MaxSequencerDrift: 600, + SequencerWindowSize: 3600, + ChannelTimeoutBedrock: 300, + SystemConfigStartBlock: 0, + }, + }, + } +} + +func CombineDeployConfig(intent *Intent, chainIntent *ChainIntent, state *State, chainState *ChainState) (genesis.DeployConfig, error) { + cfg := DefaultDeployConfig() + + var err error + if len(intent.GlobalDeployOverrides) > 0 { + cfg, err = mergeJSON(cfg, intent.GlobalDeployOverrides) + if err != nil { + return genesis.DeployConfig{}, fmt.Errorf("error merging global L2 overrides: %w", err) + + } + } + + if len(chainIntent.DeployOverrides) > 0 { + cfg, err = mergeJSON(cfg, chainIntent.DeployOverrides) + if err != nil { + return genesis.DeployConfig{}, fmt.Errorf("error merging chain L2 overrides: %w", err) + } + } + + cfg.L2ChainID = chainState.ID.Big().Uint64() + cfg.L1DependenciesConfig = genesis.L1DependenciesConfig{ + L1StandardBridgeProxy: chainState.L1StandardBridgeProxyAddress, + L1CrossDomainMessengerProxy: chainState.L1CrossDomainMessengerProxyAddress, + L1ERC721BridgeProxy: chainState.L1ERC721BridgeProxyAddress, + SystemConfigProxy: chainState.SystemConfigProxyAddress, + OptimismPortalProxy: chainState.OptimismPortalProxyAddress, + ProtocolVersionsProxy: state.SuperchainDeployment.ProtocolVersionsProxyAddress, + } + cfg.OperatorDeployConfig = genesis.OperatorDeployConfig{ + BatchSenderAddress: chainIntent.Roles.Batcher, + P2PSequencerAddress: chainIntent.Roles.UnsafeBlockSigner, + } + cfg.BatchInboxAddress = calculateBatchInboxAddr(chainState.ID) + cfg.L1ChainID = intent.L1ChainID + + return cfg, nil +} + +// mergeJSON merges the provided overrides into the input struct. Fields +// must be JSON-serializable for this to work. Overrides are applied in +// order of precedence - i.e., the last overrides will override keys from +// all preceding overrides. +func mergeJSON[T any](in T, overrides ...map[string]any) (T, error) { + var out T + inJSON, err := json.Marshal(in) + if err != nil { + return out, err + } + + var tmpMap map[string]interface{} + if err := json.Unmarshal(inJSON, &tmpMap); err != nil { + return out, err + } + + for _, override := range overrides { + for k, v := range override { + tmpMap[k] = v + } + } + + inJSON, err = json.Marshal(tmpMap) + if err != nil { + return out, err + } + + if err := json.Unmarshal(inJSON, &out); err != nil { + return out, err + } + + return out, nil +} + +func mustHexBigFromHex(hex string) *hexutil.Big { + num := hexutil.MustDecodeBig(hex) + hexBig := hexutil.Big(*num) + return &hexBig +} + +func u64UtilPtr(in uint64) *hexutil.Uint64 { + util := hexutil.Uint64(in) + return &util +} + +func calculateBatchInboxAddr(chainID common.Hash) common.Address { + var out common.Address + copy(out[1:], crypto.Keccak256(chainID[:])[:19]) + return out +} diff --git a/op-chain-ops/deployer/state/deploy_config_test.go b/op-chain-ops/deployer/state/deploy_config_test.go new file mode 100644 index 0000000000000..be431b5740cea --- /dev/null +++ b/op-chain-ops/deployer/state/deploy_config_test.go @@ -0,0 +1,36 @@ +package state + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestMergeJSON(t *testing.T) { + type testStruct struct { + A string `json:"a"` + B int `json:"b"` + C bool `json:"c"` + } + + out, err := mergeJSON( + testStruct{ + "hello", + 42, + true, + }, + map[string]any{ + "a": "world", + "c": false, + }, + map[string]any{ + "d": "shouldn't show up", + }, + ) + require.NoError(t, err) + require.EqualValues(t, out, testStruct{ + "world", + 42, + false, + }) +} diff --git a/op-chain-ops/deployer/state/intent.go b/op-chain-ops/deployer/state/intent.go new file mode 100644 index 0000000000000..755ad6bbba541 --- /dev/null +++ b/op-chain-ops/deployer/state/intent.go @@ -0,0 +1,146 @@ +package state + +import ( + "fmt" + "math/big" + "strings" + + "github.com/ethereum-optimism/optimism/op-service/ioutil" + "github.com/ethereum-optimism/optimism/op-service/jsonutil" + "github.com/ethereum/go-ethereum/common" +) + +var emptyAddress common.Address + +type Intent struct { + L1ChainID uint64 `json:"l1ChainID" toml:"l1ChainID"` + + SuperchainRoles SuperchainRoles `json:"superchainRoles" toml:"superchainRoles"` + + UseFaultProofs bool `json:"useFaultProofs" toml:"useFaultProofs"` + + UseAltDA bool `json:"useAltDA" toml:"useAltDA"` + + FundDevAccounts bool `json:"fundDevAccounts" toml:"fundDevAccounts"` + + ContractArtifactsURL *ArtifactsURL `json:"contractArtifactsURL" toml:"contractArtifactsURL"` + + ContractsRelease string `json:"contractsVersion" toml:"contractsVersion"` + + OPCMAddress common.Address `json:"opcmAddress" toml:"opcmAddress"` + + Chains []*ChainIntent `json:"chains" toml:"chains"` + + GlobalDeployOverrides map[string]any `json:"globalDeployOverrides" toml:"globalDeployOverrides"` +} + +func (c *Intent) L1ChainIDBig() *big.Int { + return big.NewInt(int64(c.L1ChainID)) +} + +func (c *Intent) Check() error { + if c.L1ChainID == 0 { + return fmt.Errorf("l1ChainID must be set") + } + + if c.UseFaultProofs && c.UseAltDA { + return fmt.Errorf("cannot use both fault proofs and alt-DA") + } + + if c.SuperchainRoles.ProxyAdminOwner == emptyAddress { + return fmt.Errorf("proxyAdminOwner must be set") + } + + if c.SuperchainRoles.ProtocolVersionsOwner == emptyAddress { + c.SuperchainRoles.ProtocolVersionsOwner = c.SuperchainRoles.ProxyAdminOwner + } + + if c.SuperchainRoles.Guardian == emptyAddress { + c.SuperchainRoles.Guardian = c.SuperchainRoles.ProxyAdminOwner + } + + if c.ContractArtifactsURL == nil { + return fmt.Errorf("contractArtifactsURL must be set") + } + + if c.ContractsRelease != "dev" && !strings.HasPrefix(c.ContractsRelease, "op-contracts/") { + return fmt.Errorf("contractsVersion must be either the literal \"dev\" or start with \"op-contracts/\"") + } + + return nil +} + +func (c *Intent) Chain(id common.Hash) (*ChainIntent, error) { + for i := range c.Chains { + if c.Chains[i].ID == id { + return c.Chains[i], nil + } + } + + return nil, fmt.Errorf("chain %d not found", id) +} + +func (c *Intent) WriteToFile(path string) error { + return jsonutil.WriteTOML(c, ioutil.ToAtomicFile(path, 0o755)) +} + +type SuperchainRoles struct { + ProxyAdminOwner common.Address `json:"proxyAdminOwner" toml:"proxyAdminOwner"` + + ProtocolVersionsOwner common.Address `json:"protocolVersionsOwner" toml:"protocolVersionsOwner"` + + Guardian common.Address `json:"guardian" toml:"guardian"` +} + +type ChainIntent struct { + ID common.Hash `json:"id" toml:"id"` + + Roles ChainRoles `json:"roles" toml:"roles"` + + DeployOverrides map[string]any `json:"deployOverrides" toml:"deployOverrides"` +} + +type ChainRoles struct { + ProxyAdminOwner common.Address `json:"proxyAdminOwner" toml:"proxyAdminOwner"` + + SystemConfigOwner common.Address `json:"systemConfigOwner" toml:"systemConfigOwner"` + + GovernanceTokenOwner common.Address `json:"governanceTokenOwner" toml:"governanceTokenOwner"` + + UnsafeBlockSigner common.Address `json:"unsafeBlockSigner" toml:"unsafeBlockSigner"` + + Batcher common.Address `json:"batcher" toml:"batcher"` + + Proposer common.Address `json:"proposer" toml:"proposer"` + + Challenger common.Address `json:"challenger" toml:"challenger"` +} + +func (c *ChainIntent) Check() error { + var emptyHash common.Hash + if c.ID == emptyHash { + return fmt.Errorf("id must be set") + } + + if c.Roles.ProxyAdminOwner == emptyAddress { + return fmt.Errorf("proxyAdminOwner must be set") + } + + if c.Roles.SystemConfigOwner == emptyAddress { + c.Roles.SystemConfigOwner = c.Roles.ProxyAdminOwner + } + + if c.Roles.GovernanceTokenOwner == emptyAddress { + c.Roles.GovernanceTokenOwner = c.Roles.ProxyAdminOwner + } + + if c.Roles.UnsafeBlockSigner == emptyAddress { + return fmt.Errorf("unsafeBlockSigner must be set") + } + + if c.Roles.Batcher == emptyAddress { + return fmt.Errorf("batcher must be set") + } + + return nil +} diff --git a/op-chain-ops/deployer/state/state.go b/op-chain-ops/deployer/state/state.go new file mode 100644 index 0000000000000..674e06d743a0e --- /dev/null +++ b/op-chain-ops/deployer/state/state.go @@ -0,0 +1,119 @@ +package state + +import ( + "bytes" + "compress/gzip" + "encoding/json" + "fmt" + + "github.com/ethereum/go-ethereum/core/types" + + "github.com/ethereum-optimism/optimism/op-chain-ops/foundry" + "github.com/ethereum-optimism/optimism/op-service/ioutil" + "github.com/ethereum-optimism/optimism/op-service/jsonutil" + "github.com/ethereum/go-ethereum/common" +) + +// State contains the data needed to recreate the deployment +// as it progresses and once it is fully applied. +type State struct { + // Version versions the state so we can update it later. + Version int `json:"version"` + + // Create2Salt is the salt used for CREATE2 deployments. + Create2Salt common.Hash `json:"create2Salt"` + + // AppliedIntent contains the chain intent that was last + // successfully applied. It is diffed against new intent + // in order to determine what deployment steps to take. + // This field is nil for new deployments. + AppliedIntent *Intent `json:"appliedIntent"` + + // SuperchainDeployment contains the addresses of the Superchain + // deployment. It only contains the proxies because the implementations + // can be looked up on chain. + SuperchainDeployment *SuperchainDeployment `json:"superchainDeployment"` + + // ImplementationsDeployment contains the addresses of the common implementation + // contracts required for the Superchain to function. + ImplementationsDeployment *ImplementationsDeployment `json:"implementationsDeployment"` + + // Chains contains data about L2 chain deployments. + Chains []*ChainState `json:"opChainDeployments"` +} + +func (s *State) WriteToFile(path string) error { + return jsonutil.WriteJSON(s, ioutil.ToAtomicFile(path, 0o755)) +} + +func (s *State) Chain(id common.Hash) (*ChainState, error) { + for _, chain := range s.Chains { + if chain.ID == id { + return chain, nil + } + } + return nil, fmt.Errorf("chain not found: %s", id.Hex()) +} + +type SuperchainDeployment struct { + ProxyAdminAddress common.Address `json:"proxyAdminAddress"` + SuperchainConfigProxyAddress common.Address `json:"superchainConfigProxyAddress"` + SuperchainConfigImplAddress common.Address `json:"superchainConfigImplAddress"` + ProtocolVersionsProxyAddress common.Address `json:"protocolVersionsProxyAddress"` + ProtocolVersionsImplAddress common.Address `json:"protocolVersionsImplAddress"` + StateDump *foundry.ForgeAllocs `json:"stateDump"` +} + +type ImplementationsDeployment struct { + OpcmProxyAddress common.Address `json:"opcmProxyAddress"` + DelayedWETHImplAddress common.Address `json:"delayedWETHImplAddress"` + OptimismPortalImplAddress common.Address `json:"optimismPortalImplAddress"` + PreimageOracleSingletonAddress common.Address `json:"preimageOracleSingletonAddress"` + MipsSingletonAddress common.Address `json:"mipsSingletonAddress"` + SystemConfigImplAddress common.Address `json:"systemConfigImplAddress"` + L1CrossDomainMessengerImplAddress common.Address `json:"l1CrossDomainMessengerImplAddress"` + L1ERC721BridgeImplAddress common.Address `json:"l1ERC721BridgeImplAddress"` + L1StandardBridgeImplAddress common.Address `json:"l1StandardBridgeImplAddress"` + OptimismMintableERC20FactoryImplAddress common.Address `json:"optimismMintableERC20FactoryImplAddress"` + DisputeGameFactoryImplAddress common.Address `json:"disputeGameFactoryImplAddress"` + StateDump *foundry.ForgeAllocs `json:"stateDump"` +} + +type ChainState struct { + ID common.Hash `json:"id"` + + ProxyAdminAddress common.Address `json:"proxyAdminAddress"` + AddressManagerAddress common.Address `json:"addressManagerAddress"` + L1ERC721BridgeProxyAddress common.Address `json:"l1ERC721BridgeProxyAddress"` + SystemConfigProxyAddress common.Address `json:"systemConfigProxyAddress"` + OptimismMintableERC20FactoryProxyAddress common.Address `json:"optimismMintableERC20FactoryProxyAddress"` + L1StandardBridgeProxyAddress common.Address `json:"l1StandardBridgeProxyAddress"` + L1CrossDomainMessengerProxyAddress common.Address `json:"l1CrossDomainMessengerProxyAddress"` + OptimismPortalProxyAddress common.Address `json:"optimismPortalProxyAddress"` + DisputeGameFactoryProxyAddress common.Address `json:"disputeGameFactoryProxyAddress"` + AnchorStateRegistryProxyAddress common.Address `json:"anchorStateRegistryProxyAddress"` + AnchorStateRegistryImplAddress common.Address `json:"anchorStateRegistryImplAddress"` + FaultDisputeGameAddress common.Address `json:"faultDisputeGameAddress"` + PermissionedDisputeGameAddress common.Address `json:"permissionedDisputeGameAddress"` + DelayedWETHPermissionedGameProxyAddress common.Address `json:"delayedWETHPermissionedGameProxyAddress"` + DelayedWETHPermissionlessGameProxyAddress common.Address `json:"delayedWETHPermissionlessGameProxyAddress"` + + Allocs Base64Bytes `json:"allocs"` + + StartBlock *types.Header `json:"startBlock"` +} + +func (c *ChainState) UnmarshalAllocs() (*foundry.ForgeAllocs, error) { + gr, err := gzip.NewReader(bytes.NewReader(c.Allocs)) + if err != nil { + return nil, fmt.Errorf("failed to create gzip reader: %w", err) + } + defer gr.Close() + + var allocs foundry.ForgeAllocs + if err := json.NewDecoder(gr).Decode(&allocs); err != nil { + return nil, fmt.Errorf("failed to decode allocs: %w", err) + } + + return &allocs, nil +} diff --git a/op-chain-ops/deployer/version/version.go b/op-chain-ops/deployer/version/version.go new file mode 100644 index 0000000000000..2456f656d45c1 --- /dev/null +++ b/op-chain-ops/deployer/version/version.go @@ -0,0 +1,6 @@ +package version + +var ( + Version = "v0.0.0" + Meta = "dev" +) diff --git a/op-chain-ops/devkeys/devkeys.go b/op-chain-ops/devkeys/devkeys.go index b4fefe04e5980..d0526c8c1d3a4 100644 --- a/op-chain-ops/devkeys/devkeys.go +++ b/op-chain-ops/devkeys/devkeys.go @@ -49,24 +49,36 @@ func ChainUserKeys(chainID *big.Int) func(index uint64) ChainUserKey { } } +type Role interface { + Key(chainID *big.Int) Key +} + // SuperchainOperatorRole identifies an account used in the operations of superchain contracts type SuperchainOperatorRole uint64 const ( // SuperchainDeployerKey is the deployer of the superchain contracts. SuperchainDeployerKey SuperchainOperatorRole = 0 + // SuperchainProxyAdminOwner is the key that owns the superchain ProxyAdmin + SuperchainProxyAdminOwner SuperchainOperatorRole = 1 // SuperchainConfigGuardianKey is the Guardian of the SuperchainConfig. - SuperchainConfigGuardianKey SuperchainOperatorRole = 1 + SuperchainConfigGuardianKey SuperchainOperatorRole = 2 + // SuperchainProtocolVersionsOwner is the key that can make ProtocolVersions changes. + SuperchainProtocolVersionsOwner SuperchainOperatorRole = 3 // DependencySetManagerKey is the key used to manage the dependency set of a superchain. - DependencySetManagerKey SuperchainOperatorRole = 2 + DependencySetManagerKey SuperchainOperatorRole = 4 ) func (role SuperchainOperatorRole) String() string { switch role { case SuperchainDeployerKey: return "superchain-deployer" + case SuperchainProxyAdminOwner: + return "superchain-proxy-admin-owner" case SuperchainConfigGuardianKey: return "superchain-config-guardian" + case SuperchainProtocolVersionsOwner: + return "superchain-protocol-versions-owner" case DependencySetManagerKey: return "dependency-set-manager" default: @@ -74,6 +86,13 @@ func (role SuperchainOperatorRole) String() string { } } +func (role SuperchainOperatorRole) Key(chainID *big.Int) Key { + return &SuperchainOperatorKey{ + ChainID: chainID, + Role: role, + } +} + // SuperchainOperatorKey is an account specific to an OperationRole of a given OP-Stack chain. type SuperchainOperatorKey struct { ChainID *big.Int @@ -122,6 +141,8 @@ const ( L1FeeVaultRecipientRole ChainOperatorRole = 8 // SequencerFeeVaultRecipientRole is the key that receives form the SequencerFeeVault predeploy SequencerFeeVaultRecipientRole ChainOperatorRole = 9 + // SystemConfigOwner is the key that can make SystemConfig changes. + SystemConfigOwner ChainOperatorRole = 10 ) func (role ChainOperatorRole) String() string { @@ -146,12 +167,14 @@ func (role ChainOperatorRole) String() string { return "l1-fee-vault-recipient" case SequencerFeeVaultRecipientRole: return "sequencer-fee-vault-recipient" + case SystemConfigOwner: + return "system-config-owner" default: return fmt.Sprintf("unknown-operator-%d", uint64(role)) } } -func (role ChainOperatorRole) Key(chainID *big.Int) *ChainOperatorKey { +func (role ChainOperatorRole) Key(chainID *big.Int) Key { return &ChainOperatorKey{ ChainID: chainID, Role: role, diff --git a/op-chain-ops/foundry/allocs.go b/op-chain-ops/foundry/allocs.go index b7300511431d9..af0c28f4faf00 100644 --- a/op-chain-ops/foundry/allocs.go +++ b/op-chain-ops/foundry/allocs.go @@ -82,6 +82,10 @@ func (d *ForgeAllocs) Copy() *ForgeAllocs { return &ForgeAllocs{Accounts: out} } +func (d ForgeAllocs) MarshalJSON() ([]byte, error) { + return json.Marshal(d.Accounts) +} + func (d *ForgeAllocs) UnmarshalJSON(b []byte) error { // forge, since integrating Alloy, likes to hex-encode everything. type forgeAllocAccount struct { diff --git a/op-chain-ops/foundry/allocs_test.go b/op-chain-ops/foundry/allocs_test.go index a11d69fa9eff1..6d19557016cb9 100644 --- a/op-chain-ops/foundry/allocs_test.go +++ b/op-chain-ops/foundry/allocs_test.go @@ -1,6 +1,8 @@ package foundry import ( + "encoding/json" + "math/big" "os" "testing" @@ -96,3 +98,24 @@ func TestForgeAllocs_FromState(t *testing.T) { require.Equal(t, "0", allocs.Accounts[contract].Balance.String()) require.Equal(t, uint64(30), allocs.Accounts[contract].Nonce) } + +func TestForgeAllocs_Marshaling(t *testing.T) { + data := &ForgeAllocs{ + Accounts: map[common.Address]types.Account{ + common.HexToAddress("0x12345"): { + Balance: big.NewInt(12345), + Code: []byte{0x01, 0x02, 0x03}, + Nonce: 123, + Storage: map[common.Hash]common.Hash{ + common.HexToHash("0x12345"): common.HexToHash("0x12345"), + }, + }, + }, + } + + out, err := json.Marshal(data) + require.NoError(t, err) + + var in ForgeAllocs + require.NoError(t, json.Unmarshal(out, &in)) +} diff --git a/op-chain-ops/foundry/artifactsfs.go b/op-chain-ops/foundry/artifactsfs.go index 2b5599c85c202..13229c41bc069 100644 --- a/op-chain-ops/foundry/artifactsfs.go +++ b/op-chain-ops/foundry/artifactsfs.go @@ -9,14 +9,14 @@ import ( "strings" ) -type statDirFs interface { +type StatDirFs interface { fs.StatFS fs.ReadDirFS } func OpenArtifactsDir(dirPath string) *ArtifactsFS { dir := os.DirFS(dirPath) - if d, ok := dir.(statDirFs); !ok { + if d, ok := dir.(StatDirFs); !ok { panic("Go DirFS guarantees changed") } else { return &ArtifactsFS{FS: d} @@ -29,7 +29,7 @@ func OpenArtifactsDir(dirPath string) *ArtifactsFS { // See OpenArtifactsDir for reading from a local directory. // Alternative FS systems, like a tarball, may be used too. type ArtifactsFS struct { - FS statDirFs + FS StatDirFs } // ListArtifacts lists the artifacts. Each artifact matches a source-file name. diff --git a/op-chain-ops/genesis/config.go b/op-chain-ops/genesis/config.go index 0fc628727fe68..26f675b30e7fa 100644 --- a/op-chain-ops/genesis/config.go +++ b/op-chain-ops/genesis/config.go @@ -230,9 +230,9 @@ type GasPriceOracleDeployConfig struct { // Deprecated: Since Ecotone, this field is superseded by GasPriceOracleBaseFeeScalar and GasPriceOracleBlobBaseFeeScalar. GasPriceOracleScalar uint64 `json:"gasPriceOracleScalar"` // GasPriceOracleBaseFeeScalar represents the value of the base fee scalar used for fee calculations. - GasPriceOracleBaseFeeScalar uint32 `json:"gasPriceOracleBaseFeeScalar"` + GasPriceOracleBaseFeeScalar uint32 `json:"gasPriceOracleBaseFeeScalar" evm:"basefeeScalar"` // GasPriceOracleBlobBaseFeeScalar represents the value of the blob base fee scalar used for fee calculations. - GasPriceOracleBlobBaseFeeScalar uint32 `json:"gasPriceOracleBlobBaseFeeScalar"` + GasPriceOracleBlobBaseFeeScalar uint32 `json:"gasPriceOracleBlobBaseFeeScalar" evm:"blobbasefeeScalar"` } var _ ConfigChecker = (*GasPriceOracleDeployConfig)(nil) @@ -282,7 +282,7 @@ func (d *GasTokenDeployConfig) Check(log log.Logger) error { // OperatorDeployConfig configures the hot-key addresses for operations such as sequencing and batch-submission. type OperatorDeployConfig struct { // P2PSequencerAddress is the address of the key the sequencer uses to sign blocks on the P2P layer. - P2PSequencerAddress common.Address `json:"p2pSequencerAddress"` + P2PSequencerAddress common.Address `json:"p2pSequencerAddress" evm:"p2pSequencerAddress"` // BatchSenderAddress represents the initial sequencer account that authorizes batches. // Transactions sent from this account to the batch inbox address are considered valid. BatchSenderAddress common.Address `json:"batchSenderAddress"` @@ -627,7 +627,7 @@ type OutputOracleDeployConfig struct { L2OutputOracleSubmissionInterval uint64 `json:"l2OutputOracleSubmissionInterval"` // L2OutputOracleStartingTimestamp is the starting timestamp for the L2OutputOracle. // MUST be the same as the timestamp of the L2OO start block. - L2OutputOracleStartingTimestamp int `json:"l2OutputOracleStartingTimestamp"` + L2OutputOracleStartingTimestamp int64 `json:"l2OutputOracleStartingTimestamp"` // L2OutputOracleStartingBlockNumber is the starting block number for the L2OutputOracle. // Must be greater than or equal to the first Bedrock block. The first L2 output will correspond // to this value plus the submission interval. @@ -732,6 +732,8 @@ type L1DependenciesConfig struct { // DAChallengeProxy represents the L1 address of the DataAvailabilityChallenge contract. DAChallengeProxy common.Address `json:"daChallengeProxy"` + + ProtocolVersionsProxy common.Address `json:"protocolVersionsProxy"` } // DependencyContext is the contextual configuration needed to verify the L1 dependencies, @@ -808,7 +810,7 @@ type DeployConfig struct { // The L2 genesis timestamp does not affect the initial L2 account state: // the storage of the L1Block contract at genesis is zeroed, since the adoption of // the L2-genesis allocs-generation through solidity script. - L1StartingBlockTag *MarshalableRPCBlockNumberOrHash `json:"l1StartingBlockTag"` + L1StartingBlockTag *MarshalableRPCBlockNumberOrHash `json:"l1StartingBlockTag" evm:"-"` // L1 contracts configuration. // The deployer of the contracts chooses which sub-systems to deploy. @@ -820,7 +822,7 @@ type DeployConfig struct { L1DependenciesConfig // Legacy, ignored, here for strict-JSON decoding to be accepted. - LegacyDeployConfig + LegacyDeployConfig `evm:"-"` } // Copy will deeply copy the DeployConfig. This does a JSON roundtrip to copy @@ -877,7 +879,7 @@ func (d *DeployConfig) SetDeployments(deployments *L1Deployments) { // RollupConfig converts a DeployConfig to a rollup.Config. If Ecotone is active at genesis, the // Overhead value is considered a noop. -func (d *DeployConfig) RollupConfig(l1StartBlock *types.Block, l2GenesisBlockHash common.Hash, l2GenesisBlockNumber uint64) (*rollup.Config, error) { +func (d *DeployConfig) RollupConfig(l1StartBlock *types.Header, l2GenesisBlockHash common.Hash, l2GenesisBlockNumber uint64) (*rollup.Config, error) { if d.OptimismPortalProxy == (common.Address{}) { return nil, errors.New("OptimismPortalProxy cannot be address(0)") } @@ -894,17 +896,19 @@ func (d *DeployConfig) RollupConfig(l1StartBlock *types.Block, l2GenesisBlockHas } } + l1StartTime := l1StartBlock.Time + return &rollup.Config{ Genesis: rollup.Genesis{ L1: eth.BlockID{ Hash: l1StartBlock.Hash(), - Number: l1StartBlock.NumberU64(), + Number: l1StartBlock.Number.Uint64(), }, L2: eth.BlockID{ Hash: l2GenesisBlockHash, Number: l2GenesisBlockNumber, }, - L2Time: l1StartBlock.Time(), + L2Time: l1StartBlock.Time, SystemConfig: eth.SystemConfig{ BatcherAddr: d.BatchSenderAddress, Overhead: eth.Bytes32(common.BigToHash(new(big.Int).SetUint64(d.GasPriceOracleOverhead))), @@ -912,23 +916,24 @@ func (d *DeployConfig) RollupConfig(l1StartBlock *types.Block, l2GenesisBlockHas GasLimit: uint64(d.L2GenesisBlockGasLimit), }, }, - BlockTime: d.L2BlockTime, - MaxSequencerDrift: d.MaxSequencerDrift, - SeqWindowSize: d.SequencerWindowSize, - ChannelTimeoutBedrock: d.ChannelTimeoutBedrock, - L1ChainID: new(big.Int).SetUint64(d.L1ChainID), - L2ChainID: new(big.Int).SetUint64(d.L2ChainID), - BatchInboxAddress: d.BatchInboxAddress, - DepositContractAddress: d.OptimismPortalProxy, - L1SystemConfigAddress: d.SystemConfigProxy, - RegolithTime: d.RegolithTime(l1StartBlock.Time()), - CanyonTime: d.CanyonTime(l1StartBlock.Time()), - DeltaTime: d.DeltaTime(l1StartBlock.Time()), - EcotoneTime: d.EcotoneTime(l1StartBlock.Time()), - FjordTime: d.FjordTime(l1StartBlock.Time()), - GraniteTime: d.GraniteTime(l1StartBlock.Time()), - InteropTime: d.InteropTime(l1StartBlock.Time()), - AltDAConfig: altDA, + BlockTime: d.L2BlockTime, + MaxSequencerDrift: d.MaxSequencerDrift, + SeqWindowSize: d.SequencerWindowSize, + ChannelTimeoutBedrock: d.ChannelTimeoutBedrock, + L1ChainID: new(big.Int).SetUint64(d.L1ChainID), + L2ChainID: new(big.Int).SetUint64(d.L2ChainID), + BatchInboxAddress: d.BatchInboxAddress, + DepositContractAddress: d.OptimismPortalProxy, + L1SystemConfigAddress: d.SystemConfigProxy, + RegolithTime: d.RegolithTime(l1StartTime), + CanyonTime: d.CanyonTime(l1StartTime), + DeltaTime: d.DeltaTime(l1StartTime), + EcotoneTime: d.EcotoneTime(l1StartTime), + FjordTime: d.FjordTime(l1StartTime), + GraniteTime: d.GraniteTime(l1StartTime), + InteropTime: d.InteropTime(l1StartTime), + ProtocolVersionsAddress: d.ProtocolVersionsProxy, + AltDAConfig: altDA, }, nil } diff --git a/op-chain-ops/genesis/genesis.go b/op-chain-ops/genesis/genesis.go index f517912e109a7..dc7a44ad7ddf5 100644 --- a/op-chain-ops/genesis/genesis.go +++ b/op-chain-ops/genesis/genesis.go @@ -22,7 +22,7 @@ const defaultGasLimit = 30_000_000 var BedrockTransitionBlockExtraData = []byte("BEDROCK") // NewL2Genesis will create a new L2 genesis -func NewL2Genesis(config *DeployConfig, block *types.Block) (*core.Genesis, error) { +func NewL2Genesis(config *DeployConfig, l1StartHeader *types.Header) (*core.Genesis, error) { if config.L2ChainID == 0 { return nil, errors.New("must define L2 ChainID") } @@ -40,6 +40,8 @@ func NewL2Genesis(config *DeployConfig, block *types.Block) (*core.Genesis, erro eip1559Elasticity = 10 } + l1StartTime := l1StartHeader.Time + optimismChainConfig := params.ChainConfig{ ChainID: new(big.Int).SetUint64(config.L2ChainID), HomesteadBlock: big.NewInt(0), @@ -61,14 +63,14 @@ func NewL2Genesis(config *DeployConfig, block *types.Block) (*core.Genesis, erro TerminalTotalDifficulty: big.NewInt(0), TerminalTotalDifficultyPassed: true, BedrockBlock: new(big.Int).SetUint64(uint64(config.L2GenesisBlockNumber)), - RegolithTime: config.RegolithTime(block.Time()), - CanyonTime: config.CanyonTime(block.Time()), - ShanghaiTime: config.CanyonTime(block.Time()), - CancunTime: config.EcotoneTime(block.Time()), - EcotoneTime: config.EcotoneTime(block.Time()), - FjordTime: config.FjordTime(block.Time()), - GraniteTime: config.GraniteTime(block.Time()), - InteropTime: config.InteropTime(block.Time()), + RegolithTime: config.RegolithTime(l1StartTime), + CanyonTime: config.CanyonTime(l1StartTime), + ShanghaiTime: config.CanyonTime(l1StartTime), + CancunTime: config.EcotoneTime(l1StartTime), + EcotoneTime: config.EcotoneTime(l1StartTime), + FjordTime: config.FjordTime(l1StartTime), + GraniteTime: config.GraniteTime(l1StartTime), + InteropTime: config.InteropTime(l1StartTime), Optimism: ¶ms.OptimismConfig{ EIP1559Denominator: eip1559Denom, EIP1559Elasticity: eip1559Elasticity, @@ -102,7 +104,7 @@ func NewL2Genesis(config *DeployConfig, block *types.Block) (*core.Genesis, erro genesis := &core.Genesis{ Config: &optimismChainConfig, Nonce: uint64(config.L2GenesisBlockNonce), - Timestamp: block.Time(), + Timestamp: l1StartTime, ExtraData: extraData, GasLimit: uint64(gasLimit), Difficulty: difficulty.ToInt(), diff --git a/op-chain-ops/genesis/layer_one.go b/op-chain-ops/genesis/layer_one.go index e7d5692764963..7178cccebb94b 100644 --- a/op-chain-ops/genesis/layer_one.go +++ b/op-chain-ops/genesis/layer_one.go @@ -31,7 +31,7 @@ func BuildL1DeveloperGenesis(config *DeployConfig, dump *foundry.ForgeAllocs, l1 return nil, fmt.Errorf("cannot create L1 developer genesis: %w", err) } - if genesis.Alloc != nil && len(genesis.Alloc) != 0 { + if len(genesis.Alloc) != 0 { panic("Did not expect NewL1Genesis to generate non-empty state") // sanity check for dev purposes. } // copy, for safety when the dump is reused (like in e2e testing) diff --git a/op-chain-ops/genesis/layer_two.go b/op-chain-ops/genesis/layer_two.go index 46c17a4f9c763..5e79b55ce69dc 100644 --- a/op-chain-ops/genesis/layer_two.go +++ b/op-chain-ops/genesis/layer_two.go @@ -36,7 +36,7 @@ var ( type AllocsLoader func(mode L2AllocsMode) *foundry.ForgeAllocs // BuildL2Genesis will build the L2 genesis block. -func BuildL2Genesis(config *DeployConfig, dump *foundry.ForgeAllocs, l1StartBlock *types.Block) (*core.Genesis, error) { +func BuildL2Genesis(config *DeployConfig, dump *foundry.ForgeAllocs, l1StartBlock *types.Header) (*core.Genesis, error) { genspec, err := NewL2Genesis(config, l1StartBlock) if err != nil { return nil, err 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 dfe420b2b7f44..1d0702e0218ee 100644 --- a/op-chain-ops/genesis/testdata/test-deploy-config-full.json +++ b/op-chain-ops/genesis/testdata/test-deploy-config-full.json @@ -55,6 +55,7 @@ "systemConfigProxy": "0x4200000000000000000000000000000000000061", "optimismPortalProxy": "0x4200000000000000000000000000000000000062", "proxyAdminOwner": "0x0000000000000000000000000000000000000222", + "protocolVersionsProxy": "0x0000000000000000000000000000000000000000", "gasPriceOracleBaseFeeScalar": 0, "gasPriceOracleBlobBaseFeeScalar": 0, "gasPriceOracleOverhead": 2100, diff --git a/op-chain-ops/genesis/withdrawal_network.go b/op-chain-ops/genesis/withdrawal_network.go index f52f12d5558dc..6aa753d36bd85 100644 --- a/op-chain-ops/genesis/withdrawal_network.go +++ b/op-chain-ops/genesis/withdrawal_network.go @@ -4,6 +4,8 @@ import ( "encoding/json" "fmt" "strconv" + + "github.com/holiman/uint256" ) // WithdrawalNetwork represents the network that withdrawals are sent to. @@ -32,6 +34,11 @@ func (w *WithdrawalNetwork) ToUint8() uint8 { } } +func (w WithdrawalNetwork) ToABI() []byte { + out := uint256.NewInt(uint64(w.ToUint8())).Bytes32() + return out[:] +} + // FromUint8 converts a uint8 to a WithdrawalNetwork. func FromUint8(i uint8) WithdrawalNetwork { switch i { diff --git a/op-chain-ops/interopgen/configs.go b/op-chain-ops/interopgen/configs.go new file mode 100644 index 0000000000000..f40d29904c2f5 --- /dev/null +++ b/op-chain-ops/interopgen/configs.go @@ -0,0 +1,110 @@ +package interopgen + +import ( + "errors" + "fmt" + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/log" + + "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" +) + +type L1Config struct { + ChainID *big.Int + genesis.DevL1DeployConfig + Prefund map[common.Address]*big.Int +} + +func (c *L1Config) Check(log log.Logger) error { + if c.ChainID == nil { + return errors.New("missing L1 chain ID") + } + // nothing to check on c.DevL1DeployConfig + return nil +} + +type SuperFaultProofConfig struct { + WithdrawalDelaySeconds *big.Int + MinProposalSizeBytes *big.Int + ChallengePeriodSeconds *big.Int + ProofMaturityDelaySeconds *big.Int + DisputeGameFinalityDelaySeconds *big.Int +} + +type OPCMImplementationsConfig struct { + Release string + + FaultProof SuperFaultProofConfig + + UseInterop bool // to deploy Interop implementation contracts, instead of the regular ones. + + StandardVersionsToml string // serialized string of superchain-registry 'standard-versions.toml' file +} + +type SuperchainConfig struct { + Deployer common.Address + + ProxyAdminOwner common.Address + ProtocolVersionsOwner common.Address + + Paused bool + + Implementations OPCMImplementationsConfig + + genesis.SuperchainL1DeployConfig +} + +func (c *SuperchainConfig) Check(log log.Logger) error { + if c.Deployer == (common.Address{}) { + return errors.New("missing superchain deployer address") + } + if c.ProxyAdminOwner == (common.Address{}) { + return errors.New("missing superchain ProxyAdminOwner address") + } + if err := c.SuperchainL1DeployConfig.Check(log); err != nil { + return err + } + return nil +} + +type L2Config struct { + Deployer common.Address // account used to deploy contracts to L2 + Proposer common.Address + Challenger common.Address + SystemConfigOwner common.Address + genesis.L2InitializationConfig + Prefund map[common.Address]*big.Int +} + +func (c *L2Config) Check(log log.Logger) error { + if c.Deployer == (common.Address{}) { + return errors.New("missing L2 deployer address") + } + if err := c.L2InitializationConfig.Check(log); err != nil { + return err + } + return nil +} + +type WorldConfig struct { + L1 *L1Config + Superchain *SuperchainConfig + L2s map[string]*L2Config +} + +func (c *WorldConfig) Check(log log.Logger) error { + if err := c.L1.Check(log); err != nil { + return fmt.Errorf("invalid L1 config: %w", err) + } + if err := c.Superchain.Check(log); err != nil { + return fmt.Errorf("invalid Superchain config: %w", err) + } + for l2ChainID, l2Cfg := range c.L2s { + if err := l2Cfg.Check(log.New("l2", &l2ChainID)); err != nil { + return fmt.Errorf("invalid L2 (chain ID %s) config: %w", l2ChainID, err) + } + } + return nil +} diff --git a/op-chain-ops/interopgen/deploy.go b/op-chain-ops/interopgen/deploy.go new file mode 100644 index 0000000000000..be837484e5124 --- /dev/null +++ b/op-chain-ops/interopgen/deploy.go @@ -0,0 +1,341 @@ +package interopgen + +import ( + "errors" + "fmt" + "math/big" + + "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-chain-ops/deployer/opcm" + "github.com/ethereum-optimism/optimism/op-chain-ops/foundry" + "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" + "github.com/ethereum-optimism/optimism/op-chain-ops/genesis/beacondeposit" + "github.com/ethereum-optimism/optimism/op-chain-ops/interopgen/deployers" + "github.com/ethereum-optimism/optimism/op-chain-ops/script" +) + +var ( + // sysGenesisDeployer is used as tx.origin/msg.sender on system genesis script calls. + // At the end we verify none of the deployed contracts persist (there may be temporary ones, to insert bytecode). + sysGenesisDeployer = common.Address(crypto.Keccak256([]byte("System genesis deployer"))[12:]) +) + +func Deploy(logger log.Logger, fa *foundry.ArtifactsFS, srcFS *foundry.SourceMapFS, cfg *WorldConfig) (*WorldDeployment, *WorldOutput, error) { + // Sanity check all L2s have consistent chain ID and attach to the same L1 + for id, l2Cfg := range cfg.L2s { + if fmt.Sprintf("%d", l2Cfg.L2ChainID) != id { + return nil, nil, fmt.Errorf("chain L2 %s declared different L2 chain ID %d in config", id, l2Cfg.L2ChainID) + } + if !cfg.L1.ChainID.IsUint64() || cfg.L1.ChainID.Uint64() != l2Cfg.L1ChainID { + return nil, nil, fmt.Errorf("chain L2 %s declared different L1 chain ID %d in config than global %d", id, l2Cfg.L1ChainID, cfg.L1.ChainID) + } + } + + deployments := &WorldDeployment{ + L2s: make(map[string]*L2Deployment), + } + + l1Host := createL1(logger, fa, srcFS, cfg.L1) + if err := l1Host.EnableCheats(); err != nil { + return nil, nil, fmt.Errorf("failed to enable cheats in L1 state: %w", err) + } + + l1Deployment, err := prepareInitialL1(l1Host, cfg.L1) + if err != nil { + return nil, nil, fmt.Errorf("failed to deploy initial L1 content: %w", err) + } + deployments.L1 = l1Deployment + + superDeployment, err := deploySuperchainToL1(l1Host, cfg.Superchain) + if err != nil { + return nil, nil, fmt.Errorf("failed to deploy superchain to L1: %w", err) + } + deployments.Superchain = superDeployment + + // We deploy contracts for each L2 to the L1 + // because we need to compute the genesis block hash + // to put into the L2 genesis configs, and can thus not mutate the L1 state + // after creating the final config for any particular L2. Will add comments. + + for l2ChainID, l2Cfg := range cfg.L2s { + l2Deployment, err := deployL2ToL1(l1Host, cfg.Superchain, superDeployment, l2Cfg) + if err != nil { + return nil, nil, fmt.Errorf("failed to deploy L2 %d to L1: %w", &l2ChainID, err) + } + deployments.L2s[l2ChainID] = l2Deployment + } + + out := &WorldOutput{ + L2s: make(map[string]*L2Output), + } + l1Out, err := completeL1(l1Host, cfg.L1) + if err != nil { + return nil, nil, fmt.Errorf("failed to complete L1: %w", err) + } + out.L1 = l1Out + + // Now that the L1 does not change anymore we can compute the L1 genesis block, to anchor all the L2s to. + l1GenesisBlock := l1Out.Genesis.ToBlock() + genesisTimestamp := l1Out.Genesis.Timestamp + + for l2ChainID, l2Cfg := range cfg.L2s { + l2Host := createL2(logger, fa, srcFS, l2Cfg, genesisTimestamp) + if err := l2Host.EnableCheats(); err != nil { + return nil, nil, fmt.Errorf("failed to enable cheats in L2 state %s: %w", l2ChainID, err) + } + if err := genesisL2(l2Host, l2Cfg, deployments.L2s[l2ChainID]); err != nil { + return nil, nil, fmt.Errorf("failed to apply genesis data to L2 %s: %w", l2ChainID, err) + } + l2Out, err := completeL2(l2Host, l2Cfg, l1GenesisBlock, deployments.L2s[l2ChainID]) + if err != nil { + return nil, nil, fmt.Errorf("failed to complete L2 %s: %w", l2ChainID, err) + } + out.L2s[l2ChainID] = l2Out + } + return deployments, out, nil +} + +func createL1(logger log.Logger, fa *foundry.ArtifactsFS, srcFS *foundry.SourceMapFS, cfg *L1Config) *script.Host { + l1Context := script.Context{ + ChainID: cfg.ChainID, + Sender: sysGenesisDeployer, + Origin: sysGenesisDeployer, + FeeRecipient: common.Address{}, + GasLimit: script.DefaultFoundryGasLimit, + BlockNum: uint64(cfg.L1GenesisBlockNumber), + Timestamp: uint64(cfg.L1GenesisBlockTimestamp), + PrevRandao: cfg.L1GenesisBlockMixHash, + BlobHashes: nil, + } + l1Host := script.NewHost(logger.New("role", "l1", "chain", cfg.ChainID), fa, srcFS, l1Context) + return l1Host +} + +func createL2(logger log.Logger, fa *foundry.ArtifactsFS, srcFS *foundry.SourceMapFS, l2Cfg *L2Config, genesisTimestamp uint64) *script.Host { + l2Context := script.Context{ + ChainID: new(big.Int).SetUint64(l2Cfg.L2ChainID), + Sender: sysGenesisDeployer, + Origin: sysGenesisDeployer, + FeeRecipient: common.Address{}, + GasLimit: script.DefaultFoundryGasLimit, + BlockNum: uint64(l2Cfg.L2GenesisBlockNumber), + Timestamp: genesisTimestamp, + PrevRandao: l2Cfg.L2GenesisBlockMixHash, + BlobHashes: nil, + } + l2Host := script.NewHost(logger.New("role", "l2", "chain", l2Cfg.L2ChainID), fa, srcFS, l2Context) + l2Host.SetEnvVar("OUTPUT_MODE", "none") // we don't use the cheatcode, but capture the state outside of EVM execution + l2Host.SetEnvVar("FORK", "granite") // latest fork + return l2Host +} + +// prepareInitialL1 deploys basics such as preinstalls to L1 (incl. EIP-4788) +func prepareInitialL1(l1Host *script.Host, cfg *L1Config) (*L1Deployment, error) { + l1Host.SetTxOrigin(sysGenesisDeployer) + + if err := deployers.InsertPreinstalls(l1Host); err != nil { + return nil, fmt.Errorf("failed to install preinstalls in L1: %w", err) + } + // No global contracts inserted at this point. + // All preinstalls have known constant addresses. + return &L1Deployment{}, nil +} + +func deploySuperchainToL1(l1Host *script.Host, superCfg *SuperchainConfig) (*SuperchainDeployment, error) { + l1Host.SetTxOrigin(superCfg.Deployer) + + superDeployment, err := opcm.DeploySuperchain(l1Host, opcm.DeploySuperchainInput{ + SuperchainProxyAdminOwner: superCfg.ProxyAdminOwner, + ProtocolVersionsOwner: superCfg.ProtocolVersionsOwner, + Guardian: superCfg.SuperchainConfigGuardian, + Paused: superCfg.Paused, + RequiredProtocolVersion: superCfg.RequiredProtocolVersion, + RecommendedProtocolVersion: superCfg.RecommendedProtocolVersion, + }) + if err != nil { + return nil, fmt.Errorf("failed to deploy Superchain contracts: %w", err) + } + + implementationsDeployment, err := opcm.DeployImplementations(l1Host, opcm.DeployImplementationsInput{ + WithdrawalDelaySeconds: superCfg.Implementations.FaultProof.WithdrawalDelaySeconds, + MinProposalSizeBytes: superCfg.Implementations.FaultProof.MinProposalSizeBytes, + ChallengePeriodSeconds: superCfg.Implementations.FaultProof.ChallengePeriodSeconds, + ProofMaturityDelaySeconds: superCfg.Implementations.FaultProof.ProofMaturityDelaySeconds, + DisputeGameFinalityDelaySeconds: superCfg.Implementations.FaultProof.DisputeGameFinalityDelaySeconds, + Release: superCfg.Implementations.Release, + SuperchainConfigProxy: superDeployment.SuperchainConfigProxy, + ProtocolVersionsProxy: superDeployment.ProtocolVersionsProxy, + SuperchainProxyAdmin: superDeployment.SuperchainProxyAdmin, + UseInterop: superCfg.Implementations.UseInterop, + StandardVersionsToml: opcm.StandardVersionsData, + }) + if err != nil { + return nil, fmt.Errorf("failed to deploy Implementations contracts: %w", err) + } + + // Collect deployment addresses + // This could all be automatic once we have better output-contract typing/scripting + return &SuperchainDeployment{ + Implementations: Implementations(implementationsDeployment), + ProxyAdmin: superDeployment.SuperchainProxyAdmin, + ProtocolVersions: superDeployment.ProtocolVersionsImpl, + ProtocolVersionsProxy: superDeployment.ProtocolVersionsProxy, + SuperchainConfig: superDeployment.SuperchainConfigImpl, + SuperchainConfigProxy: superDeployment.SuperchainConfigProxy, + }, nil +} + +func deployL2ToL1(l1Host *script.Host, superCfg *SuperchainConfig, superDeployment *SuperchainDeployment, cfg *L2Config) (*L2Deployment, error) { + if cfg.UseAltDA { + return nil, errors.New("alt-da mode not supported yet") + } + + l1Host.SetTxOrigin(cfg.Deployer) + + output, err := opcm.DeployOPChain(l1Host, opcm.DeployOPChainInput{ + OpChainProxyAdminOwner: cfg.ProxyAdminOwner, + SystemConfigOwner: cfg.SystemConfigOwner, + Batcher: cfg.BatchSenderAddress, + UnsafeBlockSigner: cfg.P2PSequencerAddress, + Proposer: cfg.Proposer, + Challenger: cfg.Challenger, + BasefeeScalar: cfg.GasPriceOracleBaseFeeScalar, + BlobBaseFeeScalar: cfg.GasPriceOracleBlobBaseFeeScalar, + L2ChainId: new(big.Int).SetUint64(cfg.L2ChainID), + OpcmProxy: superDeployment.OpcmProxy, + }) + if err != nil { + return nil, fmt.Errorf("failed to deploy L2 OP chain: %w", err) + } + + // Collect deployment addresses + return &L2Deployment{ + L2OpchainDeployment: L2OpchainDeployment(output), + }, nil +} + +func genesisL2(l2Host *script.Host, cfg *L2Config, deployment *L2Deployment) error { + if err := opcm.L2Genesis(l2Host, &opcm.L2GenesisInput{ + L1Deployments: opcm.L1Deployments{ + L1CrossDomainMessengerProxy: deployment.L1CrossDomainMessengerProxy, + L1StandardBridgeProxy: deployment.L1StandardBridgeProxy, + L1ERC721BridgeProxy: deployment.L1ERC721BridgeProxy, + }, + L2Config: cfg.L2InitializationConfig, + }); err != nil { + return fmt.Errorf("failed L2 genesis: %w", err) + } + + return nil +} + +func completeL1(l1Host *script.Host, cfg *L1Config) (*L1Output, error) { + l1Genesis, err := genesis.NewL1Genesis(&genesis.DeployConfig{ + L2InitializationConfig: genesis.L2InitializationConfig{ + L2CoreDeployConfig: genesis.L2CoreDeployConfig{ + L1ChainID: cfg.ChainID.Uint64(), + }, + }, + DevL1DeployConfig: cfg.DevL1DeployConfig, + }) + if err != nil { + return nil, fmt.Errorf("failed to build L1 genesis template: %w", err) + } + allocs, err := l1Host.StateDump() + if err != nil { + return nil, fmt.Errorf("failed to dump L1 state: %w", err) + } + + // Sanity check that the default deployer didn't include anything, + // and make sure it's not in the state. + if err := ensureNoDeployed(allocs, sysGenesisDeployer); err != nil { + return nil, fmt.Errorf("unexpected deployed account content by L1 genesis deployer: %w", err) + } + + for addr, amount := range cfg.Prefund { + acc := allocs.Accounts[addr] + acc.Balance = amount + allocs.Accounts[addr] = acc + } + + l1Genesis.Alloc = allocs.Accounts + + // Insert an empty beaconchain deposit contract with valid empty-tree prestate. + // This is part of dev-genesis, but not part of scripts yet. + beaconDepositAddr := common.HexToAddress("0x1111111111111111111111111111111111111111") + if err := beacondeposit.InsertEmptyBeaconDepositContract(l1Genesis, beaconDepositAddr); err != nil { + return nil, fmt.Errorf("failed to insert beacon deposit contract into L1 dev genesis: %w", err) + } + + return &L1Output{ + Genesis: l1Genesis, + }, nil +} + +func completeL2(l2Host *script.Host, cfg *L2Config, l1Block *types.Block, deployment *L2Deployment) (*L2Output, error) { + deployCfg := &genesis.DeployConfig{ + L2InitializationConfig: cfg.L2InitializationConfig, + L1DependenciesConfig: genesis.L1DependenciesConfig{ + L1StandardBridgeProxy: deployment.L1StandardBridgeProxy, + L1CrossDomainMessengerProxy: deployment.L1CrossDomainMessengerProxy, + L1ERC721BridgeProxy: deployment.L1ERC721BridgeProxy, + SystemConfigProxy: deployment.SystemConfigProxy, + OptimismPortalProxy: deployment.OptimismPortalProxy, + DAChallengeProxy: common.Address{}, // unsupported for now + }, + } + // l1Block is used to determine genesis time. + l2Genesis, err := genesis.NewL2Genesis(deployCfg, l1Block.Header()) + if err != nil { + return nil, fmt.Errorf("failed to build L2 genesis config: %w", err) + } + + allocs, err := l2Host.StateDump() + if err != nil { + return nil, fmt.Errorf("failed to dump L1 state: %w", err) + } + + // Sanity check that the default deployer didn't include anything, + // and make sure it's not in the state. + if err := ensureNoDeployed(allocs, sysGenesisDeployer); err != nil { + return nil, fmt.Errorf("unexpected deployed account content by L2 genesis deployer: %w", err) + } + + for addr, amount := range cfg.Prefund { + acc := allocs.Accounts[addr] + acc.Balance = amount + allocs.Accounts[addr] = acc + } + + l2Genesis.Alloc = allocs.Accounts + l2GenesisBlock := l2Genesis.ToBlock() + + rollupCfg, err := deployCfg.RollupConfig(l1Block.Header(), l2GenesisBlock.Hash(), l2GenesisBlock.NumberU64()) + if err != nil { + return nil, fmt.Errorf("failed to build L2 rollup config: %w", err) + } + return &L2Output{ + Genesis: l2Genesis, + RollupCfg: rollupCfg, + }, nil +} + +// ensureNoDeployed checks that non of the contracts that +// could have been deployed by the given deployer address are around. +// And removes deployer from the allocs. +func ensureNoDeployed(allocs *foundry.ForgeAllocs, deployer common.Address) error { + // Sanity check we have no deploy output that's not meant to be there. + for i := uint64(0); i <= allocs.Accounts[deployer].Nonce; i++ { + addr := crypto.CreateAddress(deployer, i) + if _, ok := allocs.Accounts[addr]; ok { + return fmt.Errorf("system deployer output %s (deployed with nonce %d) was not cleaned up", addr, i) + } + } + // Don't include the deployer account + delete(allocs.Accounts, deployer) + return nil +} diff --git a/op-chain-ops/interopgen/deployers/preinstalls.go b/op-chain-ops/interopgen/deployers/preinstalls.go new file mode 100644 index 0000000000000..8a4dca1af26d8 --- /dev/null +++ b/op-chain-ops/interopgen/deployers/preinstalls.go @@ -0,0 +1,24 @@ +package deployers + +import ( + "fmt" + + "github.com/ethereum-optimism/optimism/op-chain-ops/script" +) + +type PreinstallsScript struct { + SetPreinstalls func() error +} + +func InsertPreinstalls(host *script.Host) error { + l2GenesisScript, cleanupL2Genesis, err := script.WithScript[PreinstallsScript](host, "SetPreinstalls.s.sol", "SetPreinstalls") + if err != nil { + return fmt.Errorf("failed to load SetPreinstalls script: %w", err) + } + defer cleanupL2Genesis() + + if err := l2GenesisScript.SetPreinstalls(); err != nil { + return fmt.Errorf("failed to set preinstalls: %w", err) + } + return nil +} diff --git a/op-chain-ops/interopgen/deployments.go b/op-chain-ops/interopgen/deployments.go new file mode 100644 index 0000000000000..ba18fbfdf9bde --- /dev/null +++ b/op-chain-ops/interopgen/deployments.go @@ -0,0 +1,68 @@ +package interopgen + +import ( + "github.com/ethereum/go-ethereum/common" +) + +type L1Deployment struct { + // No global deployed contracts that aren't part of the superchain, yet. +} + +type Implementations struct { + OpcmProxy common.Address `json:"OPCMProxy"` + OpcmImpl common.Address `json:"OPCMImpl"` + DelayedWETHImpl common.Address `json:"DelayedWETHImpl"` + OptimismPortalImpl common.Address `json:"OptimismPortalImpl"` + PreimageOracleSingleton common.Address `json:"PreimageOracleSingleton"` + MipsSingleton common.Address `json:"MipsSingleton"` + SystemConfigImpl common.Address `json:"SystemConfigImpl"` + L1CrossDomainMessengerImpl common.Address `json:"L1CrossDomainMessengerImpl"` + L1ERC721BridgeImpl common.Address `json:"L1ERC721BridgeImpl"` + L1StandardBridgeImpl common.Address `json:"L1StandardBridgeImpl"` + OptimismMintableERC20FactoryImpl common.Address `json:"OptimismMintableERC20FactoryImpl"` + DisputeGameFactoryImpl common.Address `json:"DisputeGameFactoryImpl"` +} + +type SuperchainDeployment struct { + Implementations + + ProxyAdmin common.Address `json:"ProxyAdmin"` + + ProtocolVersions common.Address `json:"ProtocolVersions"` + ProtocolVersionsProxy common.Address `json:"ProtocolVersionsProxy"` + + SuperchainConfig common.Address `json:"SuperchainConfig"` + SuperchainConfigProxy common.Address `json:"SuperchainConfigProxy"` +} + +type L2OpchainDeployment struct { + OpChainProxyAdmin common.Address `json:"OpChainProxyAdmin"` + AddressManager common.Address `json:"AddressManager"` + L1ERC721BridgeProxy common.Address `json:"L1ERC721BridgeProxy"` + SystemConfigProxy common.Address `json:"SystemConfigProxy"` + OptimismMintableERC20FactoryProxy common.Address `json:"OptimismMintableERC20FactoryProxy"` + L1StandardBridgeProxy common.Address `json:"L1StandardBridgeProxy"` + L1CrossDomainMessengerProxy common.Address `json:"L1CrossDomainMessengerProxy"` + // Fault proof contracts below. + OptimismPortalProxy common.Address `json:"OptimismPortalProxy"` + DisputeGameFactoryProxy common.Address `json:"DisputeGameFactoryProxy"` + AnchorStateRegistryProxy common.Address `json:"AnchorStateRegistryProxy"` + AnchorStateRegistryImpl common.Address `json:"AnchorStateRegistryImpl"` + FaultDisputeGame common.Address `json:"FaultDisputeGame"` + PermissionedDisputeGame common.Address `json:"PermissionedDisputeGame"` + DelayedWETHPermissionedGameProxy common.Address `json:"DelayedWETHPermissionedGameProxy"` + DelayedWETHPermissionlessGameProxy common.Address `json:"DelayedWETHPermissionlessGameProxy"` +} + +type L2Deployment struct { + L2OpchainDeployment + + // In the future this may contain optional extras, + // e.g. a Safe that will own the L2 chain contracts +} + +type WorldDeployment struct { + L1 *L1Deployment `json:"L1"` + Superchain *SuperchainDeployment `json:"Superchain"` + L2s map[string]*L2Deployment `json:"L2s"` +} diff --git a/op-chain-ops/interopgen/outputs.go b/op-chain-ops/interopgen/outputs.go new file mode 100644 index 0000000000000..c0543ab06293e --- /dev/null +++ b/op-chain-ops/interopgen/outputs.go @@ -0,0 +1,21 @@ +package interopgen + +import ( + "github.com/ethereum/go-ethereum/core" + + "github.com/ethereum-optimism/optimism/op-node/rollup" +) + +type L1Output struct { + Genesis *core.Genesis +} + +type L2Output struct { + Genesis *core.Genesis + RollupCfg *rollup.Config +} + +type WorldOutput struct { + L1 *L1Output + L2s map[string]*L2Output +} diff --git a/op-chain-ops/interopgen/recipe.go b/op-chain-ops/interopgen/recipe.go new file mode 100644 index 0000000000000..eea42b87e0a47 --- /dev/null +++ b/op-chain-ops/interopgen/recipe.go @@ -0,0 +1,275 @@ +package interopgen + +import ( + "fmt" + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/params" + + "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/opcm" + "github.com/ethereum-optimism/optimism/op-chain-ops/devkeys" + "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" +) + +type InteropDevRecipe struct { + L1ChainID uint64 + L2ChainIDs []uint64 + GenesisTimestamp uint64 +} + +func (r *InteropDevRecipe) Build(addrs devkeys.Addresses) (*WorldConfig, error) { + // L1 genesis + l1Cfg := &L1Config{ + ChainID: new(big.Int).SetUint64(r.L1ChainID), + DevL1DeployConfig: genesis.DevL1DeployConfig{ + L1BlockTime: 6, + L1GenesisBlockTimestamp: hexutil.Uint64(r.GenesisTimestamp), + L1GenesisBlockGasLimit: 30_000_000, + }, + Prefund: make(map[common.Address]*big.Int), + } + + // TODO(#11887): consider making the number of prefunded keys configurable. + l1Users := devkeys.ChainUserKeys(l1Cfg.ChainID) + for i := uint64(0); i < 20; i++ { + userAddr, err := addrs.Address(l1Users(i)) + if err != nil { + return nil, fmt.Errorf("failed to get L1 user addr %d: %w", i, err) + } + l1Cfg.Prefund[userAddr] = Ether(10_000_000) + } + + superchainOps := devkeys.SuperchainOperatorKeys(l1Cfg.ChainID) + + superchainDeployer, err := addrs.Address(superchainOps(devkeys.SuperchainDeployerKey)) + if err != nil { + return nil, err + } + superchainProxyAdmin, err := addrs.Address(superchainOps(devkeys.SuperchainProxyAdminOwner)) + if err != nil { + return nil, err + } + superchainProtocolVersionsOwner, err := addrs.Address(superchainOps(devkeys.SuperchainProtocolVersionsOwner)) + if err != nil { + return nil, err + } + superchainConfigGuardian, err := addrs.Address(superchainOps(devkeys.SuperchainConfigGuardianKey)) + if err != nil { + return nil, err + } + l1Cfg.Prefund[superchainDeployer] = Ether(10_000_000) + l1Cfg.Prefund[superchainProxyAdmin] = Ether(10_000_000) + l1Cfg.Prefund[superchainConfigGuardian] = Ether(10_000_000) + + superchainCfg := &SuperchainConfig{ + ProxyAdminOwner: superchainProxyAdmin, + ProtocolVersionsOwner: superchainProtocolVersionsOwner, + Deployer: superchainDeployer, + Implementations: OPCMImplementationsConfig{ + Release: "dev", + FaultProof: SuperFaultProofConfig{ + WithdrawalDelaySeconds: big.NewInt(604800), + MinProposalSizeBytes: big.NewInt(10000), + ChallengePeriodSeconds: big.NewInt(120), + ProofMaturityDelaySeconds: big.NewInt(12), + DisputeGameFinalityDelaySeconds: big.NewInt(6), + }, + UseInterop: true, + StandardVersionsToml: opcm.StandardVersionsData, + }, + SuperchainL1DeployConfig: genesis.SuperchainL1DeployConfig{ + RequiredProtocolVersion: params.OPStackSupport, + RecommendedProtocolVersion: params.OPStackSupport, + SuperchainConfigGuardian: superchainConfigGuardian, + }, + } + world := &WorldConfig{ + L1: l1Cfg, + Superchain: superchainCfg, + L2s: make(map[string]*L2Config), + } + for _, l2ChainID := range r.L2ChainIDs { + l2Cfg, err := InteropL2DevConfig(r.L1ChainID, l2ChainID, addrs) + if err != nil { + return nil, fmt.Errorf("failed to generate L2 config for chain %d: %w", l2ChainID, err) + } + if err := prefundL2Accounts(l1Cfg, l2Cfg, addrs); err != nil { + return nil, fmt.Errorf("failed to prefund addresses on L1 for L2 chain %d: %w", l2ChainID, err) + } + world.L2s[fmt.Sprintf("%d", l2ChainID)] = l2Cfg + } + return world, nil +} + +func prefundL2Accounts(l1Cfg *L1Config, l2Cfg *L2Config, addrs devkeys.Addresses) error { + l1Cfg.Prefund[l2Cfg.BatchSenderAddress] = Ether(10_000_000) + l1Cfg.Prefund[l2Cfg.Deployer] = Ether(10_000_000) + l1Cfg.Prefund[l2Cfg.FinalSystemOwner] = Ether(10_000_000) + proposer, err := addrs.Address(devkeys.ChainOperatorKey{ + ChainID: new(big.Int).SetUint64(l2Cfg.L2ChainID), + Role: devkeys.ProposerRole, + }) + if err != nil { + return err + } + l1Cfg.Prefund[proposer] = Ether(10_000_000) + challenger, err := addrs.Address(devkeys.ChainOperatorKey{ + ChainID: new(big.Int).SetUint64(l2Cfg.L2ChainID), + Role: devkeys.ChallengerRole, + }) + if err != nil { + return err + } + l1Cfg.Prefund[challenger] = Ether(10_000_000) + return nil +} + +func InteropL2DevConfig(l1ChainID, l2ChainID uint64, addrs devkeys.Addresses) (*L2Config, error) { + // Padded chain ID, hex encoded, prefixed with 0xff like inboxes, then 0x02 to signify devnet. + batchInboxAddress := common.HexToAddress(fmt.Sprintf("0xff02%016x", l2ChainID)) + chainOps := devkeys.ChainOperatorKeys(new(big.Int).SetUint64(l2ChainID)) + + deployer, err := addrs.Address(chainOps(devkeys.DeployerRole)) + if err != nil { + return nil, err + } + l1ProxyAdminOwner, err := addrs.Address(chainOps(devkeys.L1ProxyAdminOwnerRole)) + if err != nil { + return nil, err + } + l2ProxyAdminOwner, err := addrs.Address(chainOps(devkeys.L2ProxyAdminOwnerRole)) + if err != nil { + return nil, err + } + baseFeeVaultRecipient, err := addrs.Address(chainOps(devkeys.BaseFeeVaultRecipientRole)) + if err != nil { + return nil, err + } + l1FeeVaultRecipient, err := addrs.Address(chainOps(devkeys.L1FeeVaultRecipientRole)) + if err != nil { + return nil, err + } + sequencerFeeVaultRecipient, err := addrs.Address(chainOps(devkeys.SequencerFeeVaultRecipientRole)) + if err != nil { + return nil, err + } + sequencerP2P, err := addrs.Address(chainOps(devkeys.SequencerP2PRole)) + if err != nil { + return nil, err + } + batcher, err := addrs.Address(chainOps(devkeys.BatcherRole)) + if err != nil { + return nil, err + } + proposer, err := addrs.Address(chainOps(devkeys.ProposerRole)) + if err != nil { + return nil, err + } + challenger, err := addrs.Address(chainOps(devkeys.ChallengerRole)) + if err != nil { + return nil, err + } + systemConfigOwner, err := addrs.Address(chainOps(devkeys.SystemConfigOwner)) + if err != nil { + return nil, err + } + + l2Cfg := &L2Config{ + Deployer: deployer, + Proposer: proposer, + Challenger: challenger, + SystemConfigOwner: systemConfigOwner, + L2InitializationConfig: genesis.L2InitializationConfig{ + DevDeployConfig: genesis.DevDeployConfig{ + FundDevAccounts: true, + }, + L2GenesisBlockDeployConfig: genesis.L2GenesisBlockDeployConfig{ + L2GenesisBlockGasLimit: 30_000_000, + L2GenesisBlockBaseFeePerGas: (*hexutil.Big)(big.NewInt(params.InitialBaseFee)), + }, + OwnershipDeployConfig: genesis.OwnershipDeployConfig{ + ProxyAdminOwner: l2ProxyAdminOwner, + FinalSystemOwner: l1ProxyAdminOwner, + }, + L2VaultsDeployConfig: genesis.L2VaultsDeployConfig{ + BaseFeeVaultRecipient: baseFeeVaultRecipient, + L1FeeVaultRecipient: l1FeeVaultRecipient, + SequencerFeeVaultRecipient: sequencerFeeVaultRecipient, + BaseFeeVaultMinimumWithdrawalAmount: (*hexutil.Big)(Ether(10)), + L1FeeVaultMinimumWithdrawalAmount: (*hexutil.Big)(Ether(10)), + SequencerFeeVaultMinimumWithdrawalAmount: (*hexutil.Big)(Ether(10)), + BaseFeeVaultWithdrawalNetwork: "remote", + L1FeeVaultWithdrawalNetwork: "remote", + SequencerFeeVaultWithdrawalNetwork: "remote", + }, + GovernanceDeployConfig: genesis.GovernanceDeployConfig{ + EnableGovernance: false, + }, + GasPriceOracleDeployConfig: genesis.GasPriceOracleDeployConfig{ + GasPriceOracleBaseFeeScalar: 1368, + GasPriceOracleBlobBaseFeeScalar: 810949, + }, + GasTokenDeployConfig: genesis.GasTokenDeployConfig{ + UseCustomGasToken: false, + }, + OperatorDeployConfig: genesis.OperatorDeployConfig{ + P2PSequencerAddress: sequencerP2P, + BatchSenderAddress: batcher, + }, + EIP1559DeployConfig: genesis.EIP1559DeployConfig{ + EIP1559Elasticity: 6, + EIP1559Denominator: 50, + EIP1559DenominatorCanyon: 250, + }, + UpgradeScheduleDeployConfig: genesis.UpgradeScheduleDeployConfig{ + L2GenesisRegolithTimeOffset: new(hexutil.Uint64), + L2GenesisCanyonTimeOffset: new(hexutil.Uint64), + L2GenesisDeltaTimeOffset: new(hexutil.Uint64), + L2GenesisEcotoneTimeOffset: new(hexutil.Uint64), + L2GenesisFjordTimeOffset: new(hexutil.Uint64), + L2GenesisGraniteTimeOffset: new(hexutil.Uint64), + L2GenesisInteropTimeOffset: new(hexutil.Uint64), + L1CancunTimeOffset: new(hexutil.Uint64), + UseInterop: true, + }, + L2CoreDeployConfig: genesis.L2CoreDeployConfig{ + L1ChainID: l1ChainID, + L2ChainID: l2ChainID, + L2BlockTime: 2, + FinalizationPeriodSeconds: 2, // instant output finalization + MaxSequencerDrift: 300, + SequencerWindowSize: 200, + ChannelTimeoutBedrock: 120, + BatchInboxAddress: batchInboxAddress, + SystemConfigStartBlock: 0, + }, + AltDADeployConfig: genesis.AltDADeployConfig{ + UseAltDA: false, + }, + }, + Prefund: make(map[common.Address]*big.Int), + } + + // TODO(#11887): consider making the number of prefunded keys configurable. + l2Users := devkeys.ChainUserKeys(new(big.Int).SetUint64(l2ChainID)) + for i := uint64(0); i < 20; i++ { + userAddr, err := addrs.Address(l2Users(i)) + if err != nil { + return nil, fmt.Errorf("failed to get L2 user addr %d: %w", i, err) + } + l2Cfg.Prefund[userAddr] = Ether(10_000_000) + } + + l2Cfg.Prefund[l2ProxyAdminOwner] = Ether(10_000_000) + + return l2Cfg, nil +} + +var etherScalar = new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil) + +// Ether converts a uint64 Ether amount into a *big.Int amount in wei units, for allocating test balances. +func Ether(v uint64) *big.Int { + return new(big.Int).Mul(new(big.Int).SetUint64(v), etherScalar) +} diff --git a/op-chain-ops/script/cheatcodes_environment.go b/op-chain-ops/script/cheatcodes_environment.go index 2299a3e1a05be..92baa429010eb 100644 --- a/op-chain-ops/script/cheatcodes_environment.go +++ b/op-chain-ops/script/cheatcodes_environment.go @@ -183,31 +183,26 @@ func (c *CheatCodesPrecompile) Coinbase(addr common.Address) { // Broadcast_afc98040 implements https://book.getfoundry.sh/cheatcodes/broadcast func (c *CheatCodesPrecompile) Broadcast_afc98040() error { - c.h.log.Info("broadcasting next call") return c.h.Prank(nil, nil, false, true) } // Broadcast_e6962cdb implements https://book.getfoundry.sh/cheatcodes/broadcast func (c *CheatCodesPrecompile) Broadcast_e6962cdb(who common.Address) error { - c.h.log.Info("broadcasting next call", "who", who) return c.h.Prank(&who, nil, false, true) } // StartBroadcast_7fb5297f implements https://book.getfoundry.sh/cheatcodes/start-broadcast func (c *CheatCodesPrecompile) StartBroadcast_7fb5297f() error { - c.h.log.Info("starting repeat-broadcast") return c.h.Prank(nil, nil, true, true) } // StartBroadcast_7fec2a8d implements https://book.getfoundry.sh/cheatcodes/start-broadcast func (c *CheatCodesPrecompile) StartBroadcast_7fec2a8d(who common.Address) error { - c.h.log.Info("starting repeat-broadcast", "who", who) return c.h.Prank(&who, nil, true, true) } // StopBroadcast implements https://book.getfoundry.sh/cheatcodes/stop-broadcast func (c *CheatCodesPrecompile) StopBroadcast() error { - c.h.log.Info("stopping repeat-broadcast") return c.h.StopPrank(true) } diff --git a/op-chain-ops/script/cheatcodes_utilities.go b/op-chain-ops/script/cheatcodes_utilities.go index 2ae53a52e9109..022befa606275 100644 --- a/op-chain-ops/script/cheatcodes_utilities.go +++ b/op-chain-ops/script/cheatcodes_utilities.go @@ -3,9 +3,12 @@ package script import ( "fmt" "math/big" + "regexp" "strconv" "strings" + "github.com/BurntSushi/toml" + hdwallet "github.com/ethereum-optimism/go-ethereum-hdwallet" "github.com/ethereum/go-ethereum/accounts" @@ -188,5 +191,77 @@ func (c *CheatCodesPrecompile) Breakpoint_f7d39a8d(name string, v bool) { } } +// ParseTomlAddress_65e7c844 implements https://book.getfoundry.sh/cheatcodes/parse-toml. This +// method is not well optimized or implemented. It's optimized for quickly delivering OPCM. We +// can come back and clean it up more later. +func (c *CheatCodesPrecompile) ParseTomlAddress_65e7c844(tomlStr string, key string) (common.Address, error) { + var data map[string]any + if err := toml.Unmarshal([]byte(tomlStr), &data); err != nil { + return common.Address{}, fmt.Errorf("failed to parse TOML: %w", err) + } + + keys, err := SplitJSONPathKeys(key) + if err != nil { + return common.Address{}, fmt.Errorf("failed to split keys: %w", err) + } + + loc := data + for i, k := range keys { + value, ok := loc[k] + if !ok { + return common.Address{}, fmt.Errorf("key %q not found in TOML", k) + } + + if i == len(keys)-1 { + addrStr, ok := value.(string) + if !ok { + return common.Address{}, fmt.Errorf("key %q is not a string", key) + } + if !common.IsHexAddress(addrStr) { + return common.Address{}, fmt.Errorf("key %q is not a valid address", key) + } + return common.HexToAddress(addrStr), nil + } + + next, ok := value.(map[string]any) + if !ok { + return common.Address{}, fmt.Errorf("key %q is not a nested map", key) + } + loc = next + } + + panic("should never get here") +} + // unsupported //func (c *CheatCodesPrecompile) CreateWallet() {} + +// SplitJSONPathKeys splits a JSON path into keys. It supports bracket notation. There is a much +// better way to implement this, but I'm keeping this simple for now. +func SplitJSONPathKeys(path string) ([]string, error) { + var out []string + bracketSplit := regexp.MustCompile(`[\[\]]`).Split(path, -1) + for _, split := range bracketSplit { + if len(split) == 0 { + continue + } + + split = strings.ReplaceAll(split, "\"", "") + split = strings.ReplaceAll(split, " ", "") + + if !strings.HasPrefix(split, ".") { + out = append(out, split) + continue + } + + keys := strings.Split(split, ".") + for _, key := range keys { + if len(key) == 0 { + continue + } + out = append(out, key) + } + } + + return out, nil +} diff --git a/op-chain-ops/script/cheatcodes_utilities_test.go b/op-chain-ops/script/cheatcodes_utilities_test.go new file mode 100644 index 0000000000000..23936a10e344e --- /dev/null +++ b/op-chain-ops/script/cheatcodes_utilities_test.go @@ -0,0 +1,59 @@ +package script + +import ( + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" +) + +const tomlTest = ` +foo = "0x0d4CE7B6a91A35c31D7D62b327D19617c8da6F23" + +[foomap] +[foomap."bar.bump"] +baz = "0xff4ce7b6a91a35c31d7d62b327d19617c8da6f23" +` + +func TestSplitJSONPathKeys(t *testing.T) { + tests := []struct { + name string + path string + expected []string + }{ + { + "simple", + ".foo.bar", + []string{"foo", "bar"}, + }, + { + "bracket keys", + ".foo[\"hey\"].bar", + []string{"foo", "hey", "bar"}, + }, + { + "bracket keys with dots", + ".foo[\"hey.there\"].bar", + []string{"foo", "hey.there", "bar"}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := SplitJSONPathKeys(tt.path) + require.NoError(t, err) + require.Equal(t, tt.expected, got) + }) + } +} + +func TestParseTomlAddress(t *testing.T) { + c := &CheatCodesPrecompile{} + + addr, err := c.ParseTomlAddress_65e7c844(tomlTest, "foo") + require.NoError(t, err) + require.Equal(t, common.HexToAddress("0x0d4ce7b6a91a35c31d7d62b327d19617c8da6f23"), addr) + + addr, err = c.ParseTomlAddress_65e7c844(tomlTest, "foomap[\"bar.bump\"].baz") + require.NoError(t, err) + require.Equal(t, common.HexToAddress("0xff4ce7b6a91a35c31d7d62b327d19617c8da6f23"), addr) +} diff --git a/op-chain-ops/script/console.go b/op-chain-ops/script/console.go index c9283b464ba54..b3bba1ed0ff20 100644 --- a/op-chain-ops/script/console.go +++ b/op-chain-ops/script/console.go @@ -1,20 +1,247 @@ package script import ( + "bytes" + "fmt" + "math/big" + "reflect" + "strconv" + "strings" + "text/scanner" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/log" ) +//go:generate go run ./consolegen --abi-txt=console2.txt --out=console2_gen.go + type ConsolePrecompile struct { logger log.Logger sender func() common.Address } -func (c *ConsolePrecompile) log(ctx ...any) { +func (c *ConsolePrecompile) log(args ...any) { sender := c.sender() + logger := c.logger.With("sender", sender) + if len(args) == 0 { + logger.Info("") + return + } + if msg, ok := args[0].(string); ok { // if starting with a string, use it as message. And format with args if needed. + logger.Info(consoleFormat(msg, args[1:]...)) + return + } else { + logger.Info(consoleFormat("", args...)) + } +} - // Log the sender, since the self-address is always equal to the ConsoleAddr - c.logger.With("sender", sender).Info("console", ctx...) +type stringFormat struct{} +type numberFormat struct{} +type objectFormat struct{} +type integerFormat struct{} +type exponentialFormat struct { + precision int } +type hexadecimalFormat struct{} -//go:generate go run ./consolegen --abi-txt=console2.txt --out=console2_gen.go +func formatBigInt(x *big.Int, precision int) string { + if precision < 0 { + precision = len(new(big.Int).Abs(x).String()) - 1 + return formatBigIntFixedPrecision(x, uint(precision)) + fmt.Sprintf("e%d", precision) + } + return formatBigIntFixedPrecision(x, uint(precision)) +} + +func formatBigIntFixedPrecision(x *big.Int, precision uint) string { + prec := new(big.Int).Exp(big.NewInt(10), big.NewInt(int64(precision)), nil) + integer, remainder := new(big.Int).QuoRem(x, prec, new(big.Int)) + if remainder.Sign() != 0 { + decimal := fmt.Sprintf("%0"+fmt.Sprintf("%d", precision)+"d", + new(big.Int).Abs(remainder)) + decimal = strings.TrimRight(decimal, "0") + return fmt.Sprintf("%d.%s", integer, decimal) + } else { + return fmt.Sprintf("%d", integer) + } +} + +// formatValue formats a value v following the given format-spec. +func formatValue(v any, spec any) string { + switch x := v.(type) { + case string: + switch spec.(type) { + case stringFormat: + return x + case objectFormat: + return fmt.Sprintf("'%s'", v) + default: + return "NaN" + } + case bool: + switch spec.(type) { + case stringFormat: + return fmt.Sprintf("%v", x) + case objectFormat: + return fmt.Sprintf("'%v'", x) + case numberFormat: + if x { + return "1" + } + return "0" + default: + return "NaN" + } + case *big.Int: + switch s := spec.(type) { + case stringFormat, objectFormat, numberFormat, integerFormat: + return fmt.Sprintf("%d", x) + case exponentialFormat: + return formatBigInt(x, s.precision) + case hexadecimalFormat: + return (*hexutil.Big)(x).String() + default: + return fmt.Sprintf("%d", x) + } + case *ABIInt256: + switch s := spec.(type) { + case stringFormat, objectFormat, numberFormat, integerFormat: + return fmt.Sprintf("%d", (*big.Int)(x)) + case exponentialFormat: + return formatBigInt((*big.Int)(x), s.precision) + case hexadecimalFormat: + return (*hexutil.Big)(x).String() + default: + return fmt.Sprintf("%d", (*big.Int)(x)) + } + case common.Address: + switch spec.(type) { + case stringFormat, hexadecimalFormat: + return x.String() + case objectFormat: + return fmt.Sprintf("'%s'", x) + default: + return "NaN" + } + default: + if typ := reflect.TypeOf(v); (typ.Kind() == reflect.Array || typ.Kind() == reflect.Slice) && + typ.Elem().Kind() == reflect.Uint8 { + switch spec.(type) { + case stringFormat, hexadecimalFormat: + return fmt.Sprintf("0x%x", v) + case objectFormat: + return fmt.Sprintf("'0x%x'", v) + default: + return "NaN" + } + } + return fmt.Sprintf("%v", v) + } +} + +// consoleFormat emulates the foundry-flavor of printf, to format console.log data. +func consoleFormat(fmtMsg string, values ...any) string { + var sc scanner.Scanner + sc.Init(bytes.NewReader([]byte(fmtMsg))) + // default scanner settings are for Go source code parsing. Reset all of that. + sc.Whitespace = 0 + sc.Mode = 0 + sc.IsIdentRune = func(ch rune, i int) bool { + return false + } + + nextValue := func() (v any, ok bool) { + if len(values) > 0 { + v = values[0] + values = values[1:] + return v, true + } + return nil, false + } + + // Parses a format-spec from a string sequence (excl. the % prefix) + // Returns the spec (if any), and the consumed characters (to abort with / fall back to) + formatSpecFromChars := func() (spec any, consumed string) { + fmtChar := sc.Scan() + switch fmtChar { + case 's': + return stringFormat{}, "s" + case 'd': + return numberFormat{}, "d" + case 'i': + return integerFormat{}, "i" + case 'o': + return objectFormat{}, "o" + case 'e': + return exponentialFormat{precision: -1}, "e" + case 'x': + return hexadecimalFormat{}, "x" + case scanner.EOF: + return nil, "" + default: + for ; fmtChar != scanner.EOF; fmtChar = sc.Scan() { + if fmtChar == 'e' { + precision, err := strconv.ParseUint(consumed, 10, 16) + consumed += "e" + if err != nil { + return nil, consumed + } + return exponentialFormat{precision: int(precision)}, consumed + } + consumed += string(fmtChar) + if !strings.ContainsRune("0123456789", fmtChar) { + return nil, consumed + } + } + return nil, consumed + } + } + + expectFmt := false + var out strings.Builder + for sc.Peek() != scanner.EOF { + if expectFmt { + expectFmt = false + spec, consumed := formatSpecFromChars() + if spec != nil { + value, ok := nextValue() + if ok { + out.WriteString(formatValue(value, spec)) + } else { + // rather than panic with an .expect() like foundry, + // just log the original format string + out.WriteRune('%') + out.WriteString(consumed) + } + } else { + // on parser failure, write '%' and consumed characters + out.WriteRune('%') + out.WriteString(consumed) + } + } else { + tok := sc.Scan() + if tok == '%' { + next := sc.Peek() + switch next { + case '%': // %% formats as "%" + out.WriteRune('%') + case scanner.EOF: + out.WriteRune(tok) + default: + expectFmt = true + } + } else { + out.WriteRune(tok) + } + } + } + + // for all remaining values, append them to the output + for _, v := range values { + if out.Len() > 0 { + out.WriteRune(' ') + } + out.WriteString(formatValue(v, stringFormat{})) + } + return out.String() +} diff --git a/op-chain-ops/script/console2_gen.go b/op-chain-ops/script/console2_gen.go index 9430a9441ccec..0c6dcc44f462b 100644 --- a/op-chain-ops/script/console2_gen.go +++ b/op-chain-ops/script/console2_gen.go @@ -13,1502 +13,1501 @@ func (c *ConsolePrecompile) Log_51973ec9() { } func (c *ConsolePrecompile) Log_665bf134(p0 common.Address, p1 common.Address, p2 common.Address, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_0e378994(p0 common.Address, p1 common.Address, p2 common.Address, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_018c84c2(p0 common.Address, p1 common.Address, p2 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_f808da20(p0 common.Address, p1 common.Address, p2 common.Address, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_94250d77(p0 common.Address, p1 common.Address, p2 common.Address, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_9f1bc36e(p0 common.Address, p1 common.Address, p2 bool, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_2cd4134a(p0 common.Address, p1 common.Address, p2 bool, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_f2a66286(p0 common.Address, p1 common.Address, p2 bool) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_aa6540c8(p0 common.Address, p1 common.Address, p2 bool, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_3971e78c(p0 common.Address, p1 common.Address, p2 bool, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_daf0d4aa(p0 common.Address, p1 common.Address) { - c.log("p0", p0, "p1", p1) + c.log(p0, p1) } func (c *ConsolePrecompile) Log_8f736d16(p0 common.Address, p1 common.Address, p2 string, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_6f1a594e(p0 common.Address, p1 common.Address, p2 string, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_007150be(p0 common.Address, p1 common.Address, p2 string) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_21bdaf25(p0 common.Address, p1 common.Address, p2 string, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_ef1cefe7(p0 common.Address, p1 common.Address, p2 string, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_8da6def5(p0 common.Address, p1 common.Address, p2 *big.Int, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_9b4254e2(p0 common.Address, p1 common.Address, p2 *big.Int, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_17fe6185(p0 common.Address, p1 common.Address, p2 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_fdb4f990(p0 common.Address, p1 common.Address, p2 *big.Int, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_be553481(p0 common.Address, p1 common.Address, p2 *big.Int, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_660375dd(p0 common.Address, p1 bool, p2 common.Address, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_a6f50b0f(p0 common.Address, p1 bool, p2 common.Address, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_f11699ed(p0 common.Address, p1 bool, p2 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_2dd778e6(p0 common.Address, p1 bool, p2 common.Address, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_a75c59de(p0 common.Address, p1 bool, p2 common.Address, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_cf394485(p0 common.Address, p1 bool, p2 bool, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_cac43479(p0 common.Address, p1 bool, p2 bool, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_eb830c92(p0 common.Address, p1 bool, p2 bool) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_dfc4a2e8(p0 common.Address, p1 bool, p2 bool, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_8c4e5de6(p0 common.Address, p1 bool, p2 bool, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_75b605d3(p0 common.Address, p1 bool) { - c.log("p0", p0, "p1", p1) + c.log(p0, p1) } func (c *ConsolePrecompile) Log_19fd4956(p0 common.Address, p1 bool, p2 string, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_50ad461d(p0 common.Address, p1 bool, p2 string, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_212255cc(p0 common.Address, p1 bool, p2 string) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_475c5c33(p0 common.Address, p1 bool, p2 string, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_80e6a20b(p0 common.Address, p1 bool, p2 string, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_ccf790a1(p0 common.Address, p1 bool, p2 *big.Int, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_c4643e20(p0 common.Address, p1 bool, p2 *big.Int, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_9c4f99fb(p0 common.Address, p1 bool, p2 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_0aa6cfad(p0 common.Address, p1 bool, p2 *big.Int, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_386ff5f4(p0 common.Address, p1 bool, p2 *big.Int, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_2c2ecbc2(p0 common.Address) { - c.log("p0", p0) + c.log(p0) } func (c *ConsolePrecompile) Log_0d36fa20(p0 common.Address, p1 string, p2 common.Address, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_0df12b76(p0 common.Address, p1 string, p2 common.Address, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_f08744e8(p0 common.Address, p1 string, p2 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_f7e36245(p0 common.Address, p1 string, p2 common.Address, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_457fe3cf(p0 common.Address, p1 string, p2 common.Address, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_205871c2(p0 common.Address, p1 string, p2 bool, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_5f1d5c9f(p0 common.Address, p1 string, p2 bool, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_cf020fb1(p0 common.Address, p1 string, p2 bool) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_bc0b61fe(p0 common.Address, p1 string, p2 bool, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_515e38b6(p0 common.Address, p1 string, p2 bool, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_759f86bb(p0 common.Address, p1 string) { - c.log("p0", p0, "p1", p1) + c.log(p0, p1) } func (c *ConsolePrecompile) Log_a04e2f87(p0 common.Address, p1 string, p2 string, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_35a5071f(p0 common.Address, p1 string, p2 string, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_fb772265(p0 common.Address, p1 string, p2 string) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_5d02c50b(p0 common.Address, p1 string, p2 string, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_159f8927(p0 common.Address, p1 string, p2 string, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_63183678(p0 common.Address, p1 string, p2 *big.Int, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_0ef7e050(p0 common.Address, p1 string, p2 *big.Int, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_67dd6ff1(p0 common.Address, p1 string, p2 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_448830a8(p0 common.Address, p1 string, p2 *big.Int, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_1dc8e1b8(p0 common.Address, p1 string, p2 *big.Int, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_478d1c62(p0 common.Address, p1 *big.Int, p2 common.Address, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_a1bcc9b3(p0 common.Address, p1 *big.Int, p2 common.Address, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_7bc0d848(p0 common.Address, p1 *big.Int, p2 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_1da986ea(p0 common.Address, p1 *big.Int, p2 common.Address, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_100f650e(p0 common.Address, p1 *big.Int, p2 common.Address, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_a31bfdcc(p0 common.Address, p1 *big.Int, p2 bool, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_3bf5e537(p0 common.Address, p1 *big.Int, p2 bool, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_678209a8(p0 common.Address, p1 *big.Int, p2 bool) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_c5ad85f9(p0 common.Address, p1 *big.Int, p2 bool, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_22f6b999(p0 common.Address, p1 *big.Int, p2 bool, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_8309e8a8(p0 common.Address, p1 *big.Int) { - c.log("p0", p0, "p1", p1) + c.log(p0, p1) } func (c *ConsolePrecompile) Log_5c430d47(p0 common.Address, p1 *big.Int, p2 string, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_cf18105c(p0 common.Address, p1 *big.Int, p2 string, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_a1f2e8aa(p0 common.Address, p1 *big.Int, p2 string) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_88a8c406(p0 common.Address, p1 *big.Int, p2 string, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_bf01f891(p0 common.Address, p1 *big.Int, p2 string, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_20e3984d(p0 common.Address, p1 *big.Int, p2 *big.Int, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_66f1bc67(p0 common.Address, p1 *big.Int, p2 *big.Int, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_b69bcaf6(p0 common.Address, p1 *big.Int, p2 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_4a28c017(p0 common.Address, p1 *big.Int, p2 *big.Int, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_34f0e636(p0 common.Address, p1 *big.Int, p2 *big.Int, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_1d14d001(p0 bool, p1 common.Address, p2 common.Address, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_46600be0(p0 bool, p1 common.Address, p2 common.Address, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_d2763667(p0 bool, p1 common.Address, p2 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_d812a167(p0 bool, p1 common.Address, p2 common.Address, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_0c66d1be(p0 bool, p1 common.Address, p2 common.Address, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_1c41a336(p0 bool, p1 common.Address, p2 bool, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_6a9c478b(p0 bool, p1 common.Address, p2 bool, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_18c9c746(p0 bool, p1 common.Address, p2 bool) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_4a66cb34(p0 bool, p1 common.Address, p2 bool, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_07831502(p0 bool, p1 common.Address, p2 bool, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_853c4849(p0 bool, p1 common.Address) { - c.log("p0", p0, "p1", p1) + c.log(p0, p1) } func (c *ConsolePrecompile) Log_6f7c603e(p0 bool, p1 common.Address, p2 string, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_e2bfd60b(p0 bool, p1 common.Address, p2 string, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_de9a9270(p0 bool, p1 common.Address, p2 string) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_a73c1db6(p0 bool, p1 common.Address, p2 string, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_c21f64c7(p0 bool, p1 common.Address, p2 string, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_136b05dd(p0 bool, p1 common.Address, p2 *big.Int, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_d6019f1c(p0 bool, p1 common.Address, p2 *big.Int, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_5f7b9afb(p0 bool, p1 common.Address, p2 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_51f09ff8(p0 bool, p1 common.Address, p2 *big.Int, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_7bf181a1(p0 bool, p1 common.Address, p2 *big.Int, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_f4880ea4(p0 bool, p1 bool, p2 common.Address, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_c0a302d8(p0 bool, p1 bool, p2 common.Address, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_1078f68d(p0 bool, p1 bool, p2 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_a0a47963(p0 bool, p1 bool, p2 common.Address, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_4c123d57(p0 bool, p1 bool, p2 common.Address, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_8c329b1a(p0 bool, p1 bool, p2 bool, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_3b2a5ce0(p0 bool, p1 bool, p2 bool, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_50709698(p0 bool, p1 bool, p2 bool) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_2ae408d4(p0 bool, p1 bool, p2 bool, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_6d7045c1(p0 bool, p1 bool, p2 bool, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_2a110e83(p0 bool, p1 bool) { - c.log("p0", p0, "p1", p1) + c.log(p0, p1) } func (c *ConsolePrecompile) Log_f9ad2b89(p0 bool, p1 bool, p2 string, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_b857163a(p0 bool, p1 bool, p2 string, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_2555fa46(p0 bool, p1 bool, p2 string) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_6d1e8751(p0 bool, p1 bool, p2 string, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_e3a9ca2f(p0 bool, p1 bool, p2 string, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_54a7a9a0(p0 bool, p1 bool, p2 *big.Int, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_619e4d0e(p0 bool, p1 bool, p2 *big.Int, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_12f21602(p0 bool, p1 bool, p2 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_7dd4d0e0(p0 bool, p1 bool, p2 *big.Int, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_0bb00eab(p0 bool, p1 bool, p2 *big.Int, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_32458eed(p0 bool) { - c.log("p0", p0) + c.log(p0) } func (c *ConsolePrecompile) Log_2b2b18dc(p0 bool, p1 string, p2 common.Address, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_6dd434ca(p0 bool, p1 string, p2 common.Address, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_9591b953(p0 bool, p1 string, p2 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_12d6c788(p0 bool, p1 string, p2 common.Address, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_a5cada94(p0 bool, p1 string, p2 common.Address, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_538e06ab(p0 bool, p1 string, p2 bool, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_dc5e935b(p0 bool, p1 string, p2 bool, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_dbb4c247(p0 bool, p1 string, p2 bool) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_483d0416(p0 bool, p1 string, p2 bool, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_1606a393(p0 bool, p1 string, p2 bool, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_8feac525(p0 bool, p1 string) { - c.log("p0", p0, "p1", p1) + c.log(p0, p1) } func (c *ConsolePrecompile) Log_97d394d8(p0 bool, p1 string, p2 string, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_1e4b87e5(p0 bool, p1 string, p2 string, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_b076847f(p0 bool, p1 string, p2 string) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_1762e32a(p0 bool, p1 string, p2 string, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_7be0c3eb(p0 bool, p1 string, p2 string, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_1596a1ce(p0 bool, p1 string, p2 *big.Int, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_6b0e5d53(p0 bool, p1 string, p2 *big.Int, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_1093ee11(p0 bool, p1 string, p2 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_1ad96de6(p0 bool, p1 string, p2 *big.Int, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_28863fcb(p0 bool, p1 string, p2 *big.Int, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_26f560a8(p0 bool, p1 *big.Int, p2 common.Address, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_b4c314ff(p0 bool, p1 *big.Int, p2 common.Address, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_088ef9d2(p0 bool, p1 *big.Int, p2 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_1bb3b09a(p0 bool, p1 *big.Int, p2 common.Address, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_1537dc87(p0 bool, p1 *big.Int, p2 common.Address, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_9acd3616(p0 bool, p1 *big.Int, p2 bool, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_ceb5f4d7(p0 bool, p1 *big.Int, p2 bool, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_e8defba9(p0 bool, p1 *big.Int, p2 bool) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_9143dbb1(p0 bool, p1 *big.Int, p2 bool, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_7f9bbca2(p0 bool, p1 *big.Int, p2 bool, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_399174d3(p0 bool, p1 *big.Int) { - c.log("p0", p0, "p1", p1) + c.log(p0, p1) } func (c *ConsolePrecompile) Log_fedd1fff(p0 bool, p1 *big.Int, p2 string, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_e5e70b2b(p0 bool, p1 *big.Int, p2 string, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_c3fc3970(p0 bool, p1 *big.Int, p2 string) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_f5bc2249(p0 bool, p1 *big.Int, p2 string, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_6a1199e2(p0 bool, p1 *big.Int, p2 string, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_00dd87b9(p0 bool, p1 *big.Int, p2 *big.Int, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_be984353(p0 bool, p1 *big.Int, p2 *big.Int, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_37103367(p0 bool, p1 *big.Int, p2 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_8e69fb5d(p0 bool, p1 *big.Int, p2 *big.Int, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_374bb4b2(p0 bool, p1 *big.Int, p2 *big.Int, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_013d178b(p0 [10]byte) { - c.log("p0", hexutil.Bytes(p0[:])) + c.log(hexutil.Bytes(p0[:])) } func (c *ConsolePrecompile) Log_04004a2e(p0 [11]byte) { - c.log("p0", hexutil.Bytes(p0[:])) + c.log(hexutil.Bytes(p0[:])) } func (c *ConsolePrecompile) Log_86a06abd(p0 [12]byte) { - c.log("p0", hexutil.Bytes(p0[:])) + c.log(hexutil.Bytes(p0[:])) } func (c *ConsolePrecompile) Log_94529e34(p0 [13]byte) { - c.log("p0", hexutil.Bytes(p0[:])) + c.log(hexutil.Bytes(p0[:])) } func (c *ConsolePrecompile) Log_9266f07f(p0 [14]byte) { - c.log("p0", hexutil.Bytes(p0[:])) + c.log(hexutil.Bytes(p0[:])) } func (c *ConsolePrecompile) Log_da9574e0(p0 [15]byte) { - c.log("p0", hexutil.Bytes(p0[:])) + c.log(hexutil.Bytes(p0[:])) } func (c *ConsolePrecompile) Log_665c6104(p0 [16]byte) { - c.log("p0", hexutil.Bytes(p0[:])) + c.log(hexutil.Bytes(p0[:])) } func (c *ConsolePrecompile) Log_339f673a(p0 [17]byte) { - c.log("p0", hexutil.Bytes(p0[:])) + c.log(hexutil.Bytes(p0[:])) } func (c *ConsolePrecompile) Log_c4d23d9a(p0 [18]byte) { - c.log("p0", hexutil.Bytes(p0[:])) + c.log(hexutil.Bytes(p0[:])) } func (c *ConsolePrecompile) Log_5e6b5a33(p0 [19]byte) { - c.log("p0", hexutil.Bytes(p0[:])) + c.log(hexutil.Bytes(p0[:])) } func (c *ConsolePrecompile) Log_6e18a128(p0 [1]byte) { - c.log("p0", hexutil.Bytes(p0[:])) + c.log(hexutil.Bytes(p0[:])) } func (c *ConsolePrecompile) Log_5188e3e9(p0 [20]byte) { - c.log("p0", hexutil.Bytes(p0[:])) + c.log(hexutil.Bytes(p0[:])) } func (c *ConsolePrecompile) Log_e9da3560(p0 [21]byte) { - c.log("p0", hexutil.Bytes(p0[:])) + c.log(hexutil.Bytes(p0[:])) } func (c *ConsolePrecompile) Log_d5fae89c(p0 [22]byte) { - c.log("p0", hexutil.Bytes(p0[:])) + c.log(hexutil.Bytes(p0[:])) } func (c *ConsolePrecompile) Log_aba1cf0d(p0 [23]byte) { - c.log("p0", hexutil.Bytes(p0[:])) + c.log(hexutil.Bytes(p0[:])) } func (c *ConsolePrecompile) Log_f1b35b34(p0 [24]byte) { - c.log("p0", hexutil.Bytes(p0[:])) + c.log(hexutil.Bytes(p0[:])) } func (c *ConsolePrecompile) Log_0b84bc58(p0 [25]byte) { - c.log("p0", hexutil.Bytes(p0[:])) + c.log(hexutil.Bytes(p0[:])) } func (c *ConsolePrecompile) Log_f8b149f1(p0 [26]byte) { - c.log("p0", hexutil.Bytes(p0[:])) + c.log(hexutil.Bytes(p0[:])) } func (c *ConsolePrecompile) Log_3a3757dd(p0 [27]byte) { - c.log("p0", hexutil.Bytes(p0[:])) + c.log(hexutil.Bytes(p0[:])) } func (c *ConsolePrecompile) Log_c82aeaee(p0 [28]byte) { - c.log("p0", hexutil.Bytes(p0[:])) + c.log(hexutil.Bytes(p0[:])) } func (c *ConsolePrecompile) Log_4b69c3d5(p0 [29]byte) { - c.log("p0", hexutil.Bytes(p0[:])) + c.log(hexutil.Bytes(p0[:])) } func (c *ConsolePrecompile) Log_e9b62296(p0 [2]byte) { - c.log("p0", hexutil.Bytes(p0[:])) + c.log(hexutil.Bytes(p0[:])) } func (c *ConsolePrecompile) Log_ee12c4ed(p0 [30]byte) { - c.log("p0", hexutil.Bytes(p0[:])) + c.log(hexutil.Bytes(p0[:])) } func (c *ConsolePrecompile) Log_c2854d92(p0 [31]byte) { - c.log("p0", hexutil.Bytes(p0[:])) + c.log(hexutil.Bytes(p0[:])) } func (c *ConsolePrecompile) Log_27b7cf85(p0 [32]byte) { - c.log("p0", hexutil.Bytes(p0[:])) + c.log(hexutil.Bytes(p0[:])) } func (c *ConsolePrecompile) Log_2d834926(p0 [3]byte) { - c.log("p0", hexutil.Bytes(p0[:])) + c.log(hexutil.Bytes(p0[:])) } func (c *ConsolePrecompile) Log_e05f48d1(p0 [4]byte) { - c.log("p0", hexutil.Bytes(p0[:])) + c.log(hexutil.Bytes(p0[:])) } func (c *ConsolePrecompile) Log_a684808d(p0 [5]byte) { - c.log("p0", hexutil.Bytes(p0[:])) + c.log(hexutil.Bytes(p0[:])) } func (c *ConsolePrecompile) Log_ae84a591(p0 [6]byte) { - c.log("p0", hexutil.Bytes(p0[:])) + c.log(hexutil.Bytes(p0[:])) } func (c *ConsolePrecompile) Log_4ed57e28(p0 [7]byte) { - c.log("p0", hexutil.Bytes(p0[:])) + c.log(hexutil.Bytes(p0[:])) } func (c *ConsolePrecompile) Log_4f84252e(p0 [8]byte) { - c.log("p0", hexutil.Bytes(p0[:])) + c.log(hexutil.Bytes(p0[:])) } func (c *ConsolePrecompile) Log_90bd8cd0(p0 [9]byte) { - c.log("p0", hexutil.Bytes(p0[:])) + c.log(hexutil.Bytes(p0[:])) } func (c *ConsolePrecompile) Log_0be77f56(p0 hexutil.Bytes) { - c.log("p0", p0) + c.log(p0) } func (c *ConsolePrecompile) Log_2d5b6cb9(p0 *ABIInt256) { - c.log("p0", (*big.Int)(p0)) + c.log((*big.Int)(p0)) } func (c *ConsolePrecompile) Log_ed8f28f6(p0 string, p1 common.Address, p2 common.Address, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_b59dbd60(p0 string, p1 common.Address, p2 common.Address, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_fcec75e0(p0 string, p1 common.Address, p2 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_800a1c67(p0 string, p1 common.Address, p2 common.Address, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_8ef3f399(p0 string, p1 common.Address, p2 common.Address, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_223603bd(p0 string, p1 common.Address, p2 bool, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_79884c2b(p0 string, p1 common.Address, p2 bool, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_c91d5ed4(p0 string, p1 common.Address, p2 bool) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_0454c079(p0 string, p1 common.Address, p2 bool, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_3e9f866a(p0 string, p1 common.Address, p2 bool, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_319af333(p0 string, p1 common.Address) { - c.log("p0", p0, "p1", p1) + c.log(p0, p1) } func (c *ConsolePrecompile) Log_aabc9a31(p0 string, p1 common.Address, p2 string, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_5f15d28c(p0 string, p1 common.Address, p2 string, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_e0e9ad4f(p0 string, p1 common.Address, p2 string) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_245986f2(p0 string, p1 common.Address, p2 string, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_91d1112e(p0 string, p1 common.Address, p2 string, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_63fb8bc5(p0 string, p1 common.Address, p2 *big.Int, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_fc4845f0(p0 string, p1 common.Address, p2 *big.Int, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_0d26b925(p0 string, p1 common.Address, p2 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_5a477632(p0 string, p1 common.Address, p2 *big.Int, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_f8f51b1e(p0 string, p1 common.Address, p2 *big.Int, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_33e9dd1d(p0 string, p1 bool, p2 common.Address, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_958c28c6(p0 string, p1 bool, p2 common.Address, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_932bbb38(p0 string, p1 bool, p2 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_2d8e33a4(p0 string, p1 bool, p2 common.Address, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_5d08bb05(p0 string, p1 bool, p2 common.Address, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_7190a529(p0 string, p1 bool, p2 bool, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_895af8c5(p0 string, p1 bool, p2 bool, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_850b7ad6(p0 string, p1 bool, p2 bool) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_9d22d5dd(p0 string, p1 bool, p2 bool, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_8e3f78a9(p0 string, p1 bool, p2 bool, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_c3b55635(p0 string, p1 bool) { - c.log("p0", p0, "p1", p1) + c.log(p0, p1) } func (c *ConsolePrecompile) Log_e0625b29(p0 string, p1 bool, p2 string, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_3f8a701d(p0 string, p1 bool, p2 string, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_e298f47d(p0 string, p1 bool, p2 string) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_a826caeb(p0 string, p1 bool, p2 string, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_24f91465(p0 string, p1 bool, p2 string, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_935e09bf(p0 string, p1 bool, p2 *big.Int, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_8af7cf8a(p0 string, p1 bool, p2 *big.Int, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_c95958d6(p0 string, p1 bool, p2 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_742d6ee7(p0 string, p1 bool, p2 *big.Int, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_64b5bb67(p0 string, p1 bool, p2 *big.Int, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_3ca6268e(p0 string, p1 *ABIInt256) { - c.log("p0", p0, "p1", (*big.Int)(p1)) + c.log(p0, (*big.Int)(p1)) } func (c *ConsolePrecompile) Log_41304fac(p0 string) { - c.log("p0", p0) + c.log(p0) } func (c *ConsolePrecompile) Log_439c7bef(p0 string, p1 string, p2 common.Address, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_5ccd4e37(p0 string, p1 string, p2 common.Address, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_95ed0195(p0 string, p1 string, p2 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_eb1bff80(p0 string, p1 string, p2 common.Address, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_7cc3c607(p0 string, p1 string, p2 common.Address, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_c371c7db(p0 string, p1 string, p2 bool, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_40785869(p0 string, p1 string, p2 bool, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_b0e0f9b5(p0 string, p1 string, p2 bool) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_5e84b0ea(p0 string, p1 string, p2 bool, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_d6aefad2(p0 string, p1 string, p2 bool, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_4b5c4277(p0 string, p1 string) { - c.log("p0", p0, "p1", p1) + c.log(p0, p1) } func (c *ConsolePrecompile) Log_6d572f44(p0 string, p1 string, p2 string, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_2c1754ed(p0 string, p1 string, p2 string, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_2ced7cef(p0 string, p1 string, p2 string) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_de68f20a(p0 string, p1 string, p2 string, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_8eafb02b(p0 string, p1 string, p2 string, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_1023f7b2(p0 string, p1 string, p2 *big.Int, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_c3a8a654(p0 string, p1 string, p2 *big.Int, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_5821efa1(p0 string, p1 string, p2 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_5d1a971a(p0 string, p1 string, p2 *big.Int, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_f45d7d2c(p0 string, p1 string, p2 *big.Int, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_5ea2b7ae(p0 string, p1 *big.Int, p2 common.Address, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_82112a42(p0 string, p1 *big.Int, p2 common.Address, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_1c7ec448(p0 string, p1 *big.Int, p2 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_9ffb2f93(p0 string, p1 *big.Int, p2 common.Address, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_4f04fdc6(p0 string, p1 *big.Int, p2 common.Address, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_e0e95b98(p0 string, p1 *big.Int, p2 bool, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_354c36d6(p0 string, p1 *big.Int, p2 bool, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_ca7733b1(p0 string, p1 *big.Int, p2 bool) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_abf73a98(p0 string, p1 *big.Int, p2 bool, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_e41b6f6f(p0 string, p1 *big.Int, p2 bool, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_b60e72cc(p0 string, p1 *big.Int) { - c.log("p0", p0, "p1", p1) + c.log(p0, p1) } func (c *ConsolePrecompile) Log_7c4632a4(p0 string, p1 *big.Int, p2 string, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_7d24491d(p0 string, p1 *big.Int, p2 string, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_5970e089(p0 string, p1 *big.Int, p2 string) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_5ab84e1f(p0 string, p1 *big.Int, p2 string, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_c67ea9d1(p0 string, p1 *big.Int, p2 string, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_e21de278(p0 string, p1 *big.Int, p2 *big.Int, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_7626db92(p0 string, p1 *big.Int, p2 *big.Int, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_ca47c4eb(p0 string, p1 *big.Int, p2 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_854b3496(p0 string, p1 *big.Int, p2 *big.Int, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_a7a87853(p0 string, p1 *big.Int, p2 *big.Int, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_2488b414(p0 *big.Int, p1 common.Address, p2 common.Address, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_091ffaf5(p0 *big.Int, p1 common.Address, p2 common.Address, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_bcfd9be0(p0 *big.Int, p1 common.Address, p2 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_031c6f73(p0 *big.Int, p1 common.Address, p2 common.Address, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_736efbb6(p0 *big.Int, p1 common.Address, p2 common.Address, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_ef72c513(p0 *big.Int, p1 common.Address, p2 bool, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_e351140f(p0 *big.Int, p1 common.Address, p2 bool, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_9b6ec042(p0 *big.Int, p1 common.Address, p2 bool) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_90fb06aa(p0 *big.Int, p1 common.Address, p2 bool, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_5abd992a(p0 *big.Int, p1 common.Address, p2 bool, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_69276c86(p0 *big.Int, p1 common.Address) { - c.log("p0", p0, "p1", p1) + c.log(p0, p1) } func (c *ConsolePrecompile) Log_9cba8fff(p0 *big.Int, p1 common.Address, p2 string, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_cc32ab07(p0 *big.Int, p1 common.Address, p2 string, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_63cb41f9(p0 *big.Int, p1 common.Address, p2 string) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_3e128ca3(p0 *big.Int, p1 common.Address, p2 string, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_46826b5d(p0 *big.Int, p1 common.Address, p2 string, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_15c127b5(p0 *big.Int, p1 common.Address, p2 *big.Int, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_5f743a7c(p0 *big.Int, p1 common.Address, p2 *big.Int, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_5a9b5ed5(p0 *big.Int, p1 common.Address, p2 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_ddb06521(p0 *big.Int, p1 common.Address, p2 *big.Int, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_0c9cd9c1(p0 *big.Int, p1 common.Address, p2 *big.Int, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_a1ef4cbb(p0 *big.Int, p1 bool, p2 common.Address, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_454d54a5(p0 *big.Int, p1 bool, p2 common.Address, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_35085f7b(p0 *big.Int, p1 bool, p2 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_ade052c7(p0 *big.Int, p1 bool, p2 common.Address, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_078287f5(p0 *big.Int, p1 bool, p2 common.Address, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_69640b59(p0 *big.Int, p1 bool, p2 bool, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_b6f577a1(p0 *big.Int, p1 bool, p2 bool, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_20718650(p0 *big.Int, p1 bool, p2 bool) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_dddb9561(p0 *big.Int, p1 bool, p2 bool, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_7464ce23(p0 *big.Int, p1 bool, p2 bool, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_1c9d7eb3(p0 *big.Int, p1 bool) { - c.log("p0", p0, "p1", p1) + c.log(p0, p1) } func (c *ConsolePrecompile) Log_ef529018(p0 *big.Int, p1 bool, p2 string, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_eb928d7f(p0 *big.Int, p1 bool, p2 string, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_85775021(p0 *big.Int, p1 bool, p2 string) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_68c8b8bd(p0 *big.Int, p1 bool, p2 string, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_2c1d0746(p0 *big.Int, p1 bool, p2 string, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_88cb6041(p0 *big.Int, p1 bool, p2 *big.Int, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_91a02e2a(p0 *big.Int, p1 bool, p2 *big.Int, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_20098014(p0 *big.Int, p1 bool, p2 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_de03e774(p0 *big.Int, p1 bool, p2 *big.Int, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_c6acc7a8(p0 *big.Int, p1 bool, p2 *big.Int, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_f82c50f1(p0 *big.Int) { - c.log("p0", p0) + c.log(p0) } func (c *ConsolePrecompile) Log_6168ed61(p0 *big.Int, p1 string, p2 common.Address, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_90c30a56(p0 *big.Int, p1 string, p2 common.Address, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_7afac959(p0 *big.Int, p1 string, p2 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_9c3adfa1(p0 *big.Int, p1 string, p2 common.Address, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_e8d3018d(p0 *big.Int, p1 string, p2 common.Address, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_ae2ec581(p0 *big.Int, p1 string, p2 bool, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_ba535d9c(p0 *big.Int, p1 string, p2 bool, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_4ceda75a(p0 *big.Int, p1 string, p2 bool) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_d2d423cd(p0 *big.Int, p1 string, p2 bool, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_cf009880(p0 *big.Int, p1 string, p2 bool, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_643fd0df(p0 *big.Int, p1 string) { - c.log("p0", p0, "p1", p1) + c.log(p0, p1) } func (c *ConsolePrecompile) Log_d583c602(p0 *big.Int, p1 string, p2 string, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_b3a6b6bd(p0 *big.Int, p1 string, p2 string, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_b115611f(p0 *big.Int, p1 string, p2 string) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_21ad0683(p0 *big.Int, p1 string, p2 string, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_b028c9bd(p0 *big.Int, p1 string, p2 string, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_3b2279b4(p0 *big.Int, p1 string, p2 *big.Int, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_691a8f74(p0 *big.Int, p1 string, p2 *big.Int, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_37aa7d4c(p0 *big.Int, p1 string, p2 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_b7b914ca(p0 *big.Int, p1 string, p2 *big.Int, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_82c25b74(p0 *big.Int, p1 string, p2 *big.Int, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_56a5d1b1(p0 *big.Int, p1 *big.Int, p2 common.Address, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_15cac476(p0 *big.Int, p1 *big.Int, p2 common.Address, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_5c96b331(p0 *big.Int, p1 *big.Int, p2 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_6cde40b8(p0 *big.Int, p1 *big.Int, p2 common.Address, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_88f6e4b2(p0 *big.Int, p1 *big.Int, p2 common.Address, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_9a816a83(p0 *big.Int, p1 *big.Int, p2 bool, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_ab085ae6(p0 *big.Int, p1 *big.Int, p2 bool, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_4766da72(p0 *big.Int, p1 *big.Int, p2 bool) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_a5b4fc99(p0 *big.Int, p1 *big.Int, p2 bool, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_eb7f6fd2(p0 *big.Int, p1 *big.Int, p2 bool, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_f666715a(p0 *big.Int, p1 *big.Int) { - c.log("p0", p0, "p1", p1) + c.log(p0, p1) } func (c *ConsolePrecompile) Log_42d21db7(p0 *big.Int, p1 *big.Int, p2 string, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_7af6ab25(p0 *big.Int, p1 *big.Int, p2 string, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_71d04af2(p0 *big.Int, p1 *big.Int, p2 string) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_27d8afd2(p0 *big.Int, p1 *big.Int, p2 string, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_5da297eb(p0 *big.Int, p1 *big.Int, p2 string, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_fa8185af(p0 *big.Int, p1 *big.Int, p2 *big.Int, p3 common.Address) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_c598d185(p0 *big.Int, p1 *big.Int, p2 *big.Int, p3 bool) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_d1ed7a3c(p0 *big.Int, p1 *big.Int, p2 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2) + c.log(p0, p1, p2) } func (c *ConsolePrecompile) Log_59cfcbe3(p0 *big.Int, p1 *big.Int, p2 *big.Int, p3 string) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } func (c *ConsolePrecompile) Log_193fb800(p0 *big.Int, p1 *big.Int, p2 *big.Int, p3 *big.Int) { - c.log("p0", p0, "p1", p1, "p2", p2, "p3", p3) + c.log(p0, p1, p2, p3) } - diff --git a/op-chain-ops/script/console_test.go b/op-chain-ops/script/console_test.go index bfce8e6148d4d..d67f5efc0f5f5 100644 --- a/op-chain-ops/script/console_test.go +++ b/op-chain-ops/script/console_test.go @@ -1,15 +1,16 @@ package script import ( + "fmt" "log/slog" + "math/big" "math/rand" // nosemgrep "testing" - "github.com/stretchr/testify/require" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/log" + "github.com/stretchr/testify/require" "github.com/ethereum-optimism/optimism/op-service/testlog" "github.com/ethereum-optimism/optimism/op-service/testutils" @@ -50,8 +51,25 @@ func TestConsole(t *testing.T) { }) } - require.NotNil(t, captLog.FindLog(testlog.NewMessageFilter("console"))) - require.NotNil(t, captLog.FindLog(testlog.NewAttributesFilter("p0", alice.String()))) - require.NotNil(t, captLog.FindLog(testlog.NewAttributesFilter("p1", bob.String()))) + require.NotNil(t, captLog.FindLog(testlog.NewMessageFilter(fmt.Sprintf("%s %s", alice, bob)))) require.NotNil(t, captLog.FindLog(testlog.NewAttributesFilter("sender", sender.String()))) } + +func TestFormatter(t *testing.T) { + got := consoleFormat("hello %d world %x example %3e", + big.NewInt(3), big.NewInt(0xc0ffee), big.NewInt(42), big.NewInt(123)) + require.Equal(t, "hello 3 world 0xc0ffee example 0.042 123", got) + require.Equal(t, "4.2", consoleFormat("%8e", big.NewInt(420000000))) + require.Equal(t, "foo true bar false", consoleFormat("foo %s bar %s", true, false)) + require.Equal(t, "foo 1 bar 0", consoleFormat("foo %d bar %d", true, false)) + require.Equal(t, "sender: "+DefaultSenderAddr.String(), + consoleFormat("sender: %s", DefaultSenderAddr)) + require.Equal(t, "long 0.000000000000000042 number", consoleFormat("long %18e number", big.NewInt(42))) + require.Equal(t, "long 4200.000000000000000003 number", consoleFormat("long %18e number", + new(big.Int).Add(new(big.Int).Mul( + big.NewInt(42), + new(big.Int).Exp(big.NewInt(10), big.NewInt(20), nil), + ), big.NewInt(3)))) + require.Equal(t, "1.23456e5", consoleFormat("%e", big.NewInt(123456))) + require.Equal(t, "-1.23456e5", consoleFormat("%e", (*ABIInt256)(big.NewInt(-123456)))) +} diff --git a/op-chain-ops/script/consolegen/main.go b/op-chain-ops/script/consolegen/main.go index bc20869eda133..9a3140d52f454 100644 --- a/op-chain-ops/script/consolegen/main.go +++ b/op-chain-ops/script/consolegen/main.go @@ -71,7 +71,6 @@ import ( if p == "" { continue } - out.WriteString(fmt.Sprintf(`"p%d", `, i)) out.WriteString(prettyArg(fmt.Sprintf("p%d", i), p)) if i != len(params)-1 { out.WriteString(", ") diff --git a/op-chain-ops/script/deterministic.go b/op-chain-ops/script/deterministic.go new file mode 100644 index 0000000000000..c7b02632a55ea --- /dev/null +++ b/op-chain-ops/script/deterministic.go @@ -0,0 +1,9 @@ +package script + +import "github.com/ethereum/go-ethereum/common" + +var ( + // DeterministicDeployerAddress is the address of the deterministic deployer Forge uses + // to provide deterministic contract addresses. + DeterministicDeployerAddress = common.HexToAddress("0x4e59b44847b379578588920ca78fbf26c0b4956c") +) diff --git a/op-chain-ops/script/prank.go b/op-chain-ops/script/prank.go index e60548e0f41a0..b6a68f4c44b17 100644 --- a/op-chain-ops/script/prank.go +++ b/op-chain-ops/script/prank.go @@ -1,13 +1,19 @@ package script import ( + "bytes" + "crypto/sha256" + "encoding/binary" "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/vm" + "github.com/ethereum/go-ethereum/crypto" ) // Prank represents an active prank task for the next sub-call. @@ -48,6 +54,13 @@ func (h *Host) handleCaller(caller vm.ContractRef) vm.ContractRef { if len(h.callStack) > 0 { parentCallFrame := h.callStack[len(h.callStack)-1] if parentCallFrame.Prank != nil && caller.Address() != VMAddr { // pranks do not apply to the cheatcode precompile + if parentCallFrame.Prank.Broadcast && parentCallFrame.LastOp == vm.CREATE2 && h.useCreate2Deployer { + return &prankRef{ + prank: DeterministicDeployerAddress, + ref: caller, + } + } + if parentCallFrame.Prank.Sender != nil { return &prankRef{ prank: *parentCallFrame.Prank.Sender, @@ -69,7 +82,7 @@ func (h *Host) Prank(msgSender *common.Address, txOrigin *common.Address, repeat h.log.Warn("no call stack") return nil // cannot prank while not in a call. } - cf := &h.callStack[len(h.callStack)-1] + cf := h.callStack[len(h.callStack)-1] if cf.Prank != nil { if cf.Prank.Broadcast && !broadcast { return errors.New("you have an active broadcast; broadcasting and pranks are not compatible") @@ -78,7 +91,11 @@ func (h *Host) Prank(msgSender *common.Address, txOrigin *common.Address, repeat return errors.New("you have an active prank; broadcasting and pranks are not compatible") } } - h.log.Warn("prank", "sender", msgSender) + if broadcast { + h.log.Debug("starting broadcast", "sender", msgSender, "repeat", repeat) + } else { + h.log.Debug("starting prank", "sender", msgSender, "repeat", repeat) + } cf.Prank = &Prank{ Sender: msgSender, Origin: txOrigin, @@ -94,7 +111,7 @@ func (h *Host) StopPrank(broadcast bool) error { if len(h.callStack) == 0 { return nil } - cf := &h.callStack[len(h.callStack)-1] + cf := h.callStack[len(h.callStack)-1] if cf.Prank == nil { if broadcast { return errors.New("no broadcast in progress to stop") @@ -108,6 +125,11 @@ func (h *Host) StopPrank(broadcast bool) error { if !cf.Prank.Broadcast && broadcast { return errors.New("no broadcast in progress to stop") } + if broadcast { + h.log.Debug("stopping broadcast") + } else { + h.log.Debug("stopping prank") + } cf.Prank = nil return nil } @@ -118,7 +140,7 @@ func (h *Host) CallerMode() CallerMode { if len(h.callStack) == 0 { return CallerModeNone } - cf := &h.callStack[len(h.callStack)-1] + cf := h.callStack[len(h.callStack)-1] if cf.Prank != nil { if cf.Prank.Broadcast { if cf.Prank.Repeat { @@ -148,3 +170,125 @@ const ( CallerModePrank CallerModeRecurrentPrank ) + +type BroadcastType string + +const ( + BroadcastCall BroadcastType = "call" + BroadcastCreate BroadcastType = "create" + // BroadcastCreate2 is to be broadcast via the Create2Deployer, + // and not really documented much anywhere. + BroadcastCreate2 BroadcastType = "create2" +) + +func (bt BroadcastType) String() string { + return string(bt) +} + +func (bt BroadcastType) MarshalText() ([]byte, error) { + return []byte(bt.String()), nil +} + +func (bt *BroadcastType) UnmarshalText(data []byte) error { + v := BroadcastType(data) + switch v { + case BroadcastCall, BroadcastCreate, BroadcastCreate2: + *bt = v + return nil + default: + return fmt.Errorf("unrecognized broadcast type bytes: %x", data) + } +} + +// Broadcast captures a transaction that was selected to be broadcast +// via vm.broadcast(). Actually submitting the transaction is left up +// to other tools. +type Broadcast struct { + From common.Address `json:"from"` + To common.Address `json:"to"` // set to expected contract address, if this is a deployment + Input hexutil.Bytes `json:"input"` // set to contract-creation code, if this is a deployment + Value *hexutil.U256 `json:"value"` + Salt common.Hash `json:"salt"` // set if this is a Create2 broadcast + GasUsed uint64 `json:"gasUsed"` + Type BroadcastType `json:"type"` + Nonce uint64 `json:"nonce"` // pre-state nonce of From, before any increment (always 0 if create2) +} + +// ID returns a hash that can be used to identify the broadcast. +// This is used instead of the transaction hash since broadcasting +// tools can change gas limits and other fields which would change +// the resulting transaction hash. +func (b Broadcast) ID() common.Hash { + h := sha256.New() + _, _ = h.Write(b.From[:]) + _, _ = h.Write(b.To[:]) + _, _ = h.Write(b.Input) + _, _ = h.Write(((*uint256.Int)(b.Value)).Bytes()) + _, _ = h.Write(b.Salt[:]) + nonce := make([]byte, 8) + binary.BigEndian.PutUint64(nonce, b.Nonce) + _, _ = h.Write(nonce) + sum := h.Sum(nil) + return common.BytesToHash(sum) +} + +// NewBroadcast creates a Broadcast from a parent callframe, and the completed child callframe. +// This method is preferred to manually creating the struct since it correctly handles +// data that must be copied prior to being returned to prevent accidental mutation. +func NewBroadcast(parent, current *CallFrame) Broadcast { + ctx := current.Ctx + + value := ctx.CallValue() + if value == nil { + value = uint256.NewInt(0) + } + + // Code is tracked separate from calldata input, + // even though they are the same thing for a regular contract creation + input := ctx.CallInput() + if ctx.Contract.IsDeployment { + input = ctx.Contract.Code + } + + bcast := Broadcast{ + From: ctx.Caller(), + To: ctx.Address(), + // Need to clone the input below since memory is reused in the VM + Input: bytes.Clone(input), + Value: (*hexutil.U256)(value.Clone()), + GasUsed: current.GasUsed, + } + + switch parent.LastOp { + case vm.CREATE: + bcast.Type = BroadcastCreate + // Nonce bump was already applied, but we need the pre-state + bcast.Nonce = current.CallerNonce - 1 + expectedAddr := crypto.CreateAddress(bcast.From, bcast.Nonce) + if expectedAddr != bcast.To { + panic(fmt.Errorf("script bug: create broadcast has "+ + "unexpected address: %s, expected %s. Sender: %s, Nonce: %d", + bcast.To, expectedAddr, bcast.From, bcast.Nonce)) + } + case vm.CREATE2: + bcast.Salt = parent.LastCreate2Salt + initHash := crypto.Keccak256Hash(bcast.Input) + expectedAddr := crypto.CreateAddress2(bcast.From, bcast.Salt, initHash[:]) + // Sanity-check the create2 salt is correct by checking the address computation. + if expectedAddr != bcast.To { + panic(fmt.Errorf("script bug: create2 broadcast has "+ + "unexpected address: %s, expected %s. Sender: %s, Salt: %s, Inithash: %s", + bcast.To, expectedAddr, bcast.From, bcast.Salt, initHash)) + } + bcast.Type = BroadcastCreate2 + bcast.Nonce = 0 // always 0. The nonce should not matter for create2. + case vm.CALL: + bcast.Type = BroadcastCall + // Nonce bump was already applied, but we need the pre-state + bcast.Nonce = current.CallerNonce - 1 + default: + panic(fmt.Errorf("unexpected broadcast operation %s", parent.LastOp)) + } + + return bcast +} diff --git a/op-chain-ops/script/precompile.go b/op-chain-ops/script/precompile.go index 56094b9c2e0b7..2dcea66018834 100644 --- a/op-chain-ops/script/precompile.go +++ b/op-chain-ops/script/precompile.go @@ -10,11 +10,15 @@ import ( "strings" "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/core/vm" "github.com/ethereum/go-ethereum/crypto" ) +var setterFnSig = "set(bytes4,address)" +var setterFnBytes4 = bytes4(setterFnSig) + // precompileFunc is a prepared function to perform a method call / field read with ABI decoding/encoding. type precompileFunc struct { goName string @@ -52,12 +56,20 @@ func rightPad32(data []byte) []byte { return append(out, make([]byte, 32-(len(out)%32))...) } +type settableField struct { + name string + value *reflect.Value +} + // Precompile is a wrapper around a Go object, making it a precompile. type Precompile[E any] struct { Precompile E fieldsOnly bool + fieldSetter bool + settable map[[4]byte]*settableField + // abiMethods is effectively the jump-table for 4-byte ABI calls to the precompile. abiMethods map[[4]byte]*precompileFunc } @@ -70,6 +82,10 @@ func WithFieldsOnly[E any](p *Precompile[E]) { p.fieldsOnly = true } +func WithFieldSetter[E any](p *Precompile[E]) { + p.fieldSetter = true +} + // NewPrecompile wraps a Go object into a Precompile. // All exported fields and methods will have a corresponding ABI interface. // Fields with a tag `evm:"-"` will be ignored, or can override their ABI name to x with this tag: `evm:"x"`. @@ -80,9 +96,11 @@ func WithFieldsOnly[E any](p *Precompile[E]) { // All precompile methods have 0 gas cost. func NewPrecompile[E any](e E, opts ...PrecompileOption[E]) (*Precompile[E], error) { out := &Precompile[E]{ - Precompile: e, - abiMethods: make(map[[4]byte]*precompileFunc), - fieldsOnly: false, + Precompile: e, + abiMethods: make(map[[4]byte]*precompileFunc), + fieldsOnly: false, + fieldSetter: false, + settable: make(map[[4]byte]*settableField), } for _, opt := range opts { opt(out) @@ -96,6 +114,8 @@ func NewPrecompile[E any](e E, opts ...PrecompileOption[E]) (*Precompile[E], err if err := out.setupFields(&elemVal); err != nil { return nil, fmt.Errorf("failed to setup fields of precompile: %w", err) } + // create setter that can handle of the fields + out.setupFieldSetter() return out, nil } @@ -496,9 +516,42 @@ func (p *Precompile[E]) setupStructField(fieldDef *reflect.StructField, fieldVal abiSignature: methodSig, fn: fn, } + // register field as settable + if p.fieldSetter && fieldDef.Type.AssignableTo(typeFor[common.Address]()) { + p.settable[byte4Sig] = &settableField{ + name: fieldDef.Name, + value: fieldVal, + } + } return nil } +func (p *Precompile[E]) setupFieldSetter() { + if !p.fieldSetter { + return + } + p.abiMethods[setterFnBytes4] = &precompileFunc{ + goName: "__fieldSetter___", + abiSignature: setterFnSig, + fn: func(input []byte) ([]byte, error) { + if len(input) != 32*2 { + return nil, fmt.Errorf("cannot set address field to %d bytes", len(input)) + } + if [32 - 4]byte(input[4:32]) != ([32 - 4]byte{}) { + return nil, fmt.Errorf("unexpected selector content, input: %x", input[:]) + } + selector := [4]byte(input[:4]) + f, ok := p.settable[selector] + if !ok { + return nil, fmt.Errorf("unknown address field selector 0x%x", selector) + } + addr := common.Address(input[32*2-20 : 32*2]) + f.value.Set(reflect.ValueOf(addr)) + return nil, nil + }, + } +} + // RequiredGas is part of the vm.PrecompiledContract interface, and all system precompiles use 0 gas. func (p *Precompile[E]) RequiredGas(input []byte) uint64 { return 0 diff --git a/op-chain-ops/script/precompile_test.go b/op-chain-ops/script/precompile_test.go index ba2f02202ec3e..a207c1221f9f0 100644 --- a/op-chain-ops/script/precompile_test.go +++ b/op-chain-ops/script/precompile_test.go @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/require" "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" ) @@ -119,3 +120,24 @@ func TestPrecompile(t *testing.T) { require.NoError(t, err) require.Equal(t, b32((42+100+7)*3), out) } + +type DeploymentExample struct { + FooBar common.Address +} + +func TestDeploymentOutputPrecompile(t *testing.T) { + e := &DeploymentExample{} + p, err := NewPrecompile[*DeploymentExample](e, WithFieldSetter[*DeploymentExample]) + require.NoError(t, err) + + addr := common.Address{0: 0x42, 19: 0xaa} + fooBarSelector := bytes4("fooBar()") + var input []byte + input = append(input, setterFnBytes4[:]...) + input = append(input, rightPad32(fooBarSelector[:])...) + input = append(input, leftPad32(addr[:])...) + out, err := p.Run(input) + require.NoError(t, err) + require.Empty(t, out) + require.Equal(t, addr, e.FooBar) +} diff --git a/op-chain-ops/script/script.go b/op-chain-ops/script/script.go index 5950e1db02e30..d156adb671874 100644 --- a/op-chain-ops/script/script.go +++ b/op-chain-ops/script/script.go @@ -29,6 +29,9 @@ import ( "github.com/ethereum-optimism/optimism/op-chain-ops/srcmap" ) +// jumpHistory is the amount of successful jumps to track for debugging. +const jumpHistory = 5 + // CallFrame encodes the scope context of the current call type CallFrame struct { Depth int @@ -36,10 +39,15 @@ type CallFrame struct { LastOp vm.OpCode LastPC uint64 + // To reconstruct a create2 later, e.g. on broadcast + LastCreate2Salt [32]byte + // Reverts often happen in generated code. // We want to fallback to logging the source-map position of // the non-generated code, i.e. the origin of the last successful jump. - LastJumpPC uint64 + // And beyond that, a short history of the latest jumps is useful for debugging. + // This is a list of program-counters at the time of the jump (i.e. before raching JUMPDEST). + LastJumps []uint64 Ctx *vm.ScopeContext @@ -47,6 +55,15 @@ type CallFrame struct { // Forge script does not support nested pranks on the same call-depth. // Pranks can also be broadcasting. Prank *Prank + + // GasUsed keeps track of the amount of gas used by this call frame. + // This is useful for broadcasts, which sometimes cannot correctly + // estimate gas when sending transactions in parallel. + GasUsed uint64 + + // CallerNonce keeps track of the nonce of the caller who entered the callframe + // (nonce of pranked caller, if pranked). + CallerNonce uint64 } // Host is an EVM executor that runs Forge scripts. @@ -64,7 +81,7 @@ type Host struct { precompiles map[common.Address]vm.PrecompiledContract - callStack []CallFrame + callStack []*CallFrame // serializerStates are in-progress JSON payloads by name, // for the serializeX family of cheat codes, see: @@ -79,12 +96,66 @@ type Host struct { // src-maps are disabled if this is nil. srcFS *foundry.SourceMapFS srcMaps map[common.Address]*srcmap.SourceMap + + onLabel []func(name string, addr common.Address) + + hooks *Hooks + + // isolateBroadcasts will flush the journal changes, + // and prepare the ephemeral tx context again, + // to make gas accounting of a broadcast sub-call more accurate. + isolateBroadcasts bool + + // useCreate2Deployer uses the Create2Deployer for broadcasted + // create2 calls. + useCreate2Deployer bool +} + +type HostOption func(h *Host) + +type BroadcastHook func(broadcast Broadcast) + +type Hooks struct { + OnBroadcast BroadcastHook +} + +func WithBroadcastHook(hook BroadcastHook) HostOption { + return func(h *Host) { + h.hooks.OnBroadcast = hook + } +} + +// WithIsolatedBroadcasts makes each broadcast clean the context, +// by flushing the dirty storage changes, and preparing the ephemeral state again. +// This then produces more accurate gas estimation for broadcast calls. +// This is not compatible with state-snapshots: upon cleaning, +// it is assumed that the state has to never revert back, similar to the state-dump guarantees. +func WithIsolatedBroadcasts() HostOption { + return func(h *Host) { + h.isolateBroadcasts = true + } +} + +// WithCreate2Deployer proxies each CREATE2 call through the CREATE2 deployer +// contract located at 0x4e59b44847b379578588920cA78FbF26c0B4956C. This is the Arachnid +// Create2Deployer contract Forge uses. See https://github.com/Arachnid/deterministic-deployment-proxy +// for the implementation. +func WithCreate2Deployer() HostOption { + return func(h *Host) { + h.useCreate2Deployer = true + } } // NewHost creates a Host that can load contracts from the given Artifacts FS, // and with an EVM initialized to the given executionContext. // Optionally src-map loading may be enabled, by providing a non-nil srcFS to read sources from. -func NewHost(logger log.Logger, fs *foundry.ArtifactsFS, srcFS *foundry.SourceMapFS, executionContext Context) *Host { +func NewHost( + logger log.Logger, + fs *foundry.ArtifactsFS, + srcFS *foundry.SourceMapFS, + executionContext Context, + options ...HostOption, +) *Host { h := &Host{ log: logger, af: fs, @@ -94,6 +165,13 @@ func NewHost(logger log.Logger, fs *foundry.ArtifactsFS, srcFS *foundry.SourceMa precompiles: make(map[common.Address]vm.PrecompiledContract), srcFS: srcFS, srcMaps: make(map[common.Address]*srcmap.SourceMap), + hooks: &Hooks{ + OnBroadcast: func(broadcast Broadcast) {}, + }, + } + + for _, opt := range options { + opt(h) } // Init a default chain config, with all the mainnet L1 forks activated @@ -178,6 +256,7 @@ func NewHost(logger log.Logger, fs *foundry.ArtifactsFS, srcFS *foundry.SourceMa // Hook up the Host to capture the EVM environment changes trHooks := &tracing.Hooks{ + OnEnter: h.onEnter, OnExit: h.onExit, OnOpcode: h.onOpcode, OnFault: h.onFault, @@ -297,6 +376,30 @@ func (h *Host) Wipe(addr common.Address) { h.state.SetBalance(addr, uint256.NewInt(0), tracing.BalanceChangeUnspecified) } +// SetNonce sets an account's nonce in state. +func (h *Host) SetNonce(addr common.Address, nonce uint64) { + h.state.SetNonce(addr, nonce) +} + +// GetNonce returs an account's nonce from state. +func (h *Host) GetNonce(addr common.Address) uint64 { + return h.state.GetNonce(addr) +} + +// ImportState imports a set of foundry.ForgeAllocs into the +// host's state database. It does not erase existing state +// when importing. +func (h *Host) ImportState(allocs *foundry.ForgeAllocs) { + for addr, alloc := range allocs.Accounts { + h.state.SetBalance(addr, uint256.MustFromBig(alloc.Balance), tracing.BalanceChangeUnspecified) + h.state.SetNonce(addr, alloc.Nonce) + h.state.SetCode(addr, alloc.Code) + for key, value := range alloc.Storage { + h.state.SetState(addr, key, value) + } + } +} + // getPrecompile overrides any accounts during runtime, to insert special precompiles, if activated. func (h *Host) getPrecompile(rules params.Rules, original vm.PrecompiledContract, addr common.Address) vm.PrecompiledContract { if p, ok := h.precompiles[addr]; ok { @@ -326,6 +429,52 @@ func (h *Host) HasPrecompileOverride(addr common.Address) bool { return ok } +// onEnter is a trace-hook, which we use to apply changes to the state-DB, to simulate isolated broadcast calls, +// for better gas estimation of the exact broadcast call execution. +func (h *Host) onEnter(depth int, typ byte, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) { + if len(h.callStack) == 0 { + return + } + parentCallFrame := h.callStack[len(h.callStack)-1] + if parentCallFrame.Prank == nil { + return + } + // sanity check our callframe is set up correctly + if parentCallFrame.LastOp != vm.OpCode(typ) { + panic(fmt.Errorf("parent call-frame has invalid last Op: %d", typ)) + } + if !parentCallFrame.Prank.Broadcast { + return + } + if to == VMAddr || to == ConsoleAddr { // no broadcasts to the cheatcode or console address + return + } + + // Bump nonce value, such that a broadcast Call or CREATE2 appears like a tx + if parentCallFrame.LastOp == vm.CALL || parentCallFrame.LastOp == vm.CREATE2 { + sender := parentCallFrame.Ctx.Address() + if parentCallFrame.Prank.Sender != nil { + sender = *parentCallFrame.Prank.Sender + } + h.state.SetNonce(sender, h.state.GetNonce(sender)+1) + } + + if h.isolateBroadcasts { + var dest *common.Address + switch parentCallFrame.LastOp { + case vm.CREATE, vm.CREATE2: + dest = nil // no destination address to warm up + case vm.CALL: + dest = &to + default: + return + } + h.state.Finalise(true) + // the prank msg.sender, if any, has already been applied to 'from' before onEnter + h.prelude(from, dest) + } +} + // onExit is a trace-hook, which we use to maintain an accurate view of functions, and log any revert warnings. func (h *Host) onExit(depth int, output []byte, gasUsed uint64, err error, reverted bool) { // Note: onExit runs also when going deeper, exiting the context into a nested context. @@ -338,6 +487,8 @@ func (h *Host) onExit(depth int, output []byte, gasUsed uint64, err error, rever h.log.Warn("Revert", "addr", addr, "err", err, "revertData", hexutil.Bytes(output), "depth", depth) } } + + h.callStack[len(h.callStack)-1].GasUsed += gasUsed h.unwindCallstack(depth) } @@ -354,6 +505,26 @@ func (h *Host) unwindCallstack(depth int) { if len(h.callStack) > 1 { parentCallFrame := h.callStack[len(h.callStack)-2] if parentCallFrame.Prank != nil { + if parentCallFrame.Prank.Broadcast { + if parentCallFrame.LastOp == vm.DELEGATECALL { + h.log.Warn("Cannot broadcast a delegate-call. Ignoring broadcast hook.") + } else if parentCallFrame.LastOp == vm.STATICCALL { + h.log.Trace("Broadcast is active, ignoring static-call.") + } else { + currentCallFrame := h.callStack[len(h.callStack)-1] + bcast := NewBroadcast(parentCallFrame, currentCallFrame) + h.log.Debug( + "calling broadcast hook", + "from", bcast.From, + "to", bcast.To, + "input", bcast.Input, + "value", bcast.Value, + "type", bcast.Type, + ) + h.hooks.OnBroadcast(bcast) + } + } + // While going back to the parent, restore the tx.origin. // It will later be re-applied on sub-calls if the prank persists (if Repeat == true). if parentCallFrame.Prank.Origin != nil { @@ -365,7 +536,7 @@ func (h *Host) unwindCallstack(depth int) { } } // Now pop the call-frame - h.callStack[len(h.callStack)-1] = CallFrame{} // don't hold on to the underlying call-frame resources + h.callStack[len(h.callStack)-1] = nil // don't hold on to the underlying call-frame resources h.callStack = h.callStack[:len(h.callStack)-1] } } @@ -377,24 +548,31 @@ func (h *Host) onOpcode(pc uint64, op byte, gas, cost uint64, scope tracing.OpCo // Check if we are entering a new depth, add it to the call-stack if so. // We do this here, instead of onEnter, to capture an initialized scope. if len(h.callStack) == 0 || h.callStack[len(h.callStack)-1].Depth < depth { - h.callStack = append(h.callStack, CallFrame{ - Depth: depth, - LastOp: vm.OpCode(op), - LastPC: pc, - LastJumpPC: pc, - Ctx: scopeCtx, + h.callStack = append(h.callStack, &CallFrame{ + Depth: depth, + LastOp: vm.OpCode(op), + LastPC: pc, + Ctx: scopeCtx, + CallerNonce: h.GetNonce(scopeCtx.Caller()), }) } // Sanity check that top of the call-stack matches the scope context now if len(h.callStack) == 0 || h.callStack[len(h.callStack)-1].Ctx != scopeCtx { panic("scope context changed without call-frame pop/push") } - cf := &h.callStack[len(h.callStack)-1] + cf := h.callStack[len(h.callStack)-1] if vm.OpCode(op) == vm.JUMPDEST { // remember the last PC before successful jump - cf.LastJumpPC = cf.LastPC + cf.LastJumps = append(cf.LastJumps, cf.LastPC) + if len(cf.LastJumps) > jumpHistory { + copy(cf.LastJumps[:], cf.LastJumps[len(cf.LastJumps)-jumpHistory:]) + cf.LastJumps = cf.LastJumps[:jumpHistory] + } } cf.LastOp = vm.OpCode(op) cf.LastPC = pc + if cf.LastOp == vm.CREATE2 { + cf.LastCreate2Salt = scopeCtx.Stack.Back(3).Bytes32() + } } // onStorageChange is a trace-hook to capture state changes @@ -419,7 +597,7 @@ func (h *Host) CurrentCall() CallFrame { if len(h.callStack) == 0 { return CallFrame{} } - return h.callStack[len(h.callStack)-1] + return *h.callStack[len(h.callStack)-1] } // MsgSender returns the msg.sender of the current active EVM call-frame, @@ -527,10 +705,14 @@ func (h *Host) EnforceMaxCodeSize(v bool) { func (h *Host) LogCallStack() { for _, cf := range h.callStack { callsite := "" - if srcMap, ok := h.srcMaps[cf.Ctx.Address()]; ok { + srcMap, ok := h.srcMaps[cf.Ctx.Address()] + if !ok && cf.Ctx.Contract.CodeAddr != nil { // if delegate-call, we might know the implementation code. + srcMap, ok = h.srcMaps[*cf.Ctx.Contract.CodeAddr] + } + if ok { callsite = srcMap.FormattedInfo(cf.LastPC) - if callsite == "unknown:0:0" { - callsite = srcMap.FormattedInfo(cf.LastJumpPC) + if callsite == "unknown:0:0" && len(cf.LastJumps) > 0 { + callsite = srcMap.FormattedInfo(cf.LastJumps[len(cf.LastJumps)-1]) } } input := cf.Ctx.CallInput() @@ -538,9 +720,14 @@ func (h *Host) LogCallStack() { if len(input) >= 4 { byte4 = fmt.Sprintf("0x%x", input[:4]) } - h.log.Debug("callframe", "depth", cf.Depth, "input", hexutil.Bytes(input), "pc", cf.LastPC, "op", cf.LastOp) + h.log.Debug("callframe input", "depth", cf.Depth, "input", hexutil.Bytes(input), "pc", cf.LastPC, "op", cf.LastOp) h.log.Warn("callframe", "depth", cf.Depth, "byte4", byte4, "addr", cf.Ctx.Address(), "callsite", callsite, "label", h.labels[cf.Ctx.Address()]) + if srcMap != nil { + for _, jmpPC := range cf.LastJumps { + h.log.Debug("recent jump", "depth", cf.Depth, "callsite", srcMap.FormattedInfo(jmpPC), "pc", jmpPC) + } + } } } @@ -548,4 +735,40 @@ func (h *Host) LogCallStack() { func (h *Host) Label(addr common.Address, label string) { h.log.Debug("labeling", "addr", addr, "label", label) h.labels[addr] = label + + for _, fn := range h.onLabel { + fn(label, addr) + } +} + +// NewScriptAddress creates a new address for the ScriptDeployer account, and bumps the nonce. +func (h *Host) NewScriptAddress() common.Address { + deployer := ScriptDeployer + deployNonce := h.state.GetNonce(deployer) + // compute address of script contract to be deployed + addr := crypto.CreateAddress(deployer, deployNonce) + h.state.SetNonce(deployer, deployNonce+1) + return addr +} + +func (h *Host) ChainID() *big.Int { + return new(big.Int).Set(h.chainCfg.ChainID) +} + +func (h *Host) Artifacts() *foundry.ArtifactsFS { + return h.af +} + +// RememberOnLabel links the contract source-code of srcFile upon a given label +func (h *Host) RememberOnLabel(label, srcFile, contract string) error { + artifact, err := h.af.ReadArtifact(srcFile, contract) + if err != nil { + return fmt.Errorf("failed to read artifact %s (contract %s) for label %q", srcFile, contract, label) + } + h.onLabel = append(h.onLabel, func(v string, addr common.Address) { + if label == v { + h.RememberArtifact(addr, artifact, contract) + } + }) + return nil } diff --git a/op-chain-ops/script/script_test.go b/op-chain-ops/script/script_test.go index 15e69933a3c83..9d029c801060b 100644 --- a/op-chain-ops/script/script_test.go +++ b/op-chain-ops/script/script_test.go @@ -1,11 +1,20 @@ package script import ( + "bytes" + "encoding/json" + "fmt" + "math/big" + "strings" "testing" "github.com/holiman/uint256" "github.com/stretchr/testify/require" + "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" "github.com/ethereum/go-ethereum/log" "github.com/ethereum-optimism/optimism/op-chain-ops/foundry" @@ -29,11 +38,133 @@ func TestScript(t *testing.T) { input := bytes4("run()") returnData, _, err := h.Call(scriptContext.Sender, addr, input[:], DefaultFoundryGasLimit, uint256.NewInt(0)) require.NoError(t, err, "call failed: %x", string(returnData)) - require.NotNil(t, captLog.FindLog( - testlog.NewAttributesFilter("p0", "sender nonce"), - testlog.NewAttributesFilter("p1", "1"))) + require.NotNil(t, captLog.FindLog(testlog.NewMessageFilter("sender nonce 1"))) require.NoError(t, h.cheatcodes.Precompile.DumpState("noop")) // and a second time, to see if we can revisit the host state. require.NoError(t, h.cheatcodes.Precompile.DumpState("noop")) } + +func TestScriptBroadcast(t *testing.T) { + logger := testlog.Logger(t, log.LevelDebug) + af := foundry.OpenArtifactsDir("./testdata/test-artifacts") + + mustEncodeCalldata := func(method, input string) []byte { + packer, err := abi.JSON(strings.NewReader(fmt.Sprintf(`[{"type":"function","name":"%s","inputs":[{"type":"string","name":"input"}]}]`, method))) + require.NoError(t, err) + + data, err := packer.Pack(method, input) + require.NoError(t, err) + return data + } + + fooBar, err := af.ReadArtifact("ScriptExample.s.sol", "FooBar") + require.NoError(t, err) + + expectedInitCode := bytes.Clone(fooBar.Bytecode.Object) + // Add the contract init argument we use in the script + expectedInitCode = append(expectedInitCode, leftPad32(big.NewInt(1234).Bytes())...) + salt := uint256.NewInt(42).Bytes32() + + senderAddr := common.HexToAddress("0x0000000000000000000000000000000000Badc0d") + scriptAddr := common.HexToAddress("0x5b73c5498c1e3b4dba84de0f1833c4a029d90519") + coffeeAddr := common.HexToAddress("0x0000000000000000000000000000000000C0FFEE") + cafeAddr := common.HexToAddress("0xcafe") + expBroadcasts := []Broadcast{ + { + From: scriptAddr, + To: scriptAddr, + Input: mustEncodeCalldata("call1", "single_call1"), + Value: (*hexutil.U256)(uint256.NewInt(0)), + GasUsed: 23421, + Type: BroadcastCall, + Nonce: 1, // first action by script (script already has a nonce of 1) + }, + { + From: coffeeAddr, + To: scriptAddr, + Input: mustEncodeCalldata("call1", "startstop_call1"), + Value: (*hexutil.U256)(uint256.NewInt(0)), + GasUsed: 1521, + Type: BroadcastCall, + Nonce: 0, // first action by 0xc0ffee + }, + { + From: coffeeAddr, + To: scriptAddr, + Input: mustEncodeCalldata("call2", "startstop_call2"), + Value: (*hexutil.U256)(uint256.NewInt(0)), + GasUsed: 1565, + Type: BroadcastCall, + Nonce: 1, // second action of 0xc0ffee + }, + { + From: common.HexToAddress("0x1234"), + To: scriptAddr, + Input: mustEncodeCalldata("nested1", "nested"), + Value: (*hexutil.U256)(uint256.NewInt(0)), + GasUsed: 2763, + Type: BroadcastCall, + Nonce: 0, // first action of 0x1234 + }, + { + From: common.HexToAddress("0x123456"), + To: crypto.CreateAddress(common.HexToAddress("0x123456"), 0), + Input: expectedInitCode, + Value: (*hexutil.U256)(uint256.NewInt(0)), + GasUsed: 39112, + Type: BroadcastCreate, + Nonce: 0, // first action of 0x123456 + }, + { + From: DeterministicDeployerAddress, + To: crypto.CreateAddress2(DeterministicDeployerAddress, salt, crypto.Keccak256(expectedInitCode)), + Input: expectedInitCode, + Value: (*hexutil.U256)(uint256.NewInt(0)), + Type: BroadcastCreate2, + GasUsed: 39112, + Salt: salt, + Nonce: 0, // first action of 0xcafe + }, + { + From: scriptAddr, + To: crypto.CreateAddress(scriptAddr, 2), + Input: expectedInitCode, + Value: (*hexutil.U256)(uint256.NewInt(0)), + GasUsed: 39112, + Type: BroadcastCreate, + Nonce: 2, // second action, on top of starting at 1. + }, + } + + var broadcasts []Broadcast + hook := func(broadcast Broadcast) { + broadcasts = append(broadcasts, broadcast) + } + h := NewHost(logger, af, nil, DefaultContext, WithBroadcastHook(hook), WithCreate2Deployer()) + addr, err := h.LoadContract("ScriptExample.s.sol", "ScriptExample") + require.NoError(t, err) + + require.NoError(t, h.EnableCheats()) + + input := bytes4("runBroadcast()") + returnData, _, err := h.Call(senderAddr, addr, input[:], DefaultFoundryGasLimit, uint256.NewInt(0)) + require.NoError(t, err, "call failed: %x", string(returnData)) + + expected, err := json.MarshalIndent(expBroadcasts, " ", " ") + require.NoError(t, err) + got, err := json.MarshalIndent(broadcasts, " ", " ") + require.NoError(t, err) + require.Equal(t, string(expected), string(got)) + + // Assert that the nonces for accounts participating in the + // broadcast increase. The scriptAddr check is set to 3 to + // account for the initial deployment of the contract and + // two additional calls. + require.EqualValues(t, 0, h.GetNonce(senderAddr)) + require.EqualValues(t, 3, h.GetNonce(scriptAddr)) + require.EqualValues(t, 2, h.GetNonce(coffeeAddr)) + // This is one because we still need to bump the nonce of the + // address that will perform the send to the Create2Deployer. + require.EqualValues(t, 1, h.GetNonce(cafeAddr)) +} diff --git a/op-chain-ops/script/testdata/scripts/ScriptExample.s.sol b/op-chain-ops/script/testdata/scripts/ScriptExample.s.sol index 4c1dcf6275f2d..f2f20e5ca14e9 100644 --- a/op-chain-ops/script/testdata/scripts/ScriptExample.s.sol +++ b/op-chain-ops/script/testdata/scripts/ScriptExample.s.sol @@ -8,6 +8,11 @@ interface Vm { function parseJsonKeys(string calldata json, string calldata key) external pure returns (string[] memory keys); function startPrank(address msgSender) external; function stopPrank() external; + function broadcast() external; + function broadcast(address msgSender) external; + function startBroadcast(address msgSender) external; + function startBroadcast() external; + function stopBroadcast() external; } // console is a minimal version of the console2 lib. @@ -64,6 +69,9 @@ contract ScriptExample { address internal constant VM_ADDRESS = address(uint160(uint256(keccak256("hevm cheat code")))); Vm internal constant vm = Vm(VM_ADDRESS); + // @notice counter variable to force non-pure calls. + uint256 public counter; + /// @notice example function, runs through basic cheat-codes and console logs. function run() public { bool x = vm.envOr("EXAMPLE_BOOL", false); @@ -90,9 +98,81 @@ contract ScriptExample { console.log("done!"); } + /// @notice example function, to test vm.broadcast with. + function runBroadcast() public { + console.log("nonce start", uint256(vm.getNonce(address(this)))); + + console.log("testing single"); + vm.broadcast(); + this.call1("single_call1"); + this.call2("single_call2"); + + console.log("testing start/stop"); + vm.startBroadcast(address(uint160(0xc0ffee))); + this.call1("startstop_call1"); + this.call2("startstop_call2"); + this.callPure("startstop_pure"); + vm.stopBroadcast(); + this.call1("startstop_call3"); + + console.log("testing nested"); + vm.startBroadcast(address(uint160(0x1234))); + this.nested1("nested"); + vm.stopBroadcast(); + + console.log("contract deployment"); + vm.broadcast(address(uint160(0x123456))); + FooBar x = new FooBar(1234); + require(x.foo() == 1234); + + console.log("create 2"); + vm.broadcast(address(uint160(0xcafe))); + FooBar y = new FooBar{salt: bytes32(uint256(42))}(1234); + require(y.foo() == 1234); + console.log("done!"); + + // Deploy a script without a pranked sender and check the nonce. + vm.broadcast(); + new FooBar(1234); + + console.log("nonce end", uint256(vm.getNonce(address(this)))); + } + /// @notice example external function, to force a CALL, and test vm.startPrank with. function hello(string calldata _v) external view { console.log(_v); console.log("hello msg.sender", address(msg.sender)); } + + function call1(string calldata _v) external { + counter++; + console.log(_v); + } + + function call2(string calldata _v) external { + counter++; + console.log(_v); + } + + function nested1(string calldata _v) external { + counter++; + this.nested2(_v); + } + + function nested2(string calldata _v) external { + counter++; + console.log(_v); + } + + function callPure(string calldata _v) external pure { + console.log(_v); + } +} + +contract FooBar { + uint256 public foo; + + constructor(uint256 v) { + foo = v; + } } diff --git a/op-chain-ops/script/testdata/test-artifacts/ScriptExample.s.sol/FooBar.json b/op-chain-ops/script/testdata/test-artifacts/ScriptExample.s.sol/FooBar.json new file mode 100644 index 0000000000000..ad4ac1569433c --- /dev/null +++ b/op-chain-ops/script/testdata/test-artifacts/ScriptExample.s.sol/FooBar.json @@ -0,0 +1 @@ +{"abi":[{"type":"constructor","inputs":[{"name":"v","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"function","name":"foo","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"}],"bytecode":{"object":"0x608060405234801561001057600080fd5b506040516100b23803806100b283398101604081905261002f91610037565b600055610050565b60006020828403121561004957600080fd5b5051919050565b60548061005e6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063c298557814602d575b600080fd5b603560005481565b60405190815260200160405180910390f3fea164736f6c634300080f000a","sourceMap":"5902:96:0:-:0;;;5949:47;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5982:3;:7;5902:96;;14:184:1;84:6;137:2;125:9;116:7;112:23;108:32;105:52;;;153:1;150;143:12;105:52;-1:-1:-1;176:16:1;;14:184;-1:-1:-1;14:184:1:o;:::-;5902:96:0;;;;;;","linkReferences":{}},"deployedBytecode":{"object":"0x6080604052348015600f57600080fd5b506004361060285760003560e01c8063c298557814602d575b600080fd5b603560005481565b60405190815260200160405180910390f3fea164736f6c634300080f000a","sourceMap":"5902:96:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5924:18;;;;;;;;;160:25:1;;;148:2;133:18;5924::0;;;;;;","linkReferences":{}},"methodIdentifiers":{"foo()":"c2985578"},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"v\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"foo\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"scripts/ScriptExample.s.sol\":\"FooBar\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[]},\"sources\":{\"scripts/ScriptExample.s.sol\":{\"keccak256\":\"0x8d1dfa41908e7ccc3a498a2a2aa51c5275bedbb904ce32d08f8598e36f896d8d\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5117bb7158363cae8b9dc0508d2852692fd36172f1c699ff680afbb5acebe1f3\",\"dweb:/ipfs/QmQdahJ8SPKfJ4yea5Ge9qaj5qh1TxVffhHvaWytBaL95h\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.15+commit.e14f2714"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"uint256","name":"v","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"stateMutability":"view","type":"function","name":"foo","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"remappings":[],"optimizer":{"enabled":true,"runs":999999},"metadata":{"bytecodeHash":"none"},"compilationTarget":{"scripts/ScriptExample.s.sol":"FooBar"},"evmVersion":"london","libraries":{}},"sources":{"scripts/ScriptExample.s.sol":{"keccak256":"0x8d1dfa41908e7ccc3a498a2a2aa51c5275bedbb904ce32d08f8598e36f896d8d","urls":["bzz-raw://5117bb7158363cae8b9dc0508d2852692fd36172f1c699ff680afbb5acebe1f3","dweb:/ipfs/QmQdahJ8SPKfJ4yea5Ge9qaj5qh1TxVffhHvaWytBaL95h"],"license":"MIT"}},"version":1},"storageLayout":{"storage":[{"astId":708,"contract":"scripts/ScriptExample.s.sol:FooBar","label":"foo","offset":0,"slot":"0","type":"t_uint256"}],"types":{"t_uint256":{"encoding":"inplace","label":"uint256","numberOfBytes":"32"}}},"userdoc":{"version":1,"kind":"user"},"devdoc":{"version":1,"kind":"dev"},"ast":{"absolutePath":"scripts/ScriptExample.s.sol","id":720,"exportedSymbols":{"FooBar":[719],"ScriptExample":[706],"Vm":[55],"console":[192]},"nodeType":"SourceUnit","src":"32:5967:0","nodes":[{"id":1,"nodeType":"PragmaDirective","src":"32:23:0","nodes":[],"literals":["solidity","0.8",".15"]},{"id":55,"nodeType":"ContractDefinition","src":"120:616:0","nodes":[{"id":10,"nodeType":"FunctionDefinition","src":"139:91:0","nodes":[],"functionSelector":"4777f3cf","implemented":false,"kind":"function","modifiers":[],"name":"envOr","nameLocation":"148:5:0","parameters":{"id":6,"nodeType":"ParameterList","parameters":[{"constant":false,"id":3,"mutability":"mutable","name":"name","nameLocation":"170:4:0","nodeType":"VariableDeclaration","scope":10,"src":"154:20:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":2,"name":"string","nodeType":"ElementaryTypeName","src":"154:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":5,"mutability":"mutable","name":"defaultValue","nameLocation":"181:12:0","nodeType":"VariableDeclaration","scope":10,"src":"176:17:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":4,"name":"bool","nodeType":"ElementaryTypeName","src":"176:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"src":"153:41:0"},"returnParameters":{"id":9,"nodeType":"ParameterList","parameters":[{"constant":false,"id":8,"mutability":"mutable","name":"value","nameLocation":"223:5:0","nodeType":"VariableDeclaration","scope":10,"src":"218:10:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":7,"name":"bool","nodeType":"ElementaryTypeName","src":"218:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"src":"217:12:0"},"scope":55,"stateMutability":"view","virtual":false,"visibility":"external"},{"id":17,"nodeType":"FunctionDefinition","src":"235:72:0","nodes":[],"functionSelector":"2d0335ab","implemented":false,"kind":"function","modifiers":[],"name":"getNonce","nameLocation":"244:8:0","parameters":{"id":13,"nodeType":"ParameterList","parameters":[{"constant":false,"id":12,"mutability":"mutable","name":"account","nameLocation":"261:7:0","nodeType":"VariableDeclaration","scope":17,"src":"253:15:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":11,"name":"address","nodeType":"ElementaryTypeName","src":"253:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"252:17:0"},"returnParameters":{"id":16,"nodeType":"ParameterList","parameters":[{"constant":false,"id":15,"mutability":"mutable","name":"nonce","nameLocation":"300:5:0","nodeType":"VariableDeclaration","scope":17,"src":"293:12:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"},"typeName":{"id":14,"name":"uint64","nodeType":"ElementaryTypeName","src":"293:6:0","typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}},"visibility":"internal"}],"src":"292:14:0"},"scope":55,"stateMutability":"view","virtual":false,"visibility":"external"},{"id":27,"nodeType":"FunctionDefinition","src":"312:111:0","nodes":[],"functionSelector":"213e4198","implemented":false,"kind":"function","modifiers":[],"name":"parseJsonKeys","nameLocation":"321:13:0","parameters":{"id":22,"nodeType":"ParameterList","parameters":[{"constant":false,"id":19,"mutability":"mutable","name":"json","nameLocation":"351:4:0","nodeType":"VariableDeclaration","scope":27,"src":"335:20:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":18,"name":"string","nodeType":"ElementaryTypeName","src":"335:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":21,"mutability":"mutable","name":"key","nameLocation":"373:3:0","nodeType":"VariableDeclaration","scope":27,"src":"357:19:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":20,"name":"string","nodeType":"ElementaryTypeName","src":"357:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"334:43:0"},"returnParameters":{"id":26,"nodeType":"ParameterList","parameters":[{"constant":false,"id":25,"mutability":"mutable","name":"keys","nameLocation":"417:4:0","nodeType":"VariableDeclaration","scope":27,"src":"401:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string[]"},"typeName":{"baseType":{"id":23,"name":"string","nodeType":"ElementaryTypeName","src":"401:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"id":24,"nodeType":"ArrayTypeName","src":"401:8:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_storage_$dyn_storage_ptr","typeString":"string[]"}},"visibility":"internal"}],"src":"400:22:0"},"scope":55,"stateMutability":"pure","virtual":false,"visibility":"external"},{"id":32,"nodeType":"FunctionDefinition","src":"428:48:0","nodes":[],"functionSelector":"06447d56","implemented":false,"kind":"function","modifiers":[],"name":"startPrank","nameLocation":"437:10:0","parameters":{"id":30,"nodeType":"ParameterList","parameters":[{"constant":false,"id":29,"mutability":"mutable","name":"msgSender","nameLocation":"456:9:0","nodeType":"VariableDeclaration","scope":32,"src":"448:17:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":28,"name":"address","nodeType":"ElementaryTypeName","src":"448:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"447:19:0"},"returnParameters":{"id":31,"nodeType":"ParameterList","parameters":[],"src":"475:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":35,"nodeType":"FunctionDefinition","src":"481:30:0","nodes":[],"functionSelector":"90c5013b","implemented":false,"kind":"function","modifiers":[],"name":"stopPrank","nameLocation":"490:9:0","parameters":{"id":33,"nodeType":"ParameterList","parameters":[],"src":"499:2:0"},"returnParameters":{"id":34,"nodeType":"ParameterList","parameters":[],"src":"510:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":38,"nodeType":"FunctionDefinition","src":"516:30:0","nodes":[],"functionSelector":"afc98040","implemented":false,"kind":"function","modifiers":[],"name":"broadcast","nameLocation":"525:9:0","parameters":{"id":36,"nodeType":"ParameterList","parameters":[],"src":"534:2:0"},"returnParameters":{"id":37,"nodeType":"ParameterList","parameters":[],"src":"545:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":43,"nodeType":"FunctionDefinition","src":"551:47:0","nodes":[],"functionSelector":"e6962cdb","implemented":false,"kind":"function","modifiers":[],"name":"broadcast","nameLocation":"560:9:0","parameters":{"id":41,"nodeType":"ParameterList","parameters":[{"constant":false,"id":40,"mutability":"mutable","name":"msgSender","nameLocation":"578:9:0","nodeType":"VariableDeclaration","scope":43,"src":"570:17:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":39,"name":"address","nodeType":"ElementaryTypeName","src":"570:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"569:19:0"},"returnParameters":{"id":42,"nodeType":"ParameterList","parameters":[],"src":"597:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":48,"nodeType":"FunctionDefinition","src":"603:52:0","nodes":[],"functionSelector":"7fec2a8d","implemented":false,"kind":"function","modifiers":[],"name":"startBroadcast","nameLocation":"612:14:0","parameters":{"id":46,"nodeType":"ParameterList","parameters":[{"constant":false,"id":45,"mutability":"mutable","name":"msgSender","nameLocation":"635:9:0","nodeType":"VariableDeclaration","scope":48,"src":"627:17:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":44,"name":"address","nodeType":"ElementaryTypeName","src":"627:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"626:19:0"},"returnParameters":{"id":47,"nodeType":"ParameterList","parameters":[],"src":"654:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":51,"nodeType":"FunctionDefinition","src":"660:35:0","nodes":[],"functionSelector":"7fb5297f","implemented":false,"kind":"function","modifiers":[],"name":"startBroadcast","nameLocation":"669:14:0","parameters":{"id":49,"nodeType":"ParameterList","parameters":[],"src":"683:2:0"},"returnParameters":{"id":50,"nodeType":"ParameterList","parameters":[],"src":"694:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":54,"nodeType":"FunctionDefinition","src":"700:34:0","nodes":[],"functionSelector":"76eadd36","implemented":false,"kind":"function","modifiers":[],"name":"stopBroadcast","nameLocation":"709:13:0","parameters":{"id":52,"nodeType":"ParameterList","parameters":[],"src":"722:2:0"},"returnParameters":{"id":53,"nodeType":"ParameterList","parameters":[],"src":"733:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"}],"abstract":false,"baseContracts":[],"canonicalName":"Vm","contractDependencies":[],"contractKind":"interface","fullyImplemented":false,"linearizedBaseContracts":[55],"name":"Vm","nameLocation":"130:2:0","scope":720,"usedErrors":[]},{"id":192,"nodeType":"ContractDefinition","src":"791:1622:0","nodes":[{"id":61,"nodeType":"VariableDeclaration","src":"813:86:0","nodes":[],"constant":true,"mutability":"constant","name":"CONSOLE_ADDRESS","nameLocation":"830:15:0","scope":192,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":56,"name":"address","nodeType":"ElementaryTypeName","src":"813:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"value":{"arguments":[{"hexValue":"307830303030303030303030303030303030303036333646366537333646366336353265366336663637","id":59,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"856:42:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"value":"0x000000000000000000636F6e736F6c652e6c6f67"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":58,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"848:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":57,"name":"address","nodeType":"ElementaryTypeName","src":"848:7:0","typeDescriptions":{}}},"id":60,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"848:51:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"},{"id":78,"nodeType":"FunctionDefinition","src":"906:221:0","nodes":[],"body":{"id":77,"nodeType":"Block","src":"1065:62:0","nodes":[],"statements":[{"AST":{"nodeType":"YulBlock","src":"1084:37:0","statements":[{"nodeType":"YulAssignment","src":"1098:13:0","value":{"name":"fnIn","nodeType":"YulIdentifier","src":"1107:4:0"},"variableNames":[{"name":"fnOut","nodeType":"YulIdentifier","src":"1098:5:0"}]}]},"evmVersion":"london","externalReferences":[{"declaration":67,"isOffset":false,"isSlot":false,"src":"1107:4:0","valueSize":1},{"declaration":74,"isOffset":false,"isSlot":false,"src":"1098:5:0","valueSize":1}],"id":76,"nodeType":"InlineAssembly","src":"1075:46:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"_castLogPayloadViewToPure","nameLocation":"915:25:0","parameters":{"id":68,"nodeType":"ParameterList","parameters":[{"constant":false,"id":67,"mutability":"mutable","name":"fnIn","nameLocation":"987:4:0","nodeType":"VariableDeclaration","scope":78,"src":"950:41:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) view"},"typeName":{"id":66,"nodeType":"FunctionTypeName","parameterTypes":{"id":64,"nodeType":"ParameterList","parameters":[{"constant":false,"id":63,"mutability":"mutable","name":"","nameLocation":"-1:-1:-1","nodeType":"VariableDeclaration","scope":66,"src":"959:12:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":62,"name":"bytes","nodeType":"ElementaryTypeName","src":"959:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"958:14:0"},"returnParameterTypes":{"id":65,"nodeType":"ParameterList","parameters":[],"src":"987:0:0"},"src":"950:41:0","stateMutability":"view","typeDescriptions":{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) view"},"visibility":"internal"},"visibility":"internal"}],"src":"940:57:0"},"returnParameters":{"id":75,"nodeType":"ParameterList","parameters":[{"constant":false,"id":74,"mutability":"mutable","name":"fnOut","nameLocation":"1058:5:0","nodeType":"VariableDeclaration","scope":78,"src":"1021:42:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) pure"},"typeName":{"id":73,"nodeType":"FunctionTypeName","parameterTypes":{"id":71,"nodeType":"ParameterList","parameters":[{"constant":false,"id":70,"mutability":"mutable","name":"","nameLocation":"-1:-1:-1","nodeType":"VariableDeclaration","scope":73,"src":"1030:12:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":69,"name":"bytes","nodeType":"ElementaryTypeName","src":"1030:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"1029:14:0"},"returnParameterTypes":{"id":72,"nodeType":"ParameterList","parameters":[],"src":"1058:0:0"},"src":"1021:42:0","stateMutability":"pure","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) pure"},"visibility":"internal"},"visibility":"internal"}],"src":"1020:44:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":90,"nodeType":"FunctionDefinition","src":"1133:133:0","nodes":[],"body":{"id":89,"nodeType":"Block","src":"1194:72:0","nodes":[],"statements":[{"expression":{"arguments":[{"id":86,"name":"payload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":80,"src":"1251:7:0","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"arguments":[{"id":84,"name":"_sendLogPayloadView","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":106,"src":"1230:19:0","typeDescriptions":{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) view"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) view"}],"id":83,"name":"_castLogPayloadViewToPure","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":78,"src":"1204:25:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_function_internal_view$_t_bytes_memory_ptr_$returns$__$_$returns$_t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$_$","typeString":"function (function (bytes memory) view) pure returns (function (bytes memory) pure)"}},"id":85,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1204:46:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":87,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1204:55:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":88,"nodeType":"ExpressionStatement","src":"1204:55:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"_sendLogPayload","nameLocation":"1142:15:0","parameters":{"id":81,"nodeType":"ParameterList","parameters":[{"constant":false,"id":80,"mutability":"mutable","name":"payload","nameLocation":"1171:7:0","nodeType":"VariableDeclaration","scope":90,"src":"1158:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":79,"name":"bytes","nodeType":"ElementaryTypeName","src":"1158:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"1157:22:0"},"returnParameters":{"id":82,"nodeType":"ParameterList","parameters":[],"src":"1194:0:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":106,"nodeType":"FunctionDefinition","src":"1272:380:0","nodes":[],"body":{"id":105,"nodeType":"Block","src":"1336:316:0","nodes":[],"statements":[{"assignments":[96],"declarations":[{"constant":false,"id":96,"mutability":"mutable","name":"payloadLength","nameLocation":"1354:13:0","nodeType":"VariableDeclaration","scope":105,"src":"1346:21:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":95,"name":"uint256","nodeType":"ElementaryTypeName","src":"1346:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"}],"id":99,"initialValue":{"expression":{"id":97,"name":"payload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":92,"src":"1370:7:0","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}},"id":98,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"length","nodeType":"MemberAccess","src":"1370:14:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"nodeType":"VariableDeclarationStatement","src":"1346:38:0"},{"assignments":[101],"declarations":[{"constant":false,"id":101,"mutability":"mutable","name":"consoleAddress","nameLocation":"1402:14:0","nodeType":"VariableDeclaration","scope":105,"src":"1394:22:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":100,"name":"address","nodeType":"ElementaryTypeName","src":"1394:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"id":103,"initialValue":{"id":102,"name":"CONSOLE_ADDRESS","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":61,"src":"1419:15:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"nodeType":"VariableDeclarationStatement","src":"1394:40:0"},{"AST":{"nodeType":"YulBlock","src":"1496:150:0","statements":[{"nodeType":"YulVariableDeclaration","src":"1510:36:0","value":{"arguments":[{"name":"payload","nodeType":"YulIdentifier","src":"1534:7:0"},{"kind":"number","nodeType":"YulLiteral","src":"1543:2:0","type":"","value":"32"}],"functionName":{"name":"add","nodeType":"YulIdentifier","src":"1530:3:0"},"nodeType":"YulFunctionCall","src":"1530:16:0"},"variables":[{"name":"payloadStart","nodeType":"YulTypedName","src":"1514:12:0","type":""}]},{"nodeType":"YulVariableDeclaration","src":"1559:77:0","value":{"arguments":[{"arguments":[],"functionName":{"name":"gas","nodeType":"YulIdentifier","src":"1579:3:0"},"nodeType":"YulFunctionCall","src":"1579:5:0"},{"name":"consoleAddress","nodeType":"YulIdentifier","src":"1586:14:0"},{"name":"payloadStart","nodeType":"YulIdentifier","src":"1602:12:0"},{"name":"payloadLength","nodeType":"YulIdentifier","src":"1616:13:0"},{"kind":"number","nodeType":"YulLiteral","src":"1631:1:0","type":"","value":"0"},{"kind":"number","nodeType":"YulLiteral","src":"1634:1:0","type":"","value":"0"}],"functionName":{"name":"staticcall","nodeType":"YulIdentifier","src":"1568:10:0"},"nodeType":"YulFunctionCall","src":"1568:68:0"},"variables":[{"name":"r","nodeType":"YulTypedName","src":"1563:1:0","type":""}]}]},"documentation":"@solidity memory-safe-assembly","evmVersion":"london","externalReferences":[{"declaration":101,"isOffset":false,"isSlot":false,"src":"1586:14:0","valueSize":1},{"declaration":92,"isOffset":false,"isSlot":false,"src":"1534:7:0","valueSize":1},{"declaration":96,"isOffset":false,"isSlot":false,"src":"1616:13:0","valueSize":1}],"id":104,"nodeType":"InlineAssembly","src":"1487:159:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"_sendLogPayloadView","nameLocation":"1281:19:0","parameters":{"id":93,"nodeType":"ParameterList","parameters":[{"constant":false,"id":92,"mutability":"mutable","name":"payload","nameLocation":"1314:7:0","nodeType":"VariableDeclaration","scope":106,"src":"1301:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":91,"name":"bytes","nodeType":"ElementaryTypeName","src":"1301:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"1300:22:0"},"returnParameters":{"id":94,"nodeType":"ParameterList","parameters":[],"src":"1336:0:0"},"scope":192,"stateMutability":"view","virtual":false,"visibility":"private"},{"id":120,"nodeType":"FunctionDefinition","src":"1658:121:0","nodes":[],"body":{"id":119,"nodeType":"Block","src":"1703:76:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e6729","id":114,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"1753:13:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_41304facd9323d75b11bcdd609cb38effffdb05710f7caf0e9b16c6d9d709f50","typeString":"literal_string \"log(string)\""},"value":"log(string)"},{"id":115,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":108,"src":"1768:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_41304facd9323d75b11bcdd609cb38effffdb05710f7caf0e9b16c6d9d709f50","typeString":"literal_string \"log(string)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}],"expression":{"id":112,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"1729:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":113,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"1729:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":116,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1729:42:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":111,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":90,"src":"1713:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":117,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1713:59:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":118,"nodeType":"ExpressionStatement","src":"1713:59:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"1667:3:0","parameters":{"id":109,"nodeType":"ParameterList","parameters":[{"constant":false,"id":108,"mutability":"mutable","name":"p0","nameLocation":"1685:2:0","nodeType":"VariableDeclaration","scope":120,"src":"1671:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":107,"name":"string","nodeType":"ElementaryTypeName","src":"1671:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"1670:18:0"},"returnParameters":{"id":110,"nodeType":"ParameterList","parameters":[],"src":"1703:0:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":137,"nodeType":"FunctionDefinition","src":"1785:139:0","nodes":[],"body":{"id":136,"nodeType":"Block","src":"1839:85:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c626f6f6c29","id":130,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"1889:18:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_c3b556354c088fbb43886eb83c2a04bc7089663f964d22be308197a236f5b870","typeString":"literal_string \"log(string,bool)\""},"value":"log(string,bool)"},{"id":131,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":122,"src":"1909:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":132,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":124,"src":"1913:2:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_c3b556354c088fbb43886eb83c2a04bc7089663f964d22be308197a236f5b870","typeString":"literal_string \"log(string,bool)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_bool","typeString":"bool"}],"expression":{"id":128,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"1865:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":129,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"1865:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":133,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1865:51:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":127,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":90,"src":"1849:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":134,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1849:68:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":135,"nodeType":"ExpressionStatement","src":"1849:68:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"1794:3:0","parameters":{"id":125,"nodeType":"ParameterList","parameters":[{"constant":false,"id":122,"mutability":"mutable","name":"p0","nameLocation":"1812:2:0","nodeType":"VariableDeclaration","scope":137,"src":"1798:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":121,"name":"string","nodeType":"ElementaryTypeName","src":"1798:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":124,"mutability":"mutable","name":"p1","nameLocation":"1821:2:0","nodeType":"VariableDeclaration","scope":137,"src":"1816:7:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":123,"name":"bool","nodeType":"ElementaryTypeName","src":"1816:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"src":"1797:27:0"},"returnParameters":{"id":126,"nodeType":"ParameterList","parameters":[],"src":"1839:0:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":154,"nodeType":"FunctionDefinition","src":"1930:145:0","nodes":[],"body":{"id":153,"nodeType":"Block","src":"1987:88:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c75696e7432353629","id":147,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2037:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_b60e72ccf6d57ab53eb84d7e94a9545806ed7f93c4d5673f11a64f03471e584e","typeString":"literal_string \"log(string,uint256)\""},"value":"log(string,uint256)"},{"id":148,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":139,"src":"2060:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":149,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":141,"src":"2064:2:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_b60e72ccf6d57ab53eb84d7e94a9545806ed7f93c4d5673f11a64f03471e584e","typeString":"literal_string \"log(string,uint256)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_uint256","typeString":"uint256"}],"expression":{"id":145,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"2013:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":146,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"2013:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":150,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2013:54:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":144,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":90,"src":"1997:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":151,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1997:71:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":152,"nodeType":"ExpressionStatement","src":"1997:71:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"1939:3:0","parameters":{"id":142,"nodeType":"ParameterList","parameters":[{"constant":false,"id":139,"mutability":"mutable","name":"p0","nameLocation":"1957:2:0","nodeType":"VariableDeclaration","scope":154,"src":"1943:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":138,"name":"string","nodeType":"ElementaryTypeName","src":"1943:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":141,"mutability":"mutable","name":"p1","nameLocation":"1969:2:0","nodeType":"VariableDeclaration","scope":154,"src":"1961:10:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":140,"name":"uint256","nodeType":"ElementaryTypeName","src":"1961:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"}],"src":"1942:30:0"},"returnParameters":{"id":143,"nodeType":"ParameterList","parameters":[],"src":"1987:0:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":171,"nodeType":"FunctionDefinition","src":"2081:145:0","nodes":[],"body":{"id":170,"nodeType":"Block","src":"2138:88:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c6164647265737329","id":164,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2188:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_319af333460570a1937bf195dd33445c0d0951c59127da6f1f038b9fdce3fd72","typeString":"literal_string \"log(string,address)\""},"value":"log(string,address)"},{"id":165,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":156,"src":"2211:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":166,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":158,"src":"2215:2:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_319af333460570a1937bf195dd33445c0d0951c59127da6f1f038b9fdce3fd72","typeString":"literal_string \"log(string,address)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":162,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"2164:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":163,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"2164:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":167,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2164:54:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":161,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":90,"src":"2148:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":168,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2148:71:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":169,"nodeType":"ExpressionStatement","src":"2148:71:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"2090:3:0","parameters":{"id":159,"nodeType":"ParameterList","parameters":[{"constant":false,"id":156,"mutability":"mutable","name":"p0","nameLocation":"2108:2:0","nodeType":"VariableDeclaration","scope":171,"src":"2094:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":155,"name":"string","nodeType":"ElementaryTypeName","src":"2094:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":158,"mutability":"mutable","name":"p1","nameLocation":"2120:2:0","nodeType":"VariableDeclaration","scope":171,"src":"2112:10:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":157,"name":"address","nodeType":"ElementaryTypeName","src":"2112:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"2093:30:0"},"returnParameters":{"id":160,"nodeType":"ParameterList","parameters":[],"src":"2138:0:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":191,"nodeType":"FunctionDefinition","src":"2232:179:0","nodes":[],"body":{"id":190,"nodeType":"Block","src":"2313:98:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c737472696e672c737472696e6729","id":183,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2363:27:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_2ced7cef693312206c21f0e92e3b54e2e16bf33db5eec350c78866822c665e1f","typeString":"literal_string \"log(string,string,string)\""},"value":"log(string,string,string)"},{"id":184,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"2392:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":185,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":175,"src":"2396:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":186,"name":"p2","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":177,"src":"2400:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_2ced7cef693312206c21f0e92e3b54e2e16bf33db5eec350c78866822c665e1f","typeString":"literal_string \"log(string,string,string)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}],"expression":{"id":181,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"2339:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":182,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"2339:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":187,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2339:64:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":180,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":90,"src":"2323:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":188,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2323:81:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":189,"nodeType":"ExpressionStatement","src":"2323:81:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"2241:3:0","parameters":{"id":178,"nodeType":"ParameterList","parameters":[{"constant":false,"id":173,"mutability":"mutable","name":"p0","nameLocation":"2259:2:0","nodeType":"VariableDeclaration","scope":191,"src":"2245:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":172,"name":"string","nodeType":"ElementaryTypeName","src":"2245:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":175,"mutability":"mutable","name":"p1","nameLocation":"2277:2:0","nodeType":"VariableDeclaration","scope":191,"src":"2263:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":174,"name":"string","nodeType":"ElementaryTypeName","src":"2263:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":177,"mutability":"mutable","name":"p2","nameLocation":"2295:2:0","nodeType":"VariableDeclaration","scope":191,"src":"2281:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":176,"name":"string","nodeType":"ElementaryTypeName","src":"2281:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"2244:54:0"},"returnParameters":{"id":179,"nodeType":"ParameterList","parameters":[],"src":"2313:0:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"}],"abstract":false,"baseContracts":[],"canonicalName":"console","contractDependencies":[],"contractKind":"library","fullyImplemented":true,"linearizedBaseContracts":[192],"name":"console","nameLocation":"799:7:0","scope":720,"usedErrors":[]},{"id":706,"nodeType":"ContractDefinition","src":"2541:3359:0","nodes":[{"id":207,"nodeType":"VariableDeclaration","src":"2571:94:0","nodes":[],"constant":true,"mutability":"constant","name":"VM_ADDRESS","nameLocation":"2597:10:0","scope":706,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":194,"name":"address","nodeType":"ElementaryTypeName","src":"2571:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"value":{"arguments":[{"arguments":[{"arguments":[{"arguments":[{"hexValue":"6865766d20636865617420636f6465","id":202,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2644:17:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d","typeString":"literal_string \"hevm cheat code\""},"value":"hevm cheat code"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d","typeString":"literal_string \"hevm cheat code\""}],"id":201,"name":"keccak256","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-8,"src":"2634:9:0","typeDescriptions":{"typeIdentifier":"t_function_keccak256_pure$_t_bytes_memory_ptr_$returns$_t_bytes32_$","typeString":"function (bytes memory) pure returns (bytes32)"}},"id":203,"isConstant":false,"isLValue":false,"isPure":true,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2634:28:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes32","typeString":"bytes32"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes32","typeString":"bytes32"}],"id":200,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2626:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint256_$","typeString":"type(uint256)"},"typeName":{"id":199,"name":"uint256","nodeType":"ElementaryTypeName","src":"2626:7:0","typeDescriptions":{}}},"id":204,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2626:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint256","typeString":"uint256"}],"id":198,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2618:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":197,"name":"uint160","nodeType":"ElementaryTypeName","src":"2618:7:0","typeDescriptions":{}}},"id":205,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2618:46:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":196,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2610:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":195,"name":"address","nodeType":"ElementaryTypeName","src":"2610:7:0","typeDescriptions":{}}},"id":206,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2610:55:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"},{"id":213,"nodeType":"VariableDeclaration","src":"2671:40:0","nodes":[],"constant":true,"mutability":"constant","name":"vm","nameLocation":"2692:2:0","scope":706,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"},"typeName":{"id":209,"nodeType":"UserDefinedTypeName","pathNode":{"id":208,"name":"Vm","nodeType":"IdentifierPath","referencedDeclaration":55,"src":"2671:2:0"},"referencedDeclaration":55,"src":"2671:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"value":{"arguments":[{"id":211,"name":"VM_ADDRESS","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":207,"src":"2700:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":210,"name":"Vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":55,"src":"2697:2:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_Vm_$55_$","typeString":"type(contract Vm)"}},"id":212,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2697:14:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"visibility":"internal"},{"id":215,"nodeType":"VariableDeclaration","src":"2775:22:0","nodes":[],"constant":false,"functionSelector":"61bc221a","mutability":"mutable","name":"counter","nameLocation":"2790:7:0","scope":706,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":214,"name":"uint256","nodeType":"ElementaryTypeName","src":"2775:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"public"},{"id":378,"nodeType":"FunctionDefinition","src":"2887:949:0","nodes":[],"body":{"id":377,"nodeType":"Block","src":"2909:927:0","nodes":[],"statements":[{"assignments":[220],"declarations":[{"constant":false,"id":220,"mutability":"mutable","name":"x","nameLocation":"2924:1:0","nodeType":"VariableDeclaration","scope":377,"src":"2919:6:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":219,"name":"bool","nodeType":"ElementaryTypeName","src":"2919:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"id":226,"initialValue":{"arguments":[{"hexValue":"4558414d504c455f424f4f4c","id":223,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2937:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_a634dae177a0e138ae7aaa2afae347412e148992e88c7aabd33ee71be146cb7f","typeString":"literal_string \"EXAMPLE_BOOL\""},"value":"EXAMPLE_BOOL"},{"hexValue":"66616c7365","id":224,"isConstant":false,"isLValue":false,"isPure":true,"kind":"bool","lValueRequested":false,"nodeType":"Literal","src":"2953:5:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"value":"false"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_a634dae177a0e138ae7aaa2afae347412e148992e88c7aabd33ee71be146cb7f","typeString":"literal_string \"EXAMPLE_BOOL\""},{"typeIdentifier":"t_bool","typeString":"bool"}],"expression":{"id":221,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"2928:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":222,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"envOr","nodeType":"MemberAccess","referencedDeclaration":10,"src":"2928:8:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$_t_bool_$returns$_t_bool_$","typeString":"function (string memory,bool) view external returns (bool)"}},"id":225,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2928:31:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"nodeType":"VariableDeclarationStatement","src":"2919:40:0"},{"expression":{"arguments":[{"hexValue":"626f6f6c2076616c75652066726f6d20656e76","id":230,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2981:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_5a607d0b5a1295325aa8901721d78ba402601bba6f62cebdd5235dd0204a590b","typeString":"literal_string \"bool value from env\""},"value":"bool value from env"},{"id":231,"name":"x","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":220,"src":"3004:1:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_5a607d0b5a1295325aa8901721d78ba402601bba6f62cebdd5235dd0204a590b","typeString":"literal_string \"bool value from env\""},{"typeIdentifier":"t_bool","typeString":"bool"}],"expression":{"id":227,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"2969:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":229,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":137,"src":"2969:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_bool_$returns$__$","typeString":"function (string memory,bool) pure"}},"id":232,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2969:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":233,"nodeType":"ExpressionStatement","src":"2969:37:0"},{"expression":{"arguments":[{"hexValue":"636f6e74726163742061646472","id":237,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3029:15:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_fa50728770d00fe8f6a0592f3565bbfaf063ee4077f1f5bbc003d091d33cd0c4","typeString":"literal_string \"contract addr\""},"value":"contract addr"},{"arguments":[{"id":240,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3054:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}],"id":239,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3046:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":238,"name":"address","nodeType":"ElementaryTypeName","src":"3046:7:0","typeDescriptions":{}}},"id":241,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3046:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_fa50728770d00fe8f6a0592f3565bbfaf063ee4077f1f5bbc003d091d33cd0c4","typeString":"literal_string \"contract addr\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":234,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3017:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":236,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":171,"src":"3017:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":242,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3017:43:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":243,"nodeType":"ExpressionStatement","src":"3017:43:0"},{"expression":{"arguments":[{"hexValue":"636f6e7472616374206e6f6e6365","id":247,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3082:16:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_3a23091615a5de8c0a35ffd8857a37e2c4e0b72f3ef8a34d6caf65efcd562e2f","typeString":"literal_string \"contract nonce\""},"value":"contract nonce"},{"arguments":[{"arguments":[{"id":252,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3120:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}],"id":251,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3112:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":250,"name":"address","nodeType":"ElementaryTypeName","src":"3112:7:0","typeDescriptions":{}}},"id":253,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3112:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":248,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"3100:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":249,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"getNonce","nodeType":"MemberAccess","referencedDeclaration":17,"src":"3100:11:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_address_$returns$_t_uint64_$","typeString":"function (address) view external returns (uint64)"}},"id":254,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3100:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_3a23091615a5de8c0a35ffd8857a37e2c4e0b72f3ef8a34d6caf65efcd562e2f","typeString":"literal_string \"contract nonce\""},{"typeIdentifier":"t_uint64","typeString":"uint64"}],"expression":{"id":244,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3070:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":246,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":154,"src":"3070:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_uint256_$returns$__$","typeString":"function (string memory,uint256) pure"}},"id":255,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3070:57:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":256,"nodeType":"ExpressionStatement","src":"3070:57:0"},{"expression":{"arguments":[{"hexValue":"73656e6465722061646472","id":260,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3149:13:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_8125ca2decf812b25b65606ff16dad37cb198ff0433485a7926e50feafacfc35","typeString":"literal_string \"sender addr\""},"value":"sender addr"},{"arguments":[{"expression":{"id":263,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"3172:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":264,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"3172:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":262,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3164:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":261,"name":"address","nodeType":"ElementaryTypeName","src":"3164:7:0","typeDescriptions":{}}},"id":265,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3164:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_8125ca2decf812b25b65606ff16dad37cb198ff0433485a7926e50feafacfc35","typeString":"literal_string \"sender addr\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":257,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3137:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":259,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":171,"src":"3137:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":266,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3137:47:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":267,"nodeType":"ExpressionStatement","src":"3137:47:0"},{"expression":{"arguments":[{"hexValue":"73656e646572206e6f6e6365","id":271,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3206:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_db7deb43f2f9e0404016de53b7e64c4976b54149581f7534daae2551e8cf4e40","typeString":"literal_string \"sender nonce\""},"value":"sender nonce"},{"arguments":[{"arguments":[{"expression":{"id":276,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"3242:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":277,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"3242:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":275,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3234:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":274,"name":"address","nodeType":"ElementaryTypeName","src":"3234:7:0","typeDescriptions":{}}},"id":278,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3234:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":272,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"3222:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":273,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"getNonce","nodeType":"MemberAccess","referencedDeclaration":17,"src":"3222:11:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_address_$returns$_t_uint64_$","typeString":"function (address) view external returns (uint64)"}},"id":279,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3222:32:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_db7deb43f2f9e0404016de53b7e64c4976b54149581f7534daae2551e8cf4e40","typeString":"literal_string \"sender nonce\""},{"typeIdentifier":"t_uint64","typeString":"uint64"}],"expression":{"id":268,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3194:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":270,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":154,"src":"3194:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_uint256_$returns$__$","typeString":"function (string memory,uint256) pure"}},"id":280,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3194:61:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":281,"nodeType":"ExpressionStatement","src":"3194:61:0"},{"assignments":[283],"declarations":[{"constant":false,"id":283,"mutability":"mutable","name":"json","nameLocation":"3280:4:0","nodeType":"VariableDeclaration","scope":377,"src":"3266:18:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":282,"name":"string","nodeType":"ElementaryTypeName","src":"3266:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"id":285,"initialValue":{"hexValue":"7b22726f6f745f6b6579223a205b7b2261223a20312c202262223a20327d5d7d","id":284,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3287:34:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_e95522e99766888d0261f55bd1eae5e3f3e26eaf009a16e2433eafaf0a4ecdf2","typeString":"literal_string \"{\"root_key\": [{\"a\": 1, \"b\": 2}]}\""},"value":"{\"root_key\": [{\"a\": 1, \"b\": 2}]}"},"nodeType":"VariableDeclarationStatement","src":"3266:55:0"},{"assignments":[290],"declarations":[{"constant":false,"id":290,"mutability":"mutable","name":"keys","nameLocation":"3347:4:0","nodeType":"VariableDeclaration","scope":377,"src":"3331:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string[]"},"typeName":{"baseType":{"id":288,"name":"string","nodeType":"ElementaryTypeName","src":"3331:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"id":289,"nodeType":"ArrayTypeName","src":"3331:8:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_storage_$dyn_storage_ptr","typeString":"string[]"}},"visibility":"internal"}],"id":296,"initialValue":{"arguments":[{"id":293,"name":"json","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":283,"src":"3371:4:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"hexValue":"2e726f6f745f6b65795b305d","id":294,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3377:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_d82f67100edb80050915e1ec4b565c9a8319a22efb1075e1298b7bb60101d266","typeString":"literal_string \".root_key[0]\""},"value":".root_key[0]"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_stringliteral_d82f67100edb80050915e1ec4b565c9a8319a22efb1075e1298b7bb60101d266","typeString":"literal_string \".root_key[0]\""}],"expression":{"id":291,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"3354:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":292,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"parseJsonKeys","nodeType":"MemberAccess","referencedDeclaration":27,"src":"3354:16:0","typeDescriptions":{"typeIdentifier":"t_function_external_pure$_t_string_memory_ptr_$_t_string_memory_ptr_$returns$_t_array$_t_string_memory_ptr_$dyn_memory_ptr_$","typeString":"function (string memory,string memory) pure external returns (string memory[] memory)"}},"id":295,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3354:38:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string memory[] memory"}},"nodeType":"VariableDeclarationStatement","src":"3331:61:0"},{"expression":{"arguments":[{"hexValue":"6b657973","id":300,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3414:6:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_f29790a80c4ce5f42f59892f424f9c92856c6b656c3378e2cf305b260c6f4195","typeString":"literal_string \"keys\""},"value":"keys"},{"baseExpression":{"id":301,"name":"keys","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":290,"src":"3422:4:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string memory[] memory"}},"id":303,"indexExpression":{"hexValue":"30","id":302,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"3427:1:0","typeDescriptions":{"typeIdentifier":"t_rational_0_by_1","typeString":"int_const 0"},"value":"0"},"isConstant":false,"isLValue":true,"isPure":false,"lValueRequested":false,"nodeType":"IndexAccess","src":"3422:7:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"baseExpression":{"id":304,"name":"keys","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":290,"src":"3431:4:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string memory[] memory"}},"id":306,"indexExpression":{"hexValue":"31","id":305,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"3436:1:0","typeDescriptions":{"typeIdentifier":"t_rational_1_by_1","typeString":"int_const 1"},"value":"1"},"isConstant":false,"isLValue":true,"isPure":false,"lValueRequested":false,"nodeType":"IndexAccess","src":"3431:7:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_f29790a80c4ce5f42f59892f424f9c92856c6b656c3378e2cf305b260c6f4195","typeString":"literal_string \"keys\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}],"expression":{"id":297,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3402:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":299,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":191,"src":"3402:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_string_memory_ptr_$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory,string memory,string memory) pure"}},"id":307,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3402:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":308,"nodeType":"ExpressionStatement","src":"3402:37:0"},{"expression":{"arguments":[{"hexValue":"66726f6d206f726967696e616c","id":312,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3461:15:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_77928970c8757d110f3c23e003246f49e0de890480ba9717ba659b2f56f316b2","typeString":"literal_string \"from original\""},"value":"from original"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_77928970c8757d110f3c23e003246f49e0de890480ba9717ba659b2f56f316b2","typeString":"literal_string \"from original\""}],"expression":{"id":309,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3450:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":311,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":633,"src":"3450:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":313,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3450:27:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":314,"nodeType":"ExpressionStatement","src":"3450:27:0"},{"expression":{"arguments":[{"arguments":[{"arguments":[{"hexValue":"30783432","id":322,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"3517:4:0","typeDescriptions":{"typeIdentifier":"t_rational_66_by_1","typeString":"int_const 66"},"value":"0x42"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_66_by_1","typeString":"int_const 66"}],"id":321,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3509:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":320,"name":"uint160","nodeType":"ElementaryTypeName","src":"3509:7:0","typeDescriptions":{}}},"id":323,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3509:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":319,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3501:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":318,"name":"address","nodeType":"ElementaryTypeName","src":"3501:7:0","typeDescriptions":{}}},"id":324,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3501:22:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":315,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"3487:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":317,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"startPrank","nodeType":"MemberAccess","referencedDeclaration":32,"src":"3487:13:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_address_$returns$__$","typeString":"function (address) external"}},"id":325,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3487:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":326,"nodeType":"ExpressionStatement","src":"3487:37:0"},{"expression":{"arguments":[{"hexValue":"66726f6d207072616e6b2031","id":330,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3545:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_42b34abfe37a8b0add910cda7b4a379e6538fa7a1dcafce47a02bd38f6c88e2a","typeString":"literal_string \"from prank 1\""},"value":"from prank 1"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_42b34abfe37a8b0add910cda7b4a379e6538fa7a1dcafce47a02bd38f6c88e2a","typeString":"literal_string \"from prank 1\""}],"expression":{"id":327,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3534:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":329,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":633,"src":"3534:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":331,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3534:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":332,"nodeType":"ExpressionStatement","src":"3534:26:0"},{"expression":{"arguments":[{"hexValue":"706172656e742073636f7065206d73672e73656e646572","id":336,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3582:25:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_83ec9246154d8845de47aafc5c2865c9985d2efe84472c27283879f2fbf5cc94","typeString":"literal_string \"parent scope msg.sender\""},"value":"parent scope msg.sender"},{"arguments":[{"expression":{"id":339,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"3617:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":340,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"3617:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":338,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3609:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":337,"name":"address","nodeType":"ElementaryTypeName","src":"3609:7:0","typeDescriptions":{}}},"id":341,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3609:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_83ec9246154d8845de47aafc5c2865c9985d2efe84472c27283879f2fbf5cc94","typeString":"literal_string \"parent scope msg.sender\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":333,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3570:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":335,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":171,"src":"3570:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":342,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3570:59:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":343,"nodeType":"ExpressionStatement","src":"3570:59:0"},{"expression":{"arguments":[{"hexValue":"706172656e742073636f706520636f6e74726163742e61646472","id":347,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3651:28:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_97df66250e0b2b48f0ec8d0e01eb1b8ca012d95f1572895622aa1ea433e5570f","typeString":"literal_string \"parent scope contract.addr\""},"value":"parent scope contract.addr"},{"arguments":[{"id":350,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3689:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}],"id":349,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3681:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":348,"name":"address","nodeType":"ElementaryTypeName","src":"3681:7:0","typeDescriptions":{}}},"id":351,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3681:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_97df66250e0b2b48f0ec8d0e01eb1b8ca012d95f1572895622aa1ea433e5570f","typeString":"literal_string \"parent scope contract.addr\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":344,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3639:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":346,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":171,"src":"3639:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":352,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3639:56:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":353,"nodeType":"ExpressionStatement","src":"3639:56:0"},{"expression":{"arguments":[{"hexValue":"66726f6d207072616e6b2032","id":357,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3716:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_a38a34f8cad750a79aa097a92971f8f405b51ee9d53d25c5b14fc129ba3684bb","typeString":"literal_string \"from prank 2\""},"value":"from prank 2"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_a38a34f8cad750a79aa097a92971f8f405b51ee9d53d25c5b14fc129ba3684bb","typeString":"literal_string \"from prank 2\""}],"expression":{"id":354,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3705:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":356,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":633,"src":"3705:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":358,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3705:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":359,"nodeType":"ExpressionStatement","src":"3705:26:0"},{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":360,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"3741:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":362,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"stopPrank","nodeType":"MemberAccess","referencedDeclaration":35,"src":"3741:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$__$returns$__$","typeString":"function () external"}},"id":363,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3741:14:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":364,"nodeType":"ExpressionStatement","src":"3741:14:0"},{"expression":{"arguments":[{"hexValue":"66726f6d206f726967696e616c20616761696e","id":368,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3776:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_0c805c6579e20a9c4c8e11aeab23330910a9f2da629191dc119d1730e8ed6860","typeString":"literal_string \"from original again\""},"value":"from original again"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_0c805c6579e20a9c4c8e11aeab23330910a9f2da629191dc119d1730e8ed6860","typeString":"literal_string \"from original again\""}],"expression":{"id":365,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3765:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":367,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":633,"src":"3765:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":369,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3765:33:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":370,"nodeType":"ExpressionStatement","src":"3765:33:0"},{"expression":{"arguments":[{"hexValue":"646f6e6521","id":374,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3821:7:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_080382d5c9e9e7c5e3d1d33f5e7422740375955180fadff167d8130e0c35f3fc","typeString":"literal_string \"done!\""},"value":"done!"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_080382d5c9e9e7c5e3d1d33f5e7422740375955180fadff167d8130e0c35f3fc","typeString":"literal_string \"done!\""}],"expression":{"id":371,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3809:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":373,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"3809:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":375,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3809:20:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":376,"nodeType":"ExpressionStatement","src":"3809:20:0"}]},"documentation":{"id":216,"nodeType":"StructuredDocumentation","src":"2804:78:0","text":"@notice example function, runs through basic cheat-codes and console logs."},"functionSelector":"c0406226","implemented":true,"kind":"function","modifiers":[],"name":"run","nameLocation":"2896:3:0","parameters":{"id":217,"nodeType":"ParameterList","parameters":[],"src":"2899:2:0"},"returnParameters":{"id":218,"nodeType":"ParameterList","parameters":[],"src":"2909:0:0"},"scope":706,"stateMutability":"nonpayable","virtual":false,"visibility":"public"},{"id":609,"nodeType":"FunctionDefinition","src":"3903:1258:0","nodes":[],"body":{"id":608,"nodeType":"Block","src":"3934:1227:0","nodes":[],"statements":[{"expression":{"arguments":[{"hexValue":"6e6f6e6365207374617274","id":385,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3956:13:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_71efc69b9a13b6bc1e9a14d766ff01c79022262c6daa6532fb5dfb14f8511a20","typeString":"literal_string \"nonce start\""},"value":"nonce start"},{"arguments":[{"arguments":[{"arguments":[{"id":392,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3999:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}],"id":391,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3991:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":390,"name":"address","nodeType":"ElementaryTypeName","src":"3991:7:0","typeDescriptions":{}}},"id":393,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3991:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":388,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"3979:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":389,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"getNonce","nodeType":"MemberAccess","referencedDeclaration":17,"src":"3979:11:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_address_$returns$_t_uint64_$","typeString":"function (address) view external returns (uint64)"}},"id":394,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3979:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint64","typeString":"uint64"}],"id":387,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3971:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint256_$","typeString":"type(uint256)"},"typeName":{"id":386,"name":"uint256","nodeType":"ElementaryTypeName","src":"3971:7:0","typeDescriptions":{}}},"id":395,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3971:35:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_71efc69b9a13b6bc1e9a14d766ff01c79022262c6daa6532fb5dfb14f8511a20","typeString":"literal_string \"nonce start\""},{"typeIdentifier":"t_uint256","typeString":"uint256"}],"expression":{"id":382,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3944:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":384,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":154,"src":"3944:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_uint256_$returns$__$","typeString":"function (string memory,uint256) pure"}},"id":396,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3944:63:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":397,"nodeType":"ExpressionStatement","src":"3944:63:0"},{"expression":{"arguments":[{"hexValue":"74657374696e672073696e676c65","id":401,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4030:16:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_b75103528423218e7569082dad569ed0d2ce7c0ac770c0812b220e2d369fe474","typeString":"literal_string \"testing single\""},"value":"testing single"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_b75103528423218e7569082dad569ed0d2ce7c0ac770c0812b220e2d369fe474","typeString":"literal_string \"testing single\""}],"expression":{"id":398,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"4018:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":400,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"4018:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":402,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4018:29:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":403,"nodeType":"ExpressionStatement","src":"4018:29:0"},{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":404,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4057:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":406,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"broadcast","nodeType":"MemberAccess","referencedDeclaration":38,"src":"4057:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$__$returns$__$","typeString":"function () external"}},"id":407,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4057:14:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":408,"nodeType":"ExpressionStatement","src":"4057:14:0"},{"expression":{"arguments":[{"hexValue":"73696e676c655f63616c6c31","id":412,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4092:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_5e1cad6d7a968cfacf2731373e1248ffb11f4886bced66a02a6de1a67ac8f777","typeString":"literal_string \"single_call1\""},"value":"single_call1"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_5e1cad6d7a968cfacf2731373e1248ffb11f4886bced66a02a6de1a67ac8f777","typeString":"literal_string \"single_call1\""}],"expression":{"id":409,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4081:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":411,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"call1","nodeType":"MemberAccess","referencedDeclaration":648,"src":"4081:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":413,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4081:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":414,"nodeType":"ExpressionStatement","src":"4081:26:0"},{"expression":{"arguments":[{"hexValue":"73696e676c655f63616c6c32","id":418,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4128:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_b37ddaf5d00ad9e6371de3fb71b91eef731fae1e86b768666380f7d44e1ada25","typeString":"literal_string \"single_call2\""},"value":"single_call2"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_b37ddaf5d00ad9e6371de3fb71b91eef731fae1e86b768666380f7d44e1ada25","typeString":"literal_string \"single_call2\""}],"expression":{"id":415,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4117:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":417,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"call2","nodeType":"MemberAccess","referencedDeclaration":663,"src":"4117:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":419,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4117:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":420,"nodeType":"ExpressionStatement","src":"4117:26:0"},{"expression":{"arguments":[{"hexValue":"74657374696e672073746172742f73746f70","id":424,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4166:20:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_778e886e3a1c3c5096aca76228832105f3f9269f362effd0e8ce3737787cb784","typeString":"literal_string \"testing start/stop\""},"value":"testing start/stop"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_778e886e3a1c3c5096aca76228832105f3f9269f362effd0e8ce3737787cb784","typeString":"literal_string \"testing start/stop\""}],"expression":{"id":421,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"4154:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":423,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"4154:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":425,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4154:33:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":426,"nodeType":"ExpressionStatement","src":"4154:33:0"},{"expression":{"arguments":[{"arguments":[{"arguments":[{"hexValue":"3078633066666565","id":434,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4231:8:0","typeDescriptions":{"typeIdentifier":"t_rational_12648430_by_1","typeString":"int_const 12648430"},"value":"0xc0ffee"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_12648430_by_1","typeString":"int_const 12648430"}],"id":433,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4223:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":432,"name":"uint160","nodeType":"ElementaryTypeName","src":"4223:7:0","typeDescriptions":{}}},"id":435,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4223:17:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":431,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4215:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":430,"name":"address","nodeType":"ElementaryTypeName","src":"4215:7:0","typeDescriptions":{}}},"id":436,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4215:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":427,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4197:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":429,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"startBroadcast","nodeType":"MemberAccess","referencedDeclaration":48,"src":"4197:17:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_address_$returns$__$","typeString":"function (address) external"}},"id":437,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4197:45:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":438,"nodeType":"ExpressionStatement","src":"4197:45:0"},{"expression":{"arguments":[{"hexValue":"737461727473746f705f63616c6c31","id":442,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4263:17:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_2fc2682edf10ed478ee3b9a190f6b1c88bb492b300935ce44545a1613cf8f041","typeString":"literal_string \"startstop_call1\""},"value":"startstop_call1"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_2fc2682edf10ed478ee3b9a190f6b1c88bb492b300935ce44545a1613cf8f041","typeString":"literal_string \"startstop_call1\""}],"expression":{"id":439,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4252:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":441,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"call1","nodeType":"MemberAccess","referencedDeclaration":648,"src":"4252:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":443,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4252:29:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":444,"nodeType":"ExpressionStatement","src":"4252:29:0"},{"expression":{"arguments":[{"hexValue":"737461727473746f705f63616c6c32","id":448,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4302:17:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_1a6fd77f04b28bf45d6d0e2dd4c65c0bbfeba174f849e43bb67ebca1c019cda4","typeString":"literal_string \"startstop_call2\""},"value":"startstop_call2"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_1a6fd77f04b28bf45d6d0e2dd4c65c0bbfeba174f849e43bb67ebca1c019cda4","typeString":"literal_string \"startstop_call2\""}],"expression":{"id":445,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4291:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":447,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"call2","nodeType":"MemberAccess","referencedDeclaration":663,"src":"4291:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":449,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4291:29:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":450,"nodeType":"ExpressionStatement","src":"4291:29:0"},{"expression":{"arguments":[{"hexValue":"737461727473746f705f70757265","id":454,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4344:16:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_b6e9eb1efd186b1d92b54da45026aa97a178e6eaffdf9dbf9f666fc751fb0ff9","typeString":"literal_string \"startstop_pure\""},"value":"startstop_pure"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_b6e9eb1efd186b1d92b54da45026aa97a178e6eaffdf9dbf9f666fc751fb0ff9","typeString":"literal_string \"startstop_pure\""}],"expression":{"id":451,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4330:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":453,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"callPure","nodeType":"MemberAccess","referencedDeclaration":705,"src":"4330:13:0","typeDescriptions":{"typeIdentifier":"t_function_external_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure external"}},"id":455,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4330:31:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":456,"nodeType":"ExpressionStatement","src":"4330:31:0"},{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":457,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4371:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":459,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"stopBroadcast","nodeType":"MemberAccess","referencedDeclaration":54,"src":"4371:16:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$__$returns$__$","typeString":"function () external"}},"id":460,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4371:18:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":461,"nodeType":"ExpressionStatement","src":"4371:18:0"},{"expression":{"arguments":[{"hexValue":"737461727473746f705f63616c6c33","id":465,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4410:17:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_8eb502bfdc4adda22bd960aa2ae13ce4c0ed8cc3b3791ed65e321a38cdd36f72","typeString":"literal_string \"startstop_call3\""},"value":"startstop_call3"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_8eb502bfdc4adda22bd960aa2ae13ce4c0ed8cc3b3791ed65e321a38cdd36f72","typeString":"literal_string \"startstop_call3\""}],"expression":{"id":462,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4399:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":464,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"call1","nodeType":"MemberAccess","referencedDeclaration":648,"src":"4399:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":466,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4399:29:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":467,"nodeType":"ExpressionStatement","src":"4399:29:0"},{"expression":{"arguments":[{"hexValue":"74657374696e67206e6573746564","id":471,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4451:16:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_f92f19f7a5b5b9ce341188bf4e15925f184cdb5ac135c4846ced718f259dbde5","typeString":"literal_string \"testing nested\""},"value":"testing nested"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_f92f19f7a5b5b9ce341188bf4e15925f184cdb5ac135c4846ced718f259dbde5","typeString":"literal_string \"testing nested\""}],"expression":{"id":468,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"4439:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":470,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"4439:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":472,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4439:29:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":473,"nodeType":"ExpressionStatement","src":"4439:29:0"},{"expression":{"arguments":[{"arguments":[{"arguments":[{"hexValue":"307831323334","id":481,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4512:6:0","typeDescriptions":{"typeIdentifier":"t_rational_4660_by_1","typeString":"int_const 4660"},"value":"0x1234"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_4660_by_1","typeString":"int_const 4660"}],"id":480,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4504:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":479,"name":"uint160","nodeType":"ElementaryTypeName","src":"4504:7:0","typeDescriptions":{}}},"id":482,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4504:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":478,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4496:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":477,"name":"address","nodeType":"ElementaryTypeName","src":"4496:7:0","typeDescriptions":{}}},"id":483,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4496:24:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":474,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4478:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":476,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"startBroadcast","nodeType":"MemberAccess","referencedDeclaration":48,"src":"4478:17:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_address_$returns$__$","typeString":"function (address) external"}},"id":484,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4478:43:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":485,"nodeType":"ExpressionStatement","src":"4478:43:0"},{"expression":{"arguments":[{"hexValue":"6e6573746564","id":489,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4544:8:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_4d5b14044d78fbf0c9dd8b9c49e35f09ee5a6f5b1b3b8117b5d0e15c8dd2cb09","typeString":"literal_string \"nested\""},"value":"nested"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_4d5b14044d78fbf0c9dd8b9c49e35f09ee5a6f5b1b3b8117b5d0e15c8dd2cb09","typeString":"literal_string \"nested\""}],"expression":{"id":486,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4531:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":488,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"nested1","nodeType":"MemberAccess","referencedDeclaration":678,"src":"4531:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":490,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4531:22:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":491,"nodeType":"ExpressionStatement","src":"4531:22:0"},{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":492,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4563:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":494,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"stopBroadcast","nodeType":"MemberAccess","referencedDeclaration":54,"src":"4563:16:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$__$returns$__$","typeString":"function () external"}},"id":495,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4563:18:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":496,"nodeType":"ExpressionStatement","src":"4563:18:0"},{"expression":{"arguments":[{"hexValue":"636f6e7472616374206465706c6f796d656e74","id":500,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4604:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_aaf9be86adf9b6872d87eed3526f7c55f3c5d61f4e4dd6d55ef2fcbb8ad0bd57","typeString":"literal_string \"contract deployment\""},"value":"contract deployment"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_aaf9be86adf9b6872d87eed3526f7c55f3c5d61f4e4dd6d55ef2fcbb8ad0bd57","typeString":"literal_string \"contract deployment\""}],"expression":{"id":497,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"4592:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":499,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"4592:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":501,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4592:34:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":502,"nodeType":"ExpressionStatement","src":"4592:34:0"},{"expression":{"arguments":[{"arguments":[{"arguments":[{"hexValue":"3078313233343536","id":510,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4665:8:0","typeDescriptions":{"typeIdentifier":"t_rational_1193046_by_1","typeString":"int_const 1193046"},"value":"0x123456"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_1193046_by_1","typeString":"int_const 1193046"}],"id":509,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4657:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":508,"name":"uint160","nodeType":"ElementaryTypeName","src":"4657:7:0","typeDescriptions":{}}},"id":511,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4657:17:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":507,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4649:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":506,"name":"address","nodeType":"ElementaryTypeName","src":"4649:7:0","typeDescriptions":{}}},"id":512,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4649:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":503,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4636:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":505,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"broadcast","nodeType":"MemberAccess","referencedDeclaration":43,"src":"4636:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_address_$returns$__$","typeString":"function (address) external"}},"id":513,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4636:40:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":514,"nodeType":"ExpressionStatement","src":"4636:40:0"},{"assignments":[517],"declarations":[{"constant":false,"id":517,"mutability":"mutable","name":"x","nameLocation":"4693:1:0","nodeType":"VariableDeclaration","scope":608,"src":"4686:8:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"},"typeName":{"id":516,"nodeType":"UserDefinedTypeName","pathNode":{"id":515,"name":"FooBar","nodeType":"IdentifierPath","referencedDeclaration":719,"src":"4686:6:0"},"referencedDeclaration":719,"src":"4686:6:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"visibility":"internal"}],"id":523,"initialValue":{"arguments":[{"hexValue":"31323334","id":521,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4708:4:0","typeDescriptions":{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"},"value":"1234"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"}],"id":520,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"NewExpression","src":"4697:10:0","typeDescriptions":{"typeIdentifier":"t_function_creation_nonpayable$_t_uint256_$returns$_t_contract$_FooBar_$719_$","typeString":"function (uint256) returns (contract FooBar)"},"typeName":{"id":519,"nodeType":"UserDefinedTypeName","pathNode":{"id":518,"name":"FooBar","nodeType":"IdentifierPath","referencedDeclaration":719,"src":"4701:6:0"},"referencedDeclaration":719,"src":"4701:6:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}}},"id":522,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4697:16:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"nodeType":"VariableDeclarationStatement","src":"4686:27:0"},{"expression":{"arguments":[{"commonType":{"typeIdentifier":"t_uint256","typeString":"uint256"},"id":529,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"leftExpression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":525,"name":"x","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":517,"src":"4731:1:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"id":526,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"foo","nodeType":"MemberAccess","referencedDeclaration":708,"src":"4731:5:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$__$returns$_t_uint256_$","typeString":"function () view external returns (uint256)"}},"id":527,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4731:7:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"nodeType":"BinaryOperation","operator":"==","rightExpression":{"hexValue":"31323334","id":528,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4742:4:0","typeDescriptions":{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"},"value":"1234"},"src":"4731:15:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bool","typeString":"bool"}],"id":524,"name":"require","nodeType":"Identifier","overloadedDeclarations":[-18,-18],"referencedDeclaration":-18,"src":"4723:7:0","typeDescriptions":{"typeIdentifier":"t_function_require_pure$_t_bool_$returns$__$","typeString":"function (bool) pure"}},"id":530,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4723:24:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":531,"nodeType":"ExpressionStatement","src":"4723:24:0"},{"expression":{"arguments":[{"hexValue":"6372656174652032","id":535,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4770:10:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_4411d6d4ffcd00382a95255a63761e69de9810e1236042a5c64948a7b6c04daa","typeString":"literal_string \"create 2\""},"value":"create 2"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_4411d6d4ffcd00382a95255a63761e69de9810e1236042a5c64948a7b6c04daa","typeString":"literal_string \"create 2\""}],"expression":{"id":532,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"4758:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":534,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"4758:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":536,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4758:23:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":537,"nodeType":"ExpressionStatement","src":"4758:23:0"},{"expression":{"arguments":[{"arguments":[{"arguments":[{"hexValue":"307863616665","id":545,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4820:6:0","typeDescriptions":{"typeIdentifier":"t_rational_51966_by_1","typeString":"int_const 51966"},"value":"0xcafe"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_51966_by_1","typeString":"int_const 51966"}],"id":544,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4812:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":543,"name":"uint160","nodeType":"ElementaryTypeName","src":"4812:7:0","typeDescriptions":{}}},"id":546,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4812:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":542,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4804:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":541,"name":"address","nodeType":"ElementaryTypeName","src":"4804:7:0","typeDescriptions":{}}},"id":547,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4804:24:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":538,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4791:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":540,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"broadcast","nodeType":"MemberAccess","referencedDeclaration":43,"src":"4791:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_address_$returns$__$","typeString":"function (address) external"}},"id":548,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4791:38:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":549,"nodeType":"ExpressionStatement","src":"4791:38:0"},{"assignments":[552],"declarations":[{"constant":false,"id":552,"mutability":"mutable","name":"y","nameLocation":"4846:1:0","nodeType":"VariableDeclaration","scope":608,"src":"4839:8:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"},"typeName":{"id":551,"nodeType":"UserDefinedTypeName","pathNode":{"id":550,"name":"FooBar","nodeType":"IdentifierPath","referencedDeclaration":719,"src":"4839:6:0"},"referencedDeclaration":719,"src":"4839:6:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"visibility":"internal"}],"id":566,"initialValue":{"arguments":[{"hexValue":"31323334","id":564,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4889:4:0","typeDescriptions":{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"},"value":"1234"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"}],"id":555,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"NewExpression","src":"4850:10:0","typeDescriptions":{"typeIdentifier":"t_function_creation_nonpayable$_t_uint256_$returns$_t_contract$_FooBar_$719_$","typeString":"function (uint256) returns (contract FooBar)"},"typeName":{"id":554,"nodeType":"UserDefinedTypeName","pathNode":{"id":553,"name":"FooBar","nodeType":"IdentifierPath","referencedDeclaration":719,"src":"4854:6:0"},"referencedDeclaration":719,"src":"4854:6:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}}},"id":563,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"names":["salt"],"nodeType":"FunctionCallOptions","options":[{"arguments":[{"arguments":[{"hexValue":"3432","id":560,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4883:2:0","typeDescriptions":{"typeIdentifier":"t_rational_42_by_1","typeString":"int_const 42"},"value":"42"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_42_by_1","typeString":"int_const 42"}],"id":559,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4875:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint256_$","typeString":"type(uint256)"},"typeName":{"id":558,"name":"uint256","nodeType":"ElementaryTypeName","src":"4875:7:0","typeDescriptions":{}}},"id":561,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4875:11:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint256","typeString":"uint256"}],"id":557,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4867:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_bytes32_$","typeString":"type(bytes32)"},"typeName":{"id":556,"name":"bytes32","nodeType":"ElementaryTypeName","src":"4867:7:0","typeDescriptions":{}}},"id":562,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4867:20:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes32","typeString":"bytes32"}}],"src":"4850:38:0","typeDescriptions":{"typeIdentifier":"t_function_creation_nonpayable$_t_uint256_$returns$_t_contract$_FooBar_$719_$salt","typeString":"function (uint256) returns (contract FooBar)"}},"id":565,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4850:44:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"nodeType":"VariableDeclarationStatement","src":"4839:55:0"},{"expression":{"arguments":[{"commonType":{"typeIdentifier":"t_uint256","typeString":"uint256"},"id":572,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"leftExpression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":568,"name":"y","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":552,"src":"4912:1:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"id":569,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"foo","nodeType":"MemberAccess","referencedDeclaration":708,"src":"4912:5:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$__$returns$_t_uint256_$","typeString":"function () view external returns (uint256)"}},"id":570,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4912:7:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"nodeType":"BinaryOperation","operator":"==","rightExpression":{"hexValue":"31323334","id":571,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4923:4:0","typeDescriptions":{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"},"value":"1234"},"src":"4912:15:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bool","typeString":"bool"}],"id":567,"name":"require","nodeType":"Identifier","overloadedDeclarations":[-18,-18],"referencedDeclaration":-18,"src":"4904:7:0","typeDescriptions":{"typeIdentifier":"t_function_require_pure$_t_bool_$returns$__$","typeString":"function (bool) pure"}},"id":573,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4904:24:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":574,"nodeType":"ExpressionStatement","src":"4904:24:0"},{"expression":{"arguments":[{"hexValue":"646f6e6521","id":578,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4950:7:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_080382d5c9e9e7c5e3d1d33f5e7422740375955180fadff167d8130e0c35f3fc","typeString":"literal_string \"done!\""},"value":"done!"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_080382d5c9e9e7c5e3d1d33f5e7422740375955180fadff167d8130e0c35f3fc","typeString":"literal_string \"done!\""}],"expression":{"id":575,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"4938:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":577,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"4938:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":579,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4938:20:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":580,"nodeType":"ExpressionStatement","src":"4938:20:0"},{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":581,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"5042:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":583,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"broadcast","nodeType":"MemberAccess","referencedDeclaration":38,"src":"5042:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$__$returns$__$","typeString":"function () external"}},"id":584,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5042:14:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":585,"nodeType":"ExpressionStatement","src":"5042:14:0"},{"expression":{"arguments":[{"hexValue":"31323334","id":589,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"5077:4:0","typeDescriptions":{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"},"value":"1234"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"}],"id":588,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"NewExpression","src":"5066:10:0","typeDescriptions":{"typeIdentifier":"t_function_creation_nonpayable$_t_uint256_$returns$_t_contract$_FooBar_$719_$","typeString":"function (uint256) returns (contract FooBar)"},"typeName":{"id":587,"nodeType":"UserDefinedTypeName","pathNode":{"id":586,"name":"FooBar","nodeType":"IdentifierPath","referencedDeclaration":719,"src":"5070:6:0"},"referencedDeclaration":719,"src":"5070:6:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}}},"id":590,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5066:16:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"id":591,"nodeType":"ExpressionStatement","src":"5066:16:0"},{"expression":{"arguments":[{"hexValue":"6e6f6e636520656e64","id":595,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"5105:11:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_fa629e6661ad2a2bdb09cf9a3a276ce0d722482ae5c2887650751be0938847e8","typeString":"literal_string \"nonce end\""},"value":"nonce end"},{"arguments":[{"arguments":[{"arguments":[{"id":602,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"5146:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}],"id":601,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"5138:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":600,"name":"address","nodeType":"ElementaryTypeName","src":"5138:7:0","typeDescriptions":{}}},"id":603,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5138:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":598,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"5126:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":599,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"getNonce","nodeType":"MemberAccess","referencedDeclaration":17,"src":"5126:11:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_address_$returns$_t_uint64_$","typeString":"function (address) view external returns (uint64)"}},"id":604,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5126:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint64","typeString":"uint64"}],"id":597,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"5118:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint256_$","typeString":"type(uint256)"},"typeName":{"id":596,"name":"uint256","nodeType":"ElementaryTypeName","src":"5118:7:0","typeDescriptions":{}}},"id":605,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5118:35:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_fa629e6661ad2a2bdb09cf9a3a276ce0d722482ae5c2887650751be0938847e8","typeString":"literal_string \"nonce end\""},{"typeIdentifier":"t_uint256","typeString":"uint256"}],"expression":{"id":592,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5093:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":594,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":154,"src":"5093:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_uint256_$returns$__$","typeString":"function (string memory,uint256) pure"}},"id":606,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5093:61:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":607,"nodeType":"ExpressionStatement","src":"5093:61:0"}]},"documentation":{"id":379,"nodeType":"StructuredDocumentation","src":"3842:56:0","text":"@notice example function, to test vm.broadcast with."},"functionSelector":"bef03abc","implemented":true,"kind":"function","modifiers":[],"name":"runBroadcast","nameLocation":"3912:12:0","parameters":{"id":380,"nodeType":"ParameterList","parameters":[],"src":"3924:2:0"},"returnParameters":{"id":381,"nodeType":"ParameterList","parameters":[],"src":"3934:0:0"},"scope":706,"stateMutability":"nonpayable","virtual":false,"visibility":"public"},{"id":633,"nodeType":"FunctionDefinition","src":"5256:143:0","nodes":[],"body":{"id":632,"nodeType":"Block","src":"5305:94:0","nodes":[],"statements":[{"expression":{"arguments":[{"id":618,"name":"_v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":612,"src":"5327:2:0","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}],"expression":{"id":615,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5315:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":617,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"5315:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":619,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5315:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":620,"nodeType":"ExpressionStatement","src":"5315:15:0"},{"expression":{"arguments":[{"hexValue":"68656c6c6f206d73672e73656e646572","id":624,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"5352:18:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_b3cc13bc51228b2c4c4334d82a4772908254dc0e1c512893dd16208ef13efb8e","typeString":"literal_string \"hello msg.sender\""},"value":"hello msg.sender"},{"arguments":[{"expression":{"id":627,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"5380:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":628,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"5380:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":626,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"5372:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":625,"name":"address","nodeType":"ElementaryTypeName","src":"5372:7:0","typeDescriptions":{}}},"id":629,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5372:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_b3cc13bc51228b2c4c4334d82a4772908254dc0e1c512893dd16208ef13efb8e","typeString":"literal_string \"hello msg.sender\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":621,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5340:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":623,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":171,"src":"5340:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":630,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5340:52:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":631,"nodeType":"ExpressionStatement","src":"5340:52:0"}]},"documentation":{"id":610,"nodeType":"StructuredDocumentation","src":"5167:84:0","text":"@notice example external function, to force a CALL, and test vm.startPrank with."},"functionSelector":"a777d0dc","implemented":true,"kind":"function","modifiers":[],"name":"hello","nameLocation":"5265:5:0","parameters":{"id":613,"nodeType":"ParameterList","parameters":[{"constant":false,"id":612,"mutability":"mutable","name":"_v","nameLocation":"5287:2:0","nodeType":"VariableDeclaration","scope":633,"src":"5271:18:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":611,"name":"string","nodeType":"ElementaryTypeName","src":"5271:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"5270:20:0"},"returnParameters":{"id":614,"nodeType":"ParameterList","parameters":[],"src":"5305:0:0"},"scope":706,"stateMutability":"view","virtual":false,"visibility":"external"},{"id":648,"nodeType":"FunctionDefinition","src":"5405:95:0","nodes":[],"body":{"id":647,"nodeType":"Block","src":"5449:51:0","nodes":[],"statements":[{"expression":{"id":639,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"UnaryOperation","operator":"++","prefix":false,"src":"5459:9:0","subExpression":{"id":638,"name":"counter","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":215,"src":"5459:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"id":640,"nodeType":"ExpressionStatement","src":"5459:9:0"},{"expression":{"arguments":[{"id":644,"name":"_v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":635,"src":"5490:2:0","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}],"expression":{"id":641,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5478:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":643,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"5478:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":645,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5478:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":646,"nodeType":"ExpressionStatement","src":"5478:15:0"}]},"functionSelector":"7e79255d","implemented":true,"kind":"function","modifiers":[],"name":"call1","nameLocation":"5414:5:0","parameters":{"id":636,"nodeType":"ParameterList","parameters":[{"constant":false,"id":635,"mutability":"mutable","name":"_v","nameLocation":"5436:2:0","nodeType":"VariableDeclaration","scope":648,"src":"5420:18:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":634,"name":"string","nodeType":"ElementaryTypeName","src":"5420:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"5419:20:0"},"returnParameters":{"id":637,"nodeType":"ParameterList","parameters":[],"src":"5449:0:0"},"scope":706,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":663,"nodeType":"FunctionDefinition","src":"5506:95:0","nodes":[],"body":{"id":662,"nodeType":"Block","src":"5550:51:0","nodes":[],"statements":[{"expression":{"id":654,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"UnaryOperation","operator":"++","prefix":false,"src":"5560:9:0","subExpression":{"id":653,"name":"counter","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":215,"src":"5560:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"id":655,"nodeType":"ExpressionStatement","src":"5560:9:0"},{"expression":{"arguments":[{"id":659,"name":"_v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":650,"src":"5591:2:0","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}],"expression":{"id":656,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5579:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":658,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"5579:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":660,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5579:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":661,"nodeType":"ExpressionStatement","src":"5579:15:0"}]},"functionSelector":"8d3ef7ca","implemented":true,"kind":"function","modifiers":[],"name":"call2","nameLocation":"5515:5:0","parameters":{"id":651,"nodeType":"ParameterList","parameters":[{"constant":false,"id":650,"mutability":"mutable","name":"_v","nameLocation":"5537:2:0","nodeType":"VariableDeclaration","scope":663,"src":"5521:18:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":649,"name":"string","nodeType":"ElementaryTypeName","src":"5521:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"5520:20:0"},"returnParameters":{"id":652,"nodeType":"ParameterList","parameters":[],"src":"5550:0:0"},"scope":706,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":678,"nodeType":"FunctionDefinition","src":"5607:98:0","nodes":[],"body":{"id":677,"nodeType":"Block","src":"5653:52:0","nodes":[],"statements":[{"expression":{"id":669,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"UnaryOperation","operator":"++","prefix":false,"src":"5663:9:0","subExpression":{"id":668,"name":"counter","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":215,"src":"5663:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"id":670,"nodeType":"ExpressionStatement","src":"5663:9:0"},{"expression":{"arguments":[{"id":674,"name":"_v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":665,"src":"5695:2:0","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}],"expression":{"id":671,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"5682:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":673,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"nested2","nodeType":"MemberAccess","referencedDeclaration":693,"src":"5682:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":675,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5682:16:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":676,"nodeType":"ExpressionStatement","src":"5682:16:0"}]},"functionSelector":"a76ccdfa","implemented":true,"kind":"function","modifiers":[],"name":"nested1","nameLocation":"5616:7:0","parameters":{"id":666,"nodeType":"ParameterList","parameters":[{"constant":false,"id":665,"mutability":"mutable","name":"_v","nameLocation":"5640:2:0","nodeType":"VariableDeclaration","scope":678,"src":"5624:18:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":664,"name":"string","nodeType":"ElementaryTypeName","src":"5624:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"5623:20:0"},"returnParameters":{"id":667,"nodeType":"ParameterList","parameters":[],"src":"5653:0:0"},"scope":706,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":693,"nodeType":"FunctionDefinition","src":"5711:97:0","nodes":[],"body":{"id":692,"nodeType":"Block","src":"5757:51:0","nodes":[],"statements":[{"expression":{"id":684,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"UnaryOperation","operator":"++","prefix":false,"src":"5767:9:0","subExpression":{"id":683,"name":"counter","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":215,"src":"5767:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"id":685,"nodeType":"ExpressionStatement","src":"5767:9:0"},{"expression":{"arguments":[{"id":689,"name":"_v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":680,"src":"5798:2:0","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}],"expression":{"id":686,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5786:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":688,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"5786:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":690,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5786:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":691,"nodeType":"ExpressionStatement","src":"5786:15:0"}]},"functionSelector":"dbf1282f","implemented":true,"kind":"function","modifiers":[],"name":"nested2","nameLocation":"5720:7:0","parameters":{"id":681,"nodeType":"ParameterList","parameters":[{"constant":false,"id":680,"mutability":"mutable","name":"_v","nameLocation":"5744:2:0","nodeType":"VariableDeclaration","scope":693,"src":"5728:18:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":679,"name":"string","nodeType":"ElementaryTypeName","src":"5728:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"5727:20:0"},"returnParameters":{"id":682,"nodeType":"ParameterList","parameters":[],"src":"5757:0:0"},"scope":706,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":705,"nodeType":"FunctionDefinition","src":"5814:84:0","nodes":[],"body":{"id":704,"nodeType":"Block","src":"5866:32:0","nodes":[],"statements":[{"expression":{"arguments":[{"id":701,"name":"_v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":695,"src":"5888:2:0","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}],"expression":{"id":698,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5876:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":700,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"5876:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":702,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5876:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":703,"nodeType":"ExpressionStatement","src":"5876:15:0"}]},"functionSelector":"7f8b915c","implemented":true,"kind":"function","modifiers":[],"name":"callPure","nameLocation":"5823:8:0","parameters":{"id":696,"nodeType":"ParameterList","parameters":[{"constant":false,"id":695,"mutability":"mutable","name":"_v","nameLocation":"5848:2:0","nodeType":"VariableDeclaration","scope":705,"src":"5832:18:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":694,"name":"string","nodeType":"ElementaryTypeName","src":"5832:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"5831:20:0"},"returnParameters":{"id":697,"nodeType":"ParameterList","parameters":[],"src":"5866:0:0"},"scope":706,"stateMutability":"pure","virtual":false,"visibility":"external"}],"abstract":false,"baseContracts":[],"canonicalName":"ScriptExample","contractDependencies":[719],"contractKind":"contract","documentation":{"id":193,"nodeType":"StructuredDocumentation","src":"2415:126:0","text":"@title ScriptExample\n @notice ScriptExample is an example script. The Go forge script code tests that it can run this."},"fullyImplemented":true,"linearizedBaseContracts":[706],"name":"ScriptExample","nameLocation":"2550:13:0","scope":720,"usedErrors":[]},{"id":719,"nodeType":"ContractDefinition","src":"5902:96:0","nodes":[{"id":708,"nodeType":"VariableDeclaration","src":"5924:18:0","nodes":[],"constant":false,"functionSelector":"c2985578","mutability":"mutable","name":"foo","nameLocation":"5939:3:0","scope":719,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":707,"name":"uint256","nodeType":"ElementaryTypeName","src":"5924:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"public"},{"id":718,"nodeType":"FunctionDefinition","src":"5949:47:0","nodes":[],"body":{"id":717,"nodeType":"Block","src":"5972:24:0","nodes":[],"statements":[{"expression":{"id":715,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"leftHandSide":{"id":713,"name":"foo","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":708,"src":"5982:3:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"nodeType":"Assignment","operator":"=","rightHandSide":{"id":714,"name":"v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":710,"src":"5988:1:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"src":"5982:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"id":716,"nodeType":"ExpressionStatement","src":"5982:7:0"}]},"implemented":true,"kind":"constructor","modifiers":[],"name":"","nameLocation":"-1:-1:-1","parameters":{"id":711,"nodeType":"ParameterList","parameters":[{"constant":false,"id":710,"mutability":"mutable","name":"v","nameLocation":"5969:1:0","nodeType":"VariableDeclaration","scope":718,"src":"5961:9:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":709,"name":"uint256","nodeType":"ElementaryTypeName","src":"5961:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"}],"src":"5960:11:0"},"returnParameters":{"id":712,"nodeType":"ParameterList","parameters":[],"src":"5972:0:0"},"scope":719,"stateMutability":"nonpayable","virtual":false,"visibility":"public"}],"abstract":false,"baseContracts":[],"canonicalName":"FooBar","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"linearizedBaseContracts":[719],"name":"FooBar","nameLocation":"5911:6:0","scope":720,"usedErrors":[]}],"license":"MIT"},"id":0} \ No newline at end of file diff --git a/op-chain-ops/script/testdata/test-artifacts/ScriptExample.s.sol/ScriptExample.json b/op-chain-ops/script/testdata/test-artifacts/ScriptExample.s.sol/ScriptExample.json index aab5ca4e26427..09a0bf47f02db 100644 --- a/op-chain-ops/script/testdata/test-artifacts/ScriptExample.s.sol/ScriptExample.json +++ b/op-chain-ops/script/testdata/test-artifacts/ScriptExample.s.sol/ScriptExample.json @@ -1 +1 @@ -{"abi":[{"type":"function","name":"hello","inputs":[{"name":"_v","type":"string","internalType":"string"}],"outputs":[],"stateMutability":"view"},{"type":"function","name":"run","inputs":[],"outputs":[],"stateMutability":"nonpayable"}],"bytecode":{"object":"0x608060405234801561001057600080fd5b50611079806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063a777d0dc1461003b578063c040622614610050575b600080fd5b61004e610049366004610c26565b610058565b005b61004e6100da565b61009782828080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061092d92505050565b6100d66040518060400160405280601081526020017f68656c6c6f206d73672e73656e64657200000000000000000000000000000000815250336109bf565b5050565b604080517f4777f3cf0000000000000000000000000000000000000000000000000000000081526004810191909152600c60448201527f4558414d504c455f424f4f4c0000000000000000000000000000000000000000606482015260006024820181905290737109709ecfa91a80626ff3989d68f67f5b1dd12d90634777f3cf90608401602060405180830381865afa15801561017c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101a09190610c98565b90506101e16040518060400160405280601381526020017f626f6f6c2076616c75652066726f6d20656e760000000000000000000000000081525082610a50565b6102206040518060400160405280600d81526020017f636f6e7472616374206164647200000000000000000000000000000000000000815250306109bf565b604080518082018252600e81527f636f6e7472616374206e6f6e6365000000000000000000000000000000000000602082015290517f2d0335ab0000000000000000000000000000000000000000000000000000000081523060048201526102f39190737109709ecfa91a80626ff3989d68f67f5b1dd12d90632d0335ab906024015b602060405180830381865afa1580156102c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102e49190610cc1565b67ffffffffffffffff16610ae1565b6103326040518060400160405280600b81526020017f73656e6465722061646472000000000000000000000000000000000000000000815250336109bf565b604080518082018252600c81527f73656e646572206e6f6e63650000000000000000000000000000000000000000602082015290517f2d0335ab0000000000000000000000000000000000000000000000000000000081523360048201526103b99190737109709ecfa91a80626ff3989d68f67f5b1dd12d90632d0335ab906024016102a3565b60408051808201825260208082527f7b22726f6f745f6b6579223a205b7b2261223a20312c202262223a20327d5d7d9082015290517f213e4198000000000000000000000000000000000000000000000000000000008152600090737109709ecfa91a80626ff3989d68f67f5b1dd12d9063213e41989061043e908590600401610d65565b600060405180830381865afa15801561045b573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526104a19190810190610e35565b90506105176040518060400160405280600481526020017f6b65797300000000000000000000000000000000000000000000000000000000815250826000815181106104ef576104ef610f69565b60200260200101518360018151811061050a5761050a610f69565b6020026020010151610b72565b6040517fa777d0dc00000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f66726f6d206f726967696e616c000000000000000000000000000000000000006044820152309063a777d0dc9060640160006040518083038186803b15801561059457600080fd5b505afa1580156105a8573d6000803e3d6000fd5b50506040517f06447d5600000000000000000000000000000000000000000000000000000000815260426004820152737109709ecfa91a80626ff3989d68f67f5b1dd12d92506306447d569150602401600060405180830381600087803b15801561061257600080fd5b505af1158015610626573d6000803e3d6000fd5b50506040517fa777d0dc00000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f66726f6d207072616e6b20310000000000000000000000000000000000000000604482015230925063a777d0dc915060640160006040518083038186803b1580156106a757600080fd5b505afa1580156106bb573d6000803e3d6000fd5b505050506106fe6040518060400160405280601781526020017f706172656e742073636f7065206d73672e73656e646572000000000000000000815250336109bf565b61073d6040518060400160405280601a81526020017f706172656e742073636f706520636f6e74726163742e61646472000000000000815250306109bf565b6040517fa777d0dc00000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f66726f6d207072616e6b203200000000000000000000000000000000000000006044820152309063a777d0dc9060640160006040518083038186803b1580156107ba57600080fd5b505afa1580156107ce573d6000803e3d6000fd5b505050507f885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d60001c73ffffffffffffffffffffffffffffffffffffffff166390c5013b6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561083d57600080fd5b505af1158015610851573d6000803e3d6000fd5b50506040517fa777d0dc00000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f66726f6d206f726967696e616c20616761696e00000000000000000000000000604482015230925063a777d0dc915060640160006040518083038186803b1580156108d257600080fd5b505afa1580156108e6573d6000803e3d6000fd5b505050506109286040518060400160405280600581526020017f646f6e652100000000000000000000000000000000000000000000000000000081525061092d565b505050565b6109bc816040516024016109419190610f98565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f41304fac00000000000000000000000000000000000000000000000000000000179052610c01565b50565b6100d682826040516024016109d5929190610fab565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f319af33300000000000000000000000000000000000000000000000000000000179052610c01565b6100d68282604051602401610a66929190610fe3565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fc3b5563500000000000000000000000000000000000000000000000000000000179052610c01565b6100d68282604051602401610af7929190611007565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fb60e72cc00000000000000000000000000000000000000000000000000000000179052610c01565b610928838383604051602401610b8a93929190611029565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f2ced7cef000000000000000000000000000000000000000000000000000000001790525b6109bc8180516a636f6e736f6c652e6c6f67602083016000808483855afa5050505050565b60008060208385031215610c3957600080fd5b823567ffffffffffffffff80821115610c5157600080fd5b818501915085601f830112610c6557600080fd5b813581811115610c7457600080fd5b866020828501011115610c8657600080fd5b60209290920196919550909350505050565b600060208284031215610caa57600080fd5b81518015158114610cba57600080fd5b9392505050565b600060208284031215610cd357600080fd5b815167ffffffffffffffff81168114610cba57600080fd5b60005b83811015610d06578181015183820152602001610cee565b83811115610d15576000848401525b50505050565b60008151808452610d33816020860160208601610ceb565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b604081526000610d786040830184610d1b565b8281036020840152600c81527f2e726f6f745f6b65795b305d000000000000000000000000000000000000000060208201526040810191505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610e2d57610e2d610db7565b604052919050565b60006020808385031215610e4857600080fd5b825167ffffffffffffffff80821115610e6057600080fd5b8185019150601f8681840112610e7557600080fd5b825182811115610e8757610e87610db7565b8060051b610e96868201610de6565b918252848101860191868101908a841115610eb057600080fd5b87870192505b83831015610f5b57825186811115610ece5760008081fd5b8701603f81018c13610ee05760008081fd5b88810151604088821115610ef657610ef6610db7565b610f258b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08a85011601610de6565b8281528e82848601011115610f3a5760008081fd5b610f49838d8301848701610ceb565b85525050509187019190870190610eb6565b9a9950505050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602081526000610cba6020830184610d1b565b604081526000610fbe6040830185610d1b565b905073ffffffffffffffffffffffffffffffffffffffff831660208301529392505050565b604081526000610ff66040830185610d1b565b905082151560208301529392505050565b60408152600061101a6040830185610d1b565b90508260208301529392505050565b60608152600061103c6060830186610d1b565b828103602084015261104e8186610d1b565b905082810360408401526110628185610d1b565b969550505050505056fea164736f6c634300080f000a","sourceMap":"2318:1449:0:-:0;;;;;;;;;;;;;;;;;;;","linkReferences":{}},"deployedBytecode":{"object":"0x608060405234801561001057600080fd5b50600436106100365760003560e01c8063a777d0dc1461003b578063c040622614610050575b600080fd5b61004e610049366004610c26565b610058565b005b61004e6100da565b61009782828080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061092d92505050565b6100d66040518060400160405280601081526020017f68656c6c6f206d73672e73656e64657200000000000000000000000000000000815250336109bf565b5050565b604080517f4777f3cf0000000000000000000000000000000000000000000000000000000081526004810191909152600c60448201527f4558414d504c455f424f4f4c0000000000000000000000000000000000000000606482015260006024820181905290737109709ecfa91a80626ff3989d68f67f5b1dd12d90634777f3cf90608401602060405180830381865afa15801561017c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101a09190610c98565b90506101e16040518060400160405280601381526020017f626f6f6c2076616c75652066726f6d20656e760000000000000000000000000081525082610a50565b6102206040518060400160405280600d81526020017f636f6e7472616374206164647200000000000000000000000000000000000000815250306109bf565b604080518082018252600e81527f636f6e7472616374206e6f6e6365000000000000000000000000000000000000602082015290517f2d0335ab0000000000000000000000000000000000000000000000000000000081523060048201526102f39190737109709ecfa91a80626ff3989d68f67f5b1dd12d90632d0335ab906024015b602060405180830381865afa1580156102c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102e49190610cc1565b67ffffffffffffffff16610ae1565b6103326040518060400160405280600b81526020017f73656e6465722061646472000000000000000000000000000000000000000000815250336109bf565b604080518082018252600c81527f73656e646572206e6f6e63650000000000000000000000000000000000000000602082015290517f2d0335ab0000000000000000000000000000000000000000000000000000000081523360048201526103b99190737109709ecfa91a80626ff3989d68f67f5b1dd12d90632d0335ab906024016102a3565b60408051808201825260208082527f7b22726f6f745f6b6579223a205b7b2261223a20312c202262223a20327d5d7d9082015290517f213e4198000000000000000000000000000000000000000000000000000000008152600090737109709ecfa91a80626ff3989d68f67f5b1dd12d9063213e41989061043e908590600401610d65565b600060405180830381865afa15801561045b573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526104a19190810190610e35565b90506105176040518060400160405280600481526020017f6b65797300000000000000000000000000000000000000000000000000000000815250826000815181106104ef576104ef610f69565b60200260200101518360018151811061050a5761050a610f69565b6020026020010151610b72565b6040517fa777d0dc00000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f66726f6d206f726967696e616c000000000000000000000000000000000000006044820152309063a777d0dc9060640160006040518083038186803b15801561059457600080fd5b505afa1580156105a8573d6000803e3d6000fd5b50506040517f06447d5600000000000000000000000000000000000000000000000000000000815260426004820152737109709ecfa91a80626ff3989d68f67f5b1dd12d92506306447d569150602401600060405180830381600087803b15801561061257600080fd5b505af1158015610626573d6000803e3d6000fd5b50506040517fa777d0dc00000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f66726f6d207072616e6b20310000000000000000000000000000000000000000604482015230925063a777d0dc915060640160006040518083038186803b1580156106a757600080fd5b505afa1580156106bb573d6000803e3d6000fd5b505050506106fe6040518060400160405280601781526020017f706172656e742073636f7065206d73672e73656e646572000000000000000000815250336109bf565b61073d6040518060400160405280601a81526020017f706172656e742073636f706520636f6e74726163742e61646472000000000000815250306109bf565b6040517fa777d0dc00000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f66726f6d207072616e6b203200000000000000000000000000000000000000006044820152309063a777d0dc9060640160006040518083038186803b1580156107ba57600080fd5b505afa1580156107ce573d6000803e3d6000fd5b505050507f885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d60001c73ffffffffffffffffffffffffffffffffffffffff166390c5013b6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561083d57600080fd5b505af1158015610851573d6000803e3d6000fd5b50506040517fa777d0dc00000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f66726f6d206f726967696e616c20616761696e00000000000000000000000000604482015230925063a777d0dc915060640160006040518083038186803b1580156108d257600080fd5b505afa1580156108e6573d6000803e3d6000fd5b505050506109286040518060400160405280600581526020017f646f6e652100000000000000000000000000000000000000000000000000000081525061092d565b505050565b6109bc816040516024016109419190610f98565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f41304fac00000000000000000000000000000000000000000000000000000000179052610c01565b50565b6100d682826040516024016109d5929190610fab565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f319af33300000000000000000000000000000000000000000000000000000000179052610c01565b6100d68282604051602401610a66929190610fe3565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fc3b5563500000000000000000000000000000000000000000000000000000000179052610c01565b6100d68282604051602401610af7929190611007565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fb60e72cc00000000000000000000000000000000000000000000000000000000179052610c01565b610928838383604051602401610b8a93929190611029565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f2ced7cef000000000000000000000000000000000000000000000000000000001790525b6109bc8180516a636f6e736f6c652e6c6f67602083016000808483855afa5050505050565b60008060208385031215610c3957600080fd5b823567ffffffffffffffff80821115610c5157600080fd5b818501915085601f830112610c6557600080fd5b813581811115610c7457600080fd5b866020828501011115610c8657600080fd5b60209290920196919550909350505050565b600060208284031215610caa57600080fd5b81518015158114610cba57600080fd5b9392505050565b600060208284031215610cd357600080fd5b815167ffffffffffffffff81168114610cba57600080fd5b60005b83811015610d06578181015183820152602001610cee565b83811115610d15576000848401525b50505050565b60008151808452610d33816020860160208601610ceb565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b604081526000610d786040830184610d1b565b8281036020840152600c81527f2e726f6f745f6b65795b305d000000000000000000000000000000000000000060208201526040810191505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610e2d57610e2d610db7565b604052919050565b60006020808385031215610e4857600080fd5b825167ffffffffffffffff80821115610e6057600080fd5b8185019150601f8681840112610e7557600080fd5b825182811115610e8757610e87610db7565b8060051b610e96868201610de6565b918252848101860191868101908a841115610eb057600080fd5b87870192505b83831015610f5b57825186811115610ece5760008081fd5b8701603f81018c13610ee05760008081fd5b88810151604088821115610ef657610ef6610db7565b610f258b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08a85011601610de6565b8281528e82848601011115610f3a5760008081fd5b610f49838d8301848701610ceb565b85525050509187019190870190610eb6565b9a9950505050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602081526000610cba6020830184610d1b565b604081526000610fbe6040830185610d1b565b905073ffffffffffffffffffffffffffffffffffffffff831660208301529392505050565b604081526000610ff66040830185610d1b565b905082151560208301529392505050565b60408152600061101a6040830185610d1b565b90508260208301529392505050565b60608152600061103c6060830186610d1b565b828103602084015261104e8186610d1b565b905082810360408401526110628185610d1b565b969550505050505056fea164736f6c634300080f000a","sourceMap":"2318:1449:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3622:143;;;;;;:::i;:::-;;:::i;:::-;;2578:949;;;:::i;3622:143::-;3681:15;3693:2;;3681:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;3681:11:0;;-1:-1:-1;;;3681:15:0:i;:::-;3706:52;;;;;;;;;;;;;;;;;;3746:10;3706:11;:52::i;:::-;3622:143;;:::o;2578:949::-;2619:31;;;;;;;;;817:21:1;;;;874:2;854:18;;;847:30;913:14;893:18;;;886:42;2610:6:0;980:20:1;;;973:52;;;2610:6:0;2619:8;;;;945:19:1;;2619:31:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;2610:40;;2660:37;;;;;;;;;;;;;;;;;;2695:1;2660:11;:37::i;:::-;2708:43;;;;;;;;;;;;;;;;;;2745:4;2708:11;:43::i;:::-;2761:57;;;;;;;;;;;;;;;;2791:26;;;;;2811:4;2791:26;;;1464:74:1;2761:57:0;;;2791:11;;;;1437:18:1;;2791:26:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;2761:57;;:11;:57::i;:::-;2828:47;;;;;;;;;;;;;;;;;;2863:10;2828:11;:47::i;:::-;2885:61;;;;;;;;;;;;;;;;2913:32;;;;;2933:10;2913:32;;;1464:74:1;2885:61:0;;;2913:11;;;;1437:18:1;;2913:32:0;1318:226:1;2885:61:0;2957:55;;;;;;;;;;;;;;;;;3045:38;;;;;2957:18;;3045:16;;;;:38;;2957:55;;3045:38;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;3022:61;;3093:37;;;;;;;;;;;;;;;;;;3113:4;3118:1;3113:7;;;;;;;;:::i;:::-;;;;;;;3122:4;3127:1;3122:7;;;;;;;;:::i;:::-;;;;;;;3093:11;:37::i;:::-;3141:27;;;;;5650:2:1;3141:27:0;;;5632:21:1;5689:2;5669:18;;;5662:30;5728:15;5708:18;;;5701:43;3141:4:0;;:10;;5761:18:1;;3141:27:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;3178:37:0;;;;;3208:4;3178:37;;;1464:74:1;3178:13:0;;-1:-1:-1;3178:13:0;;-1:-1:-1;1437:18:1;;3178:37:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;3225:26:0;;;;;5992:2:1;3225:26:0;;;5974:21:1;6031:2;6011:18;;;6004:30;6070:14;6050:18;;;6043:42;3225:4:0;;-1:-1:-1;3225:10:0;;-1:-1:-1;6102:18:1;;3225:26:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3261:59;;;;;;;;;;;;;;;;;;3308:10;3261:11;:59::i;:::-;3330:56;;;;;;;;;;;;;;;;;;3380:4;3330:11;:56::i;:::-;3396:26;;;;;6333:2:1;3396:26:0;;;6315:21:1;6372:2;6352:18;;;6345:30;6411:14;6391:18;;;6384:42;3396:4:0;;:10;;6443:18:1;;3396:26:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2411:28;2403:37;;3432:12;;;:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;3456:33:0;;;;;6674:2:1;3456:33:0;;;6656:21:1;6713:2;6693:18;;;6686:30;6752:21;6732:18;;;6725:49;3456:4:0;;-1:-1:-1;3456:10:0;;-1:-1:-1;6791:18:1;;3456:33:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3500:20;;;;;;;;;;;;;;;;;;:11;:20::i;:::-;2600:927;;;2578:949::o;1435:121::-;1490:59;1545:2;1506:42;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;1490:15;:59::i;:::-;1435:121;:::o;1858:145::-;1925:71;1988:2;1992;1941:54;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;1925:15;:71::i;1562:139::-;1626:68;1686:2;1690;1642:51;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;1626:15;:68::i;1707:145::-;1774:71;1837:2;1841;1790:54;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;1774:15;:71::i;2009:179::-;2100:81;2169:2;2173;2177;2116:64;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;910:133;981:55;1028:7;1147:14;;633:42;1320:2;1307:16;;1123:21;;1147:14;1307:16;633:42;1356:5;1345:68;1336:77;;1273:150;;1049:380;:::o;14:592:1:-;85:6;93;146:2;134:9;125:7;121:23;117:32;114:52;;;162:1;159;152:12;114:52;202:9;189:23;231:18;272:2;264:6;261:14;258:34;;;288:1;285;278:12;258:34;326:6;315:9;311:22;301:32;;371:7;364:4;360:2;356:13;352:27;342:55;;393:1;390;383:12;342:55;433:2;420:16;459:2;451:6;448:14;445:34;;;475:1;472;465:12;445:34;520:7;515:2;506:6;502:2;498:15;494:24;491:37;488:57;;;541:1;538;531:12;488:57;572:2;564:11;;;;;594:6;;-1:-1:-1;14:592:1;;-1:-1:-1;;;;14:592:1:o;1036:277::-;1103:6;1156:2;1144:9;1135:7;1131:23;1127:32;1124:52;;;1172:1;1169;1162:12;1124:52;1204:9;1198:16;1257:5;1250:13;1243:21;1236:5;1233:32;1223:60;;1279:1;1276;1269:12;1223:60;1302:5;1036:277;-1:-1:-1;;;1036:277:1:o;1549:288::-;1618:6;1671:2;1659:9;1650:7;1646:23;1642:32;1639:52;;;1687:1;1684;1677:12;1639:52;1719:9;1713:16;1769:18;1762:5;1758:30;1751:5;1748:41;1738:69;;1803:1;1800;1793:12;1842:258;1914:1;1924:113;1938:6;1935:1;1932:13;1924:113;;;2014:11;;;2008:18;1995:11;;;1988:39;1960:2;1953:10;1924:113;;;2055:6;2052:1;2049:13;2046:48;;;2090:1;2081:6;2076:3;2072:16;2065:27;2046:48;;1842:258;;;:::o;2105:317::-;2147:3;2185:5;2179:12;2212:6;2207:3;2200:19;2228:63;2284:6;2277:4;2272:3;2268:14;2261:4;2254:5;2250:16;2228:63;:::i;:::-;2336:2;2324:15;2341:66;2320:88;2311:98;;;;2411:4;2307:109;;2105:317;-1:-1:-1;;2105:317:1:o;2427:493::-;2677:2;2666:9;2659:21;2640:4;2703:45;2744:2;2733:9;2729:18;2721:6;2703:45;:::i;:::-;2796:9;2788:6;2784:22;2779:2;2768:9;2764:18;2757:50;2831:2;2823:6;2816:18;2867:14;2862:2;2854:6;2850:15;2843:39;2911:2;2903:6;2899:15;2891:23;;;2427:493;;;;:::o;2925:184::-;2977:77;2974:1;2967:88;3074:4;3071:1;3064:15;3098:4;3095:1;3088:15;3114:334;3185:2;3179:9;3241:2;3231:13;;3246:66;3227:86;3215:99;;3344:18;3329:34;;3365:22;;;3326:62;3323:88;;;3391:18;;:::i;:::-;3427:2;3420:22;3114:334;;-1:-1:-1;3114:334:1:o;3453:1801::-;3558:6;3589:2;3632;3620:9;3611:7;3607:23;3603:32;3600:52;;;3648:1;3645;3638:12;3600:52;3681:9;3675:16;3710:18;3751:2;3743:6;3740:14;3737:34;;;3767:1;3764;3757:12;3737:34;3805:6;3794:9;3790:22;3780:32;;3831:4;3871:7;3866:2;3862;3858:11;3854:25;3844:53;;3893:1;3890;3883:12;3844:53;3922:2;3916:9;3944:2;3940;3937:10;3934:36;;;3950:18;;:::i;:::-;3996:2;3993:1;3989:10;4019:28;4043:2;4039;4035:11;4019:28;:::i;:::-;4081:15;;;4151:11;;;4147:20;;;4112:12;;;;4179:19;;;4176:39;;;4211:1;4208;4201:12;4176:39;4243:2;4239;4235:11;4224:22;;4255:969;4271:6;4266:3;4263:15;4255:969;;;4350:3;4344:10;4386:2;4373:11;4370:19;4367:109;;;4430:1;4459:2;4455;4448:14;4367:109;4499:20;;4554:2;4546:11;;4542:25;-1:-1:-1;4532:123:1;;4609:1;4638:2;4634;4627:14;4532:123;4693:2;4689;4685:11;4679:18;4721:2;4747;4742:3;4739:11;4736:37;;;4753:18;;:::i;:::-;4799:111;4906:2;4837:66;4832:2;4827:3;4823:12;4819:85;4815:94;4799:111;:::i;:::-;4937:3;4930:5;4923:18;4984:7;4978:3;4972;4968:2;4964:12;4960:22;4957:35;4954:128;;;5034:1;5064:3;5059;5052:16;4954:128;5095:56;5147:3;5142:2;5135:5;5131:14;5125:3;5121:2;5117:12;5095:56;:::i;:::-;5164:18;;-1:-1:-1;;;4288:12:1;;;;5202;;;;4255:969;;;5243:5;3453:1801;-1:-1:-1;;;;;;;;;;3453:1801:1:o;5259:184::-;5311:77;5308:1;5301:88;5408:4;5405:1;5398:15;5432:4;5429:1;5422:15;6820:220;6969:2;6958:9;6951:21;6932:4;6989:45;7030:2;7019:9;7015:18;7007:6;6989:45;:::i;7045:340::-;7222:2;7211:9;7204:21;7185:4;7242:45;7283:2;7272:9;7268:18;7260:6;7242:45;:::i;:::-;7234:53;;7335:42;7327:6;7323:55;7318:2;7307:9;7303:18;7296:83;7045:340;;;;;:::o;7390:301::-;7561:2;7550:9;7543:21;7524:4;7581:45;7622:2;7611:9;7607:18;7599:6;7581:45;:::i;:::-;7573:53;;7676:6;7669:14;7662:22;7657:2;7646:9;7642:18;7635:50;7390:301;;;;;:::o;7696:291::-;7873:2;7862:9;7855:21;7836:4;7893:45;7934:2;7923:9;7919:18;7911:6;7893:45;:::i;:::-;7885:53;;7974:6;7969:2;7958:9;7954:18;7947:34;7696:291;;;;;:::o;7992:546::-;8237:2;8226:9;8219:21;8200:4;8263:45;8304:2;8293:9;8289:18;8281:6;8263:45;:::i;:::-;8356:9;8348:6;8344:22;8339:2;8328:9;8324:18;8317:50;8390:33;8416:6;8408;8390:33;:::i;:::-;8376:47;;8471:9;8463:6;8459:22;8454:2;8443:9;8439:18;8432:50;8499:33;8525:6;8517;8499:33;:::i;:::-;8491:41;7992:546;-1:-1:-1;;;;;;7992:546:1:o","linkReferences":{}},"methodIdentifiers":{"hello(string)":"a777d0dc","run()":"c0406226"},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_v\",\"type\":\"string\"}],\"name\":\"hello\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"run\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"title\":\"ScriptExample\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"hello(string)\":{\"notice\":\"example external function, to force a CALL, and test vm.startPrank with.\"},\"run()\":{\"notice\":\"example function, runs through basic cheat-codes and console logs.\"}},\"notice\":\"ScriptExample is an example script. The Go forge script code tests that it can run this.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"scripts/ScriptExample.s.sol\":\"ScriptExample\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[]},\"sources\":{\"scripts/ScriptExample.s.sol\":{\"keccak256\":\"0x531a2ad96c1a2c0bbfa9ab0e1195cd32551b0c10e16e7d256ce5e4c0289a8089\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://24dc6c71502c01f43fb5e113786e377c3b4cafabd5c506067d229fcdd7b037fa\",\"dweb:/ipfs/QmZ9AuxNx9Ygescfg5M4p6Abc2CCwCMZpX5xU32Fz1r4kY\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.15+commit.e14f2714"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"string","name":"_v","type":"string"}],"stateMutability":"view","type":"function","name":"hello"},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"run"}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{"hello(string)":{"notice":"example external function, to force a CALL, and test vm.startPrank with."},"run()":{"notice":"example function, runs through basic cheat-codes and console logs."}},"version":1}},"settings":{"remappings":[],"optimizer":{"enabled":true,"runs":999999},"metadata":{"bytecodeHash":"none"},"compilationTarget":{"scripts/ScriptExample.s.sol":"ScriptExample"},"evmVersion":"london","libraries":{}},"sources":{"scripts/ScriptExample.s.sol":{"keccak256":"0x531a2ad96c1a2c0bbfa9ab0e1195cd32551b0c10e16e7d256ce5e4c0289a8089","urls":["bzz-raw://24dc6c71502c01f43fb5e113786e377c3b4cafabd5c506067d229fcdd7b037fa","dweb:/ipfs/QmZ9AuxNx9Ygescfg5M4p6Abc2CCwCMZpX5xU32Fz1r4kY"],"license":"MIT"}},"version":1},"storageLayout":{"storage":[],"types":{}},"userdoc":{"version":1,"kind":"user","methods":{"hello(string)":{"notice":"example external function, to force a CALL, and test vm.startPrank with."},"run()":{"notice":"example function, runs through basic cheat-codes and console logs."}},"notice":"ScriptExample is an example script. The Go forge script code tests that it can run this."},"devdoc":{"version":1,"kind":"dev","title":"ScriptExample"},"ast":{"absolutePath":"scripts/ScriptExample.s.sol","id":383,"exportedSymbols":{"ScriptExample":[382],"Vm":[36],"console":[173]},"nodeType":"SourceUnit","src":"32:3736:0","nodes":[{"id":1,"nodeType":"PragmaDirective","src":"32:23:0","nodes":[],"literals":["solidity","0.8",".15"]},{"id":36,"nodeType":"ContractDefinition","src":"120:393:0","nodes":[{"id":10,"nodeType":"FunctionDefinition","src":"139:91:0","nodes":[],"functionSelector":"4777f3cf","implemented":false,"kind":"function","modifiers":[],"name":"envOr","nameLocation":"148:5:0","parameters":{"id":6,"nodeType":"ParameterList","parameters":[{"constant":false,"id":3,"mutability":"mutable","name":"name","nameLocation":"170:4:0","nodeType":"VariableDeclaration","scope":10,"src":"154:20:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":2,"name":"string","nodeType":"ElementaryTypeName","src":"154:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":5,"mutability":"mutable","name":"defaultValue","nameLocation":"181:12:0","nodeType":"VariableDeclaration","scope":10,"src":"176:17:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":4,"name":"bool","nodeType":"ElementaryTypeName","src":"176:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"src":"153:41:0"},"returnParameters":{"id":9,"nodeType":"ParameterList","parameters":[{"constant":false,"id":8,"mutability":"mutable","name":"value","nameLocation":"223:5:0","nodeType":"VariableDeclaration","scope":10,"src":"218:10:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":7,"name":"bool","nodeType":"ElementaryTypeName","src":"218:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"src":"217:12:0"},"scope":36,"stateMutability":"view","virtual":false,"visibility":"external"},{"id":17,"nodeType":"FunctionDefinition","src":"235:72:0","nodes":[],"functionSelector":"2d0335ab","implemented":false,"kind":"function","modifiers":[],"name":"getNonce","nameLocation":"244:8:0","parameters":{"id":13,"nodeType":"ParameterList","parameters":[{"constant":false,"id":12,"mutability":"mutable","name":"account","nameLocation":"261:7:0","nodeType":"VariableDeclaration","scope":17,"src":"253:15:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":11,"name":"address","nodeType":"ElementaryTypeName","src":"253:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"252:17:0"},"returnParameters":{"id":16,"nodeType":"ParameterList","parameters":[{"constant":false,"id":15,"mutability":"mutable","name":"nonce","nameLocation":"300:5:0","nodeType":"VariableDeclaration","scope":17,"src":"293:12:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"},"typeName":{"id":14,"name":"uint64","nodeType":"ElementaryTypeName","src":"293:6:0","typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}},"visibility":"internal"}],"src":"292:14:0"},"scope":36,"stateMutability":"view","virtual":false,"visibility":"external"},{"id":27,"nodeType":"FunctionDefinition","src":"312:111:0","nodes":[],"functionSelector":"213e4198","implemented":false,"kind":"function","modifiers":[],"name":"parseJsonKeys","nameLocation":"321:13:0","parameters":{"id":22,"nodeType":"ParameterList","parameters":[{"constant":false,"id":19,"mutability":"mutable","name":"json","nameLocation":"351:4:0","nodeType":"VariableDeclaration","scope":27,"src":"335:20:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":18,"name":"string","nodeType":"ElementaryTypeName","src":"335:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":21,"mutability":"mutable","name":"key","nameLocation":"373:3:0","nodeType":"VariableDeclaration","scope":27,"src":"357:19:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":20,"name":"string","nodeType":"ElementaryTypeName","src":"357:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"334:43:0"},"returnParameters":{"id":26,"nodeType":"ParameterList","parameters":[{"constant":false,"id":25,"mutability":"mutable","name":"keys","nameLocation":"417:4:0","nodeType":"VariableDeclaration","scope":27,"src":"401:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string[]"},"typeName":{"baseType":{"id":23,"name":"string","nodeType":"ElementaryTypeName","src":"401:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"id":24,"nodeType":"ArrayTypeName","src":"401:8:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_storage_$dyn_storage_ptr","typeString":"string[]"}},"visibility":"internal"}],"src":"400:22:0"},"scope":36,"stateMutability":"pure","virtual":false,"visibility":"external"},{"id":32,"nodeType":"FunctionDefinition","src":"428:48:0","nodes":[],"functionSelector":"06447d56","implemented":false,"kind":"function","modifiers":[],"name":"startPrank","nameLocation":"437:10:0","parameters":{"id":30,"nodeType":"ParameterList","parameters":[{"constant":false,"id":29,"mutability":"mutable","name":"msgSender","nameLocation":"456:9:0","nodeType":"VariableDeclaration","scope":32,"src":"448:17:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":28,"name":"address","nodeType":"ElementaryTypeName","src":"448:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"447:19:0"},"returnParameters":{"id":31,"nodeType":"ParameterList","parameters":[],"src":"475:0:0"},"scope":36,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":35,"nodeType":"FunctionDefinition","src":"481:30:0","nodes":[],"functionSelector":"90c5013b","implemented":false,"kind":"function","modifiers":[],"name":"stopPrank","nameLocation":"490:9:0","parameters":{"id":33,"nodeType":"ParameterList","parameters":[],"src":"499:2:0"},"returnParameters":{"id":34,"nodeType":"ParameterList","parameters":[],"src":"510:0:0"},"scope":36,"stateMutability":"nonpayable","virtual":false,"visibility":"external"}],"abstract":false,"baseContracts":[],"canonicalName":"Vm","contractDependencies":[],"contractKind":"interface","fullyImplemented":false,"linearizedBaseContracts":[36],"name":"Vm","nameLocation":"130:2:0","scope":383,"usedErrors":[]},{"id":173,"nodeType":"ContractDefinition","src":"568:1622:0","nodes":[{"id":42,"nodeType":"VariableDeclaration","src":"590:86:0","nodes":[],"constant":true,"mutability":"constant","name":"CONSOLE_ADDRESS","nameLocation":"607:15:0","scope":173,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":37,"name":"address","nodeType":"ElementaryTypeName","src":"590:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"value":{"arguments":[{"hexValue":"307830303030303030303030303030303030303036333646366537333646366336353265366336663637","id":40,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"633:42:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"value":"0x000000000000000000636F6e736F6c652e6c6f67"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":39,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"625:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":38,"name":"address","nodeType":"ElementaryTypeName","src":"625:7:0","typeDescriptions":{}}},"id":41,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"625:51:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"},{"id":59,"nodeType":"FunctionDefinition","src":"683:221:0","nodes":[],"body":{"id":58,"nodeType":"Block","src":"842:62:0","nodes":[],"statements":[{"AST":{"nodeType":"YulBlock","src":"861:37:0","statements":[{"nodeType":"YulAssignment","src":"875:13:0","value":{"name":"fnIn","nodeType":"YulIdentifier","src":"884:4:0"},"variableNames":[{"name":"fnOut","nodeType":"YulIdentifier","src":"875:5:0"}]}]},"evmVersion":"london","externalReferences":[{"declaration":48,"isOffset":false,"isSlot":false,"src":"884:4:0","valueSize":1},{"declaration":55,"isOffset":false,"isSlot":false,"src":"875:5:0","valueSize":1}],"id":57,"nodeType":"InlineAssembly","src":"852:46:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"_castLogPayloadViewToPure","nameLocation":"692:25:0","parameters":{"id":49,"nodeType":"ParameterList","parameters":[{"constant":false,"id":48,"mutability":"mutable","name":"fnIn","nameLocation":"764:4:0","nodeType":"VariableDeclaration","scope":59,"src":"727:41:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) view"},"typeName":{"id":47,"nodeType":"FunctionTypeName","parameterTypes":{"id":45,"nodeType":"ParameterList","parameters":[{"constant":false,"id":44,"mutability":"mutable","name":"","nameLocation":"-1:-1:-1","nodeType":"VariableDeclaration","scope":47,"src":"736:12:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":43,"name":"bytes","nodeType":"ElementaryTypeName","src":"736:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"735:14:0"},"returnParameterTypes":{"id":46,"nodeType":"ParameterList","parameters":[],"src":"764:0:0"},"src":"727:41:0","stateMutability":"view","typeDescriptions":{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) view"},"visibility":"internal"},"visibility":"internal"}],"src":"717:57:0"},"returnParameters":{"id":56,"nodeType":"ParameterList","parameters":[{"constant":false,"id":55,"mutability":"mutable","name":"fnOut","nameLocation":"835:5:0","nodeType":"VariableDeclaration","scope":59,"src":"798:42:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) pure"},"typeName":{"id":54,"nodeType":"FunctionTypeName","parameterTypes":{"id":52,"nodeType":"ParameterList","parameters":[{"constant":false,"id":51,"mutability":"mutable","name":"","nameLocation":"-1:-1:-1","nodeType":"VariableDeclaration","scope":54,"src":"807:12:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":50,"name":"bytes","nodeType":"ElementaryTypeName","src":"807:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"806:14:0"},"returnParameterTypes":{"id":53,"nodeType":"ParameterList","parameters":[],"src":"835:0:0"},"src":"798:42:0","stateMutability":"pure","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) pure"},"visibility":"internal"},"visibility":"internal"}],"src":"797:44:0"},"scope":173,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":71,"nodeType":"FunctionDefinition","src":"910:133:0","nodes":[],"body":{"id":70,"nodeType":"Block","src":"971:72:0","nodes":[],"statements":[{"expression":{"arguments":[{"id":67,"name":"payload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":61,"src":"1028:7:0","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"arguments":[{"id":65,"name":"_sendLogPayloadView","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":87,"src":"1007:19:0","typeDescriptions":{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) view"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) view"}],"id":64,"name":"_castLogPayloadViewToPure","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":59,"src":"981:25:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_function_internal_view$_t_bytes_memory_ptr_$returns$__$_$returns$_t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$_$","typeString":"function (function (bytes memory) view) pure returns (function (bytes memory) pure)"}},"id":66,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"981:46:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":68,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"981:55:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":69,"nodeType":"ExpressionStatement","src":"981:55:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"_sendLogPayload","nameLocation":"919:15:0","parameters":{"id":62,"nodeType":"ParameterList","parameters":[{"constant":false,"id":61,"mutability":"mutable","name":"payload","nameLocation":"948:7:0","nodeType":"VariableDeclaration","scope":71,"src":"935:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":60,"name":"bytes","nodeType":"ElementaryTypeName","src":"935:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"934:22:0"},"returnParameters":{"id":63,"nodeType":"ParameterList","parameters":[],"src":"971:0:0"},"scope":173,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":87,"nodeType":"FunctionDefinition","src":"1049:380:0","nodes":[],"body":{"id":86,"nodeType":"Block","src":"1113:316:0","nodes":[],"statements":[{"assignments":[77],"declarations":[{"constant":false,"id":77,"mutability":"mutable","name":"payloadLength","nameLocation":"1131:13:0","nodeType":"VariableDeclaration","scope":86,"src":"1123:21:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":76,"name":"uint256","nodeType":"ElementaryTypeName","src":"1123:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"}],"id":80,"initialValue":{"expression":{"id":78,"name":"payload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":73,"src":"1147:7:0","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}},"id":79,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"length","nodeType":"MemberAccess","src":"1147:14:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"nodeType":"VariableDeclarationStatement","src":"1123:38:0"},{"assignments":[82],"declarations":[{"constant":false,"id":82,"mutability":"mutable","name":"consoleAddress","nameLocation":"1179:14:0","nodeType":"VariableDeclaration","scope":86,"src":"1171:22:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":81,"name":"address","nodeType":"ElementaryTypeName","src":"1171:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"id":84,"initialValue":{"id":83,"name":"CONSOLE_ADDRESS","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":42,"src":"1196:15:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"nodeType":"VariableDeclarationStatement","src":"1171:40:0"},{"AST":{"nodeType":"YulBlock","src":"1273:150:0","statements":[{"nodeType":"YulVariableDeclaration","src":"1287:36:0","value":{"arguments":[{"name":"payload","nodeType":"YulIdentifier","src":"1311:7:0"},{"kind":"number","nodeType":"YulLiteral","src":"1320:2:0","type":"","value":"32"}],"functionName":{"name":"add","nodeType":"YulIdentifier","src":"1307:3:0"},"nodeType":"YulFunctionCall","src":"1307:16:0"},"variables":[{"name":"payloadStart","nodeType":"YulTypedName","src":"1291:12:0","type":""}]},{"nodeType":"YulVariableDeclaration","src":"1336:77:0","value":{"arguments":[{"arguments":[],"functionName":{"name":"gas","nodeType":"YulIdentifier","src":"1356:3:0"},"nodeType":"YulFunctionCall","src":"1356:5:0"},{"name":"consoleAddress","nodeType":"YulIdentifier","src":"1363:14:0"},{"name":"payloadStart","nodeType":"YulIdentifier","src":"1379:12:0"},{"name":"payloadLength","nodeType":"YulIdentifier","src":"1393:13:0"},{"kind":"number","nodeType":"YulLiteral","src":"1408:1:0","type":"","value":"0"},{"kind":"number","nodeType":"YulLiteral","src":"1411:1:0","type":"","value":"0"}],"functionName":{"name":"staticcall","nodeType":"YulIdentifier","src":"1345:10:0"},"nodeType":"YulFunctionCall","src":"1345:68:0"},"variables":[{"name":"r","nodeType":"YulTypedName","src":"1340:1:0","type":""}]}]},"documentation":"@solidity memory-safe-assembly","evmVersion":"london","externalReferences":[{"declaration":82,"isOffset":false,"isSlot":false,"src":"1363:14:0","valueSize":1},{"declaration":73,"isOffset":false,"isSlot":false,"src":"1311:7:0","valueSize":1},{"declaration":77,"isOffset":false,"isSlot":false,"src":"1393:13:0","valueSize":1}],"id":85,"nodeType":"InlineAssembly","src":"1264:159:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"_sendLogPayloadView","nameLocation":"1058:19:0","parameters":{"id":74,"nodeType":"ParameterList","parameters":[{"constant":false,"id":73,"mutability":"mutable","name":"payload","nameLocation":"1091:7:0","nodeType":"VariableDeclaration","scope":87,"src":"1078:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":72,"name":"bytes","nodeType":"ElementaryTypeName","src":"1078:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"1077:22:0"},"returnParameters":{"id":75,"nodeType":"ParameterList","parameters":[],"src":"1113:0:0"},"scope":173,"stateMutability":"view","virtual":false,"visibility":"private"},{"id":101,"nodeType":"FunctionDefinition","src":"1435:121:0","nodes":[],"body":{"id":100,"nodeType":"Block","src":"1480:76:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e6729","id":95,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"1530:13:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_41304facd9323d75b11bcdd609cb38effffdb05710f7caf0e9b16c6d9d709f50","typeString":"literal_string \"log(string)\""},"value":"log(string)"},{"id":96,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":89,"src":"1545:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_41304facd9323d75b11bcdd609cb38effffdb05710f7caf0e9b16c6d9d709f50","typeString":"literal_string \"log(string)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}],"expression":{"id":93,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"1506:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":94,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"1506:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":97,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1506:42:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":92,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":71,"src":"1490:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":98,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1490:59:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":99,"nodeType":"ExpressionStatement","src":"1490:59:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"1444:3:0","parameters":{"id":90,"nodeType":"ParameterList","parameters":[{"constant":false,"id":89,"mutability":"mutable","name":"p0","nameLocation":"1462:2:0","nodeType":"VariableDeclaration","scope":101,"src":"1448:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":88,"name":"string","nodeType":"ElementaryTypeName","src":"1448:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"1447:18:0"},"returnParameters":{"id":91,"nodeType":"ParameterList","parameters":[],"src":"1480:0:0"},"scope":173,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":118,"nodeType":"FunctionDefinition","src":"1562:139:0","nodes":[],"body":{"id":117,"nodeType":"Block","src":"1616:85:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c626f6f6c29","id":111,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"1666:18:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_c3b556354c088fbb43886eb83c2a04bc7089663f964d22be308197a236f5b870","typeString":"literal_string \"log(string,bool)\""},"value":"log(string,bool)"},{"id":112,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":103,"src":"1686:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":113,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":105,"src":"1690:2:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_c3b556354c088fbb43886eb83c2a04bc7089663f964d22be308197a236f5b870","typeString":"literal_string \"log(string,bool)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_bool","typeString":"bool"}],"expression":{"id":109,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"1642:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":110,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"1642:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":114,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1642:51:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":108,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":71,"src":"1626:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":115,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1626:68:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":116,"nodeType":"ExpressionStatement","src":"1626:68:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"1571:3:0","parameters":{"id":106,"nodeType":"ParameterList","parameters":[{"constant":false,"id":103,"mutability":"mutable","name":"p0","nameLocation":"1589:2:0","nodeType":"VariableDeclaration","scope":118,"src":"1575:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":102,"name":"string","nodeType":"ElementaryTypeName","src":"1575:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":105,"mutability":"mutable","name":"p1","nameLocation":"1598:2:0","nodeType":"VariableDeclaration","scope":118,"src":"1593:7:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":104,"name":"bool","nodeType":"ElementaryTypeName","src":"1593:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"src":"1574:27:0"},"returnParameters":{"id":107,"nodeType":"ParameterList","parameters":[],"src":"1616:0:0"},"scope":173,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":135,"nodeType":"FunctionDefinition","src":"1707:145:0","nodes":[],"body":{"id":134,"nodeType":"Block","src":"1764:88:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c75696e7432353629","id":128,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"1814:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_b60e72ccf6d57ab53eb84d7e94a9545806ed7f93c4d5673f11a64f03471e584e","typeString":"literal_string \"log(string,uint256)\""},"value":"log(string,uint256)"},{"id":129,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":120,"src":"1837:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":130,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":122,"src":"1841:2:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_b60e72ccf6d57ab53eb84d7e94a9545806ed7f93c4d5673f11a64f03471e584e","typeString":"literal_string \"log(string,uint256)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_uint256","typeString":"uint256"}],"expression":{"id":126,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"1790:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":127,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"1790:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":131,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1790:54:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":125,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":71,"src":"1774:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":132,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1774:71:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":133,"nodeType":"ExpressionStatement","src":"1774:71:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"1716:3:0","parameters":{"id":123,"nodeType":"ParameterList","parameters":[{"constant":false,"id":120,"mutability":"mutable","name":"p0","nameLocation":"1734:2:0","nodeType":"VariableDeclaration","scope":135,"src":"1720:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":119,"name":"string","nodeType":"ElementaryTypeName","src":"1720:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":122,"mutability":"mutable","name":"p1","nameLocation":"1746:2:0","nodeType":"VariableDeclaration","scope":135,"src":"1738:10:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":121,"name":"uint256","nodeType":"ElementaryTypeName","src":"1738:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"}],"src":"1719:30:0"},"returnParameters":{"id":124,"nodeType":"ParameterList","parameters":[],"src":"1764:0:0"},"scope":173,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":152,"nodeType":"FunctionDefinition","src":"1858:145:0","nodes":[],"body":{"id":151,"nodeType":"Block","src":"1915:88:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c6164647265737329","id":145,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"1965:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_319af333460570a1937bf195dd33445c0d0951c59127da6f1f038b9fdce3fd72","typeString":"literal_string \"log(string,address)\""},"value":"log(string,address)"},{"id":146,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":137,"src":"1988:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":147,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":139,"src":"1992:2:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_319af333460570a1937bf195dd33445c0d0951c59127da6f1f038b9fdce3fd72","typeString":"literal_string \"log(string,address)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":143,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"1941:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":144,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"1941:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":148,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1941:54:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":142,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":71,"src":"1925:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":149,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1925:71:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":150,"nodeType":"ExpressionStatement","src":"1925:71:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"1867:3:0","parameters":{"id":140,"nodeType":"ParameterList","parameters":[{"constant":false,"id":137,"mutability":"mutable","name":"p0","nameLocation":"1885:2:0","nodeType":"VariableDeclaration","scope":152,"src":"1871:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":136,"name":"string","nodeType":"ElementaryTypeName","src":"1871:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":139,"mutability":"mutable","name":"p1","nameLocation":"1897:2:0","nodeType":"VariableDeclaration","scope":152,"src":"1889:10:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":138,"name":"address","nodeType":"ElementaryTypeName","src":"1889:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"1870:30:0"},"returnParameters":{"id":141,"nodeType":"ParameterList","parameters":[],"src":"1915:0:0"},"scope":173,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":172,"nodeType":"FunctionDefinition","src":"2009:179:0","nodes":[],"body":{"id":171,"nodeType":"Block","src":"2090:98:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c737472696e672c737472696e6729","id":164,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2140:27:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_2ced7cef693312206c21f0e92e3b54e2e16bf33db5eec350c78866822c665e1f","typeString":"literal_string \"log(string,string,string)\""},"value":"log(string,string,string)"},{"id":165,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":154,"src":"2169:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":166,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":156,"src":"2173:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":167,"name":"p2","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":158,"src":"2177:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_2ced7cef693312206c21f0e92e3b54e2e16bf33db5eec350c78866822c665e1f","typeString":"literal_string \"log(string,string,string)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}],"expression":{"id":162,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"2116:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":163,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"2116:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":168,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2116:64:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":161,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":71,"src":"2100:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":169,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2100:81:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":170,"nodeType":"ExpressionStatement","src":"2100:81:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"2018:3:0","parameters":{"id":159,"nodeType":"ParameterList","parameters":[{"constant":false,"id":154,"mutability":"mutable","name":"p0","nameLocation":"2036:2:0","nodeType":"VariableDeclaration","scope":172,"src":"2022:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":153,"name":"string","nodeType":"ElementaryTypeName","src":"2022:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":156,"mutability":"mutable","name":"p1","nameLocation":"2054:2:0","nodeType":"VariableDeclaration","scope":172,"src":"2040:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":155,"name":"string","nodeType":"ElementaryTypeName","src":"2040:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":158,"mutability":"mutable","name":"p2","nameLocation":"2072:2:0","nodeType":"VariableDeclaration","scope":172,"src":"2058:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":157,"name":"string","nodeType":"ElementaryTypeName","src":"2058:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"2021:54:0"},"returnParameters":{"id":160,"nodeType":"ParameterList","parameters":[],"src":"2090:0:0"},"scope":173,"stateMutability":"pure","virtual":false,"visibility":"internal"}],"abstract":false,"baseContracts":[],"canonicalName":"console","contractDependencies":[],"contractKind":"library","fullyImplemented":true,"linearizedBaseContracts":[173],"name":"console","nameLocation":"576:7:0","scope":383,"usedErrors":[]},{"id":382,"nodeType":"ContractDefinition","src":"2318:1449:0","nodes":[{"id":188,"nodeType":"VariableDeclaration","src":"2348:94:0","nodes":[],"constant":true,"mutability":"constant","name":"VM_ADDRESS","nameLocation":"2374:10:0","scope":382,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":175,"name":"address","nodeType":"ElementaryTypeName","src":"2348:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"value":{"arguments":[{"arguments":[{"arguments":[{"arguments":[{"hexValue":"6865766d20636865617420636f6465","id":183,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2421:17:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d","typeString":"literal_string \"hevm cheat code\""},"value":"hevm cheat code"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d","typeString":"literal_string \"hevm cheat code\""}],"id":182,"name":"keccak256","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-8,"src":"2411:9:0","typeDescriptions":{"typeIdentifier":"t_function_keccak256_pure$_t_bytes_memory_ptr_$returns$_t_bytes32_$","typeString":"function (bytes memory) pure returns (bytes32)"}},"id":184,"isConstant":false,"isLValue":false,"isPure":true,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2411:28:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes32","typeString":"bytes32"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes32","typeString":"bytes32"}],"id":181,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2403:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint256_$","typeString":"type(uint256)"},"typeName":{"id":180,"name":"uint256","nodeType":"ElementaryTypeName","src":"2403:7:0","typeDescriptions":{}}},"id":185,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2403:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint256","typeString":"uint256"}],"id":179,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2395:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":178,"name":"uint160","nodeType":"ElementaryTypeName","src":"2395:7:0","typeDescriptions":{}}},"id":186,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2395:46:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":177,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2387:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":176,"name":"address","nodeType":"ElementaryTypeName","src":"2387:7:0","typeDescriptions":{}}},"id":187,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2387:55:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"},{"id":194,"nodeType":"VariableDeclaration","src":"2448:40:0","nodes":[],"constant":true,"mutability":"constant","name":"vm","nameLocation":"2469:2:0","scope":382,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$36","typeString":"contract Vm"},"typeName":{"id":190,"nodeType":"UserDefinedTypeName","pathNode":{"id":189,"name":"Vm","nodeType":"IdentifierPath","referencedDeclaration":36,"src":"2448:2:0"},"referencedDeclaration":36,"src":"2448:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$36","typeString":"contract Vm"}},"value":{"arguments":[{"id":192,"name":"VM_ADDRESS","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":188,"src":"2477:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":191,"name":"Vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":36,"src":"2474:2:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_Vm_$36_$","typeString":"type(contract Vm)"}},"id":193,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2474:14:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$36","typeString":"contract Vm"}},"visibility":"internal"},{"id":357,"nodeType":"FunctionDefinition","src":"2578:949:0","nodes":[],"body":{"id":356,"nodeType":"Block","src":"2600:927:0","nodes":[],"statements":[{"assignments":[199],"declarations":[{"constant":false,"id":199,"mutability":"mutable","name":"x","nameLocation":"2615:1:0","nodeType":"VariableDeclaration","scope":356,"src":"2610:6:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":198,"name":"bool","nodeType":"ElementaryTypeName","src":"2610:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"id":205,"initialValue":{"arguments":[{"hexValue":"4558414d504c455f424f4f4c","id":202,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2628:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_a634dae177a0e138ae7aaa2afae347412e148992e88c7aabd33ee71be146cb7f","typeString":"literal_string \"EXAMPLE_BOOL\""},"value":"EXAMPLE_BOOL"},{"hexValue":"66616c7365","id":203,"isConstant":false,"isLValue":false,"isPure":true,"kind":"bool","lValueRequested":false,"nodeType":"Literal","src":"2644:5:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"value":"false"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_a634dae177a0e138ae7aaa2afae347412e148992e88c7aabd33ee71be146cb7f","typeString":"literal_string \"EXAMPLE_BOOL\""},{"typeIdentifier":"t_bool","typeString":"bool"}],"expression":{"id":200,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":194,"src":"2619:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$36","typeString":"contract Vm"}},"id":201,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"envOr","nodeType":"MemberAccess","referencedDeclaration":10,"src":"2619:8:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$_t_bool_$returns$_t_bool_$","typeString":"function (string memory,bool) view external returns (bool)"}},"id":204,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2619:31:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"nodeType":"VariableDeclarationStatement","src":"2610:40:0"},{"expression":{"arguments":[{"hexValue":"626f6f6c2076616c75652066726f6d20656e76","id":209,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2672:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_5a607d0b5a1295325aa8901721d78ba402601bba6f62cebdd5235dd0204a590b","typeString":"literal_string \"bool value from env\""},"value":"bool value from env"},{"id":210,"name":"x","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":199,"src":"2695:1:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_5a607d0b5a1295325aa8901721d78ba402601bba6f62cebdd5235dd0204a590b","typeString":"literal_string \"bool value from env\""},{"typeIdentifier":"t_bool","typeString":"bool"}],"expression":{"id":206,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"2660:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":208,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":118,"src":"2660:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_bool_$returns$__$","typeString":"function (string memory,bool) pure"}},"id":211,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2660:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":212,"nodeType":"ExpressionStatement","src":"2660:37:0"},{"expression":{"arguments":[{"hexValue":"636f6e74726163742061646472","id":216,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2720:15:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_fa50728770d00fe8f6a0592f3565bbfaf063ee4077f1f5bbc003d091d33cd0c4","typeString":"literal_string \"contract addr\""},"value":"contract addr"},{"arguments":[{"id":219,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"2745:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}],"id":218,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2737:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":217,"name":"address","nodeType":"ElementaryTypeName","src":"2737:7:0","typeDescriptions":{}}},"id":220,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2737:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_fa50728770d00fe8f6a0592f3565bbfaf063ee4077f1f5bbc003d091d33cd0c4","typeString":"literal_string \"contract addr\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":213,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"2708:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":215,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":152,"src":"2708:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":221,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2708:43:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":222,"nodeType":"ExpressionStatement","src":"2708:43:0"},{"expression":{"arguments":[{"hexValue":"636f6e7472616374206e6f6e6365","id":226,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2773:16:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_3a23091615a5de8c0a35ffd8857a37e2c4e0b72f3ef8a34d6caf65efcd562e2f","typeString":"literal_string \"contract nonce\""},"value":"contract nonce"},{"arguments":[{"arguments":[{"id":231,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"2811:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}],"id":230,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2803:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":229,"name":"address","nodeType":"ElementaryTypeName","src":"2803:7:0","typeDescriptions":{}}},"id":232,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2803:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":227,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":194,"src":"2791:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$36","typeString":"contract Vm"}},"id":228,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"getNonce","nodeType":"MemberAccess","referencedDeclaration":17,"src":"2791:11:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_address_$returns$_t_uint64_$","typeString":"function (address) view external returns (uint64)"}},"id":233,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2791:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_3a23091615a5de8c0a35ffd8857a37e2c4e0b72f3ef8a34d6caf65efcd562e2f","typeString":"literal_string \"contract nonce\""},{"typeIdentifier":"t_uint64","typeString":"uint64"}],"expression":{"id":223,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"2761:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":225,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":135,"src":"2761:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_uint256_$returns$__$","typeString":"function (string memory,uint256) pure"}},"id":234,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2761:57:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":235,"nodeType":"ExpressionStatement","src":"2761:57:0"},{"expression":{"arguments":[{"hexValue":"73656e6465722061646472","id":239,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2840:13:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_8125ca2decf812b25b65606ff16dad37cb198ff0433485a7926e50feafacfc35","typeString":"literal_string \"sender addr\""},"value":"sender addr"},{"arguments":[{"expression":{"id":242,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"2863:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":243,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"2863:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":241,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2855:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":240,"name":"address","nodeType":"ElementaryTypeName","src":"2855:7:0","typeDescriptions":{}}},"id":244,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2855:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_8125ca2decf812b25b65606ff16dad37cb198ff0433485a7926e50feafacfc35","typeString":"literal_string \"sender addr\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":236,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"2828:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":238,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":152,"src":"2828:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":245,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2828:47:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":246,"nodeType":"ExpressionStatement","src":"2828:47:0"},{"expression":{"arguments":[{"hexValue":"73656e646572206e6f6e6365","id":250,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2897:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_db7deb43f2f9e0404016de53b7e64c4976b54149581f7534daae2551e8cf4e40","typeString":"literal_string \"sender nonce\""},"value":"sender nonce"},{"arguments":[{"arguments":[{"expression":{"id":255,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"2933:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":256,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"2933:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":254,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2925:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":253,"name":"address","nodeType":"ElementaryTypeName","src":"2925:7:0","typeDescriptions":{}}},"id":257,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2925:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":251,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":194,"src":"2913:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$36","typeString":"contract Vm"}},"id":252,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"getNonce","nodeType":"MemberAccess","referencedDeclaration":17,"src":"2913:11:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_address_$returns$_t_uint64_$","typeString":"function (address) view external returns (uint64)"}},"id":258,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2913:32:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_db7deb43f2f9e0404016de53b7e64c4976b54149581f7534daae2551e8cf4e40","typeString":"literal_string \"sender nonce\""},{"typeIdentifier":"t_uint64","typeString":"uint64"}],"expression":{"id":247,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"2885:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":249,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":135,"src":"2885:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_uint256_$returns$__$","typeString":"function (string memory,uint256) pure"}},"id":259,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2885:61:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":260,"nodeType":"ExpressionStatement","src":"2885:61:0"},{"assignments":[262],"declarations":[{"constant":false,"id":262,"mutability":"mutable","name":"json","nameLocation":"2971:4:0","nodeType":"VariableDeclaration","scope":356,"src":"2957:18:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":261,"name":"string","nodeType":"ElementaryTypeName","src":"2957:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"id":264,"initialValue":{"hexValue":"7b22726f6f745f6b6579223a205b7b2261223a20312c202262223a20327d5d7d","id":263,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2978:34:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_e95522e99766888d0261f55bd1eae5e3f3e26eaf009a16e2433eafaf0a4ecdf2","typeString":"literal_string \"{\"root_key\": [{\"a\": 1, \"b\": 2}]}\""},"value":"{\"root_key\": [{\"a\": 1, \"b\": 2}]}"},"nodeType":"VariableDeclarationStatement","src":"2957:55:0"},{"assignments":[269],"declarations":[{"constant":false,"id":269,"mutability":"mutable","name":"keys","nameLocation":"3038:4:0","nodeType":"VariableDeclaration","scope":356,"src":"3022:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string[]"},"typeName":{"baseType":{"id":267,"name":"string","nodeType":"ElementaryTypeName","src":"3022:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"id":268,"nodeType":"ArrayTypeName","src":"3022:8:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_storage_$dyn_storage_ptr","typeString":"string[]"}},"visibility":"internal"}],"id":275,"initialValue":{"arguments":[{"id":272,"name":"json","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":262,"src":"3062:4:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"hexValue":"2e726f6f745f6b65795b305d","id":273,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3068:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_d82f67100edb80050915e1ec4b565c9a8319a22efb1075e1298b7bb60101d266","typeString":"literal_string \".root_key[0]\""},"value":".root_key[0]"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_stringliteral_d82f67100edb80050915e1ec4b565c9a8319a22efb1075e1298b7bb60101d266","typeString":"literal_string \".root_key[0]\""}],"expression":{"id":270,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":194,"src":"3045:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$36","typeString":"contract Vm"}},"id":271,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"parseJsonKeys","nodeType":"MemberAccess","referencedDeclaration":27,"src":"3045:16:0","typeDescriptions":{"typeIdentifier":"t_function_external_pure$_t_string_memory_ptr_$_t_string_memory_ptr_$returns$_t_array$_t_string_memory_ptr_$dyn_memory_ptr_$","typeString":"function (string memory,string memory) pure external returns (string memory[] memory)"}},"id":274,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3045:38:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string memory[] memory"}},"nodeType":"VariableDeclarationStatement","src":"3022:61:0"},{"expression":{"arguments":[{"hexValue":"6b657973","id":279,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3105:6:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_f29790a80c4ce5f42f59892f424f9c92856c6b656c3378e2cf305b260c6f4195","typeString":"literal_string \"keys\""},"value":"keys"},{"baseExpression":{"id":280,"name":"keys","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":269,"src":"3113:4:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string memory[] memory"}},"id":282,"indexExpression":{"hexValue":"30","id":281,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"3118:1:0","typeDescriptions":{"typeIdentifier":"t_rational_0_by_1","typeString":"int_const 0"},"value":"0"},"isConstant":false,"isLValue":true,"isPure":false,"lValueRequested":false,"nodeType":"IndexAccess","src":"3113:7:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"baseExpression":{"id":283,"name":"keys","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":269,"src":"3122:4:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string memory[] memory"}},"id":285,"indexExpression":{"hexValue":"31","id":284,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"3127:1:0","typeDescriptions":{"typeIdentifier":"t_rational_1_by_1","typeString":"int_const 1"},"value":"1"},"isConstant":false,"isLValue":true,"isPure":false,"lValueRequested":false,"nodeType":"IndexAccess","src":"3122:7:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_f29790a80c4ce5f42f59892f424f9c92856c6b656c3378e2cf305b260c6f4195","typeString":"literal_string \"keys\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}],"expression":{"id":276,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"3093:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":278,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":172,"src":"3093:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_string_memory_ptr_$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory,string memory,string memory) pure"}},"id":286,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3093:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":287,"nodeType":"ExpressionStatement","src":"3093:37:0"},{"expression":{"arguments":[{"hexValue":"66726f6d206f726967696e616c","id":291,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3152:15:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_77928970c8757d110f3c23e003246f49e0de890480ba9717ba659b2f56f316b2","typeString":"literal_string \"from original\""},"value":"from original"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_77928970c8757d110f3c23e003246f49e0de890480ba9717ba659b2f56f316b2","typeString":"literal_string \"from original\""}],"expression":{"id":288,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3141:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}},"id":290,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":381,"src":"3141:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":292,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3141:27:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":293,"nodeType":"ExpressionStatement","src":"3141:27:0"},{"expression":{"arguments":[{"arguments":[{"arguments":[{"hexValue":"30783432","id":301,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"3208:4:0","typeDescriptions":{"typeIdentifier":"t_rational_66_by_1","typeString":"int_const 66"},"value":"0x42"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_66_by_1","typeString":"int_const 66"}],"id":300,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3200:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":299,"name":"uint160","nodeType":"ElementaryTypeName","src":"3200:7:0","typeDescriptions":{}}},"id":302,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3200:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":298,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3192:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":297,"name":"address","nodeType":"ElementaryTypeName","src":"3192:7:0","typeDescriptions":{}}},"id":303,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3192:22:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":294,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":194,"src":"3178:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$36","typeString":"contract Vm"}},"id":296,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"startPrank","nodeType":"MemberAccess","referencedDeclaration":32,"src":"3178:13:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_address_$returns$__$","typeString":"function (address) external"}},"id":304,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3178:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":305,"nodeType":"ExpressionStatement","src":"3178:37:0"},{"expression":{"arguments":[{"hexValue":"66726f6d207072616e6b2031","id":309,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3236:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_42b34abfe37a8b0add910cda7b4a379e6538fa7a1dcafce47a02bd38f6c88e2a","typeString":"literal_string \"from prank 1\""},"value":"from prank 1"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_42b34abfe37a8b0add910cda7b4a379e6538fa7a1dcafce47a02bd38f6c88e2a","typeString":"literal_string \"from prank 1\""}],"expression":{"id":306,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3225:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}},"id":308,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":381,"src":"3225:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":310,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3225:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":311,"nodeType":"ExpressionStatement","src":"3225:26:0"},{"expression":{"arguments":[{"hexValue":"706172656e742073636f7065206d73672e73656e646572","id":315,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3273:25:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_83ec9246154d8845de47aafc5c2865c9985d2efe84472c27283879f2fbf5cc94","typeString":"literal_string \"parent scope msg.sender\""},"value":"parent scope msg.sender"},{"arguments":[{"expression":{"id":318,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"3308:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":319,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"3308:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":317,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3300:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":316,"name":"address","nodeType":"ElementaryTypeName","src":"3300:7:0","typeDescriptions":{}}},"id":320,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3300:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_83ec9246154d8845de47aafc5c2865c9985d2efe84472c27283879f2fbf5cc94","typeString":"literal_string \"parent scope msg.sender\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":312,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"3261:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":314,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":152,"src":"3261:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":321,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3261:59:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":322,"nodeType":"ExpressionStatement","src":"3261:59:0"},{"expression":{"arguments":[{"hexValue":"706172656e742073636f706520636f6e74726163742e61646472","id":326,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3342:28:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_97df66250e0b2b48f0ec8d0e01eb1b8ca012d95f1572895622aa1ea433e5570f","typeString":"literal_string \"parent scope contract.addr\""},"value":"parent scope contract.addr"},{"arguments":[{"id":329,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3380:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}],"id":328,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3372:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":327,"name":"address","nodeType":"ElementaryTypeName","src":"3372:7:0","typeDescriptions":{}}},"id":330,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3372:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_97df66250e0b2b48f0ec8d0e01eb1b8ca012d95f1572895622aa1ea433e5570f","typeString":"literal_string \"parent scope contract.addr\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":323,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"3330:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":325,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":152,"src":"3330:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":331,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3330:56:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":332,"nodeType":"ExpressionStatement","src":"3330:56:0"},{"expression":{"arguments":[{"hexValue":"66726f6d207072616e6b2032","id":336,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3407:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_a38a34f8cad750a79aa097a92971f8f405b51ee9d53d25c5b14fc129ba3684bb","typeString":"literal_string \"from prank 2\""},"value":"from prank 2"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_a38a34f8cad750a79aa097a92971f8f405b51ee9d53d25c5b14fc129ba3684bb","typeString":"literal_string \"from prank 2\""}],"expression":{"id":333,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3396:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}},"id":335,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":381,"src":"3396:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":337,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3396:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":338,"nodeType":"ExpressionStatement","src":"3396:26:0"},{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":339,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":194,"src":"3432:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$36","typeString":"contract Vm"}},"id":341,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"stopPrank","nodeType":"MemberAccess","referencedDeclaration":35,"src":"3432:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$__$returns$__$","typeString":"function () external"}},"id":342,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3432:14:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":343,"nodeType":"ExpressionStatement","src":"3432:14:0"},{"expression":{"arguments":[{"hexValue":"66726f6d206f726967696e616c20616761696e","id":347,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3467:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_0c805c6579e20a9c4c8e11aeab23330910a9f2da629191dc119d1730e8ed6860","typeString":"literal_string \"from original again\""},"value":"from original again"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_0c805c6579e20a9c4c8e11aeab23330910a9f2da629191dc119d1730e8ed6860","typeString":"literal_string \"from original again\""}],"expression":{"id":344,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3456:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}},"id":346,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":381,"src":"3456:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":348,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3456:33:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":349,"nodeType":"ExpressionStatement","src":"3456:33:0"},{"expression":{"arguments":[{"hexValue":"646f6e6521","id":353,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3512:7:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_080382d5c9e9e7c5e3d1d33f5e7422740375955180fadff167d8130e0c35f3fc","typeString":"literal_string \"done!\""},"value":"done!"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_080382d5c9e9e7c5e3d1d33f5e7422740375955180fadff167d8130e0c35f3fc","typeString":"literal_string \"done!\""}],"expression":{"id":350,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"3500:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":352,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":101,"src":"3500:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":354,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3500:20:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":355,"nodeType":"ExpressionStatement","src":"3500:20:0"}]},"documentation":{"id":195,"nodeType":"StructuredDocumentation","src":"2495:78:0","text":"@notice example function, runs through basic cheat-codes and console logs."},"functionSelector":"c0406226","implemented":true,"kind":"function","modifiers":[],"name":"run","nameLocation":"2587:3:0","parameters":{"id":196,"nodeType":"ParameterList","parameters":[],"src":"2590:2:0"},"returnParameters":{"id":197,"nodeType":"ParameterList","parameters":[],"src":"2600:0:0"},"scope":382,"stateMutability":"nonpayable","virtual":false,"visibility":"public"},{"id":381,"nodeType":"FunctionDefinition","src":"3622:143:0","nodes":[],"body":{"id":380,"nodeType":"Block","src":"3671:94:0","nodes":[],"statements":[{"expression":{"arguments":[{"id":366,"name":"_v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":360,"src":"3693:2:0","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}],"expression":{"id":363,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"3681:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":365,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":101,"src":"3681:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":367,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3681:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":368,"nodeType":"ExpressionStatement","src":"3681:15:0"},{"expression":{"arguments":[{"hexValue":"68656c6c6f206d73672e73656e646572","id":372,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3718:18:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_b3cc13bc51228b2c4c4334d82a4772908254dc0e1c512893dd16208ef13efb8e","typeString":"literal_string \"hello msg.sender\""},"value":"hello msg.sender"},{"arguments":[{"expression":{"id":375,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"3746:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":376,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"3746:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":374,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3738:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":373,"name":"address","nodeType":"ElementaryTypeName","src":"3738:7:0","typeDescriptions":{}}},"id":377,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3738:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_b3cc13bc51228b2c4c4334d82a4772908254dc0e1c512893dd16208ef13efb8e","typeString":"literal_string \"hello msg.sender\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":369,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"3706:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":371,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":152,"src":"3706:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":378,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3706:52:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":379,"nodeType":"ExpressionStatement","src":"3706:52:0"}]},"documentation":{"id":358,"nodeType":"StructuredDocumentation","src":"3533:84:0","text":"@notice example external function, to force a CALL, and test vm.startPrank with."},"functionSelector":"a777d0dc","implemented":true,"kind":"function","modifiers":[],"name":"hello","nameLocation":"3631:5:0","parameters":{"id":361,"nodeType":"ParameterList","parameters":[{"constant":false,"id":360,"mutability":"mutable","name":"_v","nameLocation":"3653:2:0","nodeType":"VariableDeclaration","scope":381,"src":"3637:18:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":359,"name":"string","nodeType":"ElementaryTypeName","src":"3637:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"3636:20:0"},"returnParameters":{"id":362,"nodeType":"ParameterList","parameters":[],"src":"3671:0:0"},"scope":382,"stateMutability":"view","virtual":false,"visibility":"external"}],"abstract":false,"baseContracts":[],"canonicalName":"ScriptExample","contractDependencies":[],"contractKind":"contract","documentation":{"id":174,"nodeType":"StructuredDocumentation","src":"2192:126:0","text":"@title ScriptExample\n @notice ScriptExample is an example script. The Go forge script code tests that it can run this."},"fullyImplemented":true,"linearizedBaseContracts":[382],"name":"ScriptExample","nameLocation":"2327:13:0","scope":383,"usedErrors":[]}],"license":"MIT"},"id":0} \ No newline at end of file +{"abi":[{"type":"function","name":"call1","inputs":[{"name":"_v","type":"string","internalType":"string"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"call2","inputs":[{"name":"_v","type":"string","internalType":"string"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"callPure","inputs":[{"name":"_v","type":"string","internalType":"string"}],"outputs":[],"stateMutability":"pure"},{"type":"function","name":"counter","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"hello","inputs":[{"name":"_v","type":"string","internalType":"string"}],"outputs":[],"stateMutability":"view"},{"type":"function","name":"nested1","inputs":[{"name":"_v","type":"string","internalType":"string"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"nested2","inputs":[{"name":"_v","type":"string","internalType":"string"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"run","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"runBroadcast","inputs":[],"outputs":[],"stateMutability":"nonpayable"}],"bytecode":{"object":"0x608060405234801561001057600080fd5b5061202a806100206000396000f3fe608060405234801561001057600080fd5b50600436106100a35760003560e01c8063a76ccdfa11610076578063bef03abc1161005b578063bef03abc14610111578063c040622614610119578063dbf1282f146100c357600080fd5b8063a76ccdfa146100eb578063a777d0dc146100fe57600080fd5b806361bc221a146100a85780637e79255d146100c35780637f8b915c146100d85780638d3ef7ca146100c3575b600080fd5b6100b160005481565b60405190815260200160405180910390f35b6100d66100d1366004611a60565b610121565b005b6100d66100e6366004611a60565b610178565b6100d66100f9366004611a60565b6101b7565b6100d661010c366004611a60565b61023f565b6100d66102bd565b6100d6610f54565b60008054908061013083611ad2565b919050555061017482828080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061175b92505050565b5050565b61017482828080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061175b92505050565b6000805490806101c683611ad2565b90915550506040517fdbf1282f000000000000000000000000000000000000000000000000000000008152309063dbf1282f906102099085908590600401611b31565b600060405180830381600087803b15801561022357600080fd5b505af1158015610237573d6000803e3d6000fd5b505050505050565b61027e82828080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061175b92505050565b6101746040518060400160405280601081526020017f68656c6c6f206d73672e73656e64657200000000000000000000000000000000815250336117ed565b604080518082018252600b81527f6e6f6e6365207374617274000000000000000000000000000000000000000000602082015290517f2d0335ab0000000000000000000000000000000000000000000000000000000081523060048201526103909190737109709ecfa91a80626ff3989d68f67f5b1dd12d90632d0335ab906024015b602060405180830381865afa15801561035d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103819190611b7e565b67ffffffffffffffff1661187e565b6103ce6040518060400160405280600e81526020017f74657374696e672073696e676c6500000000000000000000000000000000000081525061175b565b7f885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d60001c73ffffffffffffffffffffffffffffffffffffffff1663afc980406040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561043957600080fd5b505af115801561044d573d6000803e3d6000fd5b50506040517f7e79255d00000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f73696e676c655f63616c6c3100000000000000000000000000000000000000006044820152309250637e79255d9150606401600060405180830381600087803b1580156104d057600080fd5b505af11580156104e4573d6000803e3d6000fd5b50506040517f8d3ef7ca00000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f73696e676c655f63616c6c3200000000000000000000000000000000000000006044820152309250638d3ef7ca9150606401600060405180830381600087803b15801561056757600080fd5b505af115801561057b573d6000803e3d6000fd5b505050506105bd6040518060400160405280601281526020017f74657374696e672073746172742f73746f70000000000000000000000000000081525061175b565b6040517f7fec2a8d00000000000000000000000000000000000000000000000000000000815262c0ffee6004820152737109709ecfa91a80626ff3989d68f67f5b1dd12d90637fec2a8d90602401600060405180830381600087803b15801561062557600080fd5b505af1158015610639573d6000803e3d6000fd5b50506040517f7e79255d00000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f737461727473746f705f63616c6c3100000000000000000000000000000000006044820152309250637e79255d9150606401600060405180830381600087803b1580156106bc57600080fd5b505af11580156106d0573d6000803e3d6000fd5b50506040517f8d3ef7ca00000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f737461727473746f705f63616c6c3200000000000000000000000000000000006044820152309250638d3ef7ca9150606401600060405180830381600087803b15801561075357600080fd5b505af1158015610767573d6000803e3d6000fd5b50506040517f7f8b915c00000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f737461727473746f705f707572650000000000000000000000000000000000006044820152309250637f8b915c915060640160006040518083038186803b1580156107e857600080fd5b505afa1580156107fc573d6000803e3d6000fd5b505050507f885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d60001c73ffffffffffffffffffffffffffffffffffffffff166376eadd366040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561086b57600080fd5b505af115801561087f573d6000803e3d6000fd5b50506040517f7e79255d00000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f737461727473746f705f63616c6c3300000000000000000000000000000000006044820152309250637e79255d9150606401600060405180830381600087803b15801561090257600080fd5b505af1158015610916573d6000803e3d6000fd5b505050506109586040518060400160405280600e81526020017f74657374696e67206e657374656400000000000000000000000000000000000081525061175b565b6040517f7fec2a8d0000000000000000000000000000000000000000000000000000000081526112346004820152737109709ecfa91a80626ff3989d68f67f5b1dd12d90637fec2a8d90602401600060405180830381600087803b1580156109bf57600080fd5b505af11580156109d3573d6000803e3d6000fd5b50506040517fa76ccdfa00000000000000000000000000000000000000000000000000000000815260206004820152600660248201527f6e65737465640000000000000000000000000000000000000000000000000000604482015230925063a76ccdfa9150606401600060405180830381600087803b158015610a5657600080fd5b505af1158015610a6a573d6000803e3d6000fd5b505050507f885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d60001c73ffffffffffffffffffffffffffffffffffffffff166376eadd366040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610ad957600080fd5b505af1158015610aed573d6000803e3d6000fd5b50505050610b2f6040518060400160405280601381526020017f636f6e7472616374206465706c6f796d656e740000000000000000000000000081525061175b565b6040517fe6962cdb000000000000000000000000000000000000000000000000000000008152621234566004820152737109709ecfa91a80626ff3989d68f67f5b1dd12d9063e6962cdb90602401600060405180830381600087803b158015610b9757600080fd5b505af1158015610bab573d6000803e3d6000fd5b5050505060006104d2604051610bc090611a54565b908152602001604051809103906000f080158015610be2573d6000803e3d6000fd5b5090508073ffffffffffffffffffffffffffffffffffffffff1663c29855786040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c30573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c549190611baf565b6104d214610c6157600080fd5b610c9f6040518060400160405280600881526020017f637265617465203200000000000000000000000000000000000000000000000081525061175b565b6040517fe6962cdb00000000000000000000000000000000000000000000000000000000815261cafe6004820152737109709ecfa91a80626ff3989d68f67f5b1dd12d9063e6962cdb90602401600060405180830381600087803b158015610d0657600080fd5b505af1158015610d1a573d6000803e3d6000fd5b505050506000602a60001b6104d2604051610d3490611a54565b9081526020018190604051809103906000f5905080158015610d5a573d6000803e3d6000fd5b5090508073ffffffffffffffffffffffffffffffffffffffff1663c29855786040518163ffffffff1660e01b8152600401602060405180830381865afa158015610da8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dcc9190611baf565b6104d214610dd957600080fd5b610e176040518060400160405280600581526020017f646f6e652100000000000000000000000000000000000000000000000000000081525061175b565b7f885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d60001c73ffffffffffffffffffffffffffffffffffffffff1663afc980406040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610e8257600080fd5b505af1158015610e96573d6000803e3d6000fd5b505050506104d2604051610ea990611a54565b908152602001604051809103906000f080158015610ecb573d6000803e3d6000fd5b5050604080518082018252600981527f6e6f6e636520656e640000000000000000000000000000000000000000000000602082015290517f2d0335ab0000000000000000000000000000000000000000000000000000000081523060048201526101749190737109709ecfa91a80626ff3989d68f67f5b1dd12d90632d0335ab90602401610340565b604080517f4777f3cf0000000000000000000000000000000000000000000000000000000081526004810191909152600c60448201527f4558414d504c455f424f4f4c0000000000000000000000000000000000000000606482015260006024820181905290737109709ecfa91a80626ff3989d68f67f5b1dd12d90634777f3cf90608401602060405180830381865afa158015610ff6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061101a9190611bc8565b905061105b6040518060400160405280601381526020017f626f6f6c2076616c75652066726f6d20656e76000000000000000000000000008152508261190f565b61109a6040518060400160405280600d81526020017f636f6e7472616374206164647200000000000000000000000000000000000000815250306117ed565b604080518082018252600e81527f636f6e7472616374206e6f6e6365000000000000000000000000000000000000602082015290517f2d0335ab0000000000000000000000000000000000000000000000000000000081523060048201526111219190737109709ecfa91a80626ff3989d68f67f5b1dd12d90632d0335ab90602401610340565b6111606040518060400160405280600b81526020017f73656e6465722061646472000000000000000000000000000000000000000000815250336117ed565b604080518082018252600c81527f73656e646572206e6f6e63650000000000000000000000000000000000000000602082015290517f2d0335ab0000000000000000000000000000000000000000000000000000000081523360048201526111e79190737109709ecfa91a80626ff3989d68f67f5b1dd12d90632d0335ab90602401610340565b60408051808201825260208082527f7b22726f6f745f6b6579223a205b7b2261223a20312c202262223a20327d5d7d9082015290517f213e4198000000000000000000000000000000000000000000000000000000008152600090737109709ecfa91a80626ff3989d68f67f5b1dd12d9063213e41989061126c908590600401611c64565b600060405180830381865afa158015611289573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526112cf9190810190611d34565b90506113456040518060400160405280600481526020017f6b657973000000000000000000000000000000000000000000000000000000008152508260008151811061131d5761131d611e68565b60200260200101518360018151811061133857611338611e68565b60200260200101516119a0565b6040517fa777d0dc00000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f66726f6d206f726967696e616c000000000000000000000000000000000000006044820152309063a777d0dc9060640160006040518083038186803b1580156113c257600080fd5b505afa1580156113d6573d6000803e3d6000fd5b50506040517f06447d5600000000000000000000000000000000000000000000000000000000815260426004820152737109709ecfa91a80626ff3989d68f67f5b1dd12d92506306447d569150602401600060405180830381600087803b15801561144057600080fd5b505af1158015611454573d6000803e3d6000fd5b50506040517fa777d0dc00000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f66726f6d207072616e6b20310000000000000000000000000000000000000000604482015230925063a777d0dc915060640160006040518083038186803b1580156114d557600080fd5b505afa1580156114e9573d6000803e3d6000fd5b5050505061152c6040518060400160405280601781526020017f706172656e742073636f7065206d73672e73656e646572000000000000000000815250336117ed565b61156b6040518060400160405280601a81526020017f706172656e742073636f706520636f6e74726163742e61646472000000000000815250306117ed565b6040517fa777d0dc00000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f66726f6d207072616e6b203200000000000000000000000000000000000000006044820152309063a777d0dc9060640160006040518083038186803b1580156115e857600080fd5b505afa1580156115fc573d6000803e3d6000fd5b505050507f885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d60001c73ffffffffffffffffffffffffffffffffffffffff166390c5013b6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561166b57600080fd5b505af115801561167f573d6000803e3d6000fd5b50506040517fa777d0dc00000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f66726f6d206f726967696e616c20616761696e00000000000000000000000000604482015230925063a777d0dc915060640160006040518083038186803b15801561170057600080fd5b505afa158015611714573d6000803e3d6000fd5b505050506117566040518060400160405280600581526020017f646f6e652100000000000000000000000000000000000000000000000000000081525061175b565b505050565b6117ea8160405160240161176f9190611e97565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f41304fac00000000000000000000000000000000000000000000000000000000179052611a2f565b50565b6101748282604051602401611803929190611eaa565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f319af33300000000000000000000000000000000000000000000000000000000179052611a2f565b6101748282604051602401611894929190611ee2565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fb60e72cc00000000000000000000000000000000000000000000000000000000179052611a2f565b6101748282604051602401611925929190611f04565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fc3b5563500000000000000000000000000000000000000000000000000000000179052611a2f565b6117568383836040516024016119b893929190611f28565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f2ced7cef000000000000000000000000000000000000000000000000000000001790525b6117ea8180516a636f6e736f6c652e6c6f67602083016000808483855afa5050505050565b60b280611f6c83390190565b60008060208385031215611a7357600080fd5b823567ffffffffffffffff80821115611a8b57600080fd5b818501915085601f830112611a9f57600080fd5b813581811115611aae57600080fd5b866020828501011115611ac057600080fd5b60209290920196919550909350505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611b2a577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5060010190565b60208152816020820152818360408301376000818301604090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101919050565b600060208284031215611b9057600080fd5b815167ffffffffffffffff81168114611ba857600080fd5b9392505050565b600060208284031215611bc157600080fd5b5051919050565b600060208284031215611bda57600080fd5b81518015158114611ba857600080fd5b60005b83811015611c05578181015183820152602001611bed565b83811115611c14576000848401525b50505050565b60008151808452611c32816020860160208601611bea565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b604081526000611c776040830184611c1a565b8281036020840152600c81527f2e726f6f745f6b65795b305d000000000000000000000000000000000000000060208201526040810191505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611d2c57611d2c611cb6565b604052919050565b60006020808385031215611d4757600080fd5b825167ffffffffffffffff80821115611d5f57600080fd5b8185019150601f8681840112611d7457600080fd5b825182811115611d8657611d86611cb6565b8060051b611d95868201611ce5565b918252848101860191868101908a841115611daf57600080fd5b87870192505b83831015611e5a57825186811115611dcd5760008081fd5b8701603f81018c13611ddf5760008081fd5b88810151604088821115611df557611df5611cb6565b611e248b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08a85011601611ce5565b8281528e82848601011115611e395760008081fd5b611e48838d8301848701611bea565b85525050509187019190870190611db5565b9a9950505050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602081526000611ba86020830184611c1a565b604081526000611ebd6040830185611c1a565b905073ffffffffffffffffffffffffffffffffffffffff831660208301529392505050565b604081526000611ef56040830185611c1a565b90508260208301529392505050565b604081526000611f176040830185611c1a565b905082151560208301529392505050565b606081526000611f3b6060830186611c1a565b8281036020840152611f4d8186611c1a565b90508281036040840152611f618185611c1a565b969550505050505056fe608060405234801561001057600080fd5b506040516100b23803806100b283398101604081905261002f91610037565b600055610050565b60006020828403121561004957600080fd5b5051919050565b60548061005e6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063c298557814602d575b600080fd5b603560005481565b60405190815260200160405180910390f3fea164736f6c634300080f000aa164736f6c634300080f000a","sourceMap":"2541:3359:0:-:0;;;;;;;;;;;;;;;;;;;","linkReferences":{}},"deployedBytecode":{"object":"0x608060405234801561001057600080fd5b50600436106100a35760003560e01c8063a76ccdfa11610076578063bef03abc1161005b578063bef03abc14610111578063c040622614610119578063dbf1282f146100c357600080fd5b8063a76ccdfa146100eb578063a777d0dc146100fe57600080fd5b806361bc221a146100a85780637e79255d146100c35780637f8b915c146100d85780638d3ef7ca146100c3575b600080fd5b6100b160005481565b60405190815260200160405180910390f35b6100d66100d1366004611a60565b610121565b005b6100d66100e6366004611a60565b610178565b6100d66100f9366004611a60565b6101b7565b6100d661010c366004611a60565b61023f565b6100d66102bd565b6100d6610f54565b60008054908061013083611ad2565b919050555061017482828080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061175b92505050565b5050565b61017482828080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061175b92505050565b6000805490806101c683611ad2565b90915550506040517fdbf1282f000000000000000000000000000000000000000000000000000000008152309063dbf1282f906102099085908590600401611b31565b600060405180830381600087803b15801561022357600080fd5b505af1158015610237573d6000803e3d6000fd5b505050505050565b61027e82828080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061175b92505050565b6101746040518060400160405280601081526020017f68656c6c6f206d73672e73656e64657200000000000000000000000000000000815250336117ed565b604080518082018252600b81527f6e6f6e6365207374617274000000000000000000000000000000000000000000602082015290517f2d0335ab0000000000000000000000000000000000000000000000000000000081523060048201526103909190737109709ecfa91a80626ff3989d68f67f5b1dd12d90632d0335ab906024015b602060405180830381865afa15801561035d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103819190611b7e565b67ffffffffffffffff1661187e565b6103ce6040518060400160405280600e81526020017f74657374696e672073696e676c6500000000000000000000000000000000000081525061175b565b7f885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d60001c73ffffffffffffffffffffffffffffffffffffffff1663afc980406040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561043957600080fd5b505af115801561044d573d6000803e3d6000fd5b50506040517f7e79255d00000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f73696e676c655f63616c6c3100000000000000000000000000000000000000006044820152309250637e79255d9150606401600060405180830381600087803b1580156104d057600080fd5b505af11580156104e4573d6000803e3d6000fd5b50506040517f8d3ef7ca00000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f73696e676c655f63616c6c3200000000000000000000000000000000000000006044820152309250638d3ef7ca9150606401600060405180830381600087803b15801561056757600080fd5b505af115801561057b573d6000803e3d6000fd5b505050506105bd6040518060400160405280601281526020017f74657374696e672073746172742f73746f70000000000000000000000000000081525061175b565b6040517f7fec2a8d00000000000000000000000000000000000000000000000000000000815262c0ffee6004820152737109709ecfa91a80626ff3989d68f67f5b1dd12d90637fec2a8d90602401600060405180830381600087803b15801561062557600080fd5b505af1158015610639573d6000803e3d6000fd5b50506040517f7e79255d00000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f737461727473746f705f63616c6c3100000000000000000000000000000000006044820152309250637e79255d9150606401600060405180830381600087803b1580156106bc57600080fd5b505af11580156106d0573d6000803e3d6000fd5b50506040517f8d3ef7ca00000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f737461727473746f705f63616c6c3200000000000000000000000000000000006044820152309250638d3ef7ca9150606401600060405180830381600087803b15801561075357600080fd5b505af1158015610767573d6000803e3d6000fd5b50506040517f7f8b915c00000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f737461727473746f705f707572650000000000000000000000000000000000006044820152309250637f8b915c915060640160006040518083038186803b1580156107e857600080fd5b505afa1580156107fc573d6000803e3d6000fd5b505050507f885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d60001c73ffffffffffffffffffffffffffffffffffffffff166376eadd366040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561086b57600080fd5b505af115801561087f573d6000803e3d6000fd5b50506040517f7e79255d00000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f737461727473746f705f63616c6c3300000000000000000000000000000000006044820152309250637e79255d9150606401600060405180830381600087803b15801561090257600080fd5b505af1158015610916573d6000803e3d6000fd5b505050506109586040518060400160405280600e81526020017f74657374696e67206e657374656400000000000000000000000000000000000081525061175b565b6040517f7fec2a8d0000000000000000000000000000000000000000000000000000000081526112346004820152737109709ecfa91a80626ff3989d68f67f5b1dd12d90637fec2a8d90602401600060405180830381600087803b1580156109bf57600080fd5b505af11580156109d3573d6000803e3d6000fd5b50506040517fa76ccdfa00000000000000000000000000000000000000000000000000000000815260206004820152600660248201527f6e65737465640000000000000000000000000000000000000000000000000000604482015230925063a76ccdfa9150606401600060405180830381600087803b158015610a5657600080fd5b505af1158015610a6a573d6000803e3d6000fd5b505050507f885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d60001c73ffffffffffffffffffffffffffffffffffffffff166376eadd366040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610ad957600080fd5b505af1158015610aed573d6000803e3d6000fd5b50505050610b2f6040518060400160405280601381526020017f636f6e7472616374206465706c6f796d656e740000000000000000000000000081525061175b565b6040517fe6962cdb000000000000000000000000000000000000000000000000000000008152621234566004820152737109709ecfa91a80626ff3989d68f67f5b1dd12d9063e6962cdb90602401600060405180830381600087803b158015610b9757600080fd5b505af1158015610bab573d6000803e3d6000fd5b5050505060006104d2604051610bc090611a54565b908152602001604051809103906000f080158015610be2573d6000803e3d6000fd5b5090508073ffffffffffffffffffffffffffffffffffffffff1663c29855786040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c30573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c549190611baf565b6104d214610c6157600080fd5b610c9f6040518060400160405280600881526020017f637265617465203200000000000000000000000000000000000000000000000081525061175b565b6040517fe6962cdb00000000000000000000000000000000000000000000000000000000815261cafe6004820152737109709ecfa91a80626ff3989d68f67f5b1dd12d9063e6962cdb90602401600060405180830381600087803b158015610d0657600080fd5b505af1158015610d1a573d6000803e3d6000fd5b505050506000602a60001b6104d2604051610d3490611a54565b9081526020018190604051809103906000f5905080158015610d5a573d6000803e3d6000fd5b5090508073ffffffffffffffffffffffffffffffffffffffff1663c29855786040518163ffffffff1660e01b8152600401602060405180830381865afa158015610da8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dcc9190611baf565b6104d214610dd957600080fd5b610e176040518060400160405280600581526020017f646f6e652100000000000000000000000000000000000000000000000000000081525061175b565b7f885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d60001c73ffffffffffffffffffffffffffffffffffffffff1663afc980406040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610e8257600080fd5b505af1158015610e96573d6000803e3d6000fd5b505050506104d2604051610ea990611a54565b908152602001604051809103906000f080158015610ecb573d6000803e3d6000fd5b5050604080518082018252600981527f6e6f6e636520656e640000000000000000000000000000000000000000000000602082015290517f2d0335ab0000000000000000000000000000000000000000000000000000000081523060048201526101749190737109709ecfa91a80626ff3989d68f67f5b1dd12d90632d0335ab90602401610340565b604080517f4777f3cf0000000000000000000000000000000000000000000000000000000081526004810191909152600c60448201527f4558414d504c455f424f4f4c0000000000000000000000000000000000000000606482015260006024820181905290737109709ecfa91a80626ff3989d68f67f5b1dd12d90634777f3cf90608401602060405180830381865afa158015610ff6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061101a9190611bc8565b905061105b6040518060400160405280601381526020017f626f6f6c2076616c75652066726f6d20656e76000000000000000000000000008152508261190f565b61109a6040518060400160405280600d81526020017f636f6e7472616374206164647200000000000000000000000000000000000000815250306117ed565b604080518082018252600e81527f636f6e7472616374206e6f6e6365000000000000000000000000000000000000602082015290517f2d0335ab0000000000000000000000000000000000000000000000000000000081523060048201526111219190737109709ecfa91a80626ff3989d68f67f5b1dd12d90632d0335ab90602401610340565b6111606040518060400160405280600b81526020017f73656e6465722061646472000000000000000000000000000000000000000000815250336117ed565b604080518082018252600c81527f73656e646572206e6f6e63650000000000000000000000000000000000000000602082015290517f2d0335ab0000000000000000000000000000000000000000000000000000000081523360048201526111e79190737109709ecfa91a80626ff3989d68f67f5b1dd12d90632d0335ab90602401610340565b60408051808201825260208082527f7b22726f6f745f6b6579223a205b7b2261223a20312c202262223a20327d5d7d9082015290517f213e4198000000000000000000000000000000000000000000000000000000008152600090737109709ecfa91a80626ff3989d68f67f5b1dd12d9063213e41989061126c908590600401611c64565b600060405180830381865afa158015611289573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526112cf9190810190611d34565b90506113456040518060400160405280600481526020017f6b657973000000000000000000000000000000000000000000000000000000008152508260008151811061131d5761131d611e68565b60200260200101518360018151811061133857611338611e68565b60200260200101516119a0565b6040517fa777d0dc00000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f66726f6d206f726967696e616c000000000000000000000000000000000000006044820152309063a777d0dc9060640160006040518083038186803b1580156113c257600080fd5b505afa1580156113d6573d6000803e3d6000fd5b50506040517f06447d5600000000000000000000000000000000000000000000000000000000815260426004820152737109709ecfa91a80626ff3989d68f67f5b1dd12d92506306447d569150602401600060405180830381600087803b15801561144057600080fd5b505af1158015611454573d6000803e3d6000fd5b50506040517fa777d0dc00000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f66726f6d207072616e6b20310000000000000000000000000000000000000000604482015230925063a777d0dc915060640160006040518083038186803b1580156114d557600080fd5b505afa1580156114e9573d6000803e3d6000fd5b5050505061152c6040518060400160405280601781526020017f706172656e742073636f7065206d73672e73656e646572000000000000000000815250336117ed565b61156b6040518060400160405280601a81526020017f706172656e742073636f706520636f6e74726163742e61646472000000000000815250306117ed565b6040517fa777d0dc00000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f66726f6d207072616e6b203200000000000000000000000000000000000000006044820152309063a777d0dc9060640160006040518083038186803b1580156115e857600080fd5b505afa1580156115fc573d6000803e3d6000fd5b505050507f885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d60001c73ffffffffffffffffffffffffffffffffffffffff166390c5013b6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561166b57600080fd5b505af115801561167f573d6000803e3d6000fd5b50506040517fa777d0dc00000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f66726f6d206f726967696e616c20616761696e00000000000000000000000000604482015230925063a777d0dc915060640160006040518083038186803b15801561170057600080fd5b505afa158015611714573d6000803e3d6000fd5b505050506117566040518060400160405280600581526020017f646f6e652100000000000000000000000000000000000000000000000000000081525061175b565b505050565b6117ea8160405160240161176f9190611e97565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f41304fac00000000000000000000000000000000000000000000000000000000179052611a2f565b50565b6101748282604051602401611803929190611eaa565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f319af33300000000000000000000000000000000000000000000000000000000179052611a2f565b6101748282604051602401611894929190611ee2565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fb60e72cc00000000000000000000000000000000000000000000000000000000179052611a2f565b6101748282604051602401611925929190611f04565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fc3b5563500000000000000000000000000000000000000000000000000000000179052611a2f565b6117568383836040516024016119b893929190611f28565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f2ced7cef000000000000000000000000000000000000000000000000000000001790525b6117ea8180516a636f6e736f6c652e6c6f67602083016000808483855afa5050505050565b60b280611f6c83390190565b60008060208385031215611a7357600080fd5b823567ffffffffffffffff80821115611a8b57600080fd5b818501915085601f830112611a9f57600080fd5b813581811115611aae57600080fd5b866020828501011115611ac057600080fd5b60209290920196919550909350505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611b2a577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5060010190565b60208152816020820152818360408301376000818301604090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101919050565b600060208284031215611b9057600080fd5b815167ffffffffffffffff81168114611ba857600080fd5b9392505050565b600060208284031215611bc157600080fd5b5051919050565b600060208284031215611bda57600080fd5b81518015158114611ba857600080fd5b60005b83811015611c05578181015183820152602001611bed565b83811115611c14576000848401525b50505050565b60008151808452611c32816020860160208601611bea565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b604081526000611c776040830184611c1a565b8281036020840152600c81527f2e726f6f745f6b65795b305d000000000000000000000000000000000000000060208201526040810191505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611d2c57611d2c611cb6565b604052919050565b60006020808385031215611d4757600080fd5b825167ffffffffffffffff80821115611d5f57600080fd5b8185019150601f8681840112611d7457600080fd5b825182811115611d8657611d86611cb6565b8060051b611d95868201611ce5565b918252848101860191868101908a841115611daf57600080fd5b87870192505b83831015611e5a57825186811115611dcd5760008081fd5b8701603f81018c13611ddf5760008081fd5b88810151604088821115611df557611df5611cb6565b611e248b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08a85011601611ce5565b8281528e82848601011115611e395760008081fd5b611e48838d8301848701611bea565b85525050509187019190870190611db5565b9a9950505050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602081526000611ba86020830184611c1a565b604081526000611ebd6040830185611c1a565b905073ffffffffffffffffffffffffffffffffffffffff831660208301529392505050565b604081526000611ef56040830185611c1a565b90508260208301529392505050565b604081526000611f176040830185611c1a565b905082151560208301529392505050565b606081526000611f3b6060830186611c1a565b8281036020840152611f4d8186611c1a565b90508281036040840152611f618185611c1a565b969550505050505056fe608060405234801561001057600080fd5b506040516100b23803806100b283398101604081905261002f91610037565b600055610050565b60006020828403121561004957600080fd5b5051919050565b60548061005e6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063c298557814602d575b600080fd5b603560005481565b60405190815260200160405180910390f3fea164736f6c634300080f000aa164736f6c634300080f000a","sourceMap":"2541:3359:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2775:22;;;;;;;;;160:25:1;;;148:2;133:18;2775:22:0;;;;;;;5405:95;;;;;;:::i;:::-;;:::i;:::-;;5814:84;;;;;;:::i;:::-;;:::i;5607:98::-;;;;;;:::i;:::-;;:::i;5256:143::-;;;;;;:::i;:::-;;:::i;3903:1258::-;;;:::i;2887:949::-;;;:::i;5405:95::-;5459:7;:9;;;:7;:9;;;:::i;:::-;;;;;;5478:15;5490:2;;5478:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;5478:11:0;;-1:-1:-1;;;5478:15:0:i;:::-;5405:95;;:::o;5814:84::-;5876:15;5888:2;;5876:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;5876:11:0;;-1:-1:-1;;;5876:15:0:i;5607:98::-;5663:7;:9;;;:7;:9;;;:::i;:::-;;;;-1:-1:-1;;5682:16:0;;;;;:4;;:12;;:16;;5695:2;;;;5682:16;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5607:98;;:::o;5256:143::-;5315:15;5327:2;;5315:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;5315:11:0;;-1:-1:-1;;;5315:15:0:i;:::-;5340:52;;;;;;;;;;;;;;;;;;5380:10;5340:11;:52::i;3903:1258::-;3944:63;;;;;;;;;;;;;;;;3979:26;;;;;3999:4;3979:26;;;1747:74:1;3944:63:0;;;3979:11;;;;1720:18:1;;3979:26:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;3971:35;;3944:11;:63::i;:::-;4018:29;;;;;;;;;;;;;;;;;;:11;:29::i;:::-;2634:28;2626:37;;4057:12;;;:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;4081:26:0;;;;;2327:2:1;4081:26:0;;;2309:21:1;2366:2;2346:18;;;2339:30;2405:14;2385:18;;;2378:42;4081:4:0;;-1:-1:-1;4081:10:0;;-1:-1:-1;2437:18:1;;4081:26:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;4117:26:0;;;;;2668:2:1;4117:26:0;;;2650:21:1;2707:2;2687:18;;;2680:30;2746:14;2726:18;;;2719:42;4117:4:0;;-1:-1:-1;4117:10:0;;-1:-1:-1;2778:18:1;;4117:26:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4154:33;;;;;;;;;;;;;;;;;;:11;:33::i;:::-;4197:45;;;;;4231:8;4197:45;;;1747:74:1;4197:17:0;;;;1720:18:1;;4197:45:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;4252:29:0;;;;;3009:2:1;4252:29:0;;;2991:21:1;3048:2;3028:18;;;3021:30;3087:17;3067:18;;;3060:45;4252:4:0;;-1:-1:-1;4252:10:0;;-1:-1:-1;3122:18:1;;4252:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;4291:29:0;;;;;3353:2:1;4291:29:0;;;3335:21:1;3392:2;3372:18;;;3365:30;3431:17;3411:18;;;3404:45;4291:4:0;;-1:-1:-1;4291:10:0;;-1:-1:-1;3466:18:1;;4291:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;4330:31:0;;;;;3697:2:1;4330:31:0;;;3679:21:1;3736:2;3716:18;;;3709:30;3775:16;3755:18;;;3748:44;4330:4:0;;-1:-1:-1;4330:13:0;;-1:-1:-1;3809:18:1;;4330:31:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2634:28;2626:37;;4371:16;;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;4399:29:0;;;;;4040:2:1;4399:29:0;;;4022:21:1;4079:2;4059:18;;;4052:30;4118:17;4098:18;;;4091:45;4399:4:0;;-1:-1:-1;4399:10:0;;-1:-1:-1;4153:18:1;;4399:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4439;;;;;;;;;;;;;;;;;;:11;:29::i;:::-;4478:43;;;;;4512:6;4478:43;;;1747:74:1;4478:17:0;;;;1720:18:1;;4478:43:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;4531:22:0;;;;;4384:2:1;4531:22:0;;;4366:21:1;4423:1;4403:18;;;4396:29;4461:8;4441:18;;;4434:36;4531:4:0;;-1:-1:-1;4531:12:0;;-1:-1:-1;4487:18:1;;4531:22:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2634:28;2626:37;;4563:16;;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4592:34;;;;;;;;;;;;;;;;;;:11;:34::i;:::-;4636:40;;;;;4665:8;4636:40;;;1747:74:1;4636:12:0;;;;1720:18:1;;4636:40:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4686:8;4708:4;4697:16;;;;;:::i;:::-;160:25:1;;;148:2;133:18;4697:16:0;;;;;;;;;;;;;;;;;;;;;;;4686:27;;4731:1;:5;;;:7;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;4742:4;4731:15;4723:24;;;;;;4758:23;;;;;;;;;;;;;;;;;;:11;:23::i;:::-;4791:38;;;;;4820:6;4791:38;;;1747:74:1;4791:12:0;;;;1720:18:1;;4791:38:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4839:8;4883:2;4867:20;;4889:4;4850:44;;;;;:::i;:::-;160:25:1;;;148:2;133:18;4850:44:0;;;;;;;;;;;;;;;;;;;;;;;;;;;4839:55;;4912:1;:5;;;:7;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;4923:4;4912:15;4904:24;;;;;;4938:20;;;;;;;;;;;;;;;;;;:11;:20::i;:::-;2634:28;2626:37;;5042:12;;;:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5077:4;5066:16;;;;;:::i;:::-;160:25:1;;;148:2;133:18;5066:16:0;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;5093:61:0;;;;;;;;;;;;;;;;5126:26;;;;;5146:4;5126:26;;;1747:74:1;5093:61:0;;;5126:11;;;;1720:18:1;;5126:26:0;1601:226:1;2887:949:0;2928:31;;;;;;;;;5104:21:1;;;;5161:2;5141:18;;;5134:30;5200:14;5180:18;;;5173:42;2919:6:0;5267:20:1;;;5260:52;;;2919:6:0;2928:8;;;;5232:19:1;;2928:31:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;2919:40;;2969:37;;;;;;;;;;;;;;;;;;3004:1;2969:11;:37::i;:::-;3017:43;;;;;;;;;;;;;;;;;;3054:4;3017:11;:43::i;:::-;3070:57;;;;;;;;;;;;;;;;3100:26;;;;;3120:4;3100:26;;;1747:74:1;3070:57:0;;;3100:11;;;;1720:18:1;;3100:26:0;1601:226:1;3070:57:0;3137:47;;;;;;;;;;;;;;;;;;3172:10;3137:11;:47::i;:::-;3194:61;;;;;;;;;;;;;;;;3222:32;;;;;3242:10;3222:32;;;1747:74:1;3194:61:0;;;3222:11;;;;1720:18:1;;3222:32:0;1601:226:1;3194:61:0;3266:55;;;;;;;;;;;;;;;;;3354:38;;;;;3266:18;;3354:16;;;;:38;;3266:55;;3354:38;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;3331:61;;3402:37;;;;;;;;;;;;;;;;;;3422:4;3427:1;3422:7;;;;;;;;:::i;:::-;;;;;;;3431:4;3436:1;3431:7;;;;;;;;:::i;:::-;;;;;;;3402:11;:37::i;:::-;3450:27;;;;;9413:2:1;3450:27:0;;;9395:21:1;9452:2;9432:18;;;9425:30;9491:15;9471:18;;;9464:43;3450:4:0;;:10;;9524:18:1;;3450:27:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;3487:37:0;;;;;3517:4;3487:37;;;1747:74:1;3487:13:0;;-1:-1:-1;3487:13:0;;-1:-1:-1;1720:18:1;;3487:37:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;3534:26:0;;;;;9755:2:1;3534:26:0;;;9737:21:1;9794:2;9774:18;;;9767:30;9833:14;9813:18;;;9806:42;3534:4:0;;-1:-1:-1;3534:10:0;;-1:-1:-1;9865:18:1;;3534:26:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3570:59;;;;;;;;;;;;;;;;;;3617:10;3570:11;:59::i;:::-;3639:56;;;;;;;;;;;;;;;;;;3689:4;3639:11;:56::i;:::-;3705:26;;;;;10096:2:1;3705:26:0;;;10078:21:1;10135:2;10115:18;;;10108:30;10174:14;10154:18;;;10147:42;3705:4:0;;:10;;10206:18:1;;3705:26:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2634:28;2626:37;;3741:12;;;:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;3765:33:0;;;;;10437:2:1;3765:33:0;;;10419:21:1;10476:2;10456:18;;;10449:30;10515:21;10495:18;;;10488:49;3765:4:0;;-1:-1:-1;3765:10:0;;-1:-1:-1;10554:18:1;;3765:33:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3809:20;;;;;;;;;;;;;;;;;;:11;:20::i;:::-;2909:927;;;2887:949::o;1658:121::-;1713:59;1768:2;1729:42;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;1713:15;:59::i;:::-;1658:121;:::o;2081:145::-;2148:71;2211:2;2215;2164:54;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;2148:15;:71::i;1930:145::-;1997:71;2060:2;2064;2013:54;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;1997:15;:71::i;1785:139::-;1849:68;1909:2;1913;1865:51;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;1849:15;:68::i;2232:179::-;2323:81;2392:2;2396;2400;2339:64;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;1133:133;1204:55;1251:7;1370:14;;856:42;1543:2;1530:16;;1346:21;;1370:14;1530:16;856:42;1579:5;1568:68;1559:77;;1496:150;;1272:380;:::o;-1:-1:-1:-;;;;;;;;:::o;196:592:1:-;267:6;275;328:2;316:9;307:7;303:23;299:32;296:52;;;344:1;341;334:12;296:52;384:9;371:23;413:18;454:2;446:6;443:14;440:34;;;470:1;467;460:12;440:34;508:6;497:9;493:22;483:32;;553:7;546:4;542:2;538:13;534:27;524:55;;575:1;572;565:12;524:55;615:2;602:16;641:2;633:6;630:14;627:34;;;657:1;654;647:12;627:34;702:7;697:2;688:6;684:2;680:15;676:24;673:37;670:57;;;723:1;720;713:12;670:57;754:2;746:11;;;;;776:6;;-1:-1:-1;196:592:1;;-1:-1:-1;;;;196:592:1:o;793:349::-;832:3;863:66;856:5;853:77;850:257;;963:77;960:1;953:88;1064:4;1061:1;1054:15;1092:4;1089:1;1082:15;850:257;-1:-1:-1;1134:1:1;1123:13;;793:349::o;1147:449::-;1306:2;1295:9;1288:21;1345:6;1340:2;1329:9;1325:18;1318:34;1402:6;1394;1389:2;1378:9;1374:18;1361:48;1458:1;1429:22;;;1453:2;1425:31;;;1418:42;;;;1512:2;1500:15;;;1517:66;1496:88;1481:104;1477:113;;1147:449;-1:-1:-1;1147:449:1:o;1832:288::-;1901:6;1954:2;1942:9;1933:7;1929:23;1925:32;1922:52;;;1970:1;1967;1960:12;1922:52;2002:9;1996:16;2052:18;2045:5;2041:30;2034:5;2031:41;2021:69;;2086:1;2083;2076:12;2021:69;2109:5;1832:288;-1:-1:-1;;;1832:288:1:o;4709:184::-;4779:6;4832:2;4820:9;4811:7;4807:23;4803:32;4800:52;;;4848:1;4845;4838:12;4800:52;-1:-1:-1;4871:16:1;;4709:184;-1:-1:-1;4709:184:1:o;5323:277::-;5390:6;5443:2;5431:9;5422:7;5418:23;5414:32;5411:52;;;5459:1;5456;5449:12;5411:52;5491:9;5485:16;5544:5;5537:13;5530:21;5523:5;5520:32;5510:60;;5566:1;5563;5556:12;5605:258;5677:1;5687:113;5701:6;5698:1;5695:13;5687:113;;;5777:11;;;5771:18;5758:11;;;5751:39;5723:2;5716:10;5687:113;;;5818:6;5815:1;5812:13;5809:48;;;5853:1;5844:6;5839:3;5835:16;5828:27;5809:48;;5605:258;;;:::o;5868:317::-;5910:3;5948:5;5942:12;5975:6;5970:3;5963:19;5991:63;6047:6;6040:4;6035:3;6031:14;6024:4;6017:5;6013:16;5991:63;:::i;:::-;6099:2;6087:15;6104:66;6083:88;6074:98;;;;6174:4;6070:109;;5868:317;-1:-1:-1;;5868:317:1:o;6190:493::-;6440:2;6429:9;6422:21;6403:4;6466:45;6507:2;6496:9;6492:18;6484:6;6466:45;:::i;:::-;6559:9;6551:6;6547:22;6542:2;6531:9;6527:18;6520:50;6594:2;6586:6;6579:18;6630:14;6625:2;6617:6;6613:15;6606:39;6674:2;6666:6;6662:15;6654:23;;;6190:493;;;;:::o;6688:184::-;6740:77;6737:1;6730:88;6837:4;6834:1;6827:15;6861:4;6858:1;6851:15;6877:334;6948:2;6942:9;7004:2;6994:13;;7009:66;6990:86;6978:99;;7107:18;7092:34;;7128:22;;;7089:62;7086:88;;;7154:18;;:::i;:::-;7190:2;7183:22;6877:334;;-1:-1:-1;6877:334:1:o;7216:1801::-;7321:6;7352:2;7395;7383:9;7374:7;7370:23;7366:32;7363:52;;;7411:1;7408;7401:12;7363:52;7444:9;7438:16;7473:18;7514:2;7506:6;7503:14;7500:34;;;7530:1;7527;7520:12;7500:34;7568:6;7557:9;7553:22;7543:32;;7594:4;7634:7;7629:2;7625;7621:11;7617:25;7607:53;;7656:1;7653;7646:12;7607:53;7685:2;7679:9;7707:2;7703;7700:10;7697:36;;;7713:18;;:::i;:::-;7759:2;7756:1;7752:10;7782:28;7806:2;7802;7798:11;7782:28;:::i;:::-;7844:15;;;7914:11;;;7910:20;;;7875:12;;;;7942:19;;;7939:39;;;7974:1;7971;7964:12;7939:39;8006:2;8002;7998:11;7987:22;;8018:969;8034:6;8029:3;8026:15;8018:969;;;8113:3;8107:10;8149:2;8136:11;8133:19;8130:109;;;8193:1;8222:2;8218;8211:14;8130:109;8262:20;;8317:2;8309:11;;8305:25;-1:-1:-1;8295:123:1;;8372:1;8401:2;8397;8390:14;8295:123;8456:2;8452;8448:11;8442:18;8484:2;8510;8505:3;8502:11;8499:37;;;8516:18;;:::i;:::-;8562:111;8669:2;8600:66;8595:2;8590:3;8586:12;8582:85;8578:94;8562:111;:::i;:::-;8700:3;8693:5;8686:18;8747:7;8741:3;8735;8731:2;8727:12;8723:22;8720:35;8717:128;;;8797:1;8827:3;8822;8815:16;8717:128;8858:56;8910:3;8905:2;8898:5;8894:14;8888:3;8884:2;8880:12;8858:56;:::i;:::-;8927:18;;-1:-1:-1;;;8051:12:1;;;;8965;;;;8018:969;;;9006:5;7216:1801;-1:-1:-1;;;;;;;;;;7216:1801:1:o;9022:184::-;9074:77;9071:1;9064:88;9171:4;9168:1;9161:15;9195:4;9192:1;9185:15;10583:220;10732:2;10721:9;10714:21;10695:4;10752:45;10793:2;10782:9;10778:18;10770:6;10752:45;:::i;10808:340::-;10985:2;10974:9;10967:21;10948:4;11005:45;11046:2;11035:9;11031:18;11023:6;11005:45;:::i;:::-;10997:53;;11098:42;11090:6;11086:55;11081:2;11070:9;11066:18;11059:83;10808:340;;;;;:::o;11153:291::-;11330:2;11319:9;11312:21;11293:4;11350:45;11391:2;11380:9;11376:18;11368:6;11350:45;:::i;:::-;11342:53;;11431:6;11426:2;11415:9;11411:18;11404:34;11153:291;;;;;:::o;11449:301::-;11620:2;11609:9;11602:21;11583:4;11640:45;11681:2;11670:9;11666:18;11658:6;11640:45;:::i;:::-;11632:53;;11735:6;11728:14;11721:22;11716:2;11705:9;11701:18;11694:50;11449:301;;;;;:::o;11755:546::-;12000:2;11989:9;11982:21;11963:4;12026:45;12067:2;12056:9;12052:18;12044:6;12026:45;:::i;:::-;12119:9;12111:6;12107:22;12102:2;12091:9;12087:18;12080:50;12153:33;12179:6;12171;12153:33;:::i;:::-;12139:47;;12234:9;12226:6;12222:22;12217:2;12206:9;12202:18;12195:50;12262:33;12288:6;12280;12262:33;:::i;:::-;12254:41;11755:546;-1:-1:-1;;;;;;11755:546:1:o","linkReferences":{}},"methodIdentifiers":{"call1(string)":"7e79255d","call2(string)":"8d3ef7ca","callPure(string)":"7f8b915c","counter()":"61bc221a","hello(string)":"a777d0dc","nested1(string)":"a76ccdfa","nested2(string)":"dbf1282f","run()":"c0406226","runBroadcast()":"bef03abc"},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_v\",\"type\":\"string\"}],\"name\":\"call1\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_v\",\"type\":\"string\"}],\"name\":\"call2\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_v\",\"type\":\"string\"}],\"name\":\"callPure\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"counter\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_v\",\"type\":\"string\"}],\"name\":\"hello\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_v\",\"type\":\"string\"}],\"name\":\"nested1\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_v\",\"type\":\"string\"}],\"name\":\"nested2\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"run\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"runBroadcast\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"title\":\"ScriptExample\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"hello(string)\":{\"notice\":\"example external function, to force a CALL, and test vm.startPrank with.\"},\"run()\":{\"notice\":\"example function, runs through basic cheat-codes and console logs.\"},\"runBroadcast()\":{\"notice\":\"example function, to test vm.broadcast with.\"}},\"notice\":\"ScriptExample is an example script. The Go forge script code tests that it can run this.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"scripts/ScriptExample.s.sol\":\"ScriptExample\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[]},\"sources\":{\"scripts/ScriptExample.s.sol\":{\"keccak256\":\"0x8d1dfa41908e7ccc3a498a2a2aa51c5275bedbb904ce32d08f8598e36f896d8d\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5117bb7158363cae8b9dc0508d2852692fd36172f1c699ff680afbb5acebe1f3\",\"dweb:/ipfs/QmQdahJ8SPKfJ4yea5Ge9qaj5qh1TxVffhHvaWytBaL95h\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.15+commit.e14f2714"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"string","name":"_v","type":"string"}],"stateMutability":"nonpayable","type":"function","name":"call1"},{"inputs":[{"internalType":"string","name":"_v","type":"string"}],"stateMutability":"nonpayable","type":"function","name":"call2"},{"inputs":[{"internalType":"string","name":"_v","type":"string"}],"stateMutability":"pure","type":"function","name":"callPure"},{"inputs":[],"stateMutability":"view","type":"function","name":"counter","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[{"internalType":"string","name":"_v","type":"string"}],"stateMutability":"view","type":"function","name":"hello"},{"inputs":[{"internalType":"string","name":"_v","type":"string"}],"stateMutability":"nonpayable","type":"function","name":"nested1"},{"inputs":[{"internalType":"string","name":"_v","type":"string"}],"stateMutability":"nonpayable","type":"function","name":"nested2"},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"run"},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"runBroadcast"}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{"hello(string)":{"notice":"example external function, to force a CALL, and test vm.startPrank with."},"run()":{"notice":"example function, runs through basic cheat-codes and console logs."},"runBroadcast()":{"notice":"example function, to test vm.broadcast with."}},"version":1}},"settings":{"remappings":[],"optimizer":{"enabled":true,"runs":999999},"metadata":{"bytecodeHash":"none"},"compilationTarget":{"scripts/ScriptExample.s.sol":"ScriptExample"},"evmVersion":"london","libraries":{}},"sources":{"scripts/ScriptExample.s.sol":{"keccak256":"0x8d1dfa41908e7ccc3a498a2a2aa51c5275bedbb904ce32d08f8598e36f896d8d","urls":["bzz-raw://5117bb7158363cae8b9dc0508d2852692fd36172f1c699ff680afbb5acebe1f3","dweb:/ipfs/QmQdahJ8SPKfJ4yea5Ge9qaj5qh1TxVffhHvaWytBaL95h"],"license":"MIT"}},"version":1},"storageLayout":{"storage":[{"astId":215,"contract":"scripts/ScriptExample.s.sol:ScriptExample","label":"counter","offset":0,"slot":"0","type":"t_uint256"}],"types":{"t_uint256":{"encoding":"inplace","label":"uint256","numberOfBytes":"32"}}},"userdoc":{"version":1,"kind":"user","methods":{"hello(string)":{"notice":"example external function, to force a CALL, and test vm.startPrank with."},"run()":{"notice":"example function, runs through basic cheat-codes and console logs."},"runBroadcast()":{"notice":"example function, to test vm.broadcast with."}},"notice":"ScriptExample is an example script. The Go forge script code tests that it can run this."},"devdoc":{"version":1,"kind":"dev","title":"ScriptExample"},"ast":{"absolutePath":"scripts/ScriptExample.s.sol","id":720,"exportedSymbols":{"FooBar":[719],"ScriptExample":[706],"Vm":[55],"console":[192]},"nodeType":"SourceUnit","src":"32:5967:0","nodes":[{"id":1,"nodeType":"PragmaDirective","src":"32:23:0","nodes":[],"literals":["solidity","0.8",".15"]},{"id":55,"nodeType":"ContractDefinition","src":"120:616:0","nodes":[{"id":10,"nodeType":"FunctionDefinition","src":"139:91:0","nodes":[],"functionSelector":"4777f3cf","implemented":false,"kind":"function","modifiers":[],"name":"envOr","nameLocation":"148:5:0","parameters":{"id":6,"nodeType":"ParameterList","parameters":[{"constant":false,"id":3,"mutability":"mutable","name":"name","nameLocation":"170:4:0","nodeType":"VariableDeclaration","scope":10,"src":"154:20:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":2,"name":"string","nodeType":"ElementaryTypeName","src":"154:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":5,"mutability":"mutable","name":"defaultValue","nameLocation":"181:12:0","nodeType":"VariableDeclaration","scope":10,"src":"176:17:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":4,"name":"bool","nodeType":"ElementaryTypeName","src":"176:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"src":"153:41:0"},"returnParameters":{"id":9,"nodeType":"ParameterList","parameters":[{"constant":false,"id":8,"mutability":"mutable","name":"value","nameLocation":"223:5:0","nodeType":"VariableDeclaration","scope":10,"src":"218:10:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":7,"name":"bool","nodeType":"ElementaryTypeName","src":"218:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"src":"217:12:0"},"scope":55,"stateMutability":"view","virtual":false,"visibility":"external"},{"id":17,"nodeType":"FunctionDefinition","src":"235:72:0","nodes":[],"functionSelector":"2d0335ab","implemented":false,"kind":"function","modifiers":[],"name":"getNonce","nameLocation":"244:8:0","parameters":{"id":13,"nodeType":"ParameterList","parameters":[{"constant":false,"id":12,"mutability":"mutable","name":"account","nameLocation":"261:7:0","nodeType":"VariableDeclaration","scope":17,"src":"253:15:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":11,"name":"address","nodeType":"ElementaryTypeName","src":"253:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"252:17:0"},"returnParameters":{"id":16,"nodeType":"ParameterList","parameters":[{"constant":false,"id":15,"mutability":"mutable","name":"nonce","nameLocation":"300:5:0","nodeType":"VariableDeclaration","scope":17,"src":"293:12:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"},"typeName":{"id":14,"name":"uint64","nodeType":"ElementaryTypeName","src":"293:6:0","typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}},"visibility":"internal"}],"src":"292:14:0"},"scope":55,"stateMutability":"view","virtual":false,"visibility":"external"},{"id":27,"nodeType":"FunctionDefinition","src":"312:111:0","nodes":[],"functionSelector":"213e4198","implemented":false,"kind":"function","modifiers":[],"name":"parseJsonKeys","nameLocation":"321:13:0","parameters":{"id":22,"nodeType":"ParameterList","parameters":[{"constant":false,"id":19,"mutability":"mutable","name":"json","nameLocation":"351:4:0","nodeType":"VariableDeclaration","scope":27,"src":"335:20:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":18,"name":"string","nodeType":"ElementaryTypeName","src":"335:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":21,"mutability":"mutable","name":"key","nameLocation":"373:3:0","nodeType":"VariableDeclaration","scope":27,"src":"357:19:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":20,"name":"string","nodeType":"ElementaryTypeName","src":"357:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"334:43:0"},"returnParameters":{"id":26,"nodeType":"ParameterList","parameters":[{"constant":false,"id":25,"mutability":"mutable","name":"keys","nameLocation":"417:4:0","nodeType":"VariableDeclaration","scope":27,"src":"401:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string[]"},"typeName":{"baseType":{"id":23,"name":"string","nodeType":"ElementaryTypeName","src":"401:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"id":24,"nodeType":"ArrayTypeName","src":"401:8:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_storage_$dyn_storage_ptr","typeString":"string[]"}},"visibility":"internal"}],"src":"400:22:0"},"scope":55,"stateMutability":"pure","virtual":false,"visibility":"external"},{"id":32,"nodeType":"FunctionDefinition","src":"428:48:0","nodes":[],"functionSelector":"06447d56","implemented":false,"kind":"function","modifiers":[],"name":"startPrank","nameLocation":"437:10:0","parameters":{"id":30,"nodeType":"ParameterList","parameters":[{"constant":false,"id":29,"mutability":"mutable","name":"msgSender","nameLocation":"456:9:0","nodeType":"VariableDeclaration","scope":32,"src":"448:17:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":28,"name":"address","nodeType":"ElementaryTypeName","src":"448:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"447:19:0"},"returnParameters":{"id":31,"nodeType":"ParameterList","parameters":[],"src":"475:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":35,"nodeType":"FunctionDefinition","src":"481:30:0","nodes":[],"functionSelector":"90c5013b","implemented":false,"kind":"function","modifiers":[],"name":"stopPrank","nameLocation":"490:9:0","parameters":{"id":33,"nodeType":"ParameterList","parameters":[],"src":"499:2:0"},"returnParameters":{"id":34,"nodeType":"ParameterList","parameters":[],"src":"510:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":38,"nodeType":"FunctionDefinition","src":"516:30:0","nodes":[],"functionSelector":"afc98040","implemented":false,"kind":"function","modifiers":[],"name":"broadcast","nameLocation":"525:9:0","parameters":{"id":36,"nodeType":"ParameterList","parameters":[],"src":"534:2:0"},"returnParameters":{"id":37,"nodeType":"ParameterList","parameters":[],"src":"545:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":43,"nodeType":"FunctionDefinition","src":"551:47:0","nodes":[],"functionSelector":"e6962cdb","implemented":false,"kind":"function","modifiers":[],"name":"broadcast","nameLocation":"560:9:0","parameters":{"id":41,"nodeType":"ParameterList","parameters":[{"constant":false,"id":40,"mutability":"mutable","name":"msgSender","nameLocation":"578:9:0","nodeType":"VariableDeclaration","scope":43,"src":"570:17:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":39,"name":"address","nodeType":"ElementaryTypeName","src":"570:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"569:19:0"},"returnParameters":{"id":42,"nodeType":"ParameterList","parameters":[],"src":"597:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":48,"nodeType":"FunctionDefinition","src":"603:52:0","nodes":[],"functionSelector":"7fec2a8d","implemented":false,"kind":"function","modifiers":[],"name":"startBroadcast","nameLocation":"612:14:0","parameters":{"id":46,"nodeType":"ParameterList","parameters":[{"constant":false,"id":45,"mutability":"mutable","name":"msgSender","nameLocation":"635:9:0","nodeType":"VariableDeclaration","scope":48,"src":"627:17:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":44,"name":"address","nodeType":"ElementaryTypeName","src":"627:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"626:19:0"},"returnParameters":{"id":47,"nodeType":"ParameterList","parameters":[],"src":"654:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":51,"nodeType":"FunctionDefinition","src":"660:35:0","nodes":[],"functionSelector":"7fb5297f","implemented":false,"kind":"function","modifiers":[],"name":"startBroadcast","nameLocation":"669:14:0","parameters":{"id":49,"nodeType":"ParameterList","parameters":[],"src":"683:2:0"},"returnParameters":{"id":50,"nodeType":"ParameterList","parameters":[],"src":"694:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":54,"nodeType":"FunctionDefinition","src":"700:34:0","nodes":[],"functionSelector":"76eadd36","implemented":false,"kind":"function","modifiers":[],"name":"stopBroadcast","nameLocation":"709:13:0","parameters":{"id":52,"nodeType":"ParameterList","parameters":[],"src":"722:2:0"},"returnParameters":{"id":53,"nodeType":"ParameterList","parameters":[],"src":"733:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"}],"abstract":false,"baseContracts":[],"canonicalName":"Vm","contractDependencies":[],"contractKind":"interface","fullyImplemented":false,"linearizedBaseContracts":[55],"name":"Vm","nameLocation":"130:2:0","scope":720,"usedErrors":[]},{"id":192,"nodeType":"ContractDefinition","src":"791:1622:0","nodes":[{"id":61,"nodeType":"VariableDeclaration","src":"813:86:0","nodes":[],"constant":true,"mutability":"constant","name":"CONSOLE_ADDRESS","nameLocation":"830:15:0","scope":192,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":56,"name":"address","nodeType":"ElementaryTypeName","src":"813:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"value":{"arguments":[{"hexValue":"307830303030303030303030303030303030303036333646366537333646366336353265366336663637","id":59,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"856:42:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"value":"0x000000000000000000636F6e736F6c652e6c6f67"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":58,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"848:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":57,"name":"address","nodeType":"ElementaryTypeName","src":"848:7:0","typeDescriptions":{}}},"id":60,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"848:51:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"},{"id":78,"nodeType":"FunctionDefinition","src":"906:221:0","nodes":[],"body":{"id":77,"nodeType":"Block","src":"1065:62:0","nodes":[],"statements":[{"AST":{"nodeType":"YulBlock","src":"1084:37:0","statements":[{"nodeType":"YulAssignment","src":"1098:13:0","value":{"name":"fnIn","nodeType":"YulIdentifier","src":"1107:4:0"},"variableNames":[{"name":"fnOut","nodeType":"YulIdentifier","src":"1098:5:0"}]}]},"evmVersion":"london","externalReferences":[{"declaration":67,"isOffset":false,"isSlot":false,"src":"1107:4:0","valueSize":1},{"declaration":74,"isOffset":false,"isSlot":false,"src":"1098:5:0","valueSize":1}],"id":76,"nodeType":"InlineAssembly","src":"1075:46:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"_castLogPayloadViewToPure","nameLocation":"915:25:0","parameters":{"id":68,"nodeType":"ParameterList","parameters":[{"constant":false,"id":67,"mutability":"mutable","name":"fnIn","nameLocation":"987:4:0","nodeType":"VariableDeclaration","scope":78,"src":"950:41:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) view"},"typeName":{"id":66,"nodeType":"FunctionTypeName","parameterTypes":{"id":64,"nodeType":"ParameterList","parameters":[{"constant":false,"id":63,"mutability":"mutable","name":"","nameLocation":"-1:-1:-1","nodeType":"VariableDeclaration","scope":66,"src":"959:12:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":62,"name":"bytes","nodeType":"ElementaryTypeName","src":"959:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"958:14:0"},"returnParameterTypes":{"id":65,"nodeType":"ParameterList","parameters":[],"src":"987:0:0"},"src":"950:41:0","stateMutability":"view","typeDescriptions":{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) view"},"visibility":"internal"},"visibility":"internal"}],"src":"940:57:0"},"returnParameters":{"id":75,"nodeType":"ParameterList","parameters":[{"constant":false,"id":74,"mutability":"mutable","name":"fnOut","nameLocation":"1058:5:0","nodeType":"VariableDeclaration","scope":78,"src":"1021:42:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) pure"},"typeName":{"id":73,"nodeType":"FunctionTypeName","parameterTypes":{"id":71,"nodeType":"ParameterList","parameters":[{"constant":false,"id":70,"mutability":"mutable","name":"","nameLocation":"-1:-1:-1","nodeType":"VariableDeclaration","scope":73,"src":"1030:12:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":69,"name":"bytes","nodeType":"ElementaryTypeName","src":"1030:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"1029:14:0"},"returnParameterTypes":{"id":72,"nodeType":"ParameterList","parameters":[],"src":"1058:0:0"},"src":"1021:42:0","stateMutability":"pure","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) pure"},"visibility":"internal"},"visibility":"internal"}],"src":"1020:44:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":90,"nodeType":"FunctionDefinition","src":"1133:133:0","nodes":[],"body":{"id":89,"nodeType":"Block","src":"1194:72:0","nodes":[],"statements":[{"expression":{"arguments":[{"id":86,"name":"payload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":80,"src":"1251:7:0","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"arguments":[{"id":84,"name":"_sendLogPayloadView","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":106,"src":"1230:19:0","typeDescriptions":{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) view"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) view"}],"id":83,"name":"_castLogPayloadViewToPure","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":78,"src":"1204:25:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_function_internal_view$_t_bytes_memory_ptr_$returns$__$_$returns$_t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$_$","typeString":"function (function (bytes memory) view) pure returns (function (bytes memory) pure)"}},"id":85,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1204:46:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":87,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1204:55:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":88,"nodeType":"ExpressionStatement","src":"1204:55:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"_sendLogPayload","nameLocation":"1142:15:0","parameters":{"id":81,"nodeType":"ParameterList","parameters":[{"constant":false,"id":80,"mutability":"mutable","name":"payload","nameLocation":"1171:7:0","nodeType":"VariableDeclaration","scope":90,"src":"1158:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":79,"name":"bytes","nodeType":"ElementaryTypeName","src":"1158:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"1157:22:0"},"returnParameters":{"id":82,"nodeType":"ParameterList","parameters":[],"src":"1194:0:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":106,"nodeType":"FunctionDefinition","src":"1272:380:0","nodes":[],"body":{"id":105,"nodeType":"Block","src":"1336:316:0","nodes":[],"statements":[{"assignments":[96],"declarations":[{"constant":false,"id":96,"mutability":"mutable","name":"payloadLength","nameLocation":"1354:13:0","nodeType":"VariableDeclaration","scope":105,"src":"1346:21:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":95,"name":"uint256","nodeType":"ElementaryTypeName","src":"1346:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"}],"id":99,"initialValue":{"expression":{"id":97,"name":"payload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":92,"src":"1370:7:0","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}},"id":98,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"length","nodeType":"MemberAccess","src":"1370:14:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"nodeType":"VariableDeclarationStatement","src":"1346:38:0"},{"assignments":[101],"declarations":[{"constant":false,"id":101,"mutability":"mutable","name":"consoleAddress","nameLocation":"1402:14:0","nodeType":"VariableDeclaration","scope":105,"src":"1394:22:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":100,"name":"address","nodeType":"ElementaryTypeName","src":"1394:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"id":103,"initialValue":{"id":102,"name":"CONSOLE_ADDRESS","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":61,"src":"1419:15:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"nodeType":"VariableDeclarationStatement","src":"1394:40:0"},{"AST":{"nodeType":"YulBlock","src":"1496:150:0","statements":[{"nodeType":"YulVariableDeclaration","src":"1510:36:0","value":{"arguments":[{"name":"payload","nodeType":"YulIdentifier","src":"1534:7:0"},{"kind":"number","nodeType":"YulLiteral","src":"1543:2:0","type":"","value":"32"}],"functionName":{"name":"add","nodeType":"YulIdentifier","src":"1530:3:0"},"nodeType":"YulFunctionCall","src":"1530:16:0"},"variables":[{"name":"payloadStart","nodeType":"YulTypedName","src":"1514:12:0","type":""}]},{"nodeType":"YulVariableDeclaration","src":"1559:77:0","value":{"arguments":[{"arguments":[],"functionName":{"name":"gas","nodeType":"YulIdentifier","src":"1579:3:0"},"nodeType":"YulFunctionCall","src":"1579:5:0"},{"name":"consoleAddress","nodeType":"YulIdentifier","src":"1586:14:0"},{"name":"payloadStart","nodeType":"YulIdentifier","src":"1602:12:0"},{"name":"payloadLength","nodeType":"YulIdentifier","src":"1616:13:0"},{"kind":"number","nodeType":"YulLiteral","src":"1631:1:0","type":"","value":"0"},{"kind":"number","nodeType":"YulLiteral","src":"1634:1:0","type":"","value":"0"}],"functionName":{"name":"staticcall","nodeType":"YulIdentifier","src":"1568:10:0"},"nodeType":"YulFunctionCall","src":"1568:68:0"},"variables":[{"name":"r","nodeType":"YulTypedName","src":"1563:1:0","type":""}]}]},"documentation":"@solidity memory-safe-assembly","evmVersion":"london","externalReferences":[{"declaration":101,"isOffset":false,"isSlot":false,"src":"1586:14:0","valueSize":1},{"declaration":92,"isOffset":false,"isSlot":false,"src":"1534:7:0","valueSize":1},{"declaration":96,"isOffset":false,"isSlot":false,"src":"1616:13:0","valueSize":1}],"id":104,"nodeType":"InlineAssembly","src":"1487:159:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"_sendLogPayloadView","nameLocation":"1281:19:0","parameters":{"id":93,"nodeType":"ParameterList","parameters":[{"constant":false,"id":92,"mutability":"mutable","name":"payload","nameLocation":"1314:7:0","nodeType":"VariableDeclaration","scope":106,"src":"1301:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":91,"name":"bytes","nodeType":"ElementaryTypeName","src":"1301:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"1300:22:0"},"returnParameters":{"id":94,"nodeType":"ParameterList","parameters":[],"src":"1336:0:0"},"scope":192,"stateMutability":"view","virtual":false,"visibility":"private"},{"id":120,"nodeType":"FunctionDefinition","src":"1658:121:0","nodes":[],"body":{"id":119,"nodeType":"Block","src":"1703:76:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e6729","id":114,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"1753:13:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_41304facd9323d75b11bcdd609cb38effffdb05710f7caf0e9b16c6d9d709f50","typeString":"literal_string \"log(string)\""},"value":"log(string)"},{"id":115,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":108,"src":"1768:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_41304facd9323d75b11bcdd609cb38effffdb05710f7caf0e9b16c6d9d709f50","typeString":"literal_string \"log(string)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}],"expression":{"id":112,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"1729:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":113,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"1729:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":116,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1729:42:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":111,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":90,"src":"1713:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":117,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1713:59:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":118,"nodeType":"ExpressionStatement","src":"1713:59:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"1667:3:0","parameters":{"id":109,"nodeType":"ParameterList","parameters":[{"constant":false,"id":108,"mutability":"mutable","name":"p0","nameLocation":"1685:2:0","nodeType":"VariableDeclaration","scope":120,"src":"1671:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":107,"name":"string","nodeType":"ElementaryTypeName","src":"1671:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"1670:18:0"},"returnParameters":{"id":110,"nodeType":"ParameterList","parameters":[],"src":"1703:0:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":137,"nodeType":"FunctionDefinition","src":"1785:139:0","nodes":[],"body":{"id":136,"nodeType":"Block","src":"1839:85:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c626f6f6c29","id":130,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"1889:18:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_c3b556354c088fbb43886eb83c2a04bc7089663f964d22be308197a236f5b870","typeString":"literal_string \"log(string,bool)\""},"value":"log(string,bool)"},{"id":131,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":122,"src":"1909:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":132,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":124,"src":"1913:2:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_c3b556354c088fbb43886eb83c2a04bc7089663f964d22be308197a236f5b870","typeString":"literal_string \"log(string,bool)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_bool","typeString":"bool"}],"expression":{"id":128,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"1865:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":129,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"1865:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":133,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1865:51:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":127,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":90,"src":"1849:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":134,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1849:68:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":135,"nodeType":"ExpressionStatement","src":"1849:68:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"1794:3:0","parameters":{"id":125,"nodeType":"ParameterList","parameters":[{"constant":false,"id":122,"mutability":"mutable","name":"p0","nameLocation":"1812:2:0","nodeType":"VariableDeclaration","scope":137,"src":"1798:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":121,"name":"string","nodeType":"ElementaryTypeName","src":"1798:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":124,"mutability":"mutable","name":"p1","nameLocation":"1821:2:0","nodeType":"VariableDeclaration","scope":137,"src":"1816:7:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":123,"name":"bool","nodeType":"ElementaryTypeName","src":"1816:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"src":"1797:27:0"},"returnParameters":{"id":126,"nodeType":"ParameterList","parameters":[],"src":"1839:0:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":154,"nodeType":"FunctionDefinition","src":"1930:145:0","nodes":[],"body":{"id":153,"nodeType":"Block","src":"1987:88:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c75696e7432353629","id":147,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2037:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_b60e72ccf6d57ab53eb84d7e94a9545806ed7f93c4d5673f11a64f03471e584e","typeString":"literal_string \"log(string,uint256)\""},"value":"log(string,uint256)"},{"id":148,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":139,"src":"2060:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":149,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":141,"src":"2064:2:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_b60e72ccf6d57ab53eb84d7e94a9545806ed7f93c4d5673f11a64f03471e584e","typeString":"literal_string \"log(string,uint256)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_uint256","typeString":"uint256"}],"expression":{"id":145,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"2013:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":146,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"2013:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":150,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2013:54:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":144,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":90,"src":"1997:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":151,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1997:71:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":152,"nodeType":"ExpressionStatement","src":"1997:71:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"1939:3:0","parameters":{"id":142,"nodeType":"ParameterList","parameters":[{"constant":false,"id":139,"mutability":"mutable","name":"p0","nameLocation":"1957:2:0","nodeType":"VariableDeclaration","scope":154,"src":"1943:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":138,"name":"string","nodeType":"ElementaryTypeName","src":"1943:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":141,"mutability":"mutable","name":"p1","nameLocation":"1969:2:0","nodeType":"VariableDeclaration","scope":154,"src":"1961:10:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":140,"name":"uint256","nodeType":"ElementaryTypeName","src":"1961:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"}],"src":"1942:30:0"},"returnParameters":{"id":143,"nodeType":"ParameterList","parameters":[],"src":"1987:0:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":171,"nodeType":"FunctionDefinition","src":"2081:145:0","nodes":[],"body":{"id":170,"nodeType":"Block","src":"2138:88:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c6164647265737329","id":164,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2188:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_319af333460570a1937bf195dd33445c0d0951c59127da6f1f038b9fdce3fd72","typeString":"literal_string \"log(string,address)\""},"value":"log(string,address)"},{"id":165,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":156,"src":"2211:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":166,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":158,"src":"2215:2:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_319af333460570a1937bf195dd33445c0d0951c59127da6f1f038b9fdce3fd72","typeString":"literal_string \"log(string,address)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":162,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"2164:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":163,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"2164:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":167,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2164:54:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":161,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":90,"src":"2148:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":168,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2148:71:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":169,"nodeType":"ExpressionStatement","src":"2148:71:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"2090:3:0","parameters":{"id":159,"nodeType":"ParameterList","parameters":[{"constant":false,"id":156,"mutability":"mutable","name":"p0","nameLocation":"2108:2:0","nodeType":"VariableDeclaration","scope":171,"src":"2094:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":155,"name":"string","nodeType":"ElementaryTypeName","src":"2094:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":158,"mutability":"mutable","name":"p1","nameLocation":"2120:2:0","nodeType":"VariableDeclaration","scope":171,"src":"2112:10:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":157,"name":"address","nodeType":"ElementaryTypeName","src":"2112:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"2093:30:0"},"returnParameters":{"id":160,"nodeType":"ParameterList","parameters":[],"src":"2138:0:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":191,"nodeType":"FunctionDefinition","src":"2232:179:0","nodes":[],"body":{"id":190,"nodeType":"Block","src":"2313:98:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c737472696e672c737472696e6729","id":183,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2363:27:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_2ced7cef693312206c21f0e92e3b54e2e16bf33db5eec350c78866822c665e1f","typeString":"literal_string \"log(string,string,string)\""},"value":"log(string,string,string)"},{"id":184,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"2392:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":185,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":175,"src":"2396:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":186,"name":"p2","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":177,"src":"2400:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_2ced7cef693312206c21f0e92e3b54e2e16bf33db5eec350c78866822c665e1f","typeString":"literal_string \"log(string,string,string)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}],"expression":{"id":181,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"2339:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":182,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"2339:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":187,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2339:64:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":180,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":90,"src":"2323:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":188,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2323:81:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":189,"nodeType":"ExpressionStatement","src":"2323:81:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"2241:3:0","parameters":{"id":178,"nodeType":"ParameterList","parameters":[{"constant":false,"id":173,"mutability":"mutable","name":"p0","nameLocation":"2259:2:0","nodeType":"VariableDeclaration","scope":191,"src":"2245:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":172,"name":"string","nodeType":"ElementaryTypeName","src":"2245:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":175,"mutability":"mutable","name":"p1","nameLocation":"2277:2:0","nodeType":"VariableDeclaration","scope":191,"src":"2263:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":174,"name":"string","nodeType":"ElementaryTypeName","src":"2263:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":177,"mutability":"mutable","name":"p2","nameLocation":"2295:2:0","nodeType":"VariableDeclaration","scope":191,"src":"2281:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":176,"name":"string","nodeType":"ElementaryTypeName","src":"2281:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"2244:54:0"},"returnParameters":{"id":179,"nodeType":"ParameterList","parameters":[],"src":"2313:0:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"}],"abstract":false,"baseContracts":[],"canonicalName":"console","contractDependencies":[],"contractKind":"library","fullyImplemented":true,"linearizedBaseContracts":[192],"name":"console","nameLocation":"799:7:0","scope":720,"usedErrors":[]},{"id":706,"nodeType":"ContractDefinition","src":"2541:3359:0","nodes":[{"id":207,"nodeType":"VariableDeclaration","src":"2571:94:0","nodes":[],"constant":true,"mutability":"constant","name":"VM_ADDRESS","nameLocation":"2597:10:0","scope":706,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":194,"name":"address","nodeType":"ElementaryTypeName","src":"2571:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"value":{"arguments":[{"arguments":[{"arguments":[{"arguments":[{"hexValue":"6865766d20636865617420636f6465","id":202,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2644:17:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d","typeString":"literal_string \"hevm cheat code\""},"value":"hevm cheat code"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d","typeString":"literal_string \"hevm cheat code\""}],"id":201,"name":"keccak256","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-8,"src":"2634:9:0","typeDescriptions":{"typeIdentifier":"t_function_keccak256_pure$_t_bytes_memory_ptr_$returns$_t_bytes32_$","typeString":"function (bytes memory) pure returns (bytes32)"}},"id":203,"isConstant":false,"isLValue":false,"isPure":true,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2634:28:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes32","typeString":"bytes32"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes32","typeString":"bytes32"}],"id":200,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2626:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint256_$","typeString":"type(uint256)"},"typeName":{"id":199,"name":"uint256","nodeType":"ElementaryTypeName","src":"2626:7:0","typeDescriptions":{}}},"id":204,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2626:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint256","typeString":"uint256"}],"id":198,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2618:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":197,"name":"uint160","nodeType":"ElementaryTypeName","src":"2618:7:0","typeDescriptions":{}}},"id":205,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2618:46:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":196,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2610:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":195,"name":"address","nodeType":"ElementaryTypeName","src":"2610:7:0","typeDescriptions":{}}},"id":206,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2610:55:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"},{"id":213,"nodeType":"VariableDeclaration","src":"2671:40:0","nodes":[],"constant":true,"mutability":"constant","name":"vm","nameLocation":"2692:2:0","scope":706,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"},"typeName":{"id":209,"nodeType":"UserDefinedTypeName","pathNode":{"id":208,"name":"Vm","nodeType":"IdentifierPath","referencedDeclaration":55,"src":"2671:2:0"},"referencedDeclaration":55,"src":"2671:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"value":{"arguments":[{"id":211,"name":"VM_ADDRESS","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":207,"src":"2700:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":210,"name":"Vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":55,"src":"2697:2:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_Vm_$55_$","typeString":"type(contract Vm)"}},"id":212,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2697:14:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"visibility":"internal"},{"id":215,"nodeType":"VariableDeclaration","src":"2775:22:0","nodes":[],"constant":false,"functionSelector":"61bc221a","mutability":"mutable","name":"counter","nameLocation":"2790:7:0","scope":706,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":214,"name":"uint256","nodeType":"ElementaryTypeName","src":"2775:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"public"},{"id":378,"nodeType":"FunctionDefinition","src":"2887:949:0","nodes":[],"body":{"id":377,"nodeType":"Block","src":"2909:927:0","nodes":[],"statements":[{"assignments":[220],"declarations":[{"constant":false,"id":220,"mutability":"mutable","name":"x","nameLocation":"2924:1:0","nodeType":"VariableDeclaration","scope":377,"src":"2919:6:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":219,"name":"bool","nodeType":"ElementaryTypeName","src":"2919:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"id":226,"initialValue":{"arguments":[{"hexValue":"4558414d504c455f424f4f4c","id":223,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2937:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_a634dae177a0e138ae7aaa2afae347412e148992e88c7aabd33ee71be146cb7f","typeString":"literal_string \"EXAMPLE_BOOL\""},"value":"EXAMPLE_BOOL"},{"hexValue":"66616c7365","id":224,"isConstant":false,"isLValue":false,"isPure":true,"kind":"bool","lValueRequested":false,"nodeType":"Literal","src":"2953:5:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"value":"false"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_a634dae177a0e138ae7aaa2afae347412e148992e88c7aabd33ee71be146cb7f","typeString":"literal_string \"EXAMPLE_BOOL\""},{"typeIdentifier":"t_bool","typeString":"bool"}],"expression":{"id":221,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"2928:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":222,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"envOr","nodeType":"MemberAccess","referencedDeclaration":10,"src":"2928:8:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$_t_bool_$returns$_t_bool_$","typeString":"function (string memory,bool) view external returns (bool)"}},"id":225,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2928:31:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"nodeType":"VariableDeclarationStatement","src":"2919:40:0"},{"expression":{"arguments":[{"hexValue":"626f6f6c2076616c75652066726f6d20656e76","id":230,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2981:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_5a607d0b5a1295325aa8901721d78ba402601bba6f62cebdd5235dd0204a590b","typeString":"literal_string \"bool value from env\""},"value":"bool value from env"},{"id":231,"name":"x","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":220,"src":"3004:1:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_5a607d0b5a1295325aa8901721d78ba402601bba6f62cebdd5235dd0204a590b","typeString":"literal_string \"bool value from env\""},{"typeIdentifier":"t_bool","typeString":"bool"}],"expression":{"id":227,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"2969:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":229,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":137,"src":"2969:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_bool_$returns$__$","typeString":"function (string memory,bool) pure"}},"id":232,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2969:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":233,"nodeType":"ExpressionStatement","src":"2969:37:0"},{"expression":{"arguments":[{"hexValue":"636f6e74726163742061646472","id":237,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3029:15:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_fa50728770d00fe8f6a0592f3565bbfaf063ee4077f1f5bbc003d091d33cd0c4","typeString":"literal_string \"contract addr\""},"value":"contract addr"},{"arguments":[{"id":240,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3054:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}],"id":239,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3046:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":238,"name":"address","nodeType":"ElementaryTypeName","src":"3046:7:0","typeDescriptions":{}}},"id":241,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3046:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_fa50728770d00fe8f6a0592f3565bbfaf063ee4077f1f5bbc003d091d33cd0c4","typeString":"literal_string \"contract addr\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":234,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3017:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":236,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":171,"src":"3017:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":242,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3017:43:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":243,"nodeType":"ExpressionStatement","src":"3017:43:0"},{"expression":{"arguments":[{"hexValue":"636f6e7472616374206e6f6e6365","id":247,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3082:16:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_3a23091615a5de8c0a35ffd8857a37e2c4e0b72f3ef8a34d6caf65efcd562e2f","typeString":"literal_string \"contract nonce\""},"value":"contract nonce"},{"arguments":[{"arguments":[{"id":252,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3120:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}],"id":251,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3112:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":250,"name":"address","nodeType":"ElementaryTypeName","src":"3112:7:0","typeDescriptions":{}}},"id":253,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3112:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":248,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"3100:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":249,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"getNonce","nodeType":"MemberAccess","referencedDeclaration":17,"src":"3100:11:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_address_$returns$_t_uint64_$","typeString":"function (address) view external returns (uint64)"}},"id":254,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3100:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_3a23091615a5de8c0a35ffd8857a37e2c4e0b72f3ef8a34d6caf65efcd562e2f","typeString":"literal_string \"contract nonce\""},{"typeIdentifier":"t_uint64","typeString":"uint64"}],"expression":{"id":244,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3070:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":246,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":154,"src":"3070:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_uint256_$returns$__$","typeString":"function (string memory,uint256) pure"}},"id":255,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3070:57:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":256,"nodeType":"ExpressionStatement","src":"3070:57:0"},{"expression":{"arguments":[{"hexValue":"73656e6465722061646472","id":260,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3149:13:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_8125ca2decf812b25b65606ff16dad37cb198ff0433485a7926e50feafacfc35","typeString":"literal_string \"sender addr\""},"value":"sender addr"},{"arguments":[{"expression":{"id":263,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"3172:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":264,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"3172:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":262,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3164:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":261,"name":"address","nodeType":"ElementaryTypeName","src":"3164:7:0","typeDescriptions":{}}},"id":265,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3164:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_8125ca2decf812b25b65606ff16dad37cb198ff0433485a7926e50feafacfc35","typeString":"literal_string \"sender addr\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":257,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3137:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":259,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":171,"src":"3137:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":266,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3137:47:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":267,"nodeType":"ExpressionStatement","src":"3137:47:0"},{"expression":{"arguments":[{"hexValue":"73656e646572206e6f6e6365","id":271,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3206:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_db7deb43f2f9e0404016de53b7e64c4976b54149581f7534daae2551e8cf4e40","typeString":"literal_string \"sender nonce\""},"value":"sender nonce"},{"arguments":[{"arguments":[{"expression":{"id":276,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"3242:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":277,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"3242:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":275,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3234:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":274,"name":"address","nodeType":"ElementaryTypeName","src":"3234:7:0","typeDescriptions":{}}},"id":278,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3234:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":272,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"3222:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":273,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"getNonce","nodeType":"MemberAccess","referencedDeclaration":17,"src":"3222:11:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_address_$returns$_t_uint64_$","typeString":"function (address) view external returns (uint64)"}},"id":279,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3222:32:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_db7deb43f2f9e0404016de53b7e64c4976b54149581f7534daae2551e8cf4e40","typeString":"literal_string \"sender nonce\""},{"typeIdentifier":"t_uint64","typeString":"uint64"}],"expression":{"id":268,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3194:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":270,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":154,"src":"3194:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_uint256_$returns$__$","typeString":"function (string memory,uint256) pure"}},"id":280,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3194:61:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":281,"nodeType":"ExpressionStatement","src":"3194:61:0"},{"assignments":[283],"declarations":[{"constant":false,"id":283,"mutability":"mutable","name":"json","nameLocation":"3280:4:0","nodeType":"VariableDeclaration","scope":377,"src":"3266:18:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":282,"name":"string","nodeType":"ElementaryTypeName","src":"3266:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"id":285,"initialValue":{"hexValue":"7b22726f6f745f6b6579223a205b7b2261223a20312c202262223a20327d5d7d","id":284,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3287:34:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_e95522e99766888d0261f55bd1eae5e3f3e26eaf009a16e2433eafaf0a4ecdf2","typeString":"literal_string \"{\"root_key\": [{\"a\": 1, \"b\": 2}]}\""},"value":"{\"root_key\": [{\"a\": 1, \"b\": 2}]}"},"nodeType":"VariableDeclarationStatement","src":"3266:55:0"},{"assignments":[290],"declarations":[{"constant":false,"id":290,"mutability":"mutable","name":"keys","nameLocation":"3347:4:0","nodeType":"VariableDeclaration","scope":377,"src":"3331:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string[]"},"typeName":{"baseType":{"id":288,"name":"string","nodeType":"ElementaryTypeName","src":"3331:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"id":289,"nodeType":"ArrayTypeName","src":"3331:8:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_storage_$dyn_storage_ptr","typeString":"string[]"}},"visibility":"internal"}],"id":296,"initialValue":{"arguments":[{"id":293,"name":"json","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":283,"src":"3371:4:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"hexValue":"2e726f6f745f6b65795b305d","id":294,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3377:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_d82f67100edb80050915e1ec4b565c9a8319a22efb1075e1298b7bb60101d266","typeString":"literal_string \".root_key[0]\""},"value":".root_key[0]"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_stringliteral_d82f67100edb80050915e1ec4b565c9a8319a22efb1075e1298b7bb60101d266","typeString":"literal_string \".root_key[0]\""}],"expression":{"id":291,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"3354:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":292,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"parseJsonKeys","nodeType":"MemberAccess","referencedDeclaration":27,"src":"3354:16:0","typeDescriptions":{"typeIdentifier":"t_function_external_pure$_t_string_memory_ptr_$_t_string_memory_ptr_$returns$_t_array$_t_string_memory_ptr_$dyn_memory_ptr_$","typeString":"function (string memory,string memory) pure external returns (string memory[] memory)"}},"id":295,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3354:38:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string memory[] memory"}},"nodeType":"VariableDeclarationStatement","src":"3331:61:0"},{"expression":{"arguments":[{"hexValue":"6b657973","id":300,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3414:6:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_f29790a80c4ce5f42f59892f424f9c92856c6b656c3378e2cf305b260c6f4195","typeString":"literal_string \"keys\""},"value":"keys"},{"baseExpression":{"id":301,"name":"keys","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":290,"src":"3422:4:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string memory[] memory"}},"id":303,"indexExpression":{"hexValue":"30","id":302,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"3427:1:0","typeDescriptions":{"typeIdentifier":"t_rational_0_by_1","typeString":"int_const 0"},"value":"0"},"isConstant":false,"isLValue":true,"isPure":false,"lValueRequested":false,"nodeType":"IndexAccess","src":"3422:7:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"baseExpression":{"id":304,"name":"keys","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":290,"src":"3431:4:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string memory[] memory"}},"id":306,"indexExpression":{"hexValue":"31","id":305,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"3436:1:0","typeDescriptions":{"typeIdentifier":"t_rational_1_by_1","typeString":"int_const 1"},"value":"1"},"isConstant":false,"isLValue":true,"isPure":false,"lValueRequested":false,"nodeType":"IndexAccess","src":"3431:7:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_f29790a80c4ce5f42f59892f424f9c92856c6b656c3378e2cf305b260c6f4195","typeString":"literal_string \"keys\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}],"expression":{"id":297,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3402:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":299,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":191,"src":"3402:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_string_memory_ptr_$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory,string memory,string memory) pure"}},"id":307,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3402:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":308,"nodeType":"ExpressionStatement","src":"3402:37:0"},{"expression":{"arguments":[{"hexValue":"66726f6d206f726967696e616c","id":312,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3461:15:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_77928970c8757d110f3c23e003246f49e0de890480ba9717ba659b2f56f316b2","typeString":"literal_string \"from original\""},"value":"from original"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_77928970c8757d110f3c23e003246f49e0de890480ba9717ba659b2f56f316b2","typeString":"literal_string \"from original\""}],"expression":{"id":309,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3450:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":311,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":633,"src":"3450:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":313,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3450:27:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":314,"nodeType":"ExpressionStatement","src":"3450:27:0"},{"expression":{"arguments":[{"arguments":[{"arguments":[{"hexValue":"30783432","id":322,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"3517:4:0","typeDescriptions":{"typeIdentifier":"t_rational_66_by_1","typeString":"int_const 66"},"value":"0x42"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_66_by_1","typeString":"int_const 66"}],"id":321,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3509:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":320,"name":"uint160","nodeType":"ElementaryTypeName","src":"3509:7:0","typeDescriptions":{}}},"id":323,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3509:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":319,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3501:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":318,"name":"address","nodeType":"ElementaryTypeName","src":"3501:7:0","typeDescriptions":{}}},"id":324,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3501:22:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":315,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"3487:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":317,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"startPrank","nodeType":"MemberAccess","referencedDeclaration":32,"src":"3487:13:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_address_$returns$__$","typeString":"function (address) external"}},"id":325,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3487:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":326,"nodeType":"ExpressionStatement","src":"3487:37:0"},{"expression":{"arguments":[{"hexValue":"66726f6d207072616e6b2031","id":330,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3545:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_42b34abfe37a8b0add910cda7b4a379e6538fa7a1dcafce47a02bd38f6c88e2a","typeString":"literal_string \"from prank 1\""},"value":"from prank 1"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_42b34abfe37a8b0add910cda7b4a379e6538fa7a1dcafce47a02bd38f6c88e2a","typeString":"literal_string \"from prank 1\""}],"expression":{"id":327,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3534:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":329,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":633,"src":"3534:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":331,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3534:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":332,"nodeType":"ExpressionStatement","src":"3534:26:0"},{"expression":{"arguments":[{"hexValue":"706172656e742073636f7065206d73672e73656e646572","id":336,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3582:25:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_83ec9246154d8845de47aafc5c2865c9985d2efe84472c27283879f2fbf5cc94","typeString":"literal_string \"parent scope msg.sender\""},"value":"parent scope msg.sender"},{"arguments":[{"expression":{"id":339,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"3617:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":340,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"3617:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":338,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3609:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":337,"name":"address","nodeType":"ElementaryTypeName","src":"3609:7:0","typeDescriptions":{}}},"id":341,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3609:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_83ec9246154d8845de47aafc5c2865c9985d2efe84472c27283879f2fbf5cc94","typeString":"literal_string \"parent scope msg.sender\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":333,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3570:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":335,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":171,"src":"3570:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":342,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3570:59:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":343,"nodeType":"ExpressionStatement","src":"3570:59:0"},{"expression":{"arguments":[{"hexValue":"706172656e742073636f706520636f6e74726163742e61646472","id":347,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3651:28:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_97df66250e0b2b48f0ec8d0e01eb1b8ca012d95f1572895622aa1ea433e5570f","typeString":"literal_string \"parent scope contract.addr\""},"value":"parent scope contract.addr"},{"arguments":[{"id":350,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3689:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}],"id":349,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3681:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":348,"name":"address","nodeType":"ElementaryTypeName","src":"3681:7:0","typeDescriptions":{}}},"id":351,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3681:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_97df66250e0b2b48f0ec8d0e01eb1b8ca012d95f1572895622aa1ea433e5570f","typeString":"literal_string \"parent scope contract.addr\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":344,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3639:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":346,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":171,"src":"3639:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":352,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3639:56:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":353,"nodeType":"ExpressionStatement","src":"3639:56:0"},{"expression":{"arguments":[{"hexValue":"66726f6d207072616e6b2032","id":357,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3716:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_a38a34f8cad750a79aa097a92971f8f405b51ee9d53d25c5b14fc129ba3684bb","typeString":"literal_string \"from prank 2\""},"value":"from prank 2"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_a38a34f8cad750a79aa097a92971f8f405b51ee9d53d25c5b14fc129ba3684bb","typeString":"literal_string \"from prank 2\""}],"expression":{"id":354,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3705:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":356,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":633,"src":"3705:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":358,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3705:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":359,"nodeType":"ExpressionStatement","src":"3705:26:0"},{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":360,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"3741:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":362,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"stopPrank","nodeType":"MemberAccess","referencedDeclaration":35,"src":"3741:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$__$returns$__$","typeString":"function () external"}},"id":363,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3741:14:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":364,"nodeType":"ExpressionStatement","src":"3741:14:0"},{"expression":{"arguments":[{"hexValue":"66726f6d206f726967696e616c20616761696e","id":368,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3776:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_0c805c6579e20a9c4c8e11aeab23330910a9f2da629191dc119d1730e8ed6860","typeString":"literal_string \"from original again\""},"value":"from original again"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_0c805c6579e20a9c4c8e11aeab23330910a9f2da629191dc119d1730e8ed6860","typeString":"literal_string \"from original again\""}],"expression":{"id":365,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3765:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":367,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":633,"src":"3765:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":369,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3765:33:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":370,"nodeType":"ExpressionStatement","src":"3765:33:0"},{"expression":{"arguments":[{"hexValue":"646f6e6521","id":374,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3821:7:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_080382d5c9e9e7c5e3d1d33f5e7422740375955180fadff167d8130e0c35f3fc","typeString":"literal_string \"done!\""},"value":"done!"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_080382d5c9e9e7c5e3d1d33f5e7422740375955180fadff167d8130e0c35f3fc","typeString":"literal_string \"done!\""}],"expression":{"id":371,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3809:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":373,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"3809:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":375,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3809:20:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":376,"nodeType":"ExpressionStatement","src":"3809:20:0"}]},"documentation":{"id":216,"nodeType":"StructuredDocumentation","src":"2804:78:0","text":"@notice example function, runs through basic cheat-codes and console logs."},"functionSelector":"c0406226","implemented":true,"kind":"function","modifiers":[],"name":"run","nameLocation":"2896:3:0","parameters":{"id":217,"nodeType":"ParameterList","parameters":[],"src":"2899:2:0"},"returnParameters":{"id":218,"nodeType":"ParameterList","parameters":[],"src":"2909:0:0"},"scope":706,"stateMutability":"nonpayable","virtual":false,"visibility":"public"},{"id":609,"nodeType":"FunctionDefinition","src":"3903:1258:0","nodes":[],"body":{"id":608,"nodeType":"Block","src":"3934:1227:0","nodes":[],"statements":[{"expression":{"arguments":[{"hexValue":"6e6f6e6365207374617274","id":385,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3956:13:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_71efc69b9a13b6bc1e9a14d766ff01c79022262c6daa6532fb5dfb14f8511a20","typeString":"literal_string \"nonce start\""},"value":"nonce start"},{"arguments":[{"arguments":[{"arguments":[{"id":392,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3999:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}],"id":391,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3991:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":390,"name":"address","nodeType":"ElementaryTypeName","src":"3991:7:0","typeDescriptions":{}}},"id":393,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3991:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":388,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"3979:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":389,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"getNonce","nodeType":"MemberAccess","referencedDeclaration":17,"src":"3979:11:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_address_$returns$_t_uint64_$","typeString":"function (address) view external returns (uint64)"}},"id":394,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3979:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint64","typeString":"uint64"}],"id":387,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3971:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint256_$","typeString":"type(uint256)"},"typeName":{"id":386,"name":"uint256","nodeType":"ElementaryTypeName","src":"3971:7:0","typeDescriptions":{}}},"id":395,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3971:35:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_71efc69b9a13b6bc1e9a14d766ff01c79022262c6daa6532fb5dfb14f8511a20","typeString":"literal_string \"nonce start\""},{"typeIdentifier":"t_uint256","typeString":"uint256"}],"expression":{"id":382,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3944:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":384,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":154,"src":"3944:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_uint256_$returns$__$","typeString":"function (string memory,uint256) pure"}},"id":396,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3944:63:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":397,"nodeType":"ExpressionStatement","src":"3944:63:0"},{"expression":{"arguments":[{"hexValue":"74657374696e672073696e676c65","id":401,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4030:16:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_b75103528423218e7569082dad569ed0d2ce7c0ac770c0812b220e2d369fe474","typeString":"literal_string \"testing single\""},"value":"testing single"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_b75103528423218e7569082dad569ed0d2ce7c0ac770c0812b220e2d369fe474","typeString":"literal_string \"testing single\""}],"expression":{"id":398,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"4018:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":400,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"4018:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":402,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4018:29:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":403,"nodeType":"ExpressionStatement","src":"4018:29:0"},{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":404,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4057:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":406,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"broadcast","nodeType":"MemberAccess","referencedDeclaration":38,"src":"4057:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$__$returns$__$","typeString":"function () external"}},"id":407,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4057:14:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":408,"nodeType":"ExpressionStatement","src":"4057:14:0"},{"expression":{"arguments":[{"hexValue":"73696e676c655f63616c6c31","id":412,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4092:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_5e1cad6d7a968cfacf2731373e1248ffb11f4886bced66a02a6de1a67ac8f777","typeString":"literal_string \"single_call1\""},"value":"single_call1"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_5e1cad6d7a968cfacf2731373e1248ffb11f4886bced66a02a6de1a67ac8f777","typeString":"literal_string \"single_call1\""}],"expression":{"id":409,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4081:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":411,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"call1","nodeType":"MemberAccess","referencedDeclaration":648,"src":"4081:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":413,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4081:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":414,"nodeType":"ExpressionStatement","src":"4081:26:0"},{"expression":{"arguments":[{"hexValue":"73696e676c655f63616c6c32","id":418,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4128:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_b37ddaf5d00ad9e6371de3fb71b91eef731fae1e86b768666380f7d44e1ada25","typeString":"literal_string \"single_call2\""},"value":"single_call2"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_b37ddaf5d00ad9e6371de3fb71b91eef731fae1e86b768666380f7d44e1ada25","typeString":"literal_string \"single_call2\""}],"expression":{"id":415,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4117:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":417,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"call2","nodeType":"MemberAccess","referencedDeclaration":663,"src":"4117:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":419,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4117:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":420,"nodeType":"ExpressionStatement","src":"4117:26:0"},{"expression":{"arguments":[{"hexValue":"74657374696e672073746172742f73746f70","id":424,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4166:20:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_778e886e3a1c3c5096aca76228832105f3f9269f362effd0e8ce3737787cb784","typeString":"literal_string \"testing start/stop\""},"value":"testing start/stop"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_778e886e3a1c3c5096aca76228832105f3f9269f362effd0e8ce3737787cb784","typeString":"literal_string \"testing start/stop\""}],"expression":{"id":421,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"4154:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":423,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"4154:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":425,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4154:33:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":426,"nodeType":"ExpressionStatement","src":"4154:33:0"},{"expression":{"arguments":[{"arguments":[{"arguments":[{"hexValue":"3078633066666565","id":434,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4231:8:0","typeDescriptions":{"typeIdentifier":"t_rational_12648430_by_1","typeString":"int_const 12648430"},"value":"0xc0ffee"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_12648430_by_1","typeString":"int_const 12648430"}],"id":433,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4223:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":432,"name":"uint160","nodeType":"ElementaryTypeName","src":"4223:7:0","typeDescriptions":{}}},"id":435,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4223:17:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":431,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4215:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":430,"name":"address","nodeType":"ElementaryTypeName","src":"4215:7:0","typeDescriptions":{}}},"id":436,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4215:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":427,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4197:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":429,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"startBroadcast","nodeType":"MemberAccess","referencedDeclaration":48,"src":"4197:17:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_address_$returns$__$","typeString":"function (address) external"}},"id":437,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4197:45:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":438,"nodeType":"ExpressionStatement","src":"4197:45:0"},{"expression":{"arguments":[{"hexValue":"737461727473746f705f63616c6c31","id":442,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4263:17:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_2fc2682edf10ed478ee3b9a190f6b1c88bb492b300935ce44545a1613cf8f041","typeString":"literal_string \"startstop_call1\""},"value":"startstop_call1"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_2fc2682edf10ed478ee3b9a190f6b1c88bb492b300935ce44545a1613cf8f041","typeString":"literal_string \"startstop_call1\""}],"expression":{"id":439,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4252:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":441,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"call1","nodeType":"MemberAccess","referencedDeclaration":648,"src":"4252:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":443,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4252:29:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":444,"nodeType":"ExpressionStatement","src":"4252:29:0"},{"expression":{"arguments":[{"hexValue":"737461727473746f705f63616c6c32","id":448,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4302:17:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_1a6fd77f04b28bf45d6d0e2dd4c65c0bbfeba174f849e43bb67ebca1c019cda4","typeString":"literal_string \"startstop_call2\""},"value":"startstop_call2"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_1a6fd77f04b28bf45d6d0e2dd4c65c0bbfeba174f849e43bb67ebca1c019cda4","typeString":"literal_string \"startstop_call2\""}],"expression":{"id":445,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4291:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":447,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"call2","nodeType":"MemberAccess","referencedDeclaration":663,"src":"4291:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":449,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4291:29:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":450,"nodeType":"ExpressionStatement","src":"4291:29:0"},{"expression":{"arguments":[{"hexValue":"737461727473746f705f70757265","id":454,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4344:16:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_b6e9eb1efd186b1d92b54da45026aa97a178e6eaffdf9dbf9f666fc751fb0ff9","typeString":"literal_string \"startstop_pure\""},"value":"startstop_pure"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_b6e9eb1efd186b1d92b54da45026aa97a178e6eaffdf9dbf9f666fc751fb0ff9","typeString":"literal_string \"startstop_pure\""}],"expression":{"id":451,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4330:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":453,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"callPure","nodeType":"MemberAccess","referencedDeclaration":705,"src":"4330:13:0","typeDescriptions":{"typeIdentifier":"t_function_external_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure external"}},"id":455,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4330:31:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":456,"nodeType":"ExpressionStatement","src":"4330:31:0"},{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":457,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4371:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":459,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"stopBroadcast","nodeType":"MemberAccess","referencedDeclaration":54,"src":"4371:16:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$__$returns$__$","typeString":"function () external"}},"id":460,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4371:18:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":461,"nodeType":"ExpressionStatement","src":"4371:18:0"},{"expression":{"arguments":[{"hexValue":"737461727473746f705f63616c6c33","id":465,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4410:17:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_8eb502bfdc4adda22bd960aa2ae13ce4c0ed8cc3b3791ed65e321a38cdd36f72","typeString":"literal_string \"startstop_call3\""},"value":"startstop_call3"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_8eb502bfdc4adda22bd960aa2ae13ce4c0ed8cc3b3791ed65e321a38cdd36f72","typeString":"literal_string \"startstop_call3\""}],"expression":{"id":462,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4399:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":464,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"call1","nodeType":"MemberAccess","referencedDeclaration":648,"src":"4399:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":466,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4399:29:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":467,"nodeType":"ExpressionStatement","src":"4399:29:0"},{"expression":{"arguments":[{"hexValue":"74657374696e67206e6573746564","id":471,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4451:16:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_f92f19f7a5b5b9ce341188bf4e15925f184cdb5ac135c4846ced718f259dbde5","typeString":"literal_string \"testing nested\""},"value":"testing nested"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_f92f19f7a5b5b9ce341188bf4e15925f184cdb5ac135c4846ced718f259dbde5","typeString":"literal_string \"testing nested\""}],"expression":{"id":468,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"4439:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":470,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"4439:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":472,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4439:29:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":473,"nodeType":"ExpressionStatement","src":"4439:29:0"},{"expression":{"arguments":[{"arguments":[{"arguments":[{"hexValue":"307831323334","id":481,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4512:6:0","typeDescriptions":{"typeIdentifier":"t_rational_4660_by_1","typeString":"int_const 4660"},"value":"0x1234"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_4660_by_1","typeString":"int_const 4660"}],"id":480,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4504:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":479,"name":"uint160","nodeType":"ElementaryTypeName","src":"4504:7:0","typeDescriptions":{}}},"id":482,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4504:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":478,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4496:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":477,"name":"address","nodeType":"ElementaryTypeName","src":"4496:7:0","typeDescriptions":{}}},"id":483,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4496:24:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":474,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4478:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":476,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"startBroadcast","nodeType":"MemberAccess","referencedDeclaration":48,"src":"4478:17:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_address_$returns$__$","typeString":"function (address) external"}},"id":484,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4478:43:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":485,"nodeType":"ExpressionStatement","src":"4478:43:0"},{"expression":{"arguments":[{"hexValue":"6e6573746564","id":489,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4544:8:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_4d5b14044d78fbf0c9dd8b9c49e35f09ee5a6f5b1b3b8117b5d0e15c8dd2cb09","typeString":"literal_string \"nested\""},"value":"nested"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_4d5b14044d78fbf0c9dd8b9c49e35f09ee5a6f5b1b3b8117b5d0e15c8dd2cb09","typeString":"literal_string \"nested\""}],"expression":{"id":486,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4531:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":488,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"nested1","nodeType":"MemberAccess","referencedDeclaration":678,"src":"4531:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":490,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4531:22:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":491,"nodeType":"ExpressionStatement","src":"4531:22:0"},{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":492,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4563:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":494,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"stopBroadcast","nodeType":"MemberAccess","referencedDeclaration":54,"src":"4563:16:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$__$returns$__$","typeString":"function () external"}},"id":495,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4563:18:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":496,"nodeType":"ExpressionStatement","src":"4563:18:0"},{"expression":{"arguments":[{"hexValue":"636f6e7472616374206465706c6f796d656e74","id":500,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4604:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_aaf9be86adf9b6872d87eed3526f7c55f3c5d61f4e4dd6d55ef2fcbb8ad0bd57","typeString":"literal_string \"contract deployment\""},"value":"contract deployment"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_aaf9be86adf9b6872d87eed3526f7c55f3c5d61f4e4dd6d55ef2fcbb8ad0bd57","typeString":"literal_string \"contract deployment\""}],"expression":{"id":497,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"4592:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":499,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"4592:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":501,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4592:34:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":502,"nodeType":"ExpressionStatement","src":"4592:34:0"},{"expression":{"arguments":[{"arguments":[{"arguments":[{"hexValue":"3078313233343536","id":510,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4665:8:0","typeDescriptions":{"typeIdentifier":"t_rational_1193046_by_1","typeString":"int_const 1193046"},"value":"0x123456"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_1193046_by_1","typeString":"int_const 1193046"}],"id":509,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4657:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":508,"name":"uint160","nodeType":"ElementaryTypeName","src":"4657:7:0","typeDescriptions":{}}},"id":511,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4657:17:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":507,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4649:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":506,"name":"address","nodeType":"ElementaryTypeName","src":"4649:7:0","typeDescriptions":{}}},"id":512,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4649:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":503,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4636:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":505,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"broadcast","nodeType":"MemberAccess","referencedDeclaration":43,"src":"4636:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_address_$returns$__$","typeString":"function (address) external"}},"id":513,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4636:40:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":514,"nodeType":"ExpressionStatement","src":"4636:40:0"},{"assignments":[517],"declarations":[{"constant":false,"id":517,"mutability":"mutable","name":"x","nameLocation":"4693:1:0","nodeType":"VariableDeclaration","scope":608,"src":"4686:8:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"},"typeName":{"id":516,"nodeType":"UserDefinedTypeName","pathNode":{"id":515,"name":"FooBar","nodeType":"IdentifierPath","referencedDeclaration":719,"src":"4686:6:0"},"referencedDeclaration":719,"src":"4686:6:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"visibility":"internal"}],"id":523,"initialValue":{"arguments":[{"hexValue":"31323334","id":521,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4708:4:0","typeDescriptions":{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"},"value":"1234"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"}],"id":520,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"NewExpression","src":"4697:10:0","typeDescriptions":{"typeIdentifier":"t_function_creation_nonpayable$_t_uint256_$returns$_t_contract$_FooBar_$719_$","typeString":"function (uint256) returns (contract FooBar)"},"typeName":{"id":519,"nodeType":"UserDefinedTypeName","pathNode":{"id":518,"name":"FooBar","nodeType":"IdentifierPath","referencedDeclaration":719,"src":"4701:6:0"},"referencedDeclaration":719,"src":"4701:6:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}}},"id":522,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4697:16:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"nodeType":"VariableDeclarationStatement","src":"4686:27:0"},{"expression":{"arguments":[{"commonType":{"typeIdentifier":"t_uint256","typeString":"uint256"},"id":529,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"leftExpression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":525,"name":"x","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":517,"src":"4731:1:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"id":526,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"foo","nodeType":"MemberAccess","referencedDeclaration":708,"src":"4731:5:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$__$returns$_t_uint256_$","typeString":"function () view external returns (uint256)"}},"id":527,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4731:7:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"nodeType":"BinaryOperation","operator":"==","rightExpression":{"hexValue":"31323334","id":528,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4742:4:0","typeDescriptions":{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"},"value":"1234"},"src":"4731:15:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bool","typeString":"bool"}],"id":524,"name":"require","nodeType":"Identifier","overloadedDeclarations":[-18,-18],"referencedDeclaration":-18,"src":"4723:7:0","typeDescriptions":{"typeIdentifier":"t_function_require_pure$_t_bool_$returns$__$","typeString":"function (bool) pure"}},"id":530,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4723:24:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":531,"nodeType":"ExpressionStatement","src":"4723:24:0"},{"expression":{"arguments":[{"hexValue":"6372656174652032","id":535,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4770:10:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_4411d6d4ffcd00382a95255a63761e69de9810e1236042a5c64948a7b6c04daa","typeString":"literal_string \"create 2\""},"value":"create 2"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_4411d6d4ffcd00382a95255a63761e69de9810e1236042a5c64948a7b6c04daa","typeString":"literal_string \"create 2\""}],"expression":{"id":532,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"4758:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":534,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"4758:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":536,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4758:23:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":537,"nodeType":"ExpressionStatement","src":"4758:23:0"},{"expression":{"arguments":[{"arguments":[{"arguments":[{"hexValue":"307863616665","id":545,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4820:6:0","typeDescriptions":{"typeIdentifier":"t_rational_51966_by_1","typeString":"int_const 51966"},"value":"0xcafe"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_51966_by_1","typeString":"int_const 51966"}],"id":544,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4812:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":543,"name":"uint160","nodeType":"ElementaryTypeName","src":"4812:7:0","typeDescriptions":{}}},"id":546,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4812:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":542,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4804:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":541,"name":"address","nodeType":"ElementaryTypeName","src":"4804:7:0","typeDescriptions":{}}},"id":547,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4804:24:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":538,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4791:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":540,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"broadcast","nodeType":"MemberAccess","referencedDeclaration":43,"src":"4791:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_address_$returns$__$","typeString":"function (address) external"}},"id":548,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4791:38:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":549,"nodeType":"ExpressionStatement","src":"4791:38:0"},{"assignments":[552],"declarations":[{"constant":false,"id":552,"mutability":"mutable","name":"y","nameLocation":"4846:1:0","nodeType":"VariableDeclaration","scope":608,"src":"4839:8:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"},"typeName":{"id":551,"nodeType":"UserDefinedTypeName","pathNode":{"id":550,"name":"FooBar","nodeType":"IdentifierPath","referencedDeclaration":719,"src":"4839:6:0"},"referencedDeclaration":719,"src":"4839:6:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"visibility":"internal"}],"id":566,"initialValue":{"arguments":[{"hexValue":"31323334","id":564,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4889:4:0","typeDescriptions":{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"},"value":"1234"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"}],"id":555,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"NewExpression","src":"4850:10:0","typeDescriptions":{"typeIdentifier":"t_function_creation_nonpayable$_t_uint256_$returns$_t_contract$_FooBar_$719_$","typeString":"function (uint256) returns (contract FooBar)"},"typeName":{"id":554,"nodeType":"UserDefinedTypeName","pathNode":{"id":553,"name":"FooBar","nodeType":"IdentifierPath","referencedDeclaration":719,"src":"4854:6:0"},"referencedDeclaration":719,"src":"4854:6:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}}},"id":563,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"names":["salt"],"nodeType":"FunctionCallOptions","options":[{"arguments":[{"arguments":[{"hexValue":"3432","id":560,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4883:2:0","typeDescriptions":{"typeIdentifier":"t_rational_42_by_1","typeString":"int_const 42"},"value":"42"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_42_by_1","typeString":"int_const 42"}],"id":559,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4875:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint256_$","typeString":"type(uint256)"},"typeName":{"id":558,"name":"uint256","nodeType":"ElementaryTypeName","src":"4875:7:0","typeDescriptions":{}}},"id":561,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4875:11:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint256","typeString":"uint256"}],"id":557,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4867:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_bytes32_$","typeString":"type(bytes32)"},"typeName":{"id":556,"name":"bytes32","nodeType":"ElementaryTypeName","src":"4867:7:0","typeDescriptions":{}}},"id":562,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4867:20:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes32","typeString":"bytes32"}}],"src":"4850:38:0","typeDescriptions":{"typeIdentifier":"t_function_creation_nonpayable$_t_uint256_$returns$_t_contract$_FooBar_$719_$salt","typeString":"function (uint256) returns (contract FooBar)"}},"id":565,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4850:44:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"nodeType":"VariableDeclarationStatement","src":"4839:55:0"},{"expression":{"arguments":[{"commonType":{"typeIdentifier":"t_uint256","typeString":"uint256"},"id":572,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"leftExpression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":568,"name":"y","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":552,"src":"4912:1:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"id":569,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"foo","nodeType":"MemberAccess","referencedDeclaration":708,"src":"4912:5:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$__$returns$_t_uint256_$","typeString":"function () view external returns (uint256)"}},"id":570,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4912:7:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"nodeType":"BinaryOperation","operator":"==","rightExpression":{"hexValue":"31323334","id":571,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4923:4:0","typeDescriptions":{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"},"value":"1234"},"src":"4912:15:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bool","typeString":"bool"}],"id":567,"name":"require","nodeType":"Identifier","overloadedDeclarations":[-18,-18],"referencedDeclaration":-18,"src":"4904:7:0","typeDescriptions":{"typeIdentifier":"t_function_require_pure$_t_bool_$returns$__$","typeString":"function (bool) pure"}},"id":573,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4904:24:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":574,"nodeType":"ExpressionStatement","src":"4904:24:0"},{"expression":{"arguments":[{"hexValue":"646f6e6521","id":578,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4950:7:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_080382d5c9e9e7c5e3d1d33f5e7422740375955180fadff167d8130e0c35f3fc","typeString":"literal_string \"done!\""},"value":"done!"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_080382d5c9e9e7c5e3d1d33f5e7422740375955180fadff167d8130e0c35f3fc","typeString":"literal_string \"done!\""}],"expression":{"id":575,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"4938:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":577,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"4938:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":579,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4938:20:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":580,"nodeType":"ExpressionStatement","src":"4938:20:0"},{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":581,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"5042:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":583,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"broadcast","nodeType":"MemberAccess","referencedDeclaration":38,"src":"5042:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$__$returns$__$","typeString":"function () external"}},"id":584,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5042:14:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":585,"nodeType":"ExpressionStatement","src":"5042:14:0"},{"expression":{"arguments":[{"hexValue":"31323334","id":589,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"5077:4:0","typeDescriptions":{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"},"value":"1234"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"}],"id":588,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"NewExpression","src":"5066:10:0","typeDescriptions":{"typeIdentifier":"t_function_creation_nonpayable$_t_uint256_$returns$_t_contract$_FooBar_$719_$","typeString":"function (uint256) returns (contract FooBar)"},"typeName":{"id":587,"nodeType":"UserDefinedTypeName","pathNode":{"id":586,"name":"FooBar","nodeType":"IdentifierPath","referencedDeclaration":719,"src":"5070:6:0"},"referencedDeclaration":719,"src":"5070:6:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}}},"id":590,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5066:16:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"id":591,"nodeType":"ExpressionStatement","src":"5066:16:0"},{"expression":{"arguments":[{"hexValue":"6e6f6e636520656e64","id":595,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"5105:11:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_fa629e6661ad2a2bdb09cf9a3a276ce0d722482ae5c2887650751be0938847e8","typeString":"literal_string \"nonce end\""},"value":"nonce end"},{"arguments":[{"arguments":[{"arguments":[{"id":602,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"5146:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}],"id":601,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"5138:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":600,"name":"address","nodeType":"ElementaryTypeName","src":"5138:7:0","typeDescriptions":{}}},"id":603,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5138:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":598,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"5126:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":599,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"getNonce","nodeType":"MemberAccess","referencedDeclaration":17,"src":"5126:11:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_address_$returns$_t_uint64_$","typeString":"function (address) view external returns (uint64)"}},"id":604,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5126:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint64","typeString":"uint64"}],"id":597,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"5118:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint256_$","typeString":"type(uint256)"},"typeName":{"id":596,"name":"uint256","nodeType":"ElementaryTypeName","src":"5118:7:0","typeDescriptions":{}}},"id":605,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5118:35:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_fa629e6661ad2a2bdb09cf9a3a276ce0d722482ae5c2887650751be0938847e8","typeString":"literal_string \"nonce end\""},{"typeIdentifier":"t_uint256","typeString":"uint256"}],"expression":{"id":592,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5093:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":594,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":154,"src":"5093:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_uint256_$returns$__$","typeString":"function (string memory,uint256) pure"}},"id":606,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5093:61:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":607,"nodeType":"ExpressionStatement","src":"5093:61:0"}]},"documentation":{"id":379,"nodeType":"StructuredDocumentation","src":"3842:56:0","text":"@notice example function, to test vm.broadcast with."},"functionSelector":"bef03abc","implemented":true,"kind":"function","modifiers":[],"name":"runBroadcast","nameLocation":"3912:12:0","parameters":{"id":380,"nodeType":"ParameterList","parameters":[],"src":"3924:2:0"},"returnParameters":{"id":381,"nodeType":"ParameterList","parameters":[],"src":"3934:0:0"},"scope":706,"stateMutability":"nonpayable","virtual":false,"visibility":"public"},{"id":633,"nodeType":"FunctionDefinition","src":"5256:143:0","nodes":[],"body":{"id":632,"nodeType":"Block","src":"5305:94:0","nodes":[],"statements":[{"expression":{"arguments":[{"id":618,"name":"_v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":612,"src":"5327:2:0","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}],"expression":{"id":615,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5315:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":617,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"5315:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":619,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5315:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":620,"nodeType":"ExpressionStatement","src":"5315:15:0"},{"expression":{"arguments":[{"hexValue":"68656c6c6f206d73672e73656e646572","id":624,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"5352:18:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_b3cc13bc51228b2c4c4334d82a4772908254dc0e1c512893dd16208ef13efb8e","typeString":"literal_string \"hello msg.sender\""},"value":"hello msg.sender"},{"arguments":[{"expression":{"id":627,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"5380:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":628,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"5380:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":626,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"5372:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":625,"name":"address","nodeType":"ElementaryTypeName","src":"5372:7:0","typeDescriptions":{}}},"id":629,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5372:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_b3cc13bc51228b2c4c4334d82a4772908254dc0e1c512893dd16208ef13efb8e","typeString":"literal_string \"hello msg.sender\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":621,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5340:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":623,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":171,"src":"5340:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":630,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5340:52:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":631,"nodeType":"ExpressionStatement","src":"5340:52:0"}]},"documentation":{"id":610,"nodeType":"StructuredDocumentation","src":"5167:84:0","text":"@notice example external function, to force a CALL, and test vm.startPrank with."},"functionSelector":"a777d0dc","implemented":true,"kind":"function","modifiers":[],"name":"hello","nameLocation":"5265:5:0","parameters":{"id":613,"nodeType":"ParameterList","parameters":[{"constant":false,"id":612,"mutability":"mutable","name":"_v","nameLocation":"5287:2:0","nodeType":"VariableDeclaration","scope":633,"src":"5271:18:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":611,"name":"string","nodeType":"ElementaryTypeName","src":"5271:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"5270:20:0"},"returnParameters":{"id":614,"nodeType":"ParameterList","parameters":[],"src":"5305:0:0"},"scope":706,"stateMutability":"view","virtual":false,"visibility":"external"},{"id":648,"nodeType":"FunctionDefinition","src":"5405:95:0","nodes":[],"body":{"id":647,"nodeType":"Block","src":"5449:51:0","nodes":[],"statements":[{"expression":{"id":639,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"UnaryOperation","operator":"++","prefix":false,"src":"5459:9:0","subExpression":{"id":638,"name":"counter","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":215,"src":"5459:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"id":640,"nodeType":"ExpressionStatement","src":"5459:9:0"},{"expression":{"arguments":[{"id":644,"name":"_v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":635,"src":"5490:2:0","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}],"expression":{"id":641,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5478:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":643,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"5478:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":645,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5478:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":646,"nodeType":"ExpressionStatement","src":"5478:15:0"}]},"functionSelector":"7e79255d","implemented":true,"kind":"function","modifiers":[],"name":"call1","nameLocation":"5414:5:0","parameters":{"id":636,"nodeType":"ParameterList","parameters":[{"constant":false,"id":635,"mutability":"mutable","name":"_v","nameLocation":"5436:2:0","nodeType":"VariableDeclaration","scope":648,"src":"5420:18:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":634,"name":"string","nodeType":"ElementaryTypeName","src":"5420:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"5419:20:0"},"returnParameters":{"id":637,"nodeType":"ParameterList","parameters":[],"src":"5449:0:0"},"scope":706,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":663,"nodeType":"FunctionDefinition","src":"5506:95:0","nodes":[],"body":{"id":662,"nodeType":"Block","src":"5550:51:0","nodes":[],"statements":[{"expression":{"id":654,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"UnaryOperation","operator":"++","prefix":false,"src":"5560:9:0","subExpression":{"id":653,"name":"counter","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":215,"src":"5560:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"id":655,"nodeType":"ExpressionStatement","src":"5560:9:0"},{"expression":{"arguments":[{"id":659,"name":"_v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":650,"src":"5591:2:0","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}],"expression":{"id":656,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5579:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":658,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"5579:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":660,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5579:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":661,"nodeType":"ExpressionStatement","src":"5579:15:0"}]},"functionSelector":"8d3ef7ca","implemented":true,"kind":"function","modifiers":[],"name":"call2","nameLocation":"5515:5:0","parameters":{"id":651,"nodeType":"ParameterList","parameters":[{"constant":false,"id":650,"mutability":"mutable","name":"_v","nameLocation":"5537:2:0","nodeType":"VariableDeclaration","scope":663,"src":"5521:18:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":649,"name":"string","nodeType":"ElementaryTypeName","src":"5521:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"5520:20:0"},"returnParameters":{"id":652,"nodeType":"ParameterList","parameters":[],"src":"5550:0:0"},"scope":706,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":678,"nodeType":"FunctionDefinition","src":"5607:98:0","nodes":[],"body":{"id":677,"nodeType":"Block","src":"5653:52:0","nodes":[],"statements":[{"expression":{"id":669,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"UnaryOperation","operator":"++","prefix":false,"src":"5663:9:0","subExpression":{"id":668,"name":"counter","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":215,"src":"5663:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"id":670,"nodeType":"ExpressionStatement","src":"5663:9:0"},{"expression":{"arguments":[{"id":674,"name":"_v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":665,"src":"5695:2:0","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}],"expression":{"id":671,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"5682:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":673,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"nested2","nodeType":"MemberAccess","referencedDeclaration":693,"src":"5682:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":675,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5682:16:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":676,"nodeType":"ExpressionStatement","src":"5682:16:0"}]},"functionSelector":"a76ccdfa","implemented":true,"kind":"function","modifiers":[],"name":"nested1","nameLocation":"5616:7:0","parameters":{"id":666,"nodeType":"ParameterList","parameters":[{"constant":false,"id":665,"mutability":"mutable","name":"_v","nameLocation":"5640:2:0","nodeType":"VariableDeclaration","scope":678,"src":"5624:18:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":664,"name":"string","nodeType":"ElementaryTypeName","src":"5624:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"5623:20:0"},"returnParameters":{"id":667,"nodeType":"ParameterList","parameters":[],"src":"5653:0:0"},"scope":706,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":693,"nodeType":"FunctionDefinition","src":"5711:97:0","nodes":[],"body":{"id":692,"nodeType":"Block","src":"5757:51:0","nodes":[],"statements":[{"expression":{"id":684,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"UnaryOperation","operator":"++","prefix":false,"src":"5767:9:0","subExpression":{"id":683,"name":"counter","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":215,"src":"5767:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"id":685,"nodeType":"ExpressionStatement","src":"5767:9:0"},{"expression":{"arguments":[{"id":689,"name":"_v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":680,"src":"5798:2:0","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}],"expression":{"id":686,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5786:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":688,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"5786:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":690,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5786:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":691,"nodeType":"ExpressionStatement","src":"5786:15:0"}]},"functionSelector":"dbf1282f","implemented":true,"kind":"function","modifiers":[],"name":"nested2","nameLocation":"5720:7:0","parameters":{"id":681,"nodeType":"ParameterList","parameters":[{"constant":false,"id":680,"mutability":"mutable","name":"_v","nameLocation":"5744:2:0","nodeType":"VariableDeclaration","scope":693,"src":"5728:18:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":679,"name":"string","nodeType":"ElementaryTypeName","src":"5728:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"5727:20:0"},"returnParameters":{"id":682,"nodeType":"ParameterList","parameters":[],"src":"5757:0:0"},"scope":706,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":705,"nodeType":"FunctionDefinition","src":"5814:84:0","nodes":[],"body":{"id":704,"nodeType":"Block","src":"5866:32:0","nodes":[],"statements":[{"expression":{"arguments":[{"id":701,"name":"_v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":695,"src":"5888:2:0","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}],"expression":{"id":698,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5876:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":700,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"5876:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":702,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5876:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":703,"nodeType":"ExpressionStatement","src":"5876:15:0"}]},"functionSelector":"7f8b915c","implemented":true,"kind":"function","modifiers":[],"name":"callPure","nameLocation":"5823:8:0","parameters":{"id":696,"nodeType":"ParameterList","parameters":[{"constant":false,"id":695,"mutability":"mutable","name":"_v","nameLocation":"5848:2:0","nodeType":"VariableDeclaration","scope":705,"src":"5832:18:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":694,"name":"string","nodeType":"ElementaryTypeName","src":"5832:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"5831:20:0"},"returnParameters":{"id":697,"nodeType":"ParameterList","parameters":[],"src":"5866:0:0"},"scope":706,"stateMutability":"pure","virtual":false,"visibility":"external"}],"abstract":false,"baseContracts":[],"canonicalName":"ScriptExample","contractDependencies":[719],"contractKind":"contract","documentation":{"id":193,"nodeType":"StructuredDocumentation","src":"2415:126:0","text":"@title ScriptExample\n @notice ScriptExample is an example script. The Go forge script code tests that it can run this."},"fullyImplemented":true,"linearizedBaseContracts":[706],"name":"ScriptExample","nameLocation":"2550:13:0","scope":720,"usedErrors":[]},{"id":719,"nodeType":"ContractDefinition","src":"5902:96:0","nodes":[{"id":708,"nodeType":"VariableDeclaration","src":"5924:18:0","nodes":[],"constant":false,"functionSelector":"c2985578","mutability":"mutable","name":"foo","nameLocation":"5939:3:0","scope":719,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":707,"name":"uint256","nodeType":"ElementaryTypeName","src":"5924:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"public"},{"id":718,"nodeType":"FunctionDefinition","src":"5949:47:0","nodes":[],"body":{"id":717,"nodeType":"Block","src":"5972:24:0","nodes":[],"statements":[{"expression":{"id":715,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"leftHandSide":{"id":713,"name":"foo","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":708,"src":"5982:3:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"nodeType":"Assignment","operator":"=","rightHandSide":{"id":714,"name":"v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":710,"src":"5988:1:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"src":"5982:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"id":716,"nodeType":"ExpressionStatement","src":"5982:7:0"}]},"implemented":true,"kind":"constructor","modifiers":[],"name":"","nameLocation":"-1:-1:-1","parameters":{"id":711,"nodeType":"ParameterList","parameters":[{"constant":false,"id":710,"mutability":"mutable","name":"v","nameLocation":"5969:1:0","nodeType":"VariableDeclaration","scope":718,"src":"5961:9:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":709,"name":"uint256","nodeType":"ElementaryTypeName","src":"5961:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"}],"src":"5960:11:0"},"returnParameters":{"id":712,"nodeType":"ParameterList","parameters":[],"src":"5972:0:0"},"scope":719,"stateMutability":"nonpayable","virtual":false,"visibility":"public"}],"abstract":false,"baseContracts":[],"canonicalName":"FooBar","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"linearizedBaseContracts":[719],"name":"FooBar","nameLocation":"5911:6:0","scope":720,"usedErrors":[]}],"license":"MIT"},"id":0} \ No newline at end of file diff --git a/op-chain-ops/script/testdata/test-artifacts/ScriptExample.s.sol/Vm.json b/op-chain-ops/script/testdata/test-artifacts/ScriptExample.s.sol/Vm.json index c60108b595af1..34175684c5aaa 100644 --- a/op-chain-ops/script/testdata/test-artifacts/ScriptExample.s.sol/Vm.json +++ b/op-chain-ops/script/testdata/test-artifacts/ScriptExample.s.sol/Vm.json @@ -1 +1 @@ -{"abi":[{"type":"function","name":"envOr","inputs":[{"name":"name","type":"string","internalType":"string"},{"name":"defaultValue","type":"bool","internalType":"bool"}],"outputs":[{"name":"value","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"getNonce","inputs":[{"name":"account","type":"address","internalType":"address"}],"outputs":[{"name":"nonce","type":"uint64","internalType":"uint64"}],"stateMutability":"view"},{"type":"function","name":"parseJsonKeys","inputs":[{"name":"json","type":"string","internalType":"string"},{"name":"key","type":"string","internalType":"string"}],"outputs":[{"name":"keys","type":"string[]","internalType":"string[]"}],"stateMutability":"pure"},{"type":"function","name":"startPrank","inputs":[{"name":"msgSender","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"stopPrank","inputs":[],"outputs":[],"stateMutability":"nonpayable"}],"bytecode":{"object":"0x","sourceMap":"","linkReferences":{}},"deployedBytecode":{"object":"0x","sourceMap":"","linkReferences":{}},"methodIdentifiers":{"envOr(string,bool)":"4777f3cf","getNonce(address)":"2d0335ab","parseJsonKeys(string,string)":"213e4198","startPrank(address)":"06447d56","stopPrank()":"90c5013b"},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"defaultValue\",\"type\":\"bool\"}],\"name\":\"envOr\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"value\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getNonce\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"json\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"}],\"name\":\"parseJsonKeys\",\"outputs\":[{\"internalType\":\"string[]\",\"name\":\"keys\",\"type\":\"string[]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"msgSender\",\"type\":\"address\"}],\"name\":\"startPrank\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stopPrank\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"scripts/ScriptExample.s.sol\":\"Vm\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[]},\"sources\":{\"scripts/ScriptExample.s.sol\":{\"keccak256\":\"0x531a2ad96c1a2c0bbfa9ab0e1195cd32551b0c10e16e7d256ce5e4c0289a8089\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://24dc6c71502c01f43fb5e113786e377c3b4cafabd5c506067d229fcdd7b037fa\",\"dweb:/ipfs/QmZ9AuxNx9Ygescfg5M4p6Abc2CCwCMZpX5xU32Fz1r4kY\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.15+commit.e14f2714"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"bool","name":"defaultValue","type":"bool"}],"stateMutability":"view","type":"function","name":"envOr","outputs":[{"internalType":"bool","name":"value","type":"bool"}]},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"stateMutability":"view","type":"function","name":"getNonce","outputs":[{"internalType":"uint64","name":"nonce","type":"uint64"}]},{"inputs":[{"internalType":"string","name":"json","type":"string"},{"internalType":"string","name":"key","type":"string"}],"stateMutability":"pure","type":"function","name":"parseJsonKeys","outputs":[{"internalType":"string[]","name":"keys","type":"string[]"}]},{"inputs":[{"internalType":"address","name":"msgSender","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"startPrank"},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"stopPrank"}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"remappings":[],"optimizer":{"enabled":true,"runs":999999},"metadata":{"bytecodeHash":"none"},"compilationTarget":{"scripts/ScriptExample.s.sol":"Vm"},"evmVersion":"london","libraries":{}},"sources":{"scripts/ScriptExample.s.sol":{"keccak256":"0x531a2ad96c1a2c0bbfa9ab0e1195cd32551b0c10e16e7d256ce5e4c0289a8089","urls":["bzz-raw://24dc6c71502c01f43fb5e113786e377c3b4cafabd5c506067d229fcdd7b037fa","dweb:/ipfs/QmZ9AuxNx9Ygescfg5M4p6Abc2CCwCMZpX5xU32Fz1r4kY"],"license":"MIT"}},"version":1},"storageLayout":{"storage":[],"types":{}},"userdoc":{"version":1,"kind":"user"},"devdoc":{"version":1,"kind":"dev"},"ast":{"absolutePath":"scripts/ScriptExample.s.sol","id":383,"exportedSymbols":{"ScriptExample":[382],"Vm":[36],"console":[173]},"nodeType":"SourceUnit","src":"32:3736:0","nodes":[{"id":1,"nodeType":"PragmaDirective","src":"32:23:0","nodes":[],"literals":["solidity","0.8",".15"]},{"id":36,"nodeType":"ContractDefinition","src":"120:393:0","nodes":[{"id":10,"nodeType":"FunctionDefinition","src":"139:91:0","nodes":[],"functionSelector":"4777f3cf","implemented":false,"kind":"function","modifiers":[],"name":"envOr","nameLocation":"148:5:0","parameters":{"id":6,"nodeType":"ParameterList","parameters":[{"constant":false,"id":3,"mutability":"mutable","name":"name","nameLocation":"170:4:0","nodeType":"VariableDeclaration","scope":10,"src":"154:20:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":2,"name":"string","nodeType":"ElementaryTypeName","src":"154:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":5,"mutability":"mutable","name":"defaultValue","nameLocation":"181:12:0","nodeType":"VariableDeclaration","scope":10,"src":"176:17:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":4,"name":"bool","nodeType":"ElementaryTypeName","src":"176:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"src":"153:41:0"},"returnParameters":{"id":9,"nodeType":"ParameterList","parameters":[{"constant":false,"id":8,"mutability":"mutable","name":"value","nameLocation":"223:5:0","nodeType":"VariableDeclaration","scope":10,"src":"218:10:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":7,"name":"bool","nodeType":"ElementaryTypeName","src":"218:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"src":"217:12:0"},"scope":36,"stateMutability":"view","virtual":false,"visibility":"external"},{"id":17,"nodeType":"FunctionDefinition","src":"235:72:0","nodes":[],"functionSelector":"2d0335ab","implemented":false,"kind":"function","modifiers":[],"name":"getNonce","nameLocation":"244:8:0","parameters":{"id":13,"nodeType":"ParameterList","parameters":[{"constant":false,"id":12,"mutability":"mutable","name":"account","nameLocation":"261:7:0","nodeType":"VariableDeclaration","scope":17,"src":"253:15:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":11,"name":"address","nodeType":"ElementaryTypeName","src":"253:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"252:17:0"},"returnParameters":{"id":16,"nodeType":"ParameterList","parameters":[{"constant":false,"id":15,"mutability":"mutable","name":"nonce","nameLocation":"300:5:0","nodeType":"VariableDeclaration","scope":17,"src":"293:12:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"},"typeName":{"id":14,"name":"uint64","nodeType":"ElementaryTypeName","src":"293:6:0","typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}},"visibility":"internal"}],"src":"292:14:0"},"scope":36,"stateMutability":"view","virtual":false,"visibility":"external"},{"id":27,"nodeType":"FunctionDefinition","src":"312:111:0","nodes":[],"functionSelector":"213e4198","implemented":false,"kind":"function","modifiers":[],"name":"parseJsonKeys","nameLocation":"321:13:0","parameters":{"id":22,"nodeType":"ParameterList","parameters":[{"constant":false,"id":19,"mutability":"mutable","name":"json","nameLocation":"351:4:0","nodeType":"VariableDeclaration","scope":27,"src":"335:20:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":18,"name":"string","nodeType":"ElementaryTypeName","src":"335:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":21,"mutability":"mutable","name":"key","nameLocation":"373:3:0","nodeType":"VariableDeclaration","scope":27,"src":"357:19:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":20,"name":"string","nodeType":"ElementaryTypeName","src":"357:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"334:43:0"},"returnParameters":{"id":26,"nodeType":"ParameterList","parameters":[{"constant":false,"id":25,"mutability":"mutable","name":"keys","nameLocation":"417:4:0","nodeType":"VariableDeclaration","scope":27,"src":"401:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string[]"},"typeName":{"baseType":{"id":23,"name":"string","nodeType":"ElementaryTypeName","src":"401:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"id":24,"nodeType":"ArrayTypeName","src":"401:8:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_storage_$dyn_storage_ptr","typeString":"string[]"}},"visibility":"internal"}],"src":"400:22:0"},"scope":36,"stateMutability":"pure","virtual":false,"visibility":"external"},{"id":32,"nodeType":"FunctionDefinition","src":"428:48:0","nodes":[],"functionSelector":"06447d56","implemented":false,"kind":"function","modifiers":[],"name":"startPrank","nameLocation":"437:10:0","parameters":{"id":30,"nodeType":"ParameterList","parameters":[{"constant":false,"id":29,"mutability":"mutable","name":"msgSender","nameLocation":"456:9:0","nodeType":"VariableDeclaration","scope":32,"src":"448:17:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":28,"name":"address","nodeType":"ElementaryTypeName","src":"448:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"447:19:0"},"returnParameters":{"id":31,"nodeType":"ParameterList","parameters":[],"src":"475:0:0"},"scope":36,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":35,"nodeType":"FunctionDefinition","src":"481:30:0","nodes":[],"functionSelector":"90c5013b","implemented":false,"kind":"function","modifiers":[],"name":"stopPrank","nameLocation":"490:9:0","parameters":{"id":33,"nodeType":"ParameterList","parameters":[],"src":"499:2:0"},"returnParameters":{"id":34,"nodeType":"ParameterList","parameters":[],"src":"510:0:0"},"scope":36,"stateMutability":"nonpayable","virtual":false,"visibility":"external"}],"abstract":false,"baseContracts":[],"canonicalName":"Vm","contractDependencies":[],"contractKind":"interface","fullyImplemented":false,"linearizedBaseContracts":[36],"name":"Vm","nameLocation":"130:2:0","scope":383,"usedErrors":[]},{"id":173,"nodeType":"ContractDefinition","src":"568:1622:0","nodes":[{"id":42,"nodeType":"VariableDeclaration","src":"590:86:0","nodes":[],"constant":true,"mutability":"constant","name":"CONSOLE_ADDRESS","nameLocation":"607:15:0","scope":173,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":37,"name":"address","nodeType":"ElementaryTypeName","src":"590:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"value":{"arguments":[{"hexValue":"307830303030303030303030303030303030303036333646366537333646366336353265366336663637","id":40,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"633:42:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"value":"0x000000000000000000636F6e736F6c652e6c6f67"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":39,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"625:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":38,"name":"address","nodeType":"ElementaryTypeName","src":"625:7:0","typeDescriptions":{}}},"id":41,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"625:51:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"},{"id":59,"nodeType":"FunctionDefinition","src":"683:221:0","nodes":[],"body":{"id":58,"nodeType":"Block","src":"842:62:0","nodes":[],"statements":[{"AST":{"nodeType":"YulBlock","src":"861:37:0","statements":[{"nodeType":"YulAssignment","src":"875:13:0","value":{"name":"fnIn","nodeType":"YulIdentifier","src":"884:4:0"},"variableNames":[{"name":"fnOut","nodeType":"YulIdentifier","src":"875:5:0"}]}]},"evmVersion":"london","externalReferences":[{"declaration":48,"isOffset":false,"isSlot":false,"src":"884:4:0","valueSize":1},{"declaration":55,"isOffset":false,"isSlot":false,"src":"875:5:0","valueSize":1}],"id":57,"nodeType":"InlineAssembly","src":"852:46:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"_castLogPayloadViewToPure","nameLocation":"692:25:0","parameters":{"id":49,"nodeType":"ParameterList","parameters":[{"constant":false,"id":48,"mutability":"mutable","name":"fnIn","nameLocation":"764:4:0","nodeType":"VariableDeclaration","scope":59,"src":"727:41:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) view"},"typeName":{"id":47,"nodeType":"FunctionTypeName","parameterTypes":{"id":45,"nodeType":"ParameterList","parameters":[{"constant":false,"id":44,"mutability":"mutable","name":"","nameLocation":"-1:-1:-1","nodeType":"VariableDeclaration","scope":47,"src":"736:12:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":43,"name":"bytes","nodeType":"ElementaryTypeName","src":"736:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"735:14:0"},"returnParameterTypes":{"id":46,"nodeType":"ParameterList","parameters":[],"src":"764:0:0"},"src":"727:41:0","stateMutability":"view","typeDescriptions":{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) view"},"visibility":"internal"},"visibility":"internal"}],"src":"717:57:0"},"returnParameters":{"id":56,"nodeType":"ParameterList","parameters":[{"constant":false,"id":55,"mutability":"mutable","name":"fnOut","nameLocation":"835:5:0","nodeType":"VariableDeclaration","scope":59,"src":"798:42:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) pure"},"typeName":{"id":54,"nodeType":"FunctionTypeName","parameterTypes":{"id":52,"nodeType":"ParameterList","parameters":[{"constant":false,"id":51,"mutability":"mutable","name":"","nameLocation":"-1:-1:-1","nodeType":"VariableDeclaration","scope":54,"src":"807:12:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":50,"name":"bytes","nodeType":"ElementaryTypeName","src":"807:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"806:14:0"},"returnParameterTypes":{"id":53,"nodeType":"ParameterList","parameters":[],"src":"835:0:0"},"src":"798:42:0","stateMutability":"pure","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) pure"},"visibility":"internal"},"visibility":"internal"}],"src":"797:44:0"},"scope":173,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":71,"nodeType":"FunctionDefinition","src":"910:133:0","nodes":[],"body":{"id":70,"nodeType":"Block","src":"971:72:0","nodes":[],"statements":[{"expression":{"arguments":[{"id":67,"name":"payload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":61,"src":"1028:7:0","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"arguments":[{"id":65,"name":"_sendLogPayloadView","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":87,"src":"1007:19:0","typeDescriptions":{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) view"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) view"}],"id":64,"name":"_castLogPayloadViewToPure","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":59,"src":"981:25:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_function_internal_view$_t_bytes_memory_ptr_$returns$__$_$returns$_t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$_$","typeString":"function (function (bytes memory) view) pure returns (function (bytes memory) pure)"}},"id":66,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"981:46:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":68,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"981:55:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":69,"nodeType":"ExpressionStatement","src":"981:55:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"_sendLogPayload","nameLocation":"919:15:0","parameters":{"id":62,"nodeType":"ParameterList","parameters":[{"constant":false,"id":61,"mutability":"mutable","name":"payload","nameLocation":"948:7:0","nodeType":"VariableDeclaration","scope":71,"src":"935:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":60,"name":"bytes","nodeType":"ElementaryTypeName","src":"935:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"934:22:0"},"returnParameters":{"id":63,"nodeType":"ParameterList","parameters":[],"src":"971:0:0"},"scope":173,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":87,"nodeType":"FunctionDefinition","src":"1049:380:0","nodes":[],"body":{"id":86,"nodeType":"Block","src":"1113:316:0","nodes":[],"statements":[{"assignments":[77],"declarations":[{"constant":false,"id":77,"mutability":"mutable","name":"payloadLength","nameLocation":"1131:13:0","nodeType":"VariableDeclaration","scope":86,"src":"1123:21:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":76,"name":"uint256","nodeType":"ElementaryTypeName","src":"1123:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"}],"id":80,"initialValue":{"expression":{"id":78,"name":"payload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":73,"src":"1147:7:0","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}},"id":79,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"length","nodeType":"MemberAccess","src":"1147:14:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"nodeType":"VariableDeclarationStatement","src":"1123:38:0"},{"assignments":[82],"declarations":[{"constant":false,"id":82,"mutability":"mutable","name":"consoleAddress","nameLocation":"1179:14:0","nodeType":"VariableDeclaration","scope":86,"src":"1171:22:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":81,"name":"address","nodeType":"ElementaryTypeName","src":"1171:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"id":84,"initialValue":{"id":83,"name":"CONSOLE_ADDRESS","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":42,"src":"1196:15:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"nodeType":"VariableDeclarationStatement","src":"1171:40:0"},{"AST":{"nodeType":"YulBlock","src":"1273:150:0","statements":[{"nodeType":"YulVariableDeclaration","src":"1287:36:0","value":{"arguments":[{"name":"payload","nodeType":"YulIdentifier","src":"1311:7:0"},{"kind":"number","nodeType":"YulLiteral","src":"1320:2:0","type":"","value":"32"}],"functionName":{"name":"add","nodeType":"YulIdentifier","src":"1307:3:0"},"nodeType":"YulFunctionCall","src":"1307:16:0"},"variables":[{"name":"payloadStart","nodeType":"YulTypedName","src":"1291:12:0","type":""}]},{"nodeType":"YulVariableDeclaration","src":"1336:77:0","value":{"arguments":[{"arguments":[],"functionName":{"name":"gas","nodeType":"YulIdentifier","src":"1356:3:0"},"nodeType":"YulFunctionCall","src":"1356:5:0"},{"name":"consoleAddress","nodeType":"YulIdentifier","src":"1363:14:0"},{"name":"payloadStart","nodeType":"YulIdentifier","src":"1379:12:0"},{"name":"payloadLength","nodeType":"YulIdentifier","src":"1393:13:0"},{"kind":"number","nodeType":"YulLiteral","src":"1408:1:0","type":"","value":"0"},{"kind":"number","nodeType":"YulLiteral","src":"1411:1:0","type":"","value":"0"}],"functionName":{"name":"staticcall","nodeType":"YulIdentifier","src":"1345:10:0"},"nodeType":"YulFunctionCall","src":"1345:68:0"},"variables":[{"name":"r","nodeType":"YulTypedName","src":"1340:1:0","type":""}]}]},"documentation":"@solidity memory-safe-assembly","evmVersion":"london","externalReferences":[{"declaration":82,"isOffset":false,"isSlot":false,"src":"1363:14:0","valueSize":1},{"declaration":73,"isOffset":false,"isSlot":false,"src":"1311:7:0","valueSize":1},{"declaration":77,"isOffset":false,"isSlot":false,"src":"1393:13:0","valueSize":1}],"id":85,"nodeType":"InlineAssembly","src":"1264:159:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"_sendLogPayloadView","nameLocation":"1058:19:0","parameters":{"id":74,"nodeType":"ParameterList","parameters":[{"constant":false,"id":73,"mutability":"mutable","name":"payload","nameLocation":"1091:7:0","nodeType":"VariableDeclaration","scope":87,"src":"1078:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":72,"name":"bytes","nodeType":"ElementaryTypeName","src":"1078:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"1077:22:0"},"returnParameters":{"id":75,"nodeType":"ParameterList","parameters":[],"src":"1113:0:0"},"scope":173,"stateMutability":"view","virtual":false,"visibility":"private"},{"id":101,"nodeType":"FunctionDefinition","src":"1435:121:0","nodes":[],"body":{"id":100,"nodeType":"Block","src":"1480:76:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e6729","id":95,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"1530:13:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_41304facd9323d75b11bcdd609cb38effffdb05710f7caf0e9b16c6d9d709f50","typeString":"literal_string \"log(string)\""},"value":"log(string)"},{"id":96,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":89,"src":"1545:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_41304facd9323d75b11bcdd609cb38effffdb05710f7caf0e9b16c6d9d709f50","typeString":"literal_string \"log(string)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}],"expression":{"id":93,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"1506:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":94,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"1506:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":97,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1506:42:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":92,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":71,"src":"1490:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":98,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1490:59:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":99,"nodeType":"ExpressionStatement","src":"1490:59:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"1444:3:0","parameters":{"id":90,"nodeType":"ParameterList","parameters":[{"constant":false,"id":89,"mutability":"mutable","name":"p0","nameLocation":"1462:2:0","nodeType":"VariableDeclaration","scope":101,"src":"1448:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":88,"name":"string","nodeType":"ElementaryTypeName","src":"1448:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"1447:18:0"},"returnParameters":{"id":91,"nodeType":"ParameterList","parameters":[],"src":"1480:0:0"},"scope":173,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":118,"nodeType":"FunctionDefinition","src":"1562:139:0","nodes":[],"body":{"id":117,"nodeType":"Block","src":"1616:85:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c626f6f6c29","id":111,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"1666:18:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_c3b556354c088fbb43886eb83c2a04bc7089663f964d22be308197a236f5b870","typeString":"literal_string \"log(string,bool)\""},"value":"log(string,bool)"},{"id":112,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":103,"src":"1686:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":113,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":105,"src":"1690:2:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_c3b556354c088fbb43886eb83c2a04bc7089663f964d22be308197a236f5b870","typeString":"literal_string \"log(string,bool)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_bool","typeString":"bool"}],"expression":{"id":109,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"1642:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":110,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"1642:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":114,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1642:51:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":108,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":71,"src":"1626:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":115,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1626:68:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":116,"nodeType":"ExpressionStatement","src":"1626:68:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"1571:3:0","parameters":{"id":106,"nodeType":"ParameterList","parameters":[{"constant":false,"id":103,"mutability":"mutable","name":"p0","nameLocation":"1589:2:0","nodeType":"VariableDeclaration","scope":118,"src":"1575:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":102,"name":"string","nodeType":"ElementaryTypeName","src":"1575:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":105,"mutability":"mutable","name":"p1","nameLocation":"1598:2:0","nodeType":"VariableDeclaration","scope":118,"src":"1593:7:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":104,"name":"bool","nodeType":"ElementaryTypeName","src":"1593:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"src":"1574:27:0"},"returnParameters":{"id":107,"nodeType":"ParameterList","parameters":[],"src":"1616:0:0"},"scope":173,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":135,"nodeType":"FunctionDefinition","src":"1707:145:0","nodes":[],"body":{"id":134,"nodeType":"Block","src":"1764:88:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c75696e7432353629","id":128,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"1814:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_b60e72ccf6d57ab53eb84d7e94a9545806ed7f93c4d5673f11a64f03471e584e","typeString":"literal_string \"log(string,uint256)\""},"value":"log(string,uint256)"},{"id":129,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":120,"src":"1837:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":130,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":122,"src":"1841:2:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_b60e72ccf6d57ab53eb84d7e94a9545806ed7f93c4d5673f11a64f03471e584e","typeString":"literal_string \"log(string,uint256)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_uint256","typeString":"uint256"}],"expression":{"id":126,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"1790:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":127,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"1790:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":131,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1790:54:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":125,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":71,"src":"1774:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":132,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1774:71:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":133,"nodeType":"ExpressionStatement","src":"1774:71:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"1716:3:0","parameters":{"id":123,"nodeType":"ParameterList","parameters":[{"constant":false,"id":120,"mutability":"mutable","name":"p0","nameLocation":"1734:2:0","nodeType":"VariableDeclaration","scope":135,"src":"1720:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":119,"name":"string","nodeType":"ElementaryTypeName","src":"1720:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":122,"mutability":"mutable","name":"p1","nameLocation":"1746:2:0","nodeType":"VariableDeclaration","scope":135,"src":"1738:10:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":121,"name":"uint256","nodeType":"ElementaryTypeName","src":"1738:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"}],"src":"1719:30:0"},"returnParameters":{"id":124,"nodeType":"ParameterList","parameters":[],"src":"1764:0:0"},"scope":173,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":152,"nodeType":"FunctionDefinition","src":"1858:145:0","nodes":[],"body":{"id":151,"nodeType":"Block","src":"1915:88:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c6164647265737329","id":145,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"1965:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_319af333460570a1937bf195dd33445c0d0951c59127da6f1f038b9fdce3fd72","typeString":"literal_string \"log(string,address)\""},"value":"log(string,address)"},{"id":146,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":137,"src":"1988:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":147,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":139,"src":"1992:2:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_319af333460570a1937bf195dd33445c0d0951c59127da6f1f038b9fdce3fd72","typeString":"literal_string \"log(string,address)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":143,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"1941:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":144,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"1941:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":148,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1941:54:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":142,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":71,"src":"1925:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":149,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1925:71:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":150,"nodeType":"ExpressionStatement","src":"1925:71:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"1867:3:0","parameters":{"id":140,"nodeType":"ParameterList","parameters":[{"constant":false,"id":137,"mutability":"mutable","name":"p0","nameLocation":"1885:2:0","nodeType":"VariableDeclaration","scope":152,"src":"1871:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":136,"name":"string","nodeType":"ElementaryTypeName","src":"1871:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":139,"mutability":"mutable","name":"p1","nameLocation":"1897:2:0","nodeType":"VariableDeclaration","scope":152,"src":"1889:10:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":138,"name":"address","nodeType":"ElementaryTypeName","src":"1889:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"1870:30:0"},"returnParameters":{"id":141,"nodeType":"ParameterList","parameters":[],"src":"1915:0:0"},"scope":173,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":172,"nodeType":"FunctionDefinition","src":"2009:179:0","nodes":[],"body":{"id":171,"nodeType":"Block","src":"2090:98:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c737472696e672c737472696e6729","id":164,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2140:27:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_2ced7cef693312206c21f0e92e3b54e2e16bf33db5eec350c78866822c665e1f","typeString":"literal_string \"log(string,string,string)\""},"value":"log(string,string,string)"},{"id":165,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":154,"src":"2169:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":166,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":156,"src":"2173:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":167,"name":"p2","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":158,"src":"2177:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_2ced7cef693312206c21f0e92e3b54e2e16bf33db5eec350c78866822c665e1f","typeString":"literal_string \"log(string,string,string)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}],"expression":{"id":162,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"2116:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":163,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"2116:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":168,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2116:64:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":161,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":71,"src":"2100:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":169,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2100:81:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":170,"nodeType":"ExpressionStatement","src":"2100:81:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"2018:3:0","parameters":{"id":159,"nodeType":"ParameterList","parameters":[{"constant":false,"id":154,"mutability":"mutable","name":"p0","nameLocation":"2036:2:0","nodeType":"VariableDeclaration","scope":172,"src":"2022:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":153,"name":"string","nodeType":"ElementaryTypeName","src":"2022:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":156,"mutability":"mutable","name":"p1","nameLocation":"2054:2:0","nodeType":"VariableDeclaration","scope":172,"src":"2040:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":155,"name":"string","nodeType":"ElementaryTypeName","src":"2040:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":158,"mutability":"mutable","name":"p2","nameLocation":"2072:2:0","nodeType":"VariableDeclaration","scope":172,"src":"2058:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":157,"name":"string","nodeType":"ElementaryTypeName","src":"2058:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"2021:54:0"},"returnParameters":{"id":160,"nodeType":"ParameterList","parameters":[],"src":"2090:0:0"},"scope":173,"stateMutability":"pure","virtual":false,"visibility":"internal"}],"abstract":false,"baseContracts":[],"canonicalName":"console","contractDependencies":[],"contractKind":"library","fullyImplemented":true,"linearizedBaseContracts":[173],"name":"console","nameLocation":"576:7:0","scope":383,"usedErrors":[]},{"id":382,"nodeType":"ContractDefinition","src":"2318:1449:0","nodes":[{"id":188,"nodeType":"VariableDeclaration","src":"2348:94:0","nodes":[],"constant":true,"mutability":"constant","name":"VM_ADDRESS","nameLocation":"2374:10:0","scope":382,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":175,"name":"address","nodeType":"ElementaryTypeName","src":"2348:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"value":{"arguments":[{"arguments":[{"arguments":[{"arguments":[{"hexValue":"6865766d20636865617420636f6465","id":183,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2421:17:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d","typeString":"literal_string \"hevm cheat code\""},"value":"hevm cheat code"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d","typeString":"literal_string \"hevm cheat code\""}],"id":182,"name":"keccak256","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-8,"src":"2411:9:0","typeDescriptions":{"typeIdentifier":"t_function_keccak256_pure$_t_bytes_memory_ptr_$returns$_t_bytes32_$","typeString":"function (bytes memory) pure returns (bytes32)"}},"id":184,"isConstant":false,"isLValue":false,"isPure":true,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2411:28:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes32","typeString":"bytes32"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes32","typeString":"bytes32"}],"id":181,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2403:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint256_$","typeString":"type(uint256)"},"typeName":{"id":180,"name":"uint256","nodeType":"ElementaryTypeName","src":"2403:7:0","typeDescriptions":{}}},"id":185,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2403:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint256","typeString":"uint256"}],"id":179,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2395:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":178,"name":"uint160","nodeType":"ElementaryTypeName","src":"2395:7:0","typeDescriptions":{}}},"id":186,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2395:46:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":177,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2387:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":176,"name":"address","nodeType":"ElementaryTypeName","src":"2387:7:0","typeDescriptions":{}}},"id":187,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2387:55:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"},{"id":194,"nodeType":"VariableDeclaration","src":"2448:40:0","nodes":[],"constant":true,"mutability":"constant","name":"vm","nameLocation":"2469:2:0","scope":382,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$36","typeString":"contract Vm"},"typeName":{"id":190,"nodeType":"UserDefinedTypeName","pathNode":{"id":189,"name":"Vm","nodeType":"IdentifierPath","referencedDeclaration":36,"src":"2448:2:0"},"referencedDeclaration":36,"src":"2448:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$36","typeString":"contract Vm"}},"value":{"arguments":[{"id":192,"name":"VM_ADDRESS","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":188,"src":"2477:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":191,"name":"Vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":36,"src":"2474:2:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_Vm_$36_$","typeString":"type(contract Vm)"}},"id":193,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2474:14:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$36","typeString":"contract Vm"}},"visibility":"internal"},{"id":357,"nodeType":"FunctionDefinition","src":"2578:949:0","nodes":[],"body":{"id":356,"nodeType":"Block","src":"2600:927:0","nodes":[],"statements":[{"assignments":[199],"declarations":[{"constant":false,"id":199,"mutability":"mutable","name":"x","nameLocation":"2615:1:0","nodeType":"VariableDeclaration","scope":356,"src":"2610:6:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":198,"name":"bool","nodeType":"ElementaryTypeName","src":"2610:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"id":205,"initialValue":{"arguments":[{"hexValue":"4558414d504c455f424f4f4c","id":202,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2628:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_a634dae177a0e138ae7aaa2afae347412e148992e88c7aabd33ee71be146cb7f","typeString":"literal_string \"EXAMPLE_BOOL\""},"value":"EXAMPLE_BOOL"},{"hexValue":"66616c7365","id":203,"isConstant":false,"isLValue":false,"isPure":true,"kind":"bool","lValueRequested":false,"nodeType":"Literal","src":"2644:5:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"value":"false"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_a634dae177a0e138ae7aaa2afae347412e148992e88c7aabd33ee71be146cb7f","typeString":"literal_string \"EXAMPLE_BOOL\""},{"typeIdentifier":"t_bool","typeString":"bool"}],"expression":{"id":200,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":194,"src":"2619:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$36","typeString":"contract Vm"}},"id":201,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"envOr","nodeType":"MemberAccess","referencedDeclaration":10,"src":"2619:8:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$_t_bool_$returns$_t_bool_$","typeString":"function (string memory,bool) view external returns (bool)"}},"id":204,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2619:31:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"nodeType":"VariableDeclarationStatement","src":"2610:40:0"},{"expression":{"arguments":[{"hexValue":"626f6f6c2076616c75652066726f6d20656e76","id":209,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2672:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_5a607d0b5a1295325aa8901721d78ba402601bba6f62cebdd5235dd0204a590b","typeString":"literal_string \"bool value from env\""},"value":"bool value from env"},{"id":210,"name":"x","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":199,"src":"2695:1:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_5a607d0b5a1295325aa8901721d78ba402601bba6f62cebdd5235dd0204a590b","typeString":"literal_string \"bool value from env\""},{"typeIdentifier":"t_bool","typeString":"bool"}],"expression":{"id":206,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"2660:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":208,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":118,"src":"2660:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_bool_$returns$__$","typeString":"function (string memory,bool) pure"}},"id":211,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2660:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":212,"nodeType":"ExpressionStatement","src":"2660:37:0"},{"expression":{"arguments":[{"hexValue":"636f6e74726163742061646472","id":216,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2720:15:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_fa50728770d00fe8f6a0592f3565bbfaf063ee4077f1f5bbc003d091d33cd0c4","typeString":"literal_string \"contract addr\""},"value":"contract addr"},{"arguments":[{"id":219,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"2745:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}],"id":218,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2737:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":217,"name":"address","nodeType":"ElementaryTypeName","src":"2737:7:0","typeDescriptions":{}}},"id":220,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2737:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_fa50728770d00fe8f6a0592f3565bbfaf063ee4077f1f5bbc003d091d33cd0c4","typeString":"literal_string \"contract addr\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":213,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"2708:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":215,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":152,"src":"2708:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":221,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2708:43:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":222,"nodeType":"ExpressionStatement","src":"2708:43:0"},{"expression":{"arguments":[{"hexValue":"636f6e7472616374206e6f6e6365","id":226,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2773:16:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_3a23091615a5de8c0a35ffd8857a37e2c4e0b72f3ef8a34d6caf65efcd562e2f","typeString":"literal_string \"contract nonce\""},"value":"contract nonce"},{"arguments":[{"arguments":[{"id":231,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"2811:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}],"id":230,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2803:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":229,"name":"address","nodeType":"ElementaryTypeName","src":"2803:7:0","typeDescriptions":{}}},"id":232,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2803:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":227,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":194,"src":"2791:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$36","typeString":"contract Vm"}},"id":228,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"getNonce","nodeType":"MemberAccess","referencedDeclaration":17,"src":"2791:11:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_address_$returns$_t_uint64_$","typeString":"function (address) view external returns (uint64)"}},"id":233,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2791:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_3a23091615a5de8c0a35ffd8857a37e2c4e0b72f3ef8a34d6caf65efcd562e2f","typeString":"literal_string \"contract nonce\""},{"typeIdentifier":"t_uint64","typeString":"uint64"}],"expression":{"id":223,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"2761:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":225,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":135,"src":"2761:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_uint256_$returns$__$","typeString":"function (string memory,uint256) pure"}},"id":234,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2761:57:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":235,"nodeType":"ExpressionStatement","src":"2761:57:0"},{"expression":{"arguments":[{"hexValue":"73656e6465722061646472","id":239,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2840:13:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_8125ca2decf812b25b65606ff16dad37cb198ff0433485a7926e50feafacfc35","typeString":"literal_string \"sender addr\""},"value":"sender addr"},{"arguments":[{"expression":{"id":242,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"2863:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":243,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"2863:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":241,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2855:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":240,"name":"address","nodeType":"ElementaryTypeName","src":"2855:7:0","typeDescriptions":{}}},"id":244,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2855:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_8125ca2decf812b25b65606ff16dad37cb198ff0433485a7926e50feafacfc35","typeString":"literal_string \"sender addr\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":236,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"2828:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":238,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":152,"src":"2828:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":245,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2828:47:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":246,"nodeType":"ExpressionStatement","src":"2828:47:0"},{"expression":{"arguments":[{"hexValue":"73656e646572206e6f6e6365","id":250,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2897:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_db7deb43f2f9e0404016de53b7e64c4976b54149581f7534daae2551e8cf4e40","typeString":"literal_string \"sender nonce\""},"value":"sender nonce"},{"arguments":[{"arguments":[{"expression":{"id":255,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"2933:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":256,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"2933:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":254,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2925:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":253,"name":"address","nodeType":"ElementaryTypeName","src":"2925:7:0","typeDescriptions":{}}},"id":257,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2925:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":251,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":194,"src":"2913:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$36","typeString":"contract Vm"}},"id":252,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"getNonce","nodeType":"MemberAccess","referencedDeclaration":17,"src":"2913:11:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_address_$returns$_t_uint64_$","typeString":"function (address) view external returns (uint64)"}},"id":258,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2913:32:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_db7deb43f2f9e0404016de53b7e64c4976b54149581f7534daae2551e8cf4e40","typeString":"literal_string \"sender nonce\""},{"typeIdentifier":"t_uint64","typeString":"uint64"}],"expression":{"id":247,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"2885:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":249,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":135,"src":"2885:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_uint256_$returns$__$","typeString":"function (string memory,uint256) pure"}},"id":259,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2885:61:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":260,"nodeType":"ExpressionStatement","src":"2885:61:0"},{"assignments":[262],"declarations":[{"constant":false,"id":262,"mutability":"mutable","name":"json","nameLocation":"2971:4:0","nodeType":"VariableDeclaration","scope":356,"src":"2957:18:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":261,"name":"string","nodeType":"ElementaryTypeName","src":"2957:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"id":264,"initialValue":{"hexValue":"7b22726f6f745f6b6579223a205b7b2261223a20312c202262223a20327d5d7d","id":263,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2978:34:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_e95522e99766888d0261f55bd1eae5e3f3e26eaf009a16e2433eafaf0a4ecdf2","typeString":"literal_string \"{\"root_key\": [{\"a\": 1, \"b\": 2}]}\""},"value":"{\"root_key\": [{\"a\": 1, \"b\": 2}]}"},"nodeType":"VariableDeclarationStatement","src":"2957:55:0"},{"assignments":[269],"declarations":[{"constant":false,"id":269,"mutability":"mutable","name":"keys","nameLocation":"3038:4:0","nodeType":"VariableDeclaration","scope":356,"src":"3022:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string[]"},"typeName":{"baseType":{"id":267,"name":"string","nodeType":"ElementaryTypeName","src":"3022:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"id":268,"nodeType":"ArrayTypeName","src":"3022:8:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_storage_$dyn_storage_ptr","typeString":"string[]"}},"visibility":"internal"}],"id":275,"initialValue":{"arguments":[{"id":272,"name":"json","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":262,"src":"3062:4:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"hexValue":"2e726f6f745f6b65795b305d","id":273,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3068:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_d82f67100edb80050915e1ec4b565c9a8319a22efb1075e1298b7bb60101d266","typeString":"literal_string \".root_key[0]\""},"value":".root_key[0]"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_stringliteral_d82f67100edb80050915e1ec4b565c9a8319a22efb1075e1298b7bb60101d266","typeString":"literal_string \".root_key[0]\""}],"expression":{"id":270,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":194,"src":"3045:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$36","typeString":"contract Vm"}},"id":271,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"parseJsonKeys","nodeType":"MemberAccess","referencedDeclaration":27,"src":"3045:16:0","typeDescriptions":{"typeIdentifier":"t_function_external_pure$_t_string_memory_ptr_$_t_string_memory_ptr_$returns$_t_array$_t_string_memory_ptr_$dyn_memory_ptr_$","typeString":"function (string memory,string memory) pure external returns (string memory[] memory)"}},"id":274,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3045:38:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string memory[] memory"}},"nodeType":"VariableDeclarationStatement","src":"3022:61:0"},{"expression":{"arguments":[{"hexValue":"6b657973","id":279,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3105:6:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_f29790a80c4ce5f42f59892f424f9c92856c6b656c3378e2cf305b260c6f4195","typeString":"literal_string \"keys\""},"value":"keys"},{"baseExpression":{"id":280,"name":"keys","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":269,"src":"3113:4:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string memory[] memory"}},"id":282,"indexExpression":{"hexValue":"30","id":281,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"3118:1:0","typeDescriptions":{"typeIdentifier":"t_rational_0_by_1","typeString":"int_const 0"},"value":"0"},"isConstant":false,"isLValue":true,"isPure":false,"lValueRequested":false,"nodeType":"IndexAccess","src":"3113:7:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"baseExpression":{"id":283,"name":"keys","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":269,"src":"3122:4:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string memory[] memory"}},"id":285,"indexExpression":{"hexValue":"31","id":284,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"3127:1:0","typeDescriptions":{"typeIdentifier":"t_rational_1_by_1","typeString":"int_const 1"},"value":"1"},"isConstant":false,"isLValue":true,"isPure":false,"lValueRequested":false,"nodeType":"IndexAccess","src":"3122:7:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_f29790a80c4ce5f42f59892f424f9c92856c6b656c3378e2cf305b260c6f4195","typeString":"literal_string \"keys\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}],"expression":{"id":276,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"3093:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":278,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":172,"src":"3093:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_string_memory_ptr_$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory,string memory,string memory) pure"}},"id":286,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3093:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":287,"nodeType":"ExpressionStatement","src":"3093:37:0"},{"expression":{"arguments":[{"hexValue":"66726f6d206f726967696e616c","id":291,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3152:15:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_77928970c8757d110f3c23e003246f49e0de890480ba9717ba659b2f56f316b2","typeString":"literal_string \"from original\""},"value":"from original"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_77928970c8757d110f3c23e003246f49e0de890480ba9717ba659b2f56f316b2","typeString":"literal_string \"from original\""}],"expression":{"id":288,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3141:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}},"id":290,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":381,"src":"3141:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":292,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3141:27:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":293,"nodeType":"ExpressionStatement","src":"3141:27:0"},{"expression":{"arguments":[{"arguments":[{"arguments":[{"hexValue":"30783432","id":301,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"3208:4:0","typeDescriptions":{"typeIdentifier":"t_rational_66_by_1","typeString":"int_const 66"},"value":"0x42"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_66_by_1","typeString":"int_const 66"}],"id":300,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3200:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":299,"name":"uint160","nodeType":"ElementaryTypeName","src":"3200:7:0","typeDescriptions":{}}},"id":302,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3200:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":298,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3192:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":297,"name":"address","nodeType":"ElementaryTypeName","src":"3192:7:0","typeDescriptions":{}}},"id":303,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3192:22:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":294,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":194,"src":"3178:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$36","typeString":"contract Vm"}},"id":296,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"startPrank","nodeType":"MemberAccess","referencedDeclaration":32,"src":"3178:13:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_address_$returns$__$","typeString":"function (address) external"}},"id":304,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3178:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":305,"nodeType":"ExpressionStatement","src":"3178:37:0"},{"expression":{"arguments":[{"hexValue":"66726f6d207072616e6b2031","id":309,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3236:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_42b34abfe37a8b0add910cda7b4a379e6538fa7a1dcafce47a02bd38f6c88e2a","typeString":"literal_string \"from prank 1\""},"value":"from prank 1"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_42b34abfe37a8b0add910cda7b4a379e6538fa7a1dcafce47a02bd38f6c88e2a","typeString":"literal_string \"from prank 1\""}],"expression":{"id":306,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3225:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}},"id":308,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":381,"src":"3225:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":310,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3225:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":311,"nodeType":"ExpressionStatement","src":"3225:26:0"},{"expression":{"arguments":[{"hexValue":"706172656e742073636f7065206d73672e73656e646572","id":315,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3273:25:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_83ec9246154d8845de47aafc5c2865c9985d2efe84472c27283879f2fbf5cc94","typeString":"literal_string \"parent scope msg.sender\""},"value":"parent scope msg.sender"},{"arguments":[{"expression":{"id":318,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"3308:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":319,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"3308:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":317,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3300:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":316,"name":"address","nodeType":"ElementaryTypeName","src":"3300:7:0","typeDescriptions":{}}},"id":320,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3300:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_83ec9246154d8845de47aafc5c2865c9985d2efe84472c27283879f2fbf5cc94","typeString":"literal_string \"parent scope msg.sender\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":312,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"3261:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":314,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":152,"src":"3261:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":321,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3261:59:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":322,"nodeType":"ExpressionStatement","src":"3261:59:0"},{"expression":{"arguments":[{"hexValue":"706172656e742073636f706520636f6e74726163742e61646472","id":326,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3342:28:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_97df66250e0b2b48f0ec8d0e01eb1b8ca012d95f1572895622aa1ea433e5570f","typeString":"literal_string \"parent scope contract.addr\""},"value":"parent scope contract.addr"},{"arguments":[{"id":329,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3380:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}],"id":328,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3372:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":327,"name":"address","nodeType":"ElementaryTypeName","src":"3372:7:0","typeDescriptions":{}}},"id":330,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3372:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_97df66250e0b2b48f0ec8d0e01eb1b8ca012d95f1572895622aa1ea433e5570f","typeString":"literal_string \"parent scope contract.addr\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":323,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"3330:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":325,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":152,"src":"3330:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":331,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3330:56:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":332,"nodeType":"ExpressionStatement","src":"3330:56:0"},{"expression":{"arguments":[{"hexValue":"66726f6d207072616e6b2032","id":336,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3407:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_a38a34f8cad750a79aa097a92971f8f405b51ee9d53d25c5b14fc129ba3684bb","typeString":"literal_string \"from prank 2\""},"value":"from prank 2"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_a38a34f8cad750a79aa097a92971f8f405b51ee9d53d25c5b14fc129ba3684bb","typeString":"literal_string \"from prank 2\""}],"expression":{"id":333,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3396:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}},"id":335,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":381,"src":"3396:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":337,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3396:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":338,"nodeType":"ExpressionStatement","src":"3396:26:0"},{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":339,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":194,"src":"3432:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$36","typeString":"contract Vm"}},"id":341,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"stopPrank","nodeType":"MemberAccess","referencedDeclaration":35,"src":"3432:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$__$returns$__$","typeString":"function () external"}},"id":342,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3432:14:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":343,"nodeType":"ExpressionStatement","src":"3432:14:0"},{"expression":{"arguments":[{"hexValue":"66726f6d206f726967696e616c20616761696e","id":347,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3467:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_0c805c6579e20a9c4c8e11aeab23330910a9f2da629191dc119d1730e8ed6860","typeString":"literal_string \"from original again\""},"value":"from original again"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_0c805c6579e20a9c4c8e11aeab23330910a9f2da629191dc119d1730e8ed6860","typeString":"literal_string \"from original again\""}],"expression":{"id":344,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3456:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}},"id":346,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":381,"src":"3456:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":348,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3456:33:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":349,"nodeType":"ExpressionStatement","src":"3456:33:0"},{"expression":{"arguments":[{"hexValue":"646f6e6521","id":353,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3512:7:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_080382d5c9e9e7c5e3d1d33f5e7422740375955180fadff167d8130e0c35f3fc","typeString":"literal_string \"done!\""},"value":"done!"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_080382d5c9e9e7c5e3d1d33f5e7422740375955180fadff167d8130e0c35f3fc","typeString":"literal_string \"done!\""}],"expression":{"id":350,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"3500:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":352,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":101,"src":"3500:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":354,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3500:20:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":355,"nodeType":"ExpressionStatement","src":"3500:20:0"}]},"documentation":{"id":195,"nodeType":"StructuredDocumentation","src":"2495:78:0","text":"@notice example function, runs through basic cheat-codes and console logs."},"functionSelector":"c0406226","implemented":true,"kind":"function","modifiers":[],"name":"run","nameLocation":"2587:3:0","parameters":{"id":196,"nodeType":"ParameterList","parameters":[],"src":"2590:2:0"},"returnParameters":{"id":197,"nodeType":"ParameterList","parameters":[],"src":"2600:0:0"},"scope":382,"stateMutability":"nonpayable","virtual":false,"visibility":"public"},{"id":381,"nodeType":"FunctionDefinition","src":"3622:143:0","nodes":[],"body":{"id":380,"nodeType":"Block","src":"3671:94:0","nodes":[],"statements":[{"expression":{"arguments":[{"id":366,"name":"_v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":360,"src":"3693:2:0","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}],"expression":{"id":363,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"3681:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":365,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":101,"src":"3681:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":367,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3681:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":368,"nodeType":"ExpressionStatement","src":"3681:15:0"},{"expression":{"arguments":[{"hexValue":"68656c6c6f206d73672e73656e646572","id":372,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3718:18:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_b3cc13bc51228b2c4c4334d82a4772908254dc0e1c512893dd16208ef13efb8e","typeString":"literal_string \"hello msg.sender\""},"value":"hello msg.sender"},{"arguments":[{"expression":{"id":375,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"3746:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":376,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"3746:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":374,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3738:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":373,"name":"address","nodeType":"ElementaryTypeName","src":"3738:7:0","typeDescriptions":{}}},"id":377,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3738:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_b3cc13bc51228b2c4c4334d82a4772908254dc0e1c512893dd16208ef13efb8e","typeString":"literal_string \"hello msg.sender\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":369,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"3706:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":371,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":152,"src":"3706:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":378,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3706:52:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":379,"nodeType":"ExpressionStatement","src":"3706:52:0"}]},"documentation":{"id":358,"nodeType":"StructuredDocumentation","src":"3533:84:0","text":"@notice example external function, to force a CALL, and test vm.startPrank with."},"functionSelector":"a777d0dc","implemented":true,"kind":"function","modifiers":[],"name":"hello","nameLocation":"3631:5:0","parameters":{"id":361,"nodeType":"ParameterList","parameters":[{"constant":false,"id":360,"mutability":"mutable","name":"_v","nameLocation":"3653:2:0","nodeType":"VariableDeclaration","scope":381,"src":"3637:18:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":359,"name":"string","nodeType":"ElementaryTypeName","src":"3637:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"3636:20:0"},"returnParameters":{"id":362,"nodeType":"ParameterList","parameters":[],"src":"3671:0:0"},"scope":382,"stateMutability":"view","virtual":false,"visibility":"external"}],"abstract":false,"baseContracts":[],"canonicalName":"ScriptExample","contractDependencies":[],"contractKind":"contract","documentation":{"id":174,"nodeType":"StructuredDocumentation","src":"2192:126:0","text":"@title ScriptExample\n @notice ScriptExample is an example script. The Go forge script code tests that it can run this."},"fullyImplemented":true,"linearizedBaseContracts":[382],"name":"ScriptExample","nameLocation":"2327:13:0","scope":383,"usedErrors":[]}],"license":"MIT"},"id":0} \ No newline at end of file +{"abi":[{"type":"function","name":"broadcast","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"broadcast","inputs":[{"name":"msgSender","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"envOr","inputs":[{"name":"name","type":"string","internalType":"string"},{"name":"defaultValue","type":"bool","internalType":"bool"}],"outputs":[{"name":"value","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"getNonce","inputs":[{"name":"account","type":"address","internalType":"address"}],"outputs":[{"name":"nonce","type":"uint64","internalType":"uint64"}],"stateMutability":"view"},{"type":"function","name":"parseJsonKeys","inputs":[{"name":"json","type":"string","internalType":"string"},{"name":"key","type":"string","internalType":"string"}],"outputs":[{"name":"keys","type":"string[]","internalType":"string[]"}],"stateMutability":"pure"},{"type":"function","name":"startBroadcast","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"startBroadcast","inputs":[{"name":"msgSender","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"startPrank","inputs":[{"name":"msgSender","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"stopBroadcast","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"stopPrank","inputs":[],"outputs":[],"stateMutability":"nonpayable"}],"bytecode":{"object":"0x","sourceMap":"","linkReferences":{}},"deployedBytecode":{"object":"0x","sourceMap":"","linkReferences":{}},"methodIdentifiers":{"broadcast()":"afc98040","broadcast(address)":"e6962cdb","envOr(string,bool)":"4777f3cf","getNonce(address)":"2d0335ab","parseJsonKeys(string,string)":"213e4198","startBroadcast()":"7fb5297f","startBroadcast(address)":"7fec2a8d","startPrank(address)":"06447d56","stopBroadcast()":"76eadd36","stopPrank()":"90c5013b"},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"broadcast\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"msgSender\",\"type\":\"address\"}],\"name\":\"broadcast\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"defaultValue\",\"type\":\"bool\"}],\"name\":\"envOr\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"value\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getNonce\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"json\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"}],\"name\":\"parseJsonKeys\",\"outputs\":[{\"internalType\":\"string[]\",\"name\":\"keys\",\"type\":\"string[]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startBroadcast\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"msgSender\",\"type\":\"address\"}],\"name\":\"startBroadcast\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"msgSender\",\"type\":\"address\"}],\"name\":\"startPrank\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stopBroadcast\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stopPrank\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"scripts/ScriptExample.s.sol\":\"Vm\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[]},\"sources\":{\"scripts/ScriptExample.s.sol\":{\"keccak256\":\"0x8d1dfa41908e7ccc3a498a2a2aa51c5275bedbb904ce32d08f8598e36f896d8d\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5117bb7158363cae8b9dc0508d2852692fd36172f1c699ff680afbb5acebe1f3\",\"dweb:/ipfs/QmQdahJ8SPKfJ4yea5Ge9qaj5qh1TxVffhHvaWytBaL95h\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.15+commit.e14f2714"},"language":"Solidity","output":{"abi":[{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"broadcast"},{"inputs":[{"internalType":"address","name":"msgSender","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"broadcast"},{"inputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"bool","name":"defaultValue","type":"bool"}],"stateMutability":"view","type":"function","name":"envOr","outputs":[{"internalType":"bool","name":"value","type":"bool"}]},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"stateMutability":"view","type":"function","name":"getNonce","outputs":[{"internalType":"uint64","name":"nonce","type":"uint64"}]},{"inputs":[{"internalType":"string","name":"json","type":"string"},{"internalType":"string","name":"key","type":"string"}],"stateMutability":"pure","type":"function","name":"parseJsonKeys","outputs":[{"internalType":"string[]","name":"keys","type":"string[]"}]},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"startBroadcast"},{"inputs":[{"internalType":"address","name":"msgSender","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"startBroadcast"},{"inputs":[{"internalType":"address","name":"msgSender","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"startPrank"},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"stopBroadcast"},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"stopPrank"}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"remappings":[],"optimizer":{"enabled":true,"runs":999999},"metadata":{"bytecodeHash":"none"},"compilationTarget":{"scripts/ScriptExample.s.sol":"Vm"},"evmVersion":"london","libraries":{}},"sources":{"scripts/ScriptExample.s.sol":{"keccak256":"0x8d1dfa41908e7ccc3a498a2a2aa51c5275bedbb904ce32d08f8598e36f896d8d","urls":["bzz-raw://5117bb7158363cae8b9dc0508d2852692fd36172f1c699ff680afbb5acebe1f3","dweb:/ipfs/QmQdahJ8SPKfJ4yea5Ge9qaj5qh1TxVffhHvaWytBaL95h"],"license":"MIT"}},"version":1},"storageLayout":{"storage":[],"types":{}},"userdoc":{"version":1,"kind":"user"},"devdoc":{"version":1,"kind":"dev"},"ast":{"absolutePath":"scripts/ScriptExample.s.sol","id":720,"exportedSymbols":{"FooBar":[719],"ScriptExample":[706],"Vm":[55],"console":[192]},"nodeType":"SourceUnit","src":"32:5967:0","nodes":[{"id":1,"nodeType":"PragmaDirective","src":"32:23:0","nodes":[],"literals":["solidity","0.8",".15"]},{"id":55,"nodeType":"ContractDefinition","src":"120:616:0","nodes":[{"id":10,"nodeType":"FunctionDefinition","src":"139:91:0","nodes":[],"functionSelector":"4777f3cf","implemented":false,"kind":"function","modifiers":[],"name":"envOr","nameLocation":"148:5:0","parameters":{"id":6,"nodeType":"ParameterList","parameters":[{"constant":false,"id":3,"mutability":"mutable","name":"name","nameLocation":"170:4:0","nodeType":"VariableDeclaration","scope":10,"src":"154:20:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":2,"name":"string","nodeType":"ElementaryTypeName","src":"154:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":5,"mutability":"mutable","name":"defaultValue","nameLocation":"181:12:0","nodeType":"VariableDeclaration","scope":10,"src":"176:17:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":4,"name":"bool","nodeType":"ElementaryTypeName","src":"176:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"src":"153:41:0"},"returnParameters":{"id":9,"nodeType":"ParameterList","parameters":[{"constant":false,"id":8,"mutability":"mutable","name":"value","nameLocation":"223:5:0","nodeType":"VariableDeclaration","scope":10,"src":"218:10:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":7,"name":"bool","nodeType":"ElementaryTypeName","src":"218:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"src":"217:12:0"},"scope":55,"stateMutability":"view","virtual":false,"visibility":"external"},{"id":17,"nodeType":"FunctionDefinition","src":"235:72:0","nodes":[],"functionSelector":"2d0335ab","implemented":false,"kind":"function","modifiers":[],"name":"getNonce","nameLocation":"244:8:0","parameters":{"id":13,"nodeType":"ParameterList","parameters":[{"constant":false,"id":12,"mutability":"mutable","name":"account","nameLocation":"261:7:0","nodeType":"VariableDeclaration","scope":17,"src":"253:15:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":11,"name":"address","nodeType":"ElementaryTypeName","src":"253:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"252:17:0"},"returnParameters":{"id":16,"nodeType":"ParameterList","parameters":[{"constant":false,"id":15,"mutability":"mutable","name":"nonce","nameLocation":"300:5:0","nodeType":"VariableDeclaration","scope":17,"src":"293:12:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"},"typeName":{"id":14,"name":"uint64","nodeType":"ElementaryTypeName","src":"293:6:0","typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}},"visibility":"internal"}],"src":"292:14:0"},"scope":55,"stateMutability":"view","virtual":false,"visibility":"external"},{"id":27,"nodeType":"FunctionDefinition","src":"312:111:0","nodes":[],"functionSelector":"213e4198","implemented":false,"kind":"function","modifiers":[],"name":"parseJsonKeys","nameLocation":"321:13:0","parameters":{"id":22,"nodeType":"ParameterList","parameters":[{"constant":false,"id":19,"mutability":"mutable","name":"json","nameLocation":"351:4:0","nodeType":"VariableDeclaration","scope":27,"src":"335:20:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":18,"name":"string","nodeType":"ElementaryTypeName","src":"335:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":21,"mutability":"mutable","name":"key","nameLocation":"373:3:0","nodeType":"VariableDeclaration","scope":27,"src":"357:19:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":20,"name":"string","nodeType":"ElementaryTypeName","src":"357:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"334:43:0"},"returnParameters":{"id":26,"nodeType":"ParameterList","parameters":[{"constant":false,"id":25,"mutability":"mutable","name":"keys","nameLocation":"417:4:0","nodeType":"VariableDeclaration","scope":27,"src":"401:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string[]"},"typeName":{"baseType":{"id":23,"name":"string","nodeType":"ElementaryTypeName","src":"401:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"id":24,"nodeType":"ArrayTypeName","src":"401:8:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_storage_$dyn_storage_ptr","typeString":"string[]"}},"visibility":"internal"}],"src":"400:22:0"},"scope":55,"stateMutability":"pure","virtual":false,"visibility":"external"},{"id":32,"nodeType":"FunctionDefinition","src":"428:48:0","nodes":[],"functionSelector":"06447d56","implemented":false,"kind":"function","modifiers":[],"name":"startPrank","nameLocation":"437:10:0","parameters":{"id":30,"nodeType":"ParameterList","parameters":[{"constant":false,"id":29,"mutability":"mutable","name":"msgSender","nameLocation":"456:9:0","nodeType":"VariableDeclaration","scope":32,"src":"448:17:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":28,"name":"address","nodeType":"ElementaryTypeName","src":"448:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"447:19:0"},"returnParameters":{"id":31,"nodeType":"ParameterList","parameters":[],"src":"475:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":35,"nodeType":"FunctionDefinition","src":"481:30:0","nodes":[],"functionSelector":"90c5013b","implemented":false,"kind":"function","modifiers":[],"name":"stopPrank","nameLocation":"490:9:0","parameters":{"id":33,"nodeType":"ParameterList","parameters":[],"src":"499:2:0"},"returnParameters":{"id":34,"nodeType":"ParameterList","parameters":[],"src":"510:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":38,"nodeType":"FunctionDefinition","src":"516:30:0","nodes":[],"functionSelector":"afc98040","implemented":false,"kind":"function","modifiers":[],"name":"broadcast","nameLocation":"525:9:0","parameters":{"id":36,"nodeType":"ParameterList","parameters":[],"src":"534:2:0"},"returnParameters":{"id":37,"nodeType":"ParameterList","parameters":[],"src":"545:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":43,"nodeType":"FunctionDefinition","src":"551:47:0","nodes":[],"functionSelector":"e6962cdb","implemented":false,"kind":"function","modifiers":[],"name":"broadcast","nameLocation":"560:9:0","parameters":{"id":41,"nodeType":"ParameterList","parameters":[{"constant":false,"id":40,"mutability":"mutable","name":"msgSender","nameLocation":"578:9:0","nodeType":"VariableDeclaration","scope":43,"src":"570:17:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":39,"name":"address","nodeType":"ElementaryTypeName","src":"570:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"569:19:0"},"returnParameters":{"id":42,"nodeType":"ParameterList","parameters":[],"src":"597:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":48,"nodeType":"FunctionDefinition","src":"603:52:0","nodes":[],"functionSelector":"7fec2a8d","implemented":false,"kind":"function","modifiers":[],"name":"startBroadcast","nameLocation":"612:14:0","parameters":{"id":46,"nodeType":"ParameterList","parameters":[{"constant":false,"id":45,"mutability":"mutable","name":"msgSender","nameLocation":"635:9:0","nodeType":"VariableDeclaration","scope":48,"src":"627:17:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":44,"name":"address","nodeType":"ElementaryTypeName","src":"627:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"626:19:0"},"returnParameters":{"id":47,"nodeType":"ParameterList","parameters":[],"src":"654:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":51,"nodeType":"FunctionDefinition","src":"660:35:0","nodes":[],"functionSelector":"7fb5297f","implemented":false,"kind":"function","modifiers":[],"name":"startBroadcast","nameLocation":"669:14:0","parameters":{"id":49,"nodeType":"ParameterList","parameters":[],"src":"683:2:0"},"returnParameters":{"id":50,"nodeType":"ParameterList","parameters":[],"src":"694:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":54,"nodeType":"FunctionDefinition","src":"700:34:0","nodes":[],"functionSelector":"76eadd36","implemented":false,"kind":"function","modifiers":[],"name":"stopBroadcast","nameLocation":"709:13:0","parameters":{"id":52,"nodeType":"ParameterList","parameters":[],"src":"722:2:0"},"returnParameters":{"id":53,"nodeType":"ParameterList","parameters":[],"src":"733:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"}],"abstract":false,"baseContracts":[],"canonicalName":"Vm","contractDependencies":[],"contractKind":"interface","fullyImplemented":false,"linearizedBaseContracts":[55],"name":"Vm","nameLocation":"130:2:0","scope":720,"usedErrors":[]},{"id":192,"nodeType":"ContractDefinition","src":"791:1622:0","nodes":[{"id":61,"nodeType":"VariableDeclaration","src":"813:86:0","nodes":[],"constant":true,"mutability":"constant","name":"CONSOLE_ADDRESS","nameLocation":"830:15:0","scope":192,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":56,"name":"address","nodeType":"ElementaryTypeName","src":"813:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"value":{"arguments":[{"hexValue":"307830303030303030303030303030303030303036333646366537333646366336353265366336663637","id":59,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"856:42:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"value":"0x000000000000000000636F6e736F6c652e6c6f67"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":58,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"848:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":57,"name":"address","nodeType":"ElementaryTypeName","src":"848:7:0","typeDescriptions":{}}},"id":60,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"848:51:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"},{"id":78,"nodeType":"FunctionDefinition","src":"906:221:0","nodes":[],"body":{"id":77,"nodeType":"Block","src":"1065:62:0","nodes":[],"statements":[{"AST":{"nodeType":"YulBlock","src":"1084:37:0","statements":[{"nodeType":"YulAssignment","src":"1098:13:0","value":{"name":"fnIn","nodeType":"YulIdentifier","src":"1107:4:0"},"variableNames":[{"name":"fnOut","nodeType":"YulIdentifier","src":"1098:5:0"}]}]},"evmVersion":"london","externalReferences":[{"declaration":67,"isOffset":false,"isSlot":false,"src":"1107:4:0","valueSize":1},{"declaration":74,"isOffset":false,"isSlot":false,"src":"1098:5:0","valueSize":1}],"id":76,"nodeType":"InlineAssembly","src":"1075:46:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"_castLogPayloadViewToPure","nameLocation":"915:25:0","parameters":{"id":68,"nodeType":"ParameterList","parameters":[{"constant":false,"id":67,"mutability":"mutable","name":"fnIn","nameLocation":"987:4:0","nodeType":"VariableDeclaration","scope":78,"src":"950:41:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) view"},"typeName":{"id":66,"nodeType":"FunctionTypeName","parameterTypes":{"id":64,"nodeType":"ParameterList","parameters":[{"constant":false,"id":63,"mutability":"mutable","name":"","nameLocation":"-1:-1:-1","nodeType":"VariableDeclaration","scope":66,"src":"959:12:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":62,"name":"bytes","nodeType":"ElementaryTypeName","src":"959:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"958:14:0"},"returnParameterTypes":{"id":65,"nodeType":"ParameterList","parameters":[],"src":"987:0:0"},"src":"950:41:0","stateMutability":"view","typeDescriptions":{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) view"},"visibility":"internal"},"visibility":"internal"}],"src":"940:57:0"},"returnParameters":{"id":75,"nodeType":"ParameterList","parameters":[{"constant":false,"id":74,"mutability":"mutable","name":"fnOut","nameLocation":"1058:5:0","nodeType":"VariableDeclaration","scope":78,"src":"1021:42:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) pure"},"typeName":{"id":73,"nodeType":"FunctionTypeName","parameterTypes":{"id":71,"nodeType":"ParameterList","parameters":[{"constant":false,"id":70,"mutability":"mutable","name":"","nameLocation":"-1:-1:-1","nodeType":"VariableDeclaration","scope":73,"src":"1030:12:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":69,"name":"bytes","nodeType":"ElementaryTypeName","src":"1030:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"1029:14:0"},"returnParameterTypes":{"id":72,"nodeType":"ParameterList","parameters":[],"src":"1058:0:0"},"src":"1021:42:0","stateMutability":"pure","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) pure"},"visibility":"internal"},"visibility":"internal"}],"src":"1020:44:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":90,"nodeType":"FunctionDefinition","src":"1133:133:0","nodes":[],"body":{"id":89,"nodeType":"Block","src":"1194:72:0","nodes":[],"statements":[{"expression":{"arguments":[{"id":86,"name":"payload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":80,"src":"1251:7:0","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"arguments":[{"id":84,"name":"_sendLogPayloadView","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":106,"src":"1230:19:0","typeDescriptions":{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) view"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) view"}],"id":83,"name":"_castLogPayloadViewToPure","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":78,"src":"1204:25:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_function_internal_view$_t_bytes_memory_ptr_$returns$__$_$returns$_t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$_$","typeString":"function (function (bytes memory) view) pure returns (function (bytes memory) pure)"}},"id":85,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1204:46:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":87,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1204:55:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":88,"nodeType":"ExpressionStatement","src":"1204:55:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"_sendLogPayload","nameLocation":"1142:15:0","parameters":{"id":81,"nodeType":"ParameterList","parameters":[{"constant":false,"id":80,"mutability":"mutable","name":"payload","nameLocation":"1171:7:0","nodeType":"VariableDeclaration","scope":90,"src":"1158:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":79,"name":"bytes","nodeType":"ElementaryTypeName","src":"1158:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"1157:22:0"},"returnParameters":{"id":82,"nodeType":"ParameterList","parameters":[],"src":"1194:0:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":106,"nodeType":"FunctionDefinition","src":"1272:380:0","nodes":[],"body":{"id":105,"nodeType":"Block","src":"1336:316:0","nodes":[],"statements":[{"assignments":[96],"declarations":[{"constant":false,"id":96,"mutability":"mutable","name":"payloadLength","nameLocation":"1354:13:0","nodeType":"VariableDeclaration","scope":105,"src":"1346:21:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":95,"name":"uint256","nodeType":"ElementaryTypeName","src":"1346:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"}],"id":99,"initialValue":{"expression":{"id":97,"name":"payload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":92,"src":"1370:7:0","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}},"id":98,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"length","nodeType":"MemberAccess","src":"1370:14:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"nodeType":"VariableDeclarationStatement","src":"1346:38:0"},{"assignments":[101],"declarations":[{"constant":false,"id":101,"mutability":"mutable","name":"consoleAddress","nameLocation":"1402:14:0","nodeType":"VariableDeclaration","scope":105,"src":"1394:22:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":100,"name":"address","nodeType":"ElementaryTypeName","src":"1394:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"id":103,"initialValue":{"id":102,"name":"CONSOLE_ADDRESS","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":61,"src":"1419:15:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"nodeType":"VariableDeclarationStatement","src":"1394:40:0"},{"AST":{"nodeType":"YulBlock","src":"1496:150:0","statements":[{"nodeType":"YulVariableDeclaration","src":"1510:36:0","value":{"arguments":[{"name":"payload","nodeType":"YulIdentifier","src":"1534:7:0"},{"kind":"number","nodeType":"YulLiteral","src":"1543:2:0","type":"","value":"32"}],"functionName":{"name":"add","nodeType":"YulIdentifier","src":"1530:3:0"},"nodeType":"YulFunctionCall","src":"1530:16:0"},"variables":[{"name":"payloadStart","nodeType":"YulTypedName","src":"1514:12:0","type":""}]},{"nodeType":"YulVariableDeclaration","src":"1559:77:0","value":{"arguments":[{"arguments":[],"functionName":{"name":"gas","nodeType":"YulIdentifier","src":"1579:3:0"},"nodeType":"YulFunctionCall","src":"1579:5:0"},{"name":"consoleAddress","nodeType":"YulIdentifier","src":"1586:14:0"},{"name":"payloadStart","nodeType":"YulIdentifier","src":"1602:12:0"},{"name":"payloadLength","nodeType":"YulIdentifier","src":"1616:13:0"},{"kind":"number","nodeType":"YulLiteral","src":"1631:1:0","type":"","value":"0"},{"kind":"number","nodeType":"YulLiteral","src":"1634:1:0","type":"","value":"0"}],"functionName":{"name":"staticcall","nodeType":"YulIdentifier","src":"1568:10:0"},"nodeType":"YulFunctionCall","src":"1568:68:0"},"variables":[{"name":"r","nodeType":"YulTypedName","src":"1563:1:0","type":""}]}]},"documentation":"@solidity memory-safe-assembly","evmVersion":"london","externalReferences":[{"declaration":101,"isOffset":false,"isSlot":false,"src":"1586:14:0","valueSize":1},{"declaration":92,"isOffset":false,"isSlot":false,"src":"1534:7:0","valueSize":1},{"declaration":96,"isOffset":false,"isSlot":false,"src":"1616:13:0","valueSize":1}],"id":104,"nodeType":"InlineAssembly","src":"1487:159:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"_sendLogPayloadView","nameLocation":"1281:19:0","parameters":{"id":93,"nodeType":"ParameterList","parameters":[{"constant":false,"id":92,"mutability":"mutable","name":"payload","nameLocation":"1314:7:0","nodeType":"VariableDeclaration","scope":106,"src":"1301:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":91,"name":"bytes","nodeType":"ElementaryTypeName","src":"1301:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"1300:22:0"},"returnParameters":{"id":94,"nodeType":"ParameterList","parameters":[],"src":"1336:0:0"},"scope":192,"stateMutability":"view","virtual":false,"visibility":"private"},{"id":120,"nodeType":"FunctionDefinition","src":"1658:121:0","nodes":[],"body":{"id":119,"nodeType":"Block","src":"1703:76:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e6729","id":114,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"1753:13:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_41304facd9323d75b11bcdd609cb38effffdb05710f7caf0e9b16c6d9d709f50","typeString":"literal_string \"log(string)\""},"value":"log(string)"},{"id":115,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":108,"src":"1768:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_41304facd9323d75b11bcdd609cb38effffdb05710f7caf0e9b16c6d9d709f50","typeString":"literal_string \"log(string)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}],"expression":{"id":112,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"1729:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":113,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"1729:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":116,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1729:42:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":111,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":90,"src":"1713:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":117,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1713:59:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":118,"nodeType":"ExpressionStatement","src":"1713:59:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"1667:3:0","parameters":{"id":109,"nodeType":"ParameterList","parameters":[{"constant":false,"id":108,"mutability":"mutable","name":"p0","nameLocation":"1685:2:0","nodeType":"VariableDeclaration","scope":120,"src":"1671:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":107,"name":"string","nodeType":"ElementaryTypeName","src":"1671:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"1670:18:0"},"returnParameters":{"id":110,"nodeType":"ParameterList","parameters":[],"src":"1703:0:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":137,"nodeType":"FunctionDefinition","src":"1785:139:0","nodes":[],"body":{"id":136,"nodeType":"Block","src":"1839:85:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c626f6f6c29","id":130,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"1889:18:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_c3b556354c088fbb43886eb83c2a04bc7089663f964d22be308197a236f5b870","typeString":"literal_string \"log(string,bool)\""},"value":"log(string,bool)"},{"id":131,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":122,"src":"1909:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":132,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":124,"src":"1913:2:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_c3b556354c088fbb43886eb83c2a04bc7089663f964d22be308197a236f5b870","typeString":"literal_string \"log(string,bool)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_bool","typeString":"bool"}],"expression":{"id":128,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"1865:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":129,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"1865:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":133,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1865:51:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":127,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":90,"src":"1849:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":134,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1849:68:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":135,"nodeType":"ExpressionStatement","src":"1849:68:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"1794:3:0","parameters":{"id":125,"nodeType":"ParameterList","parameters":[{"constant":false,"id":122,"mutability":"mutable","name":"p0","nameLocation":"1812:2:0","nodeType":"VariableDeclaration","scope":137,"src":"1798:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":121,"name":"string","nodeType":"ElementaryTypeName","src":"1798:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":124,"mutability":"mutable","name":"p1","nameLocation":"1821:2:0","nodeType":"VariableDeclaration","scope":137,"src":"1816:7:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":123,"name":"bool","nodeType":"ElementaryTypeName","src":"1816:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"src":"1797:27:0"},"returnParameters":{"id":126,"nodeType":"ParameterList","parameters":[],"src":"1839:0:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":154,"nodeType":"FunctionDefinition","src":"1930:145:0","nodes":[],"body":{"id":153,"nodeType":"Block","src":"1987:88:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c75696e7432353629","id":147,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2037:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_b60e72ccf6d57ab53eb84d7e94a9545806ed7f93c4d5673f11a64f03471e584e","typeString":"literal_string \"log(string,uint256)\""},"value":"log(string,uint256)"},{"id":148,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":139,"src":"2060:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":149,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":141,"src":"2064:2:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_b60e72ccf6d57ab53eb84d7e94a9545806ed7f93c4d5673f11a64f03471e584e","typeString":"literal_string \"log(string,uint256)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_uint256","typeString":"uint256"}],"expression":{"id":145,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"2013:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":146,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"2013:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":150,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2013:54:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":144,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":90,"src":"1997:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":151,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1997:71:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":152,"nodeType":"ExpressionStatement","src":"1997:71:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"1939:3:0","parameters":{"id":142,"nodeType":"ParameterList","parameters":[{"constant":false,"id":139,"mutability":"mutable","name":"p0","nameLocation":"1957:2:0","nodeType":"VariableDeclaration","scope":154,"src":"1943:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":138,"name":"string","nodeType":"ElementaryTypeName","src":"1943:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":141,"mutability":"mutable","name":"p1","nameLocation":"1969:2:0","nodeType":"VariableDeclaration","scope":154,"src":"1961:10:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":140,"name":"uint256","nodeType":"ElementaryTypeName","src":"1961:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"}],"src":"1942:30:0"},"returnParameters":{"id":143,"nodeType":"ParameterList","parameters":[],"src":"1987:0:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":171,"nodeType":"FunctionDefinition","src":"2081:145:0","nodes":[],"body":{"id":170,"nodeType":"Block","src":"2138:88:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c6164647265737329","id":164,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2188:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_319af333460570a1937bf195dd33445c0d0951c59127da6f1f038b9fdce3fd72","typeString":"literal_string \"log(string,address)\""},"value":"log(string,address)"},{"id":165,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":156,"src":"2211:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":166,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":158,"src":"2215:2:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_319af333460570a1937bf195dd33445c0d0951c59127da6f1f038b9fdce3fd72","typeString":"literal_string \"log(string,address)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":162,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"2164:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":163,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"2164:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":167,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2164:54:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":161,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":90,"src":"2148:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":168,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2148:71:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":169,"nodeType":"ExpressionStatement","src":"2148:71:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"2090:3:0","parameters":{"id":159,"nodeType":"ParameterList","parameters":[{"constant":false,"id":156,"mutability":"mutable","name":"p0","nameLocation":"2108:2:0","nodeType":"VariableDeclaration","scope":171,"src":"2094:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":155,"name":"string","nodeType":"ElementaryTypeName","src":"2094:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":158,"mutability":"mutable","name":"p1","nameLocation":"2120:2:0","nodeType":"VariableDeclaration","scope":171,"src":"2112:10:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":157,"name":"address","nodeType":"ElementaryTypeName","src":"2112:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"2093:30:0"},"returnParameters":{"id":160,"nodeType":"ParameterList","parameters":[],"src":"2138:0:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":191,"nodeType":"FunctionDefinition","src":"2232:179:0","nodes":[],"body":{"id":190,"nodeType":"Block","src":"2313:98:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c737472696e672c737472696e6729","id":183,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2363:27:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_2ced7cef693312206c21f0e92e3b54e2e16bf33db5eec350c78866822c665e1f","typeString":"literal_string \"log(string,string,string)\""},"value":"log(string,string,string)"},{"id":184,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"2392:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":185,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":175,"src":"2396:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":186,"name":"p2","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":177,"src":"2400:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_2ced7cef693312206c21f0e92e3b54e2e16bf33db5eec350c78866822c665e1f","typeString":"literal_string \"log(string,string,string)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}],"expression":{"id":181,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"2339:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":182,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"2339:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":187,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2339:64:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":180,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":90,"src":"2323:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":188,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2323:81:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":189,"nodeType":"ExpressionStatement","src":"2323:81:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"2241:3:0","parameters":{"id":178,"nodeType":"ParameterList","parameters":[{"constant":false,"id":173,"mutability":"mutable","name":"p0","nameLocation":"2259:2:0","nodeType":"VariableDeclaration","scope":191,"src":"2245:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":172,"name":"string","nodeType":"ElementaryTypeName","src":"2245:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":175,"mutability":"mutable","name":"p1","nameLocation":"2277:2:0","nodeType":"VariableDeclaration","scope":191,"src":"2263:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":174,"name":"string","nodeType":"ElementaryTypeName","src":"2263:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":177,"mutability":"mutable","name":"p2","nameLocation":"2295:2:0","nodeType":"VariableDeclaration","scope":191,"src":"2281:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":176,"name":"string","nodeType":"ElementaryTypeName","src":"2281:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"2244:54:0"},"returnParameters":{"id":179,"nodeType":"ParameterList","parameters":[],"src":"2313:0:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"}],"abstract":false,"baseContracts":[],"canonicalName":"console","contractDependencies":[],"contractKind":"library","fullyImplemented":true,"linearizedBaseContracts":[192],"name":"console","nameLocation":"799:7:0","scope":720,"usedErrors":[]},{"id":706,"nodeType":"ContractDefinition","src":"2541:3359:0","nodes":[{"id":207,"nodeType":"VariableDeclaration","src":"2571:94:0","nodes":[],"constant":true,"mutability":"constant","name":"VM_ADDRESS","nameLocation":"2597:10:0","scope":706,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":194,"name":"address","nodeType":"ElementaryTypeName","src":"2571:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"value":{"arguments":[{"arguments":[{"arguments":[{"arguments":[{"hexValue":"6865766d20636865617420636f6465","id":202,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2644:17:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d","typeString":"literal_string \"hevm cheat code\""},"value":"hevm cheat code"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d","typeString":"literal_string \"hevm cheat code\""}],"id":201,"name":"keccak256","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-8,"src":"2634:9:0","typeDescriptions":{"typeIdentifier":"t_function_keccak256_pure$_t_bytes_memory_ptr_$returns$_t_bytes32_$","typeString":"function (bytes memory) pure returns (bytes32)"}},"id":203,"isConstant":false,"isLValue":false,"isPure":true,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2634:28:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes32","typeString":"bytes32"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes32","typeString":"bytes32"}],"id":200,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2626:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint256_$","typeString":"type(uint256)"},"typeName":{"id":199,"name":"uint256","nodeType":"ElementaryTypeName","src":"2626:7:0","typeDescriptions":{}}},"id":204,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2626:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint256","typeString":"uint256"}],"id":198,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2618:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":197,"name":"uint160","nodeType":"ElementaryTypeName","src":"2618:7:0","typeDescriptions":{}}},"id":205,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2618:46:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":196,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2610:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":195,"name":"address","nodeType":"ElementaryTypeName","src":"2610:7:0","typeDescriptions":{}}},"id":206,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2610:55:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"},{"id":213,"nodeType":"VariableDeclaration","src":"2671:40:0","nodes":[],"constant":true,"mutability":"constant","name":"vm","nameLocation":"2692:2:0","scope":706,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"},"typeName":{"id":209,"nodeType":"UserDefinedTypeName","pathNode":{"id":208,"name":"Vm","nodeType":"IdentifierPath","referencedDeclaration":55,"src":"2671:2:0"},"referencedDeclaration":55,"src":"2671:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"value":{"arguments":[{"id":211,"name":"VM_ADDRESS","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":207,"src":"2700:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":210,"name":"Vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":55,"src":"2697:2:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_Vm_$55_$","typeString":"type(contract Vm)"}},"id":212,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2697:14:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"visibility":"internal"},{"id":215,"nodeType":"VariableDeclaration","src":"2775:22:0","nodes":[],"constant":false,"functionSelector":"61bc221a","mutability":"mutable","name":"counter","nameLocation":"2790:7:0","scope":706,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":214,"name":"uint256","nodeType":"ElementaryTypeName","src":"2775:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"public"},{"id":378,"nodeType":"FunctionDefinition","src":"2887:949:0","nodes":[],"body":{"id":377,"nodeType":"Block","src":"2909:927:0","nodes":[],"statements":[{"assignments":[220],"declarations":[{"constant":false,"id":220,"mutability":"mutable","name":"x","nameLocation":"2924:1:0","nodeType":"VariableDeclaration","scope":377,"src":"2919:6:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":219,"name":"bool","nodeType":"ElementaryTypeName","src":"2919:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"id":226,"initialValue":{"arguments":[{"hexValue":"4558414d504c455f424f4f4c","id":223,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2937:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_a634dae177a0e138ae7aaa2afae347412e148992e88c7aabd33ee71be146cb7f","typeString":"literal_string \"EXAMPLE_BOOL\""},"value":"EXAMPLE_BOOL"},{"hexValue":"66616c7365","id":224,"isConstant":false,"isLValue":false,"isPure":true,"kind":"bool","lValueRequested":false,"nodeType":"Literal","src":"2953:5:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"value":"false"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_a634dae177a0e138ae7aaa2afae347412e148992e88c7aabd33ee71be146cb7f","typeString":"literal_string \"EXAMPLE_BOOL\""},{"typeIdentifier":"t_bool","typeString":"bool"}],"expression":{"id":221,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"2928:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":222,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"envOr","nodeType":"MemberAccess","referencedDeclaration":10,"src":"2928:8:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$_t_bool_$returns$_t_bool_$","typeString":"function (string memory,bool) view external returns (bool)"}},"id":225,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2928:31:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"nodeType":"VariableDeclarationStatement","src":"2919:40:0"},{"expression":{"arguments":[{"hexValue":"626f6f6c2076616c75652066726f6d20656e76","id":230,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2981:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_5a607d0b5a1295325aa8901721d78ba402601bba6f62cebdd5235dd0204a590b","typeString":"literal_string \"bool value from env\""},"value":"bool value from env"},{"id":231,"name":"x","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":220,"src":"3004:1:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_5a607d0b5a1295325aa8901721d78ba402601bba6f62cebdd5235dd0204a590b","typeString":"literal_string \"bool value from env\""},{"typeIdentifier":"t_bool","typeString":"bool"}],"expression":{"id":227,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"2969:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":229,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":137,"src":"2969:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_bool_$returns$__$","typeString":"function (string memory,bool) pure"}},"id":232,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2969:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":233,"nodeType":"ExpressionStatement","src":"2969:37:0"},{"expression":{"arguments":[{"hexValue":"636f6e74726163742061646472","id":237,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3029:15:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_fa50728770d00fe8f6a0592f3565bbfaf063ee4077f1f5bbc003d091d33cd0c4","typeString":"literal_string \"contract addr\""},"value":"contract addr"},{"arguments":[{"id":240,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3054:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}],"id":239,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3046:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":238,"name":"address","nodeType":"ElementaryTypeName","src":"3046:7:0","typeDescriptions":{}}},"id":241,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3046:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_fa50728770d00fe8f6a0592f3565bbfaf063ee4077f1f5bbc003d091d33cd0c4","typeString":"literal_string \"contract addr\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":234,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3017:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":236,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":171,"src":"3017:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":242,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3017:43:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":243,"nodeType":"ExpressionStatement","src":"3017:43:0"},{"expression":{"arguments":[{"hexValue":"636f6e7472616374206e6f6e6365","id":247,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3082:16:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_3a23091615a5de8c0a35ffd8857a37e2c4e0b72f3ef8a34d6caf65efcd562e2f","typeString":"literal_string \"contract nonce\""},"value":"contract nonce"},{"arguments":[{"arguments":[{"id":252,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3120:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}],"id":251,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3112:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":250,"name":"address","nodeType":"ElementaryTypeName","src":"3112:7:0","typeDescriptions":{}}},"id":253,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3112:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":248,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"3100:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":249,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"getNonce","nodeType":"MemberAccess","referencedDeclaration":17,"src":"3100:11:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_address_$returns$_t_uint64_$","typeString":"function (address) view external returns (uint64)"}},"id":254,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3100:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_3a23091615a5de8c0a35ffd8857a37e2c4e0b72f3ef8a34d6caf65efcd562e2f","typeString":"literal_string \"contract nonce\""},{"typeIdentifier":"t_uint64","typeString":"uint64"}],"expression":{"id":244,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3070:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":246,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":154,"src":"3070:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_uint256_$returns$__$","typeString":"function (string memory,uint256) pure"}},"id":255,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3070:57:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":256,"nodeType":"ExpressionStatement","src":"3070:57:0"},{"expression":{"arguments":[{"hexValue":"73656e6465722061646472","id":260,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3149:13:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_8125ca2decf812b25b65606ff16dad37cb198ff0433485a7926e50feafacfc35","typeString":"literal_string \"sender addr\""},"value":"sender addr"},{"arguments":[{"expression":{"id":263,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"3172:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":264,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"3172:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":262,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3164:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":261,"name":"address","nodeType":"ElementaryTypeName","src":"3164:7:0","typeDescriptions":{}}},"id":265,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3164:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_8125ca2decf812b25b65606ff16dad37cb198ff0433485a7926e50feafacfc35","typeString":"literal_string \"sender addr\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":257,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3137:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":259,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":171,"src":"3137:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":266,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3137:47:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":267,"nodeType":"ExpressionStatement","src":"3137:47:0"},{"expression":{"arguments":[{"hexValue":"73656e646572206e6f6e6365","id":271,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3206:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_db7deb43f2f9e0404016de53b7e64c4976b54149581f7534daae2551e8cf4e40","typeString":"literal_string \"sender nonce\""},"value":"sender nonce"},{"arguments":[{"arguments":[{"expression":{"id":276,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"3242:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":277,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"3242:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":275,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3234:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":274,"name":"address","nodeType":"ElementaryTypeName","src":"3234:7:0","typeDescriptions":{}}},"id":278,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3234:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":272,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"3222:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":273,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"getNonce","nodeType":"MemberAccess","referencedDeclaration":17,"src":"3222:11:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_address_$returns$_t_uint64_$","typeString":"function (address) view external returns (uint64)"}},"id":279,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3222:32:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_db7deb43f2f9e0404016de53b7e64c4976b54149581f7534daae2551e8cf4e40","typeString":"literal_string \"sender nonce\""},{"typeIdentifier":"t_uint64","typeString":"uint64"}],"expression":{"id":268,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3194:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":270,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":154,"src":"3194:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_uint256_$returns$__$","typeString":"function (string memory,uint256) pure"}},"id":280,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3194:61:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":281,"nodeType":"ExpressionStatement","src":"3194:61:0"},{"assignments":[283],"declarations":[{"constant":false,"id":283,"mutability":"mutable","name":"json","nameLocation":"3280:4:0","nodeType":"VariableDeclaration","scope":377,"src":"3266:18:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":282,"name":"string","nodeType":"ElementaryTypeName","src":"3266:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"id":285,"initialValue":{"hexValue":"7b22726f6f745f6b6579223a205b7b2261223a20312c202262223a20327d5d7d","id":284,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3287:34:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_e95522e99766888d0261f55bd1eae5e3f3e26eaf009a16e2433eafaf0a4ecdf2","typeString":"literal_string \"{\"root_key\": [{\"a\": 1, \"b\": 2}]}\""},"value":"{\"root_key\": [{\"a\": 1, \"b\": 2}]}"},"nodeType":"VariableDeclarationStatement","src":"3266:55:0"},{"assignments":[290],"declarations":[{"constant":false,"id":290,"mutability":"mutable","name":"keys","nameLocation":"3347:4:0","nodeType":"VariableDeclaration","scope":377,"src":"3331:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string[]"},"typeName":{"baseType":{"id":288,"name":"string","nodeType":"ElementaryTypeName","src":"3331:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"id":289,"nodeType":"ArrayTypeName","src":"3331:8:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_storage_$dyn_storage_ptr","typeString":"string[]"}},"visibility":"internal"}],"id":296,"initialValue":{"arguments":[{"id":293,"name":"json","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":283,"src":"3371:4:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"hexValue":"2e726f6f745f6b65795b305d","id":294,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3377:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_d82f67100edb80050915e1ec4b565c9a8319a22efb1075e1298b7bb60101d266","typeString":"literal_string \".root_key[0]\""},"value":".root_key[0]"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_stringliteral_d82f67100edb80050915e1ec4b565c9a8319a22efb1075e1298b7bb60101d266","typeString":"literal_string \".root_key[0]\""}],"expression":{"id":291,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"3354:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":292,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"parseJsonKeys","nodeType":"MemberAccess","referencedDeclaration":27,"src":"3354:16:0","typeDescriptions":{"typeIdentifier":"t_function_external_pure$_t_string_memory_ptr_$_t_string_memory_ptr_$returns$_t_array$_t_string_memory_ptr_$dyn_memory_ptr_$","typeString":"function (string memory,string memory) pure external returns (string memory[] memory)"}},"id":295,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3354:38:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string memory[] memory"}},"nodeType":"VariableDeclarationStatement","src":"3331:61:0"},{"expression":{"arguments":[{"hexValue":"6b657973","id":300,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3414:6:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_f29790a80c4ce5f42f59892f424f9c92856c6b656c3378e2cf305b260c6f4195","typeString":"literal_string \"keys\""},"value":"keys"},{"baseExpression":{"id":301,"name":"keys","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":290,"src":"3422:4:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string memory[] memory"}},"id":303,"indexExpression":{"hexValue":"30","id":302,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"3427:1:0","typeDescriptions":{"typeIdentifier":"t_rational_0_by_1","typeString":"int_const 0"},"value":"0"},"isConstant":false,"isLValue":true,"isPure":false,"lValueRequested":false,"nodeType":"IndexAccess","src":"3422:7:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"baseExpression":{"id":304,"name":"keys","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":290,"src":"3431:4:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string memory[] memory"}},"id":306,"indexExpression":{"hexValue":"31","id":305,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"3436:1:0","typeDescriptions":{"typeIdentifier":"t_rational_1_by_1","typeString":"int_const 1"},"value":"1"},"isConstant":false,"isLValue":true,"isPure":false,"lValueRequested":false,"nodeType":"IndexAccess","src":"3431:7:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_f29790a80c4ce5f42f59892f424f9c92856c6b656c3378e2cf305b260c6f4195","typeString":"literal_string \"keys\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}],"expression":{"id":297,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3402:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":299,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":191,"src":"3402:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_string_memory_ptr_$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory,string memory,string memory) pure"}},"id":307,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3402:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":308,"nodeType":"ExpressionStatement","src":"3402:37:0"},{"expression":{"arguments":[{"hexValue":"66726f6d206f726967696e616c","id":312,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3461:15:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_77928970c8757d110f3c23e003246f49e0de890480ba9717ba659b2f56f316b2","typeString":"literal_string \"from original\""},"value":"from original"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_77928970c8757d110f3c23e003246f49e0de890480ba9717ba659b2f56f316b2","typeString":"literal_string \"from original\""}],"expression":{"id":309,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3450:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":311,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":633,"src":"3450:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":313,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3450:27:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":314,"nodeType":"ExpressionStatement","src":"3450:27:0"},{"expression":{"arguments":[{"arguments":[{"arguments":[{"hexValue":"30783432","id":322,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"3517:4:0","typeDescriptions":{"typeIdentifier":"t_rational_66_by_1","typeString":"int_const 66"},"value":"0x42"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_66_by_1","typeString":"int_const 66"}],"id":321,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3509:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":320,"name":"uint160","nodeType":"ElementaryTypeName","src":"3509:7:0","typeDescriptions":{}}},"id":323,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3509:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":319,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3501:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":318,"name":"address","nodeType":"ElementaryTypeName","src":"3501:7:0","typeDescriptions":{}}},"id":324,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3501:22:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":315,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"3487:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":317,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"startPrank","nodeType":"MemberAccess","referencedDeclaration":32,"src":"3487:13:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_address_$returns$__$","typeString":"function (address) external"}},"id":325,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3487:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":326,"nodeType":"ExpressionStatement","src":"3487:37:0"},{"expression":{"arguments":[{"hexValue":"66726f6d207072616e6b2031","id":330,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3545:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_42b34abfe37a8b0add910cda7b4a379e6538fa7a1dcafce47a02bd38f6c88e2a","typeString":"literal_string \"from prank 1\""},"value":"from prank 1"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_42b34abfe37a8b0add910cda7b4a379e6538fa7a1dcafce47a02bd38f6c88e2a","typeString":"literal_string \"from prank 1\""}],"expression":{"id":327,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3534:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":329,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":633,"src":"3534:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":331,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3534:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":332,"nodeType":"ExpressionStatement","src":"3534:26:0"},{"expression":{"arguments":[{"hexValue":"706172656e742073636f7065206d73672e73656e646572","id":336,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3582:25:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_83ec9246154d8845de47aafc5c2865c9985d2efe84472c27283879f2fbf5cc94","typeString":"literal_string \"parent scope msg.sender\""},"value":"parent scope msg.sender"},{"arguments":[{"expression":{"id":339,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"3617:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":340,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"3617:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":338,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3609:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":337,"name":"address","nodeType":"ElementaryTypeName","src":"3609:7:0","typeDescriptions":{}}},"id":341,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3609:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_83ec9246154d8845de47aafc5c2865c9985d2efe84472c27283879f2fbf5cc94","typeString":"literal_string \"parent scope msg.sender\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":333,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3570:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":335,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":171,"src":"3570:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":342,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3570:59:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":343,"nodeType":"ExpressionStatement","src":"3570:59:0"},{"expression":{"arguments":[{"hexValue":"706172656e742073636f706520636f6e74726163742e61646472","id":347,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3651:28:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_97df66250e0b2b48f0ec8d0e01eb1b8ca012d95f1572895622aa1ea433e5570f","typeString":"literal_string \"parent scope contract.addr\""},"value":"parent scope contract.addr"},{"arguments":[{"id":350,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3689:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}],"id":349,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3681:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":348,"name":"address","nodeType":"ElementaryTypeName","src":"3681:7:0","typeDescriptions":{}}},"id":351,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3681:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_97df66250e0b2b48f0ec8d0e01eb1b8ca012d95f1572895622aa1ea433e5570f","typeString":"literal_string \"parent scope contract.addr\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":344,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3639:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":346,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":171,"src":"3639:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":352,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3639:56:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":353,"nodeType":"ExpressionStatement","src":"3639:56:0"},{"expression":{"arguments":[{"hexValue":"66726f6d207072616e6b2032","id":357,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3716:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_a38a34f8cad750a79aa097a92971f8f405b51ee9d53d25c5b14fc129ba3684bb","typeString":"literal_string \"from prank 2\""},"value":"from prank 2"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_a38a34f8cad750a79aa097a92971f8f405b51ee9d53d25c5b14fc129ba3684bb","typeString":"literal_string \"from prank 2\""}],"expression":{"id":354,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3705:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":356,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":633,"src":"3705:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":358,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3705:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":359,"nodeType":"ExpressionStatement","src":"3705:26:0"},{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":360,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"3741:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":362,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"stopPrank","nodeType":"MemberAccess","referencedDeclaration":35,"src":"3741:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$__$returns$__$","typeString":"function () external"}},"id":363,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3741:14:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":364,"nodeType":"ExpressionStatement","src":"3741:14:0"},{"expression":{"arguments":[{"hexValue":"66726f6d206f726967696e616c20616761696e","id":368,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3776:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_0c805c6579e20a9c4c8e11aeab23330910a9f2da629191dc119d1730e8ed6860","typeString":"literal_string \"from original again\""},"value":"from original again"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_0c805c6579e20a9c4c8e11aeab23330910a9f2da629191dc119d1730e8ed6860","typeString":"literal_string \"from original again\""}],"expression":{"id":365,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3765:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":367,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":633,"src":"3765:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":369,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3765:33:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":370,"nodeType":"ExpressionStatement","src":"3765:33:0"},{"expression":{"arguments":[{"hexValue":"646f6e6521","id":374,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3821:7:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_080382d5c9e9e7c5e3d1d33f5e7422740375955180fadff167d8130e0c35f3fc","typeString":"literal_string \"done!\""},"value":"done!"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_080382d5c9e9e7c5e3d1d33f5e7422740375955180fadff167d8130e0c35f3fc","typeString":"literal_string \"done!\""}],"expression":{"id":371,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3809:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":373,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"3809:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":375,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3809:20:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":376,"nodeType":"ExpressionStatement","src":"3809:20:0"}]},"documentation":{"id":216,"nodeType":"StructuredDocumentation","src":"2804:78:0","text":"@notice example function, runs through basic cheat-codes and console logs."},"functionSelector":"c0406226","implemented":true,"kind":"function","modifiers":[],"name":"run","nameLocation":"2896:3:0","parameters":{"id":217,"nodeType":"ParameterList","parameters":[],"src":"2899:2:0"},"returnParameters":{"id":218,"nodeType":"ParameterList","parameters":[],"src":"2909:0:0"},"scope":706,"stateMutability":"nonpayable","virtual":false,"visibility":"public"},{"id":609,"nodeType":"FunctionDefinition","src":"3903:1258:0","nodes":[],"body":{"id":608,"nodeType":"Block","src":"3934:1227:0","nodes":[],"statements":[{"expression":{"arguments":[{"hexValue":"6e6f6e6365207374617274","id":385,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3956:13:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_71efc69b9a13b6bc1e9a14d766ff01c79022262c6daa6532fb5dfb14f8511a20","typeString":"literal_string \"nonce start\""},"value":"nonce start"},{"arguments":[{"arguments":[{"arguments":[{"id":392,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3999:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}],"id":391,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3991:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":390,"name":"address","nodeType":"ElementaryTypeName","src":"3991:7:0","typeDescriptions":{}}},"id":393,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3991:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":388,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"3979:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":389,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"getNonce","nodeType":"MemberAccess","referencedDeclaration":17,"src":"3979:11:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_address_$returns$_t_uint64_$","typeString":"function (address) view external returns (uint64)"}},"id":394,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3979:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint64","typeString":"uint64"}],"id":387,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3971:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint256_$","typeString":"type(uint256)"},"typeName":{"id":386,"name":"uint256","nodeType":"ElementaryTypeName","src":"3971:7:0","typeDescriptions":{}}},"id":395,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3971:35:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_71efc69b9a13b6bc1e9a14d766ff01c79022262c6daa6532fb5dfb14f8511a20","typeString":"literal_string \"nonce start\""},{"typeIdentifier":"t_uint256","typeString":"uint256"}],"expression":{"id":382,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3944:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":384,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":154,"src":"3944:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_uint256_$returns$__$","typeString":"function (string memory,uint256) pure"}},"id":396,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3944:63:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":397,"nodeType":"ExpressionStatement","src":"3944:63:0"},{"expression":{"arguments":[{"hexValue":"74657374696e672073696e676c65","id":401,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4030:16:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_b75103528423218e7569082dad569ed0d2ce7c0ac770c0812b220e2d369fe474","typeString":"literal_string \"testing single\""},"value":"testing single"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_b75103528423218e7569082dad569ed0d2ce7c0ac770c0812b220e2d369fe474","typeString":"literal_string \"testing single\""}],"expression":{"id":398,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"4018:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":400,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"4018:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":402,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4018:29:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":403,"nodeType":"ExpressionStatement","src":"4018:29:0"},{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":404,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4057:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":406,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"broadcast","nodeType":"MemberAccess","referencedDeclaration":38,"src":"4057:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$__$returns$__$","typeString":"function () external"}},"id":407,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4057:14:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":408,"nodeType":"ExpressionStatement","src":"4057:14:0"},{"expression":{"arguments":[{"hexValue":"73696e676c655f63616c6c31","id":412,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4092:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_5e1cad6d7a968cfacf2731373e1248ffb11f4886bced66a02a6de1a67ac8f777","typeString":"literal_string \"single_call1\""},"value":"single_call1"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_5e1cad6d7a968cfacf2731373e1248ffb11f4886bced66a02a6de1a67ac8f777","typeString":"literal_string \"single_call1\""}],"expression":{"id":409,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4081:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":411,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"call1","nodeType":"MemberAccess","referencedDeclaration":648,"src":"4081:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":413,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4081:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":414,"nodeType":"ExpressionStatement","src":"4081:26:0"},{"expression":{"arguments":[{"hexValue":"73696e676c655f63616c6c32","id":418,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4128:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_b37ddaf5d00ad9e6371de3fb71b91eef731fae1e86b768666380f7d44e1ada25","typeString":"literal_string \"single_call2\""},"value":"single_call2"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_b37ddaf5d00ad9e6371de3fb71b91eef731fae1e86b768666380f7d44e1ada25","typeString":"literal_string \"single_call2\""}],"expression":{"id":415,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4117:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":417,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"call2","nodeType":"MemberAccess","referencedDeclaration":663,"src":"4117:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":419,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4117:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":420,"nodeType":"ExpressionStatement","src":"4117:26:0"},{"expression":{"arguments":[{"hexValue":"74657374696e672073746172742f73746f70","id":424,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4166:20:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_778e886e3a1c3c5096aca76228832105f3f9269f362effd0e8ce3737787cb784","typeString":"literal_string \"testing start/stop\""},"value":"testing start/stop"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_778e886e3a1c3c5096aca76228832105f3f9269f362effd0e8ce3737787cb784","typeString":"literal_string \"testing start/stop\""}],"expression":{"id":421,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"4154:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":423,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"4154:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":425,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4154:33:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":426,"nodeType":"ExpressionStatement","src":"4154:33:0"},{"expression":{"arguments":[{"arguments":[{"arguments":[{"hexValue":"3078633066666565","id":434,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4231:8:0","typeDescriptions":{"typeIdentifier":"t_rational_12648430_by_1","typeString":"int_const 12648430"},"value":"0xc0ffee"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_12648430_by_1","typeString":"int_const 12648430"}],"id":433,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4223:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":432,"name":"uint160","nodeType":"ElementaryTypeName","src":"4223:7:0","typeDescriptions":{}}},"id":435,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4223:17:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":431,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4215:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":430,"name":"address","nodeType":"ElementaryTypeName","src":"4215:7:0","typeDescriptions":{}}},"id":436,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4215:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":427,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4197:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":429,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"startBroadcast","nodeType":"MemberAccess","referencedDeclaration":48,"src":"4197:17:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_address_$returns$__$","typeString":"function (address) external"}},"id":437,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4197:45:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":438,"nodeType":"ExpressionStatement","src":"4197:45:0"},{"expression":{"arguments":[{"hexValue":"737461727473746f705f63616c6c31","id":442,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4263:17:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_2fc2682edf10ed478ee3b9a190f6b1c88bb492b300935ce44545a1613cf8f041","typeString":"literal_string \"startstop_call1\""},"value":"startstop_call1"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_2fc2682edf10ed478ee3b9a190f6b1c88bb492b300935ce44545a1613cf8f041","typeString":"literal_string \"startstop_call1\""}],"expression":{"id":439,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4252:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":441,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"call1","nodeType":"MemberAccess","referencedDeclaration":648,"src":"4252:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":443,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4252:29:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":444,"nodeType":"ExpressionStatement","src":"4252:29:0"},{"expression":{"arguments":[{"hexValue":"737461727473746f705f63616c6c32","id":448,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4302:17:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_1a6fd77f04b28bf45d6d0e2dd4c65c0bbfeba174f849e43bb67ebca1c019cda4","typeString":"literal_string \"startstop_call2\""},"value":"startstop_call2"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_1a6fd77f04b28bf45d6d0e2dd4c65c0bbfeba174f849e43bb67ebca1c019cda4","typeString":"literal_string \"startstop_call2\""}],"expression":{"id":445,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4291:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":447,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"call2","nodeType":"MemberAccess","referencedDeclaration":663,"src":"4291:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":449,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4291:29:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":450,"nodeType":"ExpressionStatement","src":"4291:29:0"},{"expression":{"arguments":[{"hexValue":"737461727473746f705f70757265","id":454,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4344:16:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_b6e9eb1efd186b1d92b54da45026aa97a178e6eaffdf9dbf9f666fc751fb0ff9","typeString":"literal_string \"startstop_pure\""},"value":"startstop_pure"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_b6e9eb1efd186b1d92b54da45026aa97a178e6eaffdf9dbf9f666fc751fb0ff9","typeString":"literal_string \"startstop_pure\""}],"expression":{"id":451,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4330:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":453,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"callPure","nodeType":"MemberAccess","referencedDeclaration":705,"src":"4330:13:0","typeDescriptions":{"typeIdentifier":"t_function_external_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure external"}},"id":455,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4330:31:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":456,"nodeType":"ExpressionStatement","src":"4330:31:0"},{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":457,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4371:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":459,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"stopBroadcast","nodeType":"MemberAccess","referencedDeclaration":54,"src":"4371:16:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$__$returns$__$","typeString":"function () external"}},"id":460,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4371:18:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":461,"nodeType":"ExpressionStatement","src":"4371:18:0"},{"expression":{"arguments":[{"hexValue":"737461727473746f705f63616c6c33","id":465,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4410:17:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_8eb502bfdc4adda22bd960aa2ae13ce4c0ed8cc3b3791ed65e321a38cdd36f72","typeString":"literal_string \"startstop_call3\""},"value":"startstop_call3"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_8eb502bfdc4adda22bd960aa2ae13ce4c0ed8cc3b3791ed65e321a38cdd36f72","typeString":"literal_string \"startstop_call3\""}],"expression":{"id":462,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4399:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":464,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"call1","nodeType":"MemberAccess","referencedDeclaration":648,"src":"4399:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":466,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4399:29:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":467,"nodeType":"ExpressionStatement","src":"4399:29:0"},{"expression":{"arguments":[{"hexValue":"74657374696e67206e6573746564","id":471,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4451:16:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_f92f19f7a5b5b9ce341188bf4e15925f184cdb5ac135c4846ced718f259dbde5","typeString":"literal_string \"testing nested\""},"value":"testing nested"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_f92f19f7a5b5b9ce341188bf4e15925f184cdb5ac135c4846ced718f259dbde5","typeString":"literal_string \"testing nested\""}],"expression":{"id":468,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"4439:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":470,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"4439:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":472,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4439:29:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":473,"nodeType":"ExpressionStatement","src":"4439:29:0"},{"expression":{"arguments":[{"arguments":[{"arguments":[{"hexValue":"307831323334","id":481,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4512:6:0","typeDescriptions":{"typeIdentifier":"t_rational_4660_by_1","typeString":"int_const 4660"},"value":"0x1234"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_4660_by_1","typeString":"int_const 4660"}],"id":480,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4504:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":479,"name":"uint160","nodeType":"ElementaryTypeName","src":"4504:7:0","typeDescriptions":{}}},"id":482,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4504:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":478,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4496:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":477,"name":"address","nodeType":"ElementaryTypeName","src":"4496:7:0","typeDescriptions":{}}},"id":483,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4496:24:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":474,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4478:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":476,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"startBroadcast","nodeType":"MemberAccess","referencedDeclaration":48,"src":"4478:17:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_address_$returns$__$","typeString":"function (address) external"}},"id":484,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4478:43:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":485,"nodeType":"ExpressionStatement","src":"4478:43:0"},{"expression":{"arguments":[{"hexValue":"6e6573746564","id":489,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4544:8:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_4d5b14044d78fbf0c9dd8b9c49e35f09ee5a6f5b1b3b8117b5d0e15c8dd2cb09","typeString":"literal_string \"nested\""},"value":"nested"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_4d5b14044d78fbf0c9dd8b9c49e35f09ee5a6f5b1b3b8117b5d0e15c8dd2cb09","typeString":"literal_string \"nested\""}],"expression":{"id":486,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4531:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":488,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"nested1","nodeType":"MemberAccess","referencedDeclaration":678,"src":"4531:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":490,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4531:22:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":491,"nodeType":"ExpressionStatement","src":"4531:22:0"},{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":492,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4563:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":494,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"stopBroadcast","nodeType":"MemberAccess","referencedDeclaration":54,"src":"4563:16:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$__$returns$__$","typeString":"function () external"}},"id":495,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4563:18:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":496,"nodeType":"ExpressionStatement","src":"4563:18:0"},{"expression":{"arguments":[{"hexValue":"636f6e7472616374206465706c6f796d656e74","id":500,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4604:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_aaf9be86adf9b6872d87eed3526f7c55f3c5d61f4e4dd6d55ef2fcbb8ad0bd57","typeString":"literal_string \"contract deployment\""},"value":"contract deployment"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_aaf9be86adf9b6872d87eed3526f7c55f3c5d61f4e4dd6d55ef2fcbb8ad0bd57","typeString":"literal_string \"contract deployment\""}],"expression":{"id":497,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"4592:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":499,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"4592:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":501,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4592:34:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":502,"nodeType":"ExpressionStatement","src":"4592:34:0"},{"expression":{"arguments":[{"arguments":[{"arguments":[{"hexValue":"3078313233343536","id":510,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4665:8:0","typeDescriptions":{"typeIdentifier":"t_rational_1193046_by_1","typeString":"int_const 1193046"},"value":"0x123456"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_1193046_by_1","typeString":"int_const 1193046"}],"id":509,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4657:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":508,"name":"uint160","nodeType":"ElementaryTypeName","src":"4657:7:0","typeDescriptions":{}}},"id":511,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4657:17:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":507,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4649:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":506,"name":"address","nodeType":"ElementaryTypeName","src":"4649:7:0","typeDescriptions":{}}},"id":512,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4649:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":503,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4636:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":505,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"broadcast","nodeType":"MemberAccess","referencedDeclaration":43,"src":"4636:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_address_$returns$__$","typeString":"function (address) external"}},"id":513,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4636:40:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":514,"nodeType":"ExpressionStatement","src":"4636:40:0"},{"assignments":[517],"declarations":[{"constant":false,"id":517,"mutability":"mutable","name":"x","nameLocation":"4693:1:0","nodeType":"VariableDeclaration","scope":608,"src":"4686:8:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"},"typeName":{"id":516,"nodeType":"UserDefinedTypeName","pathNode":{"id":515,"name":"FooBar","nodeType":"IdentifierPath","referencedDeclaration":719,"src":"4686:6:0"},"referencedDeclaration":719,"src":"4686:6:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"visibility":"internal"}],"id":523,"initialValue":{"arguments":[{"hexValue":"31323334","id":521,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4708:4:0","typeDescriptions":{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"},"value":"1234"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"}],"id":520,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"NewExpression","src":"4697:10:0","typeDescriptions":{"typeIdentifier":"t_function_creation_nonpayable$_t_uint256_$returns$_t_contract$_FooBar_$719_$","typeString":"function (uint256) returns (contract FooBar)"},"typeName":{"id":519,"nodeType":"UserDefinedTypeName","pathNode":{"id":518,"name":"FooBar","nodeType":"IdentifierPath","referencedDeclaration":719,"src":"4701:6:0"},"referencedDeclaration":719,"src":"4701:6:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}}},"id":522,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4697:16:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"nodeType":"VariableDeclarationStatement","src":"4686:27:0"},{"expression":{"arguments":[{"commonType":{"typeIdentifier":"t_uint256","typeString":"uint256"},"id":529,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"leftExpression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":525,"name":"x","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":517,"src":"4731:1:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"id":526,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"foo","nodeType":"MemberAccess","referencedDeclaration":708,"src":"4731:5:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$__$returns$_t_uint256_$","typeString":"function () view external returns (uint256)"}},"id":527,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4731:7:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"nodeType":"BinaryOperation","operator":"==","rightExpression":{"hexValue":"31323334","id":528,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4742:4:0","typeDescriptions":{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"},"value":"1234"},"src":"4731:15:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bool","typeString":"bool"}],"id":524,"name":"require","nodeType":"Identifier","overloadedDeclarations":[-18,-18],"referencedDeclaration":-18,"src":"4723:7:0","typeDescriptions":{"typeIdentifier":"t_function_require_pure$_t_bool_$returns$__$","typeString":"function (bool) pure"}},"id":530,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4723:24:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":531,"nodeType":"ExpressionStatement","src":"4723:24:0"},{"expression":{"arguments":[{"hexValue":"6372656174652032","id":535,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4770:10:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_4411d6d4ffcd00382a95255a63761e69de9810e1236042a5c64948a7b6c04daa","typeString":"literal_string \"create 2\""},"value":"create 2"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_4411d6d4ffcd00382a95255a63761e69de9810e1236042a5c64948a7b6c04daa","typeString":"literal_string \"create 2\""}],"expression":{"id":532,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"4758:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":534,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"4758:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":536,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4758:23:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":537,"nodeType":"ExpressionStatement","src":"4758:23:0"},{"expression":{"arguments":[{"arguments":[{"arguments":[{"hexValue":"307863616665","id":545,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4820:6:0","typeDescriptions":{"typeIdentifier":"t_rational_51966_by_1","typeString":"int_const 51966"},"value":"0xcafe"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_51966_by_1","typeString":"int_const 51966"}],"id":544,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4812:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":543,"name":"uint160","nodeType":"ElementaryTypeName","src":"4812:7:0","typeDescriptions":{}}},"id":546,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4812:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":542,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4804:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":541,"name":"address","nodeType":"ElementaryTypeName","src":"4804:7:0","typeDescriptions":{}}},"id":547,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4804:24:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":538,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4791:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":540,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"broadcast","nodeType":"MemberAccess","referencedDeclaration":43,"src":"4791:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_address_$returns$__$","typeString":"function (address) external"}},"id":548,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4791:38:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":549,"nodeType":"ExpressionStatement","src":"4791:38:0"},{"assignments":[552],"declarations":[{"constant":false,"id":552,"mutability":"mutable","name":"y","nameLocation":"4846:1:0","nodeType":"VariableDeclaration","scope":608,"src":"4839:8:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"},"typeName":{"id":551,"nodeType":"UserDefinedTypeName","pathNode":{"id":550,"name":"FooBar","nodeType":"IdentifierPath","referencedDeclaration":719,"src":"4839:6:0"},"referencedDeclaration":719,"src":"4839:6:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"visibility":"internal"}],"id":566,"initialValue":{"arguments":[{"hexValue":"31323334","id":564,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4889:4:0","typeDescriptions":{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"},"value":"1234"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"}],"id":555,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"NewExpression","src":"4850:10:0","typeDescriptions":{"typeIdentifier":"t_function_creation_nonpayable$_t_uint256_$returns$_t_contract$_FooBar_$719_$","typeString":"function (uint256) returns (contract FooBar)"},"typeName":{"id":554,"nodeType":"UserDefinedTypeName","pathNode":{"id":553,"name":"FooBar","nodeType":"IdentifierPath","referencedDeclaration":719,"src":"4854:6:0"},"referencedDeclaration":719,"src":"4854:6:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}}},"id":563,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"names":["salt"],"nodeType":"FunctionCallOptions","options":[{"arguments":[{"arguments":[{"hexValue":"3432","id":560,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4883:2:0","typeDescriptions":{"typeIdentifier":"t_rational_42_by_1","typeString":"int_const 42"},"value":"42"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_42_by_1","typeString":"int_const 42"}],"id":559,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4875:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint256_$","typeString":"type(uint256)"},"typeName":{"id":558,"name":"uint256","nodeType":"ElementaryTypeName","src":"4875:7:0","typeDescriptions":{}}},"id":561,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4875:11:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint256","typeString":"uint256"}],"id":557,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4867:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_bytes32_$","typeString":"type(bytes32)"},"typeName":{"id":556,"name":"bytes32","nodeType":"ElementaryTypeName","src":"4867:7:0","typeDescriptions":{}}},"id":562,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4867:20:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes32","typeString":"bytes32"}}],"src":"4850:38:0","typeDescriptions":{"typeIdentifier":"t_function_creation_nonpayable$_t_uint256_$returns$_t_contract$_FooBar_$719_$salt","typeString":"function (uint256) returns (contract FooBar)"}},"id":565,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4850:44:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"nodeType":"VariableDeclarationStatement","src":"4839:55:0"},{"expression":{"arguments":[{"commonType":{"typeIdentifier":"t_uint256","typeString":"uint256"},"id":572,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"leftExpression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":568,"name":"y","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":552,"src":"4912:1:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"id":569,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"foo","nodeType":"MemberAccess","referencedDeclaration":708,"src":"4912:5:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$__$returns$_t_uint256_$","typeString":"function () view external returns (uint256)"}},"id":570,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4912:7:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"nodeType":"BinaryOperation","operator":"==","rightExpression":{"hexValue":"31323334","id":571,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4923:4:0","typeDescriptions":{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"},"value":"1234"},"src":"4912:15:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bool","typeString":"bool"}],"id":567,"name":"require","nodeType":"Identifier","overloadedDeclarations":[-18,-18],"referencedDeclaration":-18,"src":"4904:7:0","typeDescriptions":{"typeIdentifier":"t_function_require_pure$_t_bool_$returns$__$","typeString":"function (bool) pure"}},"id":573,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4904:24:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":574,"nodeType":"ExpressionStatement","src":"4904:24:0"},{"expression":{"arguments":[{"hexValue":"646f6e6521","id":578,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4950:7:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_080382d5c9e9e7c5e3d1d33f5e7422740375955180fadff167d8130e0c35f3fc","typeString":"literal_string \"done!\""},"value":"done!"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_080382d5c9e9e7c5e3d1d33f5e7422740375955180fadff167d8130e0c35f3fc","typeString":"literal_string \"done!\""}],"expression":{"id":575,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"4938:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":577,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"4938:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":579,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4938:20:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":580,"nodeType":"ExpressionStatement","src":"4938:20:0"},{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":581,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"5042:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":583,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"broadcast","nodeType":"MemberAccess","referencedDeclaration":38,"src":"5042:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$__$returns$__$","typeString":"function () external"}},"id":584,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5042:14:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":585,"nodeType":"ExpressionStatement","src":"5042:14:0"},{"expression":{"arguments":[{"hexValue":"31323334","id":589,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"5077:4:0","typeDescriptions":{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"},"value":"1234"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"}],"id":588,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"NewExpression","src":"5066:10:0","typeDescriptions":{"typeIdentifier":"t_function_creation_nonpayable$_t_uint256_$returns$_t_contract$_FooBar_$719_$","typeString":"function (uint256) returns (contract FooBar)"},"typeName":{"id":587,"nodeType":"UserDefinedTypeName","pathNode":{"id":586,"name":"FooBar","nodeType":"IdentifierPath","referencedDeclaration":719,"src":"5070:6:0"},"referencedDeclaration":719,"src":"5070:6:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}}},"id":590,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5066:16:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"id":591,"nodeType":"ExpressionStatement","src":"5066:16:0"},{"expression":{"arguments":[{"hexValue":"6e6f6e636520656e64","id":595,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"5105:11:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_fa629e6661ad2a2bdb09cf9a3a276ce0d722482ae5c2887650751be0938847e8","typeString":"literal_string \"nonce end\""},"value":"nonce end"},{"arguments":[{"arguments":[{"arguments":[{"id":602,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"5146:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}],"id":601,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"5138:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":600,"name":"address","nodeType":"ElementaryTypeName","src":"5138:7:0","typeDescriptions":{}}},"id":603,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5138:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":598,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"5126:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":599,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"getNonce","nodeType":"MemberAccess","referencedDeclaration":17,"src":"5126:11:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_address_$returns$_t_uint64_$","typeString":"function (address) view external returns (uint64)"}},"id":604,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5126:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint64","typeString":"uint64"}],"id":597,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"5118:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint256_$","typeString":"type(uint256)"},"typeName":{"id":596,"name":"uint256","nodeType":"ElementaryTypeName","src":"5118:7:0","typeDescriptions":{}}},"id":605,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5118:35:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_fa629e6661ad2a2bdb09cf9a3a276ce0d722482ae5c2887650751be0938847e8","typeString":"literal_string \"nonce end\""},{"typeIdentifier":"t_uint256","typeString":"uint256"}],"expression":{"id":592,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5093:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":594,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":154,"src":"5093:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_uint256_$returns$__$","typeString":"function (string memory,uint256) pure"}},"id":606,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5093:61:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":607,"nodeType":"ExpressionStatement","src":"5093:61:0"}]},"documentation":{"id":379,"nodeType":"StructuredDocumentation","src":"3842:56:0","text":"@notice example function, to test vm.broadcast with."},"functionSelector":"bef03abc","implemented":true,"kind":"function","modifiers":[],"name":"runBroadcast","nameLocation":"3912:12:0","parameters":{"id":380,"nodeType":"ParameterList","parameters":[],"src":"3924:2:0"},"returnParameters":{"id":381,"nodeType":"ParameterList","parameters":[],"src":"3934:0:0"},"scope":706,"stateMutability":"nonpayable","virtual":false,"visibility":"public"},{"id":633,"nodeType":"FunctionDefinition","src":"5256:143:0","nodes":[],"body":{"id":632,"nodeType":"Block","src":"5305:94:0","nodes":[],"statements":[{"expression":{"arguments":[{"id":618,"name":"_v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":612,"src":"5327:2:0","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}],"expression":{"id":615,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5315:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":617,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"5315:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":619,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5315:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":620,"nodeType":"ExpressionStatement","src":"5315:15:0"},{"expression":{"arguments":[{"hexValue":"68656c6c6f206d73672e73656e646572","id":624,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"5352:18:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_b3cc13bc51228b2c4c4334d82a4772908254dc0e1c512893dd16208ef13efb8e","typeString":"literal_string \"hello msg.sender\""},"value":"hello msg.sender"},{"arguments":[{"expression":{"id":627,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"5380:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":628,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"5380:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":626,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"5372:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":625,"name":"address","nodeType":"ElementaryTypeName","src":"5372:7:0","typeDescriptions":{}}},"id":629,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5372:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_b3cc13bc51228b2c4c4334d82a4772908254dc0e1c512893dd16208ef13efb8e","typeString":"literal_string \"hello msg.sender\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":621,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5340:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":623,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":171,"src":"5340:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":630,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5340:52:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":631,"nodeType":"ExpressionStatement","src":"5340:52:0"}]},"documentation":{"id":610,"nodeType":"StructuredDocumentation","src":"5167:84:0","text":"@notice example external function, to force a CALL, and test vm.startPrank with."},"functionSelector":"a777d0dc","implemented":true,"kind":"function","modifiers":[],"name":"hello","nameLocation":"5265:5:0","parameters":{"id":613,"nodeType":"ParameterList","parameters":[{"constant":false,"id":612,"mutability":"mutable","name":"_v","nameLocation":"5287:2:0","nodeType":"VariableDeclaration","scope":633,"src":"5271:18:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":611,"name":"string","nodeType":"ElementaryTypeName","src":"5271:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"5270:20:0"},"returnParameters":{"id":614,"nodeType":"ParameterList","parameters":[],"src":"5305:0:0"},"scope":706,"stateMutability":"view","virtual":false,"visibility":"external"},{"id":648,"nodeType":"FunctionDefinition","src":"5405:95:0","nodes":[],"body":{"id":647,"nodeType":"Block","src":"5449:51:0","nodes":[],"statements":[{"expression":{"id":639,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"UnaryOperation","operator":"++","prefix":false,"src":"5459:9:0","subExpression":{"id":638,"name":"counter","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":215,"src":"5459:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"id":640,"nodeType":"ExpressionStatement","src":"5459:9:0"},{"expression":{"arguments":[{"id":644,"name":"_v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":635,"src":"5490:2:0","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}],"expression":{"id":641,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5478:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":643,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"5478:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":645,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5478:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":646,"nodeType":"ExpressionStatement","src":"5478:15:0"}]},"functionSelector":"7e79255d","implemented":true,"kind":"function","modifiers":[],"name":"call1","nameLocation":"5414:5:0","parameters":{"id":636,"nodeType":"ParameterList","parameters":[{"constant":false,"id":635,"mutability":"mutable","name":"_v","nameLocation":"5436:2:0","nodeType":"VariableDeclaration","scope":648,"src":"5420:18:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":634,"name":"string","nodeType":"ElementaryTypeName","src":"5420:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"5419:20:0"},"returnParameters":{"id":637,"nodeType":"ParameterList","parameters":[],"src":"5449:0:0"},"scope":706,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":663,"nodeType":"FunctionDefinition","src":"5506:95:0","nodes":[],"body":{"id":662,"nodeType":"Block","src":"5550:51:0","nodes":[],"statements":[{"expression":{"id":654,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"UnaryOperation","operator":"++","prefix":false,"src":"5560:9:0","subExpression":{"id":653,"name":"counter","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":215,"src":"5560:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"id":655,"nodeType":"ExpressionStatement","src":"5560:9:0"},{"expression":{"arguments":[{"id":659,"name":"_v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":650,"src":"5591:2:0","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}],"expression":{"id":656,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5579:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":658,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"5579:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":660,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5579:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":661,"nodeType":"ExpressionStatement","src":"5579:15:0"}]},"functionSelector":"8d3ef7ca","implemented":true,"kind":"function","modifiers":[],"name":"call2","nameLocation":"5515:5:0","parameters":{"id":651,"nodeType":"ParameterList","parameters":[{"constant":false,"id":650,"mutability":"mutable","name":"_v","nameLocation":"5537:2:0","nodeType":"VariableDeclaration","scope":663,"src":"5521:18:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":649,"name":"string","nodeType":"ElementaryTypeName","src":"5521:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"5520:20:0"},"returnParameters":{"id":652,"nodeType":"ParameterList","parameters":[],"src":"5550:0:0"},"scope":706,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":678,"nodeType":"FunctionDefinition","src":"5607:98:0","nodes":[],"body":{"id":677,"nodeType":"Block","src":"5653:52:0","nodes":[],"statements":[{"expression":{"id":669,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"UnaryOperation","operator":"++","prefix":false,"src":"5663:9:0","subExpression":{"id":668,"name":"counter","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":215,"src":"5663:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"id":670,"nodeType":"ExpressionStatement","src":"5663:9:0"},{"expression":{"arguments":[{"id":674,"name":"_v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":665,"src":"5695:2:0","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}],"expression":{"id":671,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"5682:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":673,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"nested2","nodeType":"MemberAccess","referencedDeclaration":693,"src":"5682:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":675,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5682:16:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":676,"nodeType":"ExpressionStatement","src":"5682:16:0"}]},"functionSelector":"a76ccdfa","implemented":true,"kind":"function","modifiers":[],"name":"nested1","nameLocation":"5616:7:0","parameters":{"id":666,"nodeType":"ParameterList","parameters":[{"constant":false,"id":665,"mutability":"mutable","name":"_v","nameLocation":"5640:2:0","nodeType":"VariableDeclaration","scope":678,"src":"5624:18:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":664,"name":"string","nodeType":"ElementaryTypeName","src":"5624:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"5623:20:0"},"returnParameters":{"id":667,"nodeType":"ParameterList","parameters":[],"src":"5653:0:0"},"scope":706,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":693,"nodeType":"FunctionDefinition","src":"5711:97:0","nodes":[],"body":{"id":692,"nodeType":"Block","src":"5757:51:0","nodes":[],"statements":[{"expression":{"id":684,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"UnaryOperation","operator":"++","prefix":false,"src":"5767:9:0","subExpression":{"id":683,"name":"counter","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":215,"src":"5767:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"id":685,"nodeType":"ExpressionStatement","src":"5767:9:0"},{"expression":{"arguments":[{"id":689,"name":"_v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":680,"src":"5798:2:0","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}],"expression":{"id":686,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5786:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":688,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"5786:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":690,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5786:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":691,"nodeType":"ExpressionStatement","src":"5786:15:0"}]},"functionSelector":"dbf1282f","implemented":true,"kind":"function","modifiers":[],"name":"nested2","nameLocation":"5720:7:0","parameters":{"id":681,"nodeType":"ParameterList","parameters":[{"constant":false,"id":680,"mutability":"mutable","name":"_v","nameLocation":"5744:2:0","nodeType":"VariableDeclaration","scope":693,"src":"5728:18:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":679,"name":"string","nodeType":"ElementaryTypeName","src":"5728:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"5727:20:0"},"returnParameters":{"id":682,"nodeType":"ParameterList","parameters":[],"src":"5757:0:0"},"scope":706,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":705,"nodeType":"FunctionDefinition","src":"5814:84:0","nodes":[],"body":{"id":704,"nodeType":"Block","src":"5866:32:0","nodes":[],"statements":[{"expression":{"arguments":[{"id":701,"name":"_v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":695,"src":"5888:2:0","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}],"expression":{"id":698,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5876:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":700,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"5876:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":702,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5876:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":703,"nodeType":"ExpressionStatement","src":"5876:15:0"}]},"functionSelector":"7f8b915c","implemented":true,"kind":"function","modifiers":[],"name":"callPure","nameLocation":"5823:8:0","parameters":{"id":696,"nodeType":"ParameterList","parameters":[{"constant":false,"id":695,"mutability":"mutable","name":"_v","nameLocation":"5848:2:0","nodeType":"VariableDeclaration","scope":705,"src":"5832:18:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":694,"name":"string","nodeType":"ElementaryTypeName","src":"5832:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"5831:20:0"},"returnParameters":{"id":697,"nodeType":"ParameterList","parameters":[],"src":"5866:0:0"},"scope":706,"stateMutability":"pure","virtual":false,"visibility":"external"}],"abstract":false,"baseContracts":[],"canonicalName":"ScriptExample","contractDependencies":[719],"contractKind":"contract","documentation":{"id":193,"nodeType":"StructuredDocumentation","src":"2415:126:0","text":"@title ScriptExample\n @notice ScriptExample is an example script. The Go forge script code tests that it can run this."},"fullyImplemented":true,"linearizedBaseContracts":[706],"name":"ScriptExample","nameLocation":"2550:13:0","scope":720,"usedErrors":[]},{"id":719,"nodeType":"ContractDefinition","src":"5902:96:0","nodes":[{"id":708,"nodeType":"VariableDeclaration","src":"5924:18:0","nodes":[],"constant":false,"functionSelector":"c2985578","mutability":"mutable","name":"foo","nameLocation":"5939:3:0","scope":719,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":707,"name":"uint256","nodeType":"ElementaryTypeName","src":"5924:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"public"},{"id":718,"nodeType":"FunctionDefinition","src":"5949:47:0","nodes":[],"body":{"id":717,"nodeType":"Block","src":"5972:24:0","nodes":[],"statements":[{"expression":{"id":715,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"leftHandSide":{"id":713,"name":"foo","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":708,"src":"5982:3:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"nodeType":"Assignment","operator":"=","rightHandSide":{"id":714,"name":"v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":710,"src":"5988:1:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"src":"5982:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"id":716,"nodeType":"ExpressionStatement","src":"5982:7:0"}]},"implemented":true,"kind":"constructor","modifiers":[],"name":"","nameLocation":"-1:-1:-1","parameters":{"id":711,"nodeType":"ParameterList","parameters":[{"constant":false,"id":710,"mutability":"mutable","name":"v","nameLocation":"5969:1:0","nodeType":"VariableDeclaration","scope":718,"src":"5961:9:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":709,"name":"uint256","nodeType":"ElementaryTypeName","src":"5961:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"}],"src":"5960:11:0"},"returnParameters":{"id":712,"nodeType":"ParameterList","parameters":[],"src":"5972:0:0"},"scope":719,"stateMutability":"nonpayable","virtual":false,"visibility":"public"}],"abstract":false,"baseContracts":[],"canonicalName":"FooBar","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"linearizedBaseContracts":[719],"name":"FooBar","nameLocation":"5911:6:0","scope":720,"usedErrors":[]}],"license":"MIT"},"id":0} \ No newline at end of file diff --git a/op-chain-ops/script/testdata/test-artifacts/ScriptExample.s.sol/console.json b/op-chain-ops/script/testdata/test-artifacts/ScriptExample.s.sol/console.json index 23641034487bd..390e798a47011 100644 --- a/op-chain-ops/script/testdata/test-artifacts/ScriptExample.s.sol/console.json +++ b/op-chain-ops/script/testdata/test-artifacts/ScriptExample.s.sol/console.json @@ -1 +1 @@ -{"abi":[],"bytecode":{"object":"0x602d6037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea164736f6c634300080f000a","sourceMap":"568:1622:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;568:1622:0;;;;;;;;;;;;;;;;;","linkReferences":{}},"deployedBytecode":{"object":"0x73000000000000000000000000000000000000000030146080604052600080fdfea164736f6c634300080f000a","sourceMap":"568:1622:0:-:0;;;;;;;;","linkReferences":{}},"methodIdentifiers":{},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"scripts/ScriptExample.s.sol\":\"console\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[]},\"sources\":{\"scripts/ScriptExample.s.sol\":{\"keccak256\":\"0x531a2ad96c1a2c0bbfa9ab0e1195cd32551b0c10e16e7d256ce5e4c0289a8089\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://24dc6c71502c01f43fb5e113786e377c3b4cafabd5c506067d229fcdd7b037fa\",\"dweb:/ipfs/QmZ9AuxNx9Ygescfg5M4p6Abc2CCwCMZpX5xU32Fz1r4kY\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.15+commit.e14f2714"},"language":"Solidity","output":{"abi":[],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"remappings":[],"optimizer":{"enabled":true,"runs":999999},"metadata":{"bytecodeHash":"none"},"compilationTarget":{"scripts/ScriptExample.s.sol":"console"},"evmVersion":"london","libraries":{}},"sources":{"scripts/ScriptExample.s.sol":{"keccak256":"0x531a2ad96c1a2c0bbfa9ab0e1195cd32551b0c10e16e7d256ce5e4c0289a8089","urls":["bzz-raw://24dc6c71502c01f43fb5e113786e377c3b4cafabd5c506067d229fcdd7b037fa","dweb:/ipfs/QmZ9AuxNx9Ygescfg5M4p6Abc2CCwCMZpX5xU32Fz1r4kY"],"license":"MIT"}},"version":1},"storageLayout":{"storage":[],"types":{}},"userdoc":{"version":1,"kind":"user"},"devdoc":{"version":1,"kind":"dev"},"ast":{"absolutePath":"scripts/ScriptExample.s.sol","id":383,"exportedSymbols":{"ScriptExample":[382],"Vm":[36],"console":[173]},"nodeType":"SourceUnit","src":"32:3736:0","nodes":[{"id":1,"nodeType":"PragmaDirective","src":"32:23:0","nodes":[],"literals":["solidity","0.8",".15"]},{"id":36,"nodeType":"ContractDefinition","src":"120:393:0","nodes":[{"id":10,"nodeType":"FunctionDefinition","src":"139:91:0","nodes":[],"functionSelector":"4777f3cf","implemented":false,"kind":"function","modifiers":[],"name":"envOr","nameLocation":"148:5:0","parameters":{"id":6,"nodeType":"ParameterList","parameters":[{"constant":false,"id":3,"mutability":"mutable","name":"name","nameLocation":"170:4:0","nodeType":"VariableDeclaration","scope":10,"src":"154:20:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":2,"name":"string","nodeType":"ElementaryTypeName","src":"154:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":5,"mutability":"mutable","name":"defaultValue","nameLocation":"181:12:0","nodeType":"VariableDeclaration","scope":10,"src":"176:17:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":4,"name":"bool","nodeType":"ElementaryTypeName","src":"176:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"src":"153:41:0"},"returnParameters":{"id":9,"nodeType":"ParameterList","parameters":[{"constant":false,"id":8,"mutability":"mutable","name":"value","nameLocation":"223:5:0","nodeType":"VariableDeclaration","scope":10,"src":"218:10:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":7,"name":"bool","nodeType":"ElementaryTypeName","src":"218:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"src":"217:12:0"},"scope":36,"stateMutability":"view","virtual":false,"visibility":"external"},{"id":17,"nodeType":"FunctionDefinition","src":"235:72:0","nodes":[],"functionSelector":"2d0335ab","implemented":false,"kind":"function","modifiers":[],"name":"getNonce","nameLocation":"244:8:0","parameters":{"id":13,"nodeType":"ParameterList","parameters":[{"constant":false,"id":12,"mutability":"mutable","name":"account","nameLocation":"261:7:0","nodeType":"VariableDeclaration","scope":17,"src":"253:15:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":11,"name":"address","nodeType":"ElementaryTypeName","src":"253:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"252:17:0"},"returnParameters":{"id":16,"nodeType":"ParameterList","parameters":[{"constant":false,"id":15,"mutability":"mutable","name":"nonce","nameLocation":"300:5:0","nodeType":"VariableDeclaration","scope":17,"src":"293:12:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"},"typeName":{"id":14,"name":"uint64","nodeType":"ElementaryTypeName","src":"293:6:0","typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}},"visibility":"internal"}],"src":"292:14:0"},"scope":36,"stateMutability":"view","virtual":false,"visibility":"external"},{"id":27,"nodeType":"FunctionDefinition","src":"312:111:0","nodes":[],"functionSelector":"213e4198","implemented":false,"kind":"function","modifiers":[],"name":"parseJsonKeys","nameLocation":"321:13:0","parameters":{"id":22,"nodeType":"ParameterList","parameters":[{"constant":false,"id":19,"mutability":"mutable","name":"json","nameLocation":"351:4:0","nodeType":"VariableDeclaration","scope":27,"src":"335:20:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":18,"name":"string","nodeType":"ElementaryTypeName","src":"335:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":21,"mutability":"mutable","name":"key","nameLocation":"373:3:0","nodeType":"VariableDeclaration","scope":27,"src":"357:19:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":20,"name":"string","nodeType":"ElementaryTypeName","src":"357:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"334:43:0"},"returnParameters":{"id":26,"nodeType":"ParameterList","parameters":[{"constant":false,"id":25,"mutability":"mutable","name":"keys","nameLocation":"417:4:0","nodeType":"VariableDeclaration","scope":27,"src":"401:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string[]"},"typeName":{"baseType":{"id":23,"name":"string","nodeType":"ElementaryTypeName","src":"401:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"id":24,"nodeType":"ArrayTypeName","src":"401:8:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_storage_$dyn_storage_ptr","typeString":"string[]"}},"visibility":"internal"}],"src":"400:22:0"},"scope":36,"stateMutability":"pure","virtual":false,"visibility":"external"},{"id":32,"nodeType":"FunctionDefinition","src":"428:48:0","nodes":[],"functionSelector":"06447d56","implemented":false,"kind":"function","modifiers":[],"name":"startPrank","nameLocation":"437:10:0","parameters":{"id":30,"nodeType":"ParameterList","parameters":[{"constant":false,"id":29,"mutability":"mutable","name":"msgSender","nameLocation":"456:9:0","nodeType":"VariableDeclaration","scope":32,"src":"448:17:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":28,"name":"address","nodeType":"ElementaryTypeName","src":"448:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"447:19:0"},"returnParameters":{"id":31,"nodeType":"ParameterList","parameters":[],"src":"475:0:0"},"scope":36,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":35,"nodeType":"FunctionDefinition","src":"481:30:0","nodes":[],"functionSelector":"90c5013b","implemented":false,"kind":"function","modifiers":[],"name":"stopPrank","nameLocation":"490:9:0","parameters":{"id":33,"nodeType":"ParameterList","parameters":[],"src":"499:2:0"},"returnParameters":{"id":34,"nodeType":"ParameterList","parameters":[],"src":"510:0:0"},"scope":36,"stateMutability":"nonpayable","virtual":false,"visibility":"external"}],"abstract":false,"baseContracts":[],"canonicalName":"Vm","contractDependencies":[],"contractKind":"interface","fullyImplemented":false,"linearizedBaseContracts":[36],"name":"Vm","nameLocation":"130:2:0","scope":383,"usedErrors":[]},{"id":173,"nodeType":"ContractDefinition","src":"568:1622:0","nodes":[{"id":42,"nodeType":"VariableDeclaration","src":"590:86:0","nodes":[],"constant":true,"mutability":"constant","name":"CONSOLE_ADDRESS","nameLocation":"607:15:0","scope":173,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":37,"name":"address","nodeType":"ElementaryTypeName","src":"590:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"value":{"arguments":[{"hexValue":"307830303030303030303030303030303030303036333646366537333646366336353265366336663637","id":40,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"633:42:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"value":"0x000000000000000000636F6e736F6c652e6c6f67"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":39,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"625:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":38,"name":"address","nodeType":"ElementaryTypeName","src":"625:7:0","typeDescriptions":{}}},"id":41,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"625:51:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"},{"id":59,"nodeType":"FunctionDefinition","src":"683:221:0","nodes":[],"body":{"id":58,"nodeType":"Block","src":"842:62:0","nodes":[],"statements":[{"AST":{"nodeType":"YulBlock","src":"861:37:0","statements":[{"nodeType":"YulAssignment","src":"875:13:0","value":{"name":"fnIn","nodeType":"YulIdentifier","src":"884:4:0"},"variableNames":[{"name":"fnOut","nodeType":"YulIdentifier","src":"875:5:0"}]}]},"evmVersion":"london","externalReferences":[{"declaration":48,"isOffset":false,"isSlot":false,"src":"884:4:0","valueSize":1},{"declaration":55,"isOffset":false,"isSlot":false,"src":"875:5:0","valueSize":1}],"id":57,"nodeType":"InlineAssembly","src":"852:46:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"_castLogPayloadViewToPure","nameLocation":"692:25:0","parameters":{"id":49,"nodeType":"ParameterList","parameters":[{"constant":false,"id":48,"mutability":"mutable","name":"fnIn","nameLocation":"764:4:0","nodeType":"VariableDeclaration","scope":59,"src":"727:41:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) view"},"typeName":{"id":47,"nodeType":"FunctionTypeName","parameterTypes":{"id":45,"nodeType":"ParameterList","parameters":[{"constant":false,"id":44,"mutability":"mutable","name":"","nameLocation":"-1:-1:-1","nodeType":"VariableDeclaration","scope":47,"src":"736:12:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":43,"name":"bytes","nodeType":"ElementaryTypeName","src":"736:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"735:14:0"},"returnParameterTypes":{"id":46,"nodeType":"ParameterList","parameters":[],"src":"764:0:0"},"src":"727:41:0","stateMutability":"view","typeDescriptions":{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) view"},"visibility":"internal"},"visibility":"internal"}],"src":"717:57:0"},"returnParameters":{"id":56,"nodeType":"ParameterList","parameters":[{"constant":false,"id":55,"mutability":"mutable","name":"fnOut","nameLocation":"835:5:0","nodeType":"VariableDeclaration","scope":59,"src":"798:42:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) pure"},"typeName":{"id":54,"nodeType":"FunctionTypeName","parameterTypes":{"id":52,"nodeType":"ParameterList","parameters":[{"constant":false,"id":51,"mutability":"mutable","name":"","nameLocation":"-1:-1:-1","nodeType":"VariableDeclaration","scope":54,"src":"807:12:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":50,"name":"bytes","nodeType":"ElementaryTypeName","src":"807:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"806:14:0"},"returnParameterTypes":{"id":53,"nodeType":"ParameterList","parameters":[],"src":"835:0:0"},"src":"798:42:0","stateMutability":"pure","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) pure"},"visibility":"internal"},"visibility":"internal"}],"src":"797:44:0"},"scope":173,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":71,"nodeType":"FunctionDefinition","src":"910:133:0","nodes":[],"body":{"id":70,"nodeType":"Block","src":"971:72:0","nodes":[],"statements":[{"expression":{"arguments":[{"id":67,"name":"payload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":61,"src":"1028:7:0","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"arguments":[{"id":65,"name":"_sendLogPayloadView","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":87,"src":"1007:19:0","typeDescriptions":{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) view"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) view"}],"id":64,"name":"_castLogPayloadViewToPure","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":59,"src":"981:25:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_function_internal_view$_t_bytes_memory_ptr_$returns$__$_$returns$_t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$_$","typeString":"function (function (bytes memory) view) pure returns (function (bytes memory) pure)"}},"id":66,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"981:46:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":68,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"981:55:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":69,"nodeType":"ExpressionStatement","src":"981:55:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"_sendLogPayload","nameLocation":"919:15:0","parameters":{"id":62,"nodeType":"ParameterList","parameters":[{"constant":false,"id":61,"mutability":"mutable","name":"payload","nameLocation":"948:7:0","nodeType":"VariableDeclaration","scope":71,"src":"935:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":60,"name":"bytes","nodeType":"ElementaryTypeName","src":"935:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"934:22:0"},"returnParameters":{"id":63,"nodeType":"ParameterList","parameters":[],"src":"971:0:0"},"scope":173,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":87,"nodeType":"FunctionDefinition","src":"1049:380:0","nodes":[],"body":{"id":86,"nodeType":"Block","src":"1113:316:0","nodes":[],"statements":[{"assignments":[77],"declarations":[{"constant":false,"id":77,"mutability":"mutable","name":"payloadLength","nameLocation":"1131:13:0","nodeType":"VariableDeclaration","scope":86,"src":"1123:21:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":76,"name":"uint256","nodeType":"ElementaryTypeName","src":"1123:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"}],"id":80,"initialValue":{"expression":{"id":78,"name":"payload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":73,"src":"1147:7:0","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}},"id":79,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"length","nodeType":"MemberAccess","src":"1147:14:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"nodeType":"VariableDeclarationStatement","src":"1123:38:0"},{"assignments":[82],"declarations":[{"constant":false,"id":82,"mutability":"mutable","name":"consoleAddress","nameLocation":"1179:14:0","nodeType":"VariableDeclaration","scope":86,"src":"1171:22:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":81,"name":"address","nodeType":"ElementaryTypeName","src":"1171:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"id":84,"initialValue":{"id":83,"name":"CONSOLE_ADDRESS","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":42,"src":"1196:15:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"nodeType":"VariableDeclarationStatement","src":"1171:40:0"},{"AST":{"nodeType":"YulBlock","src":"1273:150:0","statements":[{"nodeType":"YulVariableDeclaration","src":"1287:36:0","value":{"arguments":[{"name":"payload","nodeType":"YulIdentifier","src":"1311:7:0"},{"kind":"number","nodeType":"YulLiteral","src":"1320:2:0","type":"","value":"32"}],"functionName":{"name":"add","nodeType":"YulIdentifier","src":"1307:3:0"},"nodeType":"YulFunctionCall","src":"1307:16:0"},"variables":[{"name":"payloadStart","nodeType":"YulTypedName","src":"1291:12:0","type":""}]},{"nodeType":"YulVariableDeclaration","src":"1336:77:0","value":{"arguments":[{"arguments":[],"functionName":{"name":"gas","nodeType":"YulIdentifier","src":"1356:3:0"},"nodeType":"YulFunctionCall","src":"1356:5:0"},{"name":"consoleAddress","nodeType":"YulIdentifier","src":"1363:14:0"},{"name":"payloadStart","nodeType":"YulIdentifier","src":"1379:12:0"},{"name":"payloadLength","nodeType":"YulIdentifier","src":"1393:13:0"},{"kind":"number","nodeType":"YulLiteral","src":"1408:1:0","type":"","value":"0"},{"kind":"number","nodeType":"YulLiteral","src":"1411:1:0","type":"","value":"0"}],"functionName":{"name":"staticcall","nodeType":"YulIdentifier","src":"1345:10:0"},"nodeType":"YulFunctionCall","src":"1345:68:0"},"variables":[{"name":"r","nodeType":"YulTypedName","src":"1340:1:0","type":""}]}]},"documentation":"@solidity memory-safe-assembly","evmVersion":"london","externalReferences":[{"declaration":82,"isOffset":false,"isSlot":false,"src":"1363:14:0","valueSize":1},{"declaration":73,"isOffset":false,"isSlot":false,"src":"1311:7:0","valueSize":1},{"declaration":77,"isOffset":false,"isSlot":false,"src":"1393:13:0","valueSize":1}],"id":85,"nodeType":"InlineAssembly","src":"1264:159:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"_sendLogPayloadView","nameLocation":"1058:19:0","parameters":{"id":74,"nodeType":"ParameterList","parameters":[{"constant":false,"id":73,"mutability":"mutable","name":"payload","nameLocation":"1091:7:0","nodeType":"VariableDeclaration","scope":87,"src":"1078:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":72,"name":"bytes","nodeType":"ElementaryTypeName","src":"1078:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"1077:22:0"},"returnParameters":{"id":75,"nodeType":"ParameterList","parameters":[],"src":"1113:0:0"},"scope":173,"stateMutability":"view","virtual":false,"visibility":"private"},{"id":101,"nodeType":"FunctionDefinition","src":"1435:121:0","nodes":[],"body":{"id":100,"nodeType":"Block","src":"1480:76:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e6729","id":95,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"1530:13:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_41304facd9323d75b11bcdd609cb38effffdb05710f7caf0e9b16c6d9d709f50","typeString":"literal_string \"log(string)\""},"value":"log(string)"},{"id":96,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":89,"src":"1545:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_41304facd9323d75b11bcdd609cb38effffdb05710f7caf0e9b16c6d9d709f50","typeString":"literal_string \"log(string)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}],"expression":{"id":93,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"1506:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":94,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"1506:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":97,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1506:42:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":92,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":71,"src":"1490:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":98,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1490:59:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":99,"nodeType":"ExpressionStatement","src":"1490:59:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"1444:3:0","parameters":{"id":90,"nodeType":"ParameterList","parameters":[{"constant":false,"id":89,"mutability":"mutable","name":"p0","nameLocation":"1462:2:0","nodeType":"VariableDeclaration","scope":101,"src":"1448:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":88,"name":"string","nodeType":"ElementaryTypeName","src":"1448:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"1447:18:0"},"returnParameters":{"id":91,"nodeType":"ParameterList","parameters":[],"src":"1480:0:0"},"scope":173,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":118,"nodeType":"FunctionDefinition","src":"1562:139:0","nodes":[],"body":{"id":117,"nodeType":"Block","src":"1616:85:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c626f6f6c29","id":111,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"1666:18:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_c3b556354c088fbb43886eb83c2a04bc7089663f964d22be308197a236f5b870","typeString":"literal_string \"log(string,bool)\""},"value":"log(string,bool)"},{"id":112,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":103,"src":"1686:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":113,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":105,"src":"1690:2:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_c3b556354c088fbb43886eb83c2a04bc7089663f964d22be308197a236f5b870","typeString":"literal_string \"log(string,bool)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_bool","typeString":"bool"}],"expression":{"id":109,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"1642:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":110,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"1642:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":114,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1642:51:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":108,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":71,"src":"1626:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":115,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1626:68:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":116,"nodeType":"ExpressionStatement","src":"1626:68:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"1571:3:0","parameters":{"id":106,"nodeType":"ParameterList","parameters":[{"constant":false,"id":103,"mutability":"mutable","name":"p0","nameLocation":"1589:2:0","nodeType":"VariableDeclaration","scope":118,"src":"1575:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":102,"name":"string","nodeType":"ElementaryTypeName","src":"1575:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":105,"mutability":"mutable","name":"p1","nameLocation":"1598:2:0","nodeType":"VariableDeclaration","scope":118,"src":"1593:7:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":104,"name":"bool","nodeType":"ElementaryTypeName","src":"1593:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"src":"1574:27:0"},"returnParameters":{"id":107,"nodeType":"ParameterList","parameters":[],"src":"1616:0:0"},"scope":173,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":135,"nodeType":"FunctionDefinition","src":"1707:145:0","nodes":[],"body":{"id":134,"nodeType":"Block","src":"1764:88:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c75696e7432353629","id":128,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"1814:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_b60e72ccf6d57ab53eb84d7e94a9545806ed7f93c4d5673f11a64f03471e584e","typeString":"literal_string \"log(string,uint256)\""},"value":"log(string,uint256)"},{"id":129,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":120,"src":"1837:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":130,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":122,"src":"1841:2:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_b60e72ccf6d57ab53eb84d7e94a9545806ed7f93c4d5673f11a64f03471e584e","typeString":"literal_string \"log(string,uint256)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_uint256","typeString":"uint256"}],"expression":{"id":126,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"1790:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":127,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"1790:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":131,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1790:54:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":125,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":71,"src":"1774:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":132,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1774:71:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":133,"nodeType":"ExpressionStatement","src":"1774:71:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"1716:3:0","parameters":{"id":123,"nodeType":"ParameterList","parameters":[{"constant":false,"id":120,"mutability":"mutable","name":"p0","nameLocation":"1734:2:0","nodeType":"VariableDeclaration","scope":135,"src":"1720:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":119,"name":"string","nodeType":"ElementaryTypeName","src":"1720:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":122,"mutability":"mutable","name":"p1","nameLocation":"1746:2:0","nodeType":"VariableDeclaration","scope":135,"src":"1738:10:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":121,"name":"uint256","nodeType":"ElementaryTypeName","src":"1738:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"}],"src":"1719:30:0"},"returnParameters":{"id":124,"nodeType":"ParameterList","parameters":[],"src":"1764:0:0"},"scope":173,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":152,"nodeType":"FunctionDefinition","src":"1858:145:0","nodes":[],"body":{"id":151,"nodeType":"Block","src":"1915:88:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c6164647265737329","id":145,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"1965:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_319af333460570a1937bf195dd33445c0d0951c59127da6f1f038b9fdce3fd72","typeString":"literal_string \"log(string,address)\""},"value":"log(string,address)"},{"id":146,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":137,"src":"1988:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":147,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":139,"src":"1992:2:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_319af333460570a1937bf195dd33445c0d0951c59127da6f1f038b9fdce3fd72","typeString":"literal_string \"log(string,address)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":143,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"1941:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":144,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"1941:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":148,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1941:54:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":142,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":71,"src":"1925:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":149,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1925:71:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":150,"nodeType":"ExpressionStatement","src":"1925:71:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"1867:3:0","parameters":{"id":140,"nodeType":"ParameterList","parameters":[{"constant":false,"id":137,"mutability":"mutable","name":"p0","nameLocation":"1885:2:0","nodeType":"VariableDeclaration","scope":152,"src":"1871:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":136,"name":"string","nodeType":"ElementaryTypeName","src":"1871:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":139,"mutability":"mutable","name":"p1","nameLocation":"1897:2:0","nodeType":"VariableDeclaration","scope":152,"src":"1889:10:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":138,"name":"address","nodeType":"ElementaryTypeName","src":"1889:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"1870:30:0"},"returnParameters":{"id":141,"nodeType":"ParameterList","parameters":[],"src":"1915:0:0"},"scope":173,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":172,"nodeType":"FunctionDefinition","src":"2009:179:0","nodes":[],"body":{"id":171,"nodeType":"Block","src":"2090:98:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c737472696e672c737472696e6729","id":164,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2140:27:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_2ced7cef693312206c21f0e92e3b54e2e16bf33db5eec350c78866822c665e1f","typeString":"literal_string \"log(string,string,string)\""},"value":"log(string,string,string)"},{"id":165,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":154,"src":"2169:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":166,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":156,"src":"2173:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":167,"name":"p2","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":158,"src":"2177:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_2ced7cef693312206c21f0e92e3b54e2e16bf33db5eec350c78866822c665e1f","typeString":"literal_string \"log(string,string,string)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}],"expression":{"id":162,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"2116:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":163,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"2116:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":168,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2116:64:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":161,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":71,"src":"2100:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":169,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2100:81:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":170,"nodeType":"ExpressionStatement","src":"2100:81:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"2018:3:0","parameters":{"id":159,"nodeType":"ParameterList","parameters":[{"constant":false,"id":154,"mutability":"mutable","name":"p0","nameLocation":"2036:2:0","nodeType":"VariableDeclaration","scope":172,"src":"2022:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":153,"name":"string","nodeType":"ElementaryTypeName","src":"2022:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":156,"mutability":"mutable","name":"p1","nameLocation":"2054:2:0","nodeType":"VariableDeclaration","scope":172,"src":"2040:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":155,"name":"string","nodeType":"ElementaryTypeName","src":"2040:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":158,"mutability":"mutable","name":"p2","nameLocation":"2072:2:0","nodeType":"VariableDeclaration","scope":172,"src":"2058:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":157,"name":"string","nodeType":"ElementaryTypeName","src":"2058:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"2021:54:0"},"returnParameters":{"id":160,"nodeType":"ParameterList","parameters":[],"src":"2090:0:0"},"scope":173,"stateMutability":"pure","virtual":false,"visibility":"internal"}],"abstract":false,"baseContracts":[],"canonicalName":"console","contractDependencies":[],"contractKind":"library","fullyImplemented":true,"linearizedBaseContracts":[173],"name":"console","nameLocation":"576:7:0","scope":383,"usedErrors":[]},{"id":382,"nodeType":"ContractDefinition","src":"2318:1449:0","nodes":[{"id":188,"nodeType":"VariableDeclaration","src":"2348:94:0","nodes":[],"constant":true,"mutability":"constant","name":"VM_ADDRESS","nameLocation":"2374:10:0","scope":382,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":175,"name":"address","nodeType":"ElementaryTypeName","src":"2348:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"value":{"arguments":[{"arguments":[{"arguments":[{"arguments":[{"hexValue":"6865766d20636865617420636f6465","id":183,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2421:17:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d","typeString":"literal_string \"hevm cheat code\""},"value":"hevm cheat code"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d","typeString":"literal_string \"hevm cheat code\""}],"id":182,"name":"keccak256","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-8,"src":"2411:9:0","typeDescriptions":{"typeIdentifier":"t_function_keccak256_pure$_t_bytes_memory_ptr_$returns$_t_bytes32_$","typeString":"function (bytes memory) pure returns (bytes32)"}},"id":184,"isConstant":false,"isLValue":false,"isPure":true,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2411:28:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes32","typeString":"bytes32"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes32","typeString":"bytes32"}],"id":181,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2403:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint256_$","typeString":"type(uint256)"},"typeName":{"id":180,"name":"uint256","nodeType":"ElementaryTypeName","src":"2403:7:0","typeDescriptions":{}}},"id":185,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2403:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint256","typeString":"uint256"}],"id":179,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2395:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":178,"name":"uint160","nodeType":"ElementaryTypeName","src":"2395:7:0","typeDescriptions":{}}},"id":186,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2395:46:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":177,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2387:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":176,"name":"address","nodeType":"ElementaryTypeName","src":"2387:7:0","typeDescriptions":{}}},"id":187,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2387:55:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"},{"id":194,"nodeType":"VariableDeclaration","src":"2448:40:0","nodes":[],"constant":true,"mutability":"constant","name":"vm","nameLocation":"2469:2:0","scope":382,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$36","typeString":"contract Vm"},"typeName":{"id":190,"nodeType":"UserDefinedTypeName","pathNode":{"id":189,"name":"Vm","nodeType":"IdentifierPath","referencedDeclaration":36,"src":"2448:2:0"},"referencedDeclaration":36,"src":"2448:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$36","typeString":"contract Vm"}},"value":{"arguments":[{"id":192,"name":"VM_ADDRESS","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":188,"src":"2477:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":191,"name":"Vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":36,"src":"2474:2:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_Vm_$36_$","typeString":"type(contract Vm)"}},"id":193,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2474:14:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$36","typeString":"contract Vm"}},"visibility":"internal"},{"id":357,"nodeType":"FunctionDefinition","src":"2578:949:0","nodes":[],"body":{"id":356,"nodeType":"Block","src":"2600:927:0","nodes":[],"statements":[{"assignments":[199],"declarations":[{"constant":false,"id":199,"mutability":"mutable","name":"x","nameLocation":"2615:1:0","nodeType":"VariableDeclaration","scope":356,"src":"2610:6:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":198,"name":"bool","nodeType":"ElementaryTypeName","src":"2610:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"id":205,"initialValue":{"arguments":[{"hexValue":"4558414d504c455f424f4f4c","id":202,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2628:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_a634dae177a0e138ae7aaa2afae347412e148992e88c7aabd33ee71be146cb7f","typeString":"literal_string \"EXAMPLE_BOOL\""},"value":"EXAMPLE_BOOL"},{"hexValue":"66616c7365","id":203,"isConstant":false,"isLValue":false,"isPure":true,"kind":"bool","lValueRequested":false,"nodeType":"Literal","src":"2644:5:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"value":"false"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_a634dae177a0e138ae7aaa2afae347412e148992e88c7aabd33ee71be146cb7f","typeString":"literal_string \"EXAMPLE_BOOL\""},{"typeIdentifier":"t_bool","typeString":"bool"}],"expression":{"id":200,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":194,"src":"2619:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$36","typeString":"contract Vm"}},"id":201,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"envOr","nodeType":"MemberAccess","referencedDeclaration":10,"src":"2619:8:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$_t_bool_$returns$_t_bool_$","typeString":"function (string memory,bool) view external returns (bool)"}},"id":204,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2619:31:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"nodeType":"VariableDeclarationStatement","src":"2610:40:0"},{"expression":{"arguments":[{"hexValue":"626f6f6c2076616c75652066726f6d20656e76","id":209,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2672:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_5a607d0b5a1295325aa8901721d78ba402601bba6f62cebdd5235dd0204a590b","typeString":"literal_string \"bool value from env\""},"value":"bool value from env"},{"id":210,"name":"x","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":199,"src":"2695:1:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_5a607d0b5a1295325aa8901721d78ba402601bba6f62cebdd5235dd0204a590b","typeString":"literal_string \"bool value from env\""},{"typeIdentifier":"t_bool","typeString":"bool"}],"expression":{"id":206,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"2660:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":208,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":118,"src":"2660:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_bool_$returns$__$","typeString":"function (string memory,bool) pure"}},"id":211,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2660:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":212,"nodeType":"ExpressionStatement","src":"2660:37:0"},{"expression":{"arguments":[{"hexValue":"636f6e74726163742061646472","id":216,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2720:15:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_fa50728770d00fe8f6a0592f3565bbfaf063ee4077f1f5bbc003d091d33cd0c4","typeString":"literal_string \"contract addr\""},"value":"contract addr"},{"arguments":[{"id":219,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"2745:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}],"id":218,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2737:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":217,"name":"address","nodeType":"ElementaryTypeName","src":"2737:7:0","typeDescriptions":{}}},"id":220,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2737:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_fa50728770d00fe8f6a0592f3565bbfaf063ee4077f1f5bbc003d091d33cd0c4","typeString":"literal_string \"contract addr\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":213,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"2708:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":215,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":152,"src":"2708:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":221,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2708:43:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":222,"nodeType":"ExpressionStatement","src":"2708:43:0"},{"expression":{"arguments":[{"hexValue":"636f6e7472616374206e6f6e6365","id":226,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2773:16:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_3a23091615a5de8c0a35ffd8857a37e2c4e0b72f3ef8a34d6caf65efcd562e2f","typeString":"literal_string \"contract nonce\""},"value":"contract nonce"},{"arguments":[{"arguments":[{"id":231,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"2811:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}],"id":230,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2803:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":229,"name":"address","nodeType":"ElementaryTypeName","src":"2803:7:0","typeDescriptions":{}}},"id":232,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2803:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":227,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":194,"src":"2791:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$36","typeString":"contract Vm"}},"id":228,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"getNonce","nodeType":"MemberAccess","referencedDeclaration":17,"src":"2791:11:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_address_$returns$_t_uint64_$","typeString":"function (address) view external returns (uint64)"}},"id":233,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2791:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_3a23091615a5de8c0a35ffd8857a37e2c4e0b72f3ef8a34d6caf65efcd562e2f","typeString":"literal_string \"contract nonce\""},{"typeIdentifier":"t_uint64","typeString":"uint64"}],"expression":{"id":223,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"2761:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":225,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":135,"src":"2761:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_uint256_$returns$__$","typeString":"function (string memory,uint256) pure"}},"id":234,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2761:57:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":235,"nodeType":"ExpressionStatement","src":"2761:57:0"},{"expression":{"arguments":[{"hexValue":"73656e6465722061646472","id":239,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2840:13:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_8125ca2decf812b25b65606ff16dad37cb198ff0433485a7926e50feafacfc35","typeString":"literal_string \"sender addr\""},"value":"sender addr"},{"arguments":[{"expression":{"id":242,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"2863:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":243,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"2863:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":241,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2855:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":240,"name":"address","nodeType":"ElementaryTypeName","src":"2855:7:0","typeDescriptions":{}}},"id":244,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2855:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_8125ca2decf812b25b65606ff16dad37cb198ff0433485a7926e50feafacfc35","typeString":"literal_string \"sender addr\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":236,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"2828:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":238,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":152,"src":"2828:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":245,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2828:47:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":246,"nodeType":"ExpressionStatement","src":"2828:47:0"},{"expression":{"arguments":[{"hexValue":"73656e646572206e6f6e6365","id":250,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2897:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_db7deb43f2f9e0404016de53b7e64c4976b54149581f7534daae2551e8cf4e40","typeString":"literal_string \"sender nonce\""},"value":"sender nonce"},{"arguments":[{"arguments":[{"expression":{"id":255,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"2933:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":256,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"2933:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":254,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2925:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":253,"name":"address","nodeType":"ElementaryTypeName","src":"2925:7:0","typeDescriptions":{}}},"id":257,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2925:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":251,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":194,"src":"2913:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$36","typeString":"contract Vm"}},"id":252,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"getNonce","nodeType":"MemberAccess","referencedDeclaration":17,"src":"2913:11:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_address_$returns$_t_uint64_$","typeString":"function (address) view external returns (uint64)"}},"id":258,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2913:32:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_db7deb43f2f9e0404016de53b7e64c4976b54149581f7534daae2551e8cf4e40","typeString":"literal_string \"sender nonce\""},{"typeIdentifier":"t_uint64","typeString":"uint64"}],"expression":{"id":247,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"2885:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":249,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":135,"src":"2885:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_uint256_$returns$__$","typeString":"function (string memory,uint256) pure"}},"id":259,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2885:61:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":260,"nodeType":"ExpressionStatement","src":"2885:61:0"},{"assignments":[262],"declarations":[{"constant":false,"id":262,"mutability":"mutable","name":"json","nameLocation":"2971:4:0","nodeType":"VariableDeclaration","scope":356,"src":"2957:18:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":261,"name":"string","nodeType":"ElementaryTypeName","src":"2957:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"id":264,"initialValue":{"hexValue":"7b22726f6f745f6b6579223a205b7b2261223a20312c202262223a20327d5d7d","id":263,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2978:34:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_e95522e99766888d0261f55bd1eae5e3f3e26eaf009a16e2433eafaf0a4ecdf2","typeString":"literal_string \"{\"root_key\": [{\"a\": 1, \"b\": 2}]}\""},"value":"{\"root_key\": [{\"a\": 1, \"b\": 2}]}"},"nodeType":"VariableDeclarationStatement","src":"2957:55:0"},{"assignments":[269],"declarations":[{"constant":false,"id":269,"mutability":"mutable","name":"keys","nameLocation":"3038:4:0","nodeType":"VariableDeclaration","scope":356,"src":"3022:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string[]"},"typeName":{"baseType":{"id":267,"name":"string","nodeType":"ElementaryTypeName","src":"3022:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"id":268,"nodeType":"ArrayTypeName","src":"3022:8:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_storage_$dyn_storage_ptr","typeString":"string[]"}},"visibility":"internal"}],"id":275,"initialValue":{"arguments":[{"id":272,"name":"json","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":262,"src":"3062:4:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"hexValue":"2e726f6f745f6b65795b305d","id":273,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3068:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_d82f67100edb80050915e1ec4b565c9a8319a22efb1075e1298b7bb60101d266","typeString":"literal_string \".root_key[0]\""},"value":".root_key[0]"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_stringliteral_d82f67100edb80050915e1ec4b565c9a8319a22efb1075e1298b7bb60101d266","typeString":"literal_string \".root_key[0]\""}],"expression":{"id":270,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":194,"src":"3045:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$36","typeString":"contract Vm"}},"id":271,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"parseJsonKeys","nodeType":"MemberAccess","referencedDeclaration":27,"src":"3045:16:0","typeDescriptions":{"typeIdentifier":"t_function_external_pure$_t_string_memory_ptr_$_t_string_memory_ptr_$returns$_t_array$_t_string_memory_ptr_$dyn_memory_ptr_$","typeString":"function (string memory,string memory) pure external returns (string memory[] memory)"}},"id":274,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3045:38:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string memory[] memory"}},"nodeType":"VariableDeclarationStatement","src":"3022:61:0"},{"expression":{"arguments":[{"hexValue":"6b657973","id":279,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3105:6:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_f29790a80c4ce5f42f59892f424f9c92856c6b656c3378e2cf305b260c6f4195","typeString":"literal_string \"keys\""},"value":"keys"},{"baseExpression":{"id":280,"name":"keys","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":269,"src":"3113:4:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string memory[] memory"}},"id":282,"indexExpression":{"hexValue":"30","id":281,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"3118:1:0","typeDescriptions":{"typeIdentifier":"t_rational_0_by_1","typeString":"int_const 0"},"value":"0"},"isConstant":false,"isLValue":true,"isPure":false,"lValueRequested":false,"nodeType":"IndexAccess","src":"3113:7:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"baseExpression":{"id":283,"name":"keys","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":269,"src":"3122:4:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string memory[] memory"}},"id":285,"indexExpression":{"hexValue":"31","id":284,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"3127:1:0","typeDescriptions":{"typeIdentifier":"t_rational_1_by_1","typeString":"int_const 1"},"value":"1"},"isConstant":false,"isLValue":true,"isPure":false,"lValueRequested":false,"nodeType":"IndexAccess","src":"3122:7:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_f29790a80c4ce5f42f59892f424f9c92856c6b656c3378e2cf305b260c6f4195","typeString":"literal_string \"keys\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}],"expression":{"id":276,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"3093:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":278,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":172,"src":"3093:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_string_memory_ptr_$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory,string memory,string memory) pure"}},"id":286,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3093:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":287,"nodeType":"ExpressionStatement","src":"3093:37:0"},{"expression":{"arguments":[{"hexValue":"66726f6d206f726967696e616c","id":291,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3152:15:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_77928970c8757d110f3c23e003246f49e0de890480ba9717ba659b2f56f316b2","typeString":"literal_string \"from original\""},"value":"from original"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_77928970c8757d110f3c23e003246f49e0de890480ba9717ba659b2f56f316b2","typeString":"literal_string \"from original\""}],"expression":{"id":288,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3141:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}},"id":290,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":381,"src":"3141:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":292,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3141:27:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":293,"nodeType":"ExpressionStatement","src":"3141:27:0"},{"expression":{"arguments":[{"arguments":[{"arguments":[{"hexValue":"30783432","id":301,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"3208:4:0","typeDescriptions":{"typeIdentifier":"t_rational_66_by_1","typeString":"int_const 66"},"value":"0x42"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_66_by_1","typeString":"int_const 66"}],"id":300,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3200:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":299,"name":"uint160","nodeType":"ElementaryTypeName","src":"3200:7:0","typeDescriptions":{}}},"id":302,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3200:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":298,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3192:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":297,"name":"address","nodeType":"ElementaryTypeName","src":"3192:7:0","typeDescriptions":{}}},"id":303,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3192:22:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":294,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":194,"src":"3178:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$36","typeString":"contract Vm"}},"id":296,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"startPrank","nodeType":"MemberAccess","referencedDeclaration":32,"src":"3178:13:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_address_$returns$__$","typeString":"function (address) external"}},"id":304,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3178:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":305,"nodeType":"ExpressionStatement","src":"3178:37:0"},{"expression":{"arguments":[{"hexValue":"66726f6d207072616e6b2031","id":309,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3236:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_42b34abfe37a8b0add910cda7b4a379e6538fa7a1dcafce47a02bd38f6c88e2a","typeString":"literal_string \"from prank 1\""},"value":"from prank 1"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_42b34abfe37a8b0add910cda7b4a379e6538fa7a1dcafce47a02bd38f6c88e2a","typeString":"literal_string \"from prank 1\""}],"expression":{"id":306,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3225:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}},"id":308,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":381,"src":"3225:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":310,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3225:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":311,"nodeType":"ExpressionStatement","src":"3225:26:0"},{"expression":{"arguments":[{"hexValue":"706172656e742073636f7065206d73672e73656e646572","id":315,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3273:25:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_83ec9246154d8845de47aafc5c2865c9985d2efe84472c27283879f2fbf5cc94","typeString":"literal_string \"parent scope msg.sender\""},"value":"parent scope msg.sender"},{"arguments":[{"expression":{"id":318,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"3308:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":319,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"3308:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":317,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3300:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":316,"name":"address","nodeType":"ElementaryTypeName","src":"3300:7:0","typeDescriptions":{}}},"id":320,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3300:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_83ec9246154d8845de47aafc5c2865c9985d2efe84472c27283879f2fbf5cc94","typeString":"literal_string \"parent scope msg.sender\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":312,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"3261:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":314,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":152,"src":"3261:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":321,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3261:59:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":322,"nodeType":"ExpressionStatement","src":"3261:59:0"},{"expression":{"arguments":[{"hexValue":"706172656e742073636f706520636f6e74726163742e61646472","id":326,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3342:28:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_97df66250e0b2b48f0ec8d0e01eb1b8ca012d95f1572895622aa1ea433e5570f","typeString":"literal_string \"parent scope contract.addr\""},"value":"parent scope contract.addr"},{"arguments":[{"id":329,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3380:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}],"id":328,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3372:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":327,"name":"address","nodeType":"ElementaryTypeName","src":"3372:7:0","typeDescriptions":{}}},"id":330,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3372:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_97df66250e0b2b48f0ec8d0e01eb1b8ca012d95f1572895622aa1ea433e5570f","typeString":"literal_string \"parent scope contract.addr\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":323,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"3330:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":325,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":152,"src":"3330:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":331,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3330:56:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":332,"nodeType":"ExpressionStatement","src":"3330:56:0"},{"expression":{"arguments":[{"hexValue":"66726f6d207072616e6b2032","id":336,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3407:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_a38a34f8cad750a79aa097a92971f8f405b51ee9d53d25c5b14fc129ba3684bb","typeString":"literal_string \"from prank 2\""},"value":"from prank 2"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_a38a34f8cad750a79aa097a92971f8f405b51ee9d53d25c5b14fc129ba3684bb","typeString":"literal_string \"from prank 2\""}],"expression":{"id":333,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3396:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}},"id":335,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":381,"src":"3396:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":337,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3396:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":338,"nodeType":"ExpressionStatement","src":"3396:26:0"},{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":339,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":194,"src":"3432:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$36","typeString":"contract Vm"}},"id":341,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"stopPrank","nodeType":"MemberAccess","referencedDeclaration":35,"src":"3432:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$__$returns$__$","typeString":"function () external"}},"id":342,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3432:14:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":343,"nodeType":"ExpressionStatement","src":"3432:14:0"},{"expression":{"arguments":[{"hexValue":"66726f6d206f726967696e616c20616761696e","id":347,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3467:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_0c805c6579e20a9c4c8e11aeab23330910a9f2da629191dc119d1730e8ed6860","typeString":"literal_string \"from original again\""},"value":"from original again"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_0c805c6579e20a9c4c8e11aeab23330910a9f2da629191dc119d1730e8ed6860","typeString":"literal_string \"from original again\""}],"expression":{"id":344,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3456:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}},"id":346,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":381,"src":"3456:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":348,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3456:33:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":349,"nodeType":"ExpressionStatement","src":"3456:33:0"},{"expression":{"arguments":[{"hexValue":"646f6e6521","id":353,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3512:7:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_080382d5c9e9e7c5e3d1d33f5e7422740375955180fadff167d8130e0c35f3fc","typeString":"literal_string \"done!\""},"value":"done!"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_080382d5c9e9e7c5e3d1d33f5e7422740375955180fadff167d8130e0c35f3fc","typeString":"literal_string \"done!\""}],"expression":{"id":350,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"3500:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":352,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":101,"src":"3500:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":354,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3500:20:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":355,"nodeType":"ExpressionStatement","src":"3500:20:0"}]},"documentation":{"id":195,"nodeType":"StructuredDocumentation","src":"2495:78:0","text":"@notice example function, runs through basic cheat-codes and console logs."},"functionSelector":"c0406226","implemented":true,"kind":"function","modifiers":[],"name":"run","nameLocation":"2587:3:0","parameters":{"id":196,"nodeType":"ParameterList","parameters":[],"src":"2590:2:0"},"returnParameters":{"id":197,"nodeType":"ParameterList","parameters":[],"src":"2600:0:0"},"scope":382,"stateMutability":"nonpayable","virtual":false,"visibility":"public"},{"id":381,"nodeType":"FunctionDefinition","src":"3622:143:0","nodes":[],"body":{"id":380,"nodeType":"Block","src":"3671:94:0","nodes":[],"statements":[{"expression":{"arguments":[{"id":366,"name":"_v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":360,"src":"3693:2:0","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}],"expression":{"id":363,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"3681:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":365,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":101,"src":"3681:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":367,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3681:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":368,"nodeType":"ExpressionStatement","src":"3681:15:0"},{"expression":{"arguments":[{"hexValue":"68656c6c6f206d73672e73656e646572","id":372,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3718:18:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_b3cc13bc51228b2c4c4334d82a4772908254dc0e1c512893dd16208ef13efb8e","typeString":"literal_string \"hello msg.sender\""},"value":"hello msg.sender"},{"arguments":[{"expression":{"id":375,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"3746:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":376,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"3746:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":374,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3738:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":373,"name":"address","nodeType":"ElementaryTypeName","src":"3738:7:0","typeDescriptions":{}}},"id":377,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3738:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_b3cc13bc51228b2c4c4334d82a4772908254dc0e1c512893dd16208ef13efb8e","typeString":"literal_string \"hello msg.sender\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":369,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"3706:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":371,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":152,"src":"3706:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":378,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3706:52:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":379,"nodeType":"ExpressionStatement","src":"3706:52:0"}]},"documentation":{"id":358,"nodeType":"StructuredDocumentation","src":"3533:84:0","text":"@notice example external function, to force a CALL, and test vm.startPrank with."},"functionSelector":"a777d0dc","implemented":true,"kind":"function","modifiers":[],"name":"hello","nameLocation":"3631:5:0","parameters":{"id":361,"nodeType":"ParameterList","parameters":[{"constant":false,"id":360,"mutability":"mutable","name":"_v","nameLocation":"3653:2:0","nodeType":"VariableDeclaration","scope":381,"src":"3637:18:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":359,"name":"string","nodeType":"ElementaryTypeName","src":"3637:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"3636:20:0"},"returnParameters":{"id":362,"nodeType":"ParameterList","parameters":[],"src":"3671:0:0"},"scope":382,"stateMutability":"view","virtual":false,"visibility":"external"}],"abstract":false,"baseContracts":[],"canonicalName":"ScriptExample","contractDependencies":[],"contractKind":"contract","documentation":{"id":174,"nodeType":"StructuredDocumentation","src":"2192:126:0","text":"@title ScriptExample\n @notice ScriptExample is an example script. The Go forge script code tests that it can run this."},"fullyImplemented":true,"linearizedBaseContracts":[382],"name":"ScriptExample","nameLocation":"2327:13:0","scope":383,"usedErrors":[]}],"license":"MIT"},"id":0} \ No newline at end of file +{"abi":[],"bytecode":{"object":"0x602d6037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea164736f6c634300080f000a","sourceMap":"791:1622:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;791:1622:0;;;;;;;;;;;;;;;;;","linkReferences":{}},"deployedBytecode":{"object":"0x73000000000000000000000000000000000000000030146080604052600080fdfea164736f6c634300080f000a","sourceMap":"791:1622:0:-:0;;;;;;;;","linkReferences":{}},"methodIdentifiers":{},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"scripts/ScriptExample.s.sol\":\"console\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[]},\"sources\":{\"scripts/ScriptExample.s.sol\":{\"keccak256\":\"0x8d1dfa41908e7ccc3a498a2a2aa51c5275bedbb904ce32d08f8598e36f896d8d\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5117bb7158363cae8b9dc0508d2852692fd36172f1c699ff680afbb5acebe1f3\",\"dweb:/ipfs/QmQdahJ8SPKfJ4yea5Ge9qaj5qh1TxVffhHvaWytBaL95h\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.15+commit.e14f2714"},"language":"Solidity","output":{"abi":[],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"remappings":[],"optimizer":{"enabled":true,"runs":999999},"metadata":{"bytecodeHash":"none"},"compilationTarget":{"scripts/ScriptExample.s.sol":"console"},"evmVersion":"london","libraries":{}},"sources":{"scripts/ScriptExample.s.sol":{"keccak256":"0x8d1dfa41908e7ccc3a498a2a2aa51c5275bedbb904ce32d08f8598e36f896d8d","urls":["bzz-raw://5117bb7158363cae8b9dc0508d2852692fd36172f1c699ff680afbb5acebe1f3","dweb:/ipfs/QmQdahJ8SPKfJ4yea5Ge9qaj5qh1TxVffhHvaWytBaL95h"],"license":"MIT"}},"version":1},"storageLayout":{"storage":[],"types":{}},"userdoc":{"version":1,"kind":"user"},"devdoc":{"version":1,"kind":"dev"},"ast":{"absolutePath":"scripts/ScriptExample.s.sol","id":720,"exportedSymbols":{"FooBar":[719],"ScriptExample":[706],"Vm":[55],"console":[192]},"nodeType":"SourceUnit","src":"32:5967:0","nodes":[{"id":1,"nodeType":"PragmaDirective","src":"32:23:0","nodes":[],"literals":["solidity","0.8",".15"]},{"id":55,"nodeType":"ContractDefinition","src":"120:616:0","nodes":[{"id":10,"nodeType":"FunctionDefinition","src":"139:91:0","nodes":[],"functionSelector":"4777f3cf","implemented":false,"kind":"function","modifiers":[],"name":"envOr","nameLocation":"148:5:0","parameters":{"id":6,"nodeType":"ParameterList","parameters":[{"constant":false,"id":3,"mutability":"mutable","name":"name","nameLocation":"170:4:0","nodeType":"VariableDeclaration","scope":10,"src":"154:20:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":2,"name":"string","nodeType":"ElementaryTypeName","src":"154:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":5,"mutability":"mutable","name":"defaultValue","nameLocation":"181:12:0","nodeType":"VariableDeclaration","scope":10,"src":"176:17:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":4,"name":"bool","nodeType":"ElementaryTypeName","src":"176:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"src":"153:41:0"},"returnParameters":{"id":9,"nodeType":"ParameterList","parameters":[{"constant":false,"id":8,"mutability":"mutable","name":"value","nameLocation":"223:5:0","nodeType":"VariableDeclaration","scope":10,"src":"218:10:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":7,"name":"bool","nodeType":"ElementaryTypeName","src":"218:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"src":"217:12:0"},"scope":55,"stateMutability":"view","virtual":false,"visibility":"external"},{"id":17,"nodeType":"FunctionDefinition","src":"235:72:0","nodes":[],"functionSelector":"2d0335ab","implemented":false,"kind":"function","modifiers":[],"name":"getNonce","nameLocation":"244:8:0","parameters":{"id":13,"nodeType":"ParameterList","parameters":[{"constant":false,"id":12,"mutability":"mutable","name":"account","nameLocation":"261:7:0","nodeType":"VariableDeclaration","scope":17,"src":"253:15:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":11,"name":"address","nodeType":"ElementaryTypeName","src":"253:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"252:17:0"},"returnParameters":{"id":16,"nodeType":"ParameterList","parameters":[{"constant":false,"id":15,"mutability":"mutable","name":"nonce","nameLocation":"300:5:0","nodeType":"VariableDeclaration","scope":17,"src":"293:12:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"},"typeName":{"id":14,"name":"uint64","nodeType":"ElementaryTypeName","src":"293:6:0","typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}},"visibility":"internal"}],"src":"292:14:0"},"scope":55,"stateMutability":"view","virtual":false,"visibility":"external"},{"id":27,"nodeType":"FunctionDefinition","src":"312:111:0","nodes":[],"functionSelector":"213e4198","implemented":false,"kind":"function","modifiers":[],"name":"parseJsonKeys","nameLocation":"321:13:0","parameters":{"id":22,"nodeType":"ParameterList","parameters":[{"constant":false,"id":19,"mutability":"mutable","name":"json","nameLocation":"351:4:0","nodeType":"VariableDeclaration","scope":27,"src":"335:20:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":18,"name":"string","nodeType":"ElementaryTypeName","src":"335:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":21,"mutability":"mutable","name":"key","nameLocation":"373:3:0","nodeType":"VariableDeclaration","scope":27,"src":"357:19:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":20,"name":"string","nodeType":"ElementaryTypeName","src":"357:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"334:43:0"},"returnParameters":{"id":26,"nodeType":"ParameterList","parameters":[{"constant":false,"id":25,"mutability":"mutable","name":"keys","nameLocation":"417:4:0","nodeType":"VariableDeclaration","scope":27,"src":"401:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string[]"},"typeName":{"baseType":{"id":23,"name":"string","nodeType":"ElementaryTypeName","src":"401:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"id":24,"nodeType":"ArrayTypeName","src":"401:8:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_storage_$dyn_storage_ptr","typeString":"string[]"}},"visibility":"internal"}],"src":"400:22:0"},"scope":55,"stateMutability":"pure","virtual":false,"visibility":"external"},{"id":32,"nodeType":"FunctionDefinition","src":"428:48:0","nodes":[],"functionSelector":"06447d56","implemented":false,"kind":"function","modifiers":[],"name":"startPrank","nameLocation":"437:10:0","parameters":{"id":30,"nodeType":"ParameterList","parameters":[{"constant":false,"id":29,"mutability":"mutable","name":"msgSender","nameLocation":"456:9:0","nodeType":"VariableDeclaration","scope":32,"src":"448:17:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":28,"name":"address","nodeType":"ElementaryTypeName","src":"448:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"447:19:0"},"returnParameters":{"id":31,"nodeType":"ParameterList","parameters":[],"src":"475:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":35,"nodeType":"FunctionDefinition","src":"481:30:0","nodes":[],"functionSelector":"90c5013b","implemented":false,"kind":"function","modifiers":[],"name":"stopPrank","nameLocation":"490:9:0","parameters":{"id":33,"nodeType":"ParameterList","parameters":[],"src":"499:2:0"},"returnParameters":{"id":34,"nodeType":"ParameterList","parameters":[],"src":"510:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":38,"nodeType":"FunctionDefinition","src":"516:30:0","nodes":[],"functionSelector":"afc98040","implemented":false,"kind":"function","modifiers":[],"name":"broadcast","nameLocation":"525:9:0","parameters":{"id":36,"nodeType":"ParameterList","parameters":[],"src":"534:2:0"},"returnParameters":{"id":37,"nodeType":"ParameterList","parameters":[],"src":"545:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":43,"nodeType":"FunctionDefinition","src":"551:47:0","nodes":[],"functionSelector":"e6962cdb","implemented":false,"kind":"function","modifiers":[],"name":"broadcast","nameLocation":"560:9:0","parameters":{"id":41,"nodeType":"ParameterList","parameters":[{"constant":false,"id":40,"mutability":"mutable","name":"msgSender","nameLocation":"578:9:0","nodeType":"VariableDeclaration","scope":43,"src":"570:17:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":39,"name":"address","nodeType":"ElementaryTypeName","src":"570:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"569:19:0"},"returnParameters":{"id":42,"nodeType":"ParameterList","parameters":[],"src":"597:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":48,"nodeType":"FunctionDefinition","src":"603:52:0","nodes":[],"functionSelector":"7fec2a8d","implemented":false,"kind":"function","modifiers":[],"name":"startBroadcast","nameLocation":"612:14:0","parameters":{"id":46,"nodeType":"ParameterList","parameters":[{"constant":false,"id":45,"mutability":"mutable","name":"msgSender","nameLocation":"635:9:0","nodeType":"VariableDeclaration","scope":48,"src":"627:17:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":44,"name":"address","nodeType":"ElementaryTypeName","src":"627:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"626:19:0"},"returnParameters":{"id":47,"nodeType":"ParameterList","parameters":[],"src":"654:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":51,"nodeType":"FunctionDefinition","src":"660:35:0","nodes":[],"functionSelector":"7fb5297f","implemented":false,"kind":"function","modifiers":[],"name":"startBroadcast","nameLocation":"669:14:0","parameters":{"id":49,"nodeType":"ParameterList","parameters":[],"src":"683:2:0"},"returnParameters":{"id":50,"nodeType":"ParameterList","parameters":[],"src":"694:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":54,"nodeType":"FunctionDefinition","src":"700:34:0","nodes":[],"functionSelector":"76eadd36","implemented":false,"kind":"function","modifiers":[],"name":"stopBroadcast","nameLocation":"709:13:0","parameters":{"id":52,"nodeType":"ParameterList","parameters":[],"src":"722:2:0"},"returnParameters":{"id":53,"nodeType":"ParameterList","parameters":[],"src":"733:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"}],"abstract":false,"baseContracts":[],"canonicalName":"Vm","contractDependencies":[],"contractKind":"interface","fullyImplemented":false,"linearizedBaseContracts":[55],"name":"Vm","nameLocation":"130:2:0","scope":720,"usedErrors":[]},{"id":192,"nodeType":"ContractDefinition","src":"791:1622:0","nodes":[{"id":61,"nodeType":"VariableDeclaration","src":"813:86:0","nodes":[],"constant":true,"mutability":"constant","name":"CONSOLE_ADDRESS","nameLocation":"830:15:0","scope":192,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":56,"name":"address","nodeType":"ElementaryTypeName","src":"813:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"value":{"arguments":[{"hexValue":"307830303030303030303030303030303030303036333646366537333646366336353265366336663637","id":59,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"856:42:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"value":"0x000000000000000000636F6e736F6c652e6c6f67"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":58,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"848:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":57,"name":"address","nodeType":"ElementaryTypeName","src":"848:7:0","typeDescriptions":{}}},"id":60,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"848:51:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"},{"id":78,"nodeType":"FunctionDefinition","src":"906:221:0","nodes":[],"body":{"id":77,"nodeType":"Block","src":"1065:62:0","nodes":[],"statements":[{"AST":{"nodeType":"YulBlock","src":"1084:37:0","statements":[{"nodeType":"YulAssignment","src":"1098:13:0","value":{"name":"fnIn","nodeType":"YulIdentifier","src":"1107:4:0"},"variableNames":[{"name":"fnOut","nodeType":"YulIdentifier","src":"1098:5:0"}]}]},"evmVersion":"london","externalReferences":[{"declaration":67,"isOffset":false,"isSlot":false,"src":"1107:4:0","valueSize":1},{"declaration":74,"isOffset":false,"isSlot":false,"src":"1098:5:0","valueSize":1}],"id":76,"nodeType":"InlineAssembly","src":"1075:46:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"_castLogPayloadViewToPure","nameLocation":"915:25:0","parameters":{"id":68,"nodeType":"ParameterList","parameters":[{"constant":false,"id":67,"mutability":"mutable","name":"fnIn","nameLocation":"987:4:0","nodeType":"VariableDeclaration","scope":78,"src":"950:41:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) view"},"typeName":{"id":66,"nodeType":"FunctionTypeName","parameterTypes":{"id":64,"nodeType":"ParameterList","parameters":[{"constant":false,"id":63,"mutability":"mutable","name":"","nameLocation":"-1:-1:-1","nodeType":"VariableDeclaration","scope":66,"src":"959:12:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":62,"name":"bytes","nodeType":"ElementaryTypeName","src":"959:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"958:14:0"},"returnParameterTypes":{"id":65,"nodeType":"ParameterList","parameters":[],"src":"987:0:0"},"src":"950:41:0","stateMutability":"view","typeDescriptions":{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) view"},"visibility":"internal"},"visibility":"internal"}],"src":"940:57:0"},"returnParameters":{"id":75,"nodeType":"ParameterList","parameters":[{"constant":false,"id":74,"mutability":"mutable","name":"fnOut","nameLocation":"1058:5:0","nodeType":"VariableDeclaration","scope":78,"src":"1021:42:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) pure"},"typeName":{"id":73,"nodeType":"FunctionTypeName","parameterTypes":{"id":71,"nodeType":"ParameterList","parameters":[{"constant":false,"id":70,"mutability":"mutable","name":"","nameLocation":"-1:-1:-1","nodeType":"VariableDeclaration","scope":73,"src":"1030:12:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":69,"name":"bytes","nodeType":"ElementaryTypeName","src":"1030:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"1029:14:0"},"returnParameterTypes":{"id":72,"nodeType":"ParameterList","parameters":[],"src":"1058:0:0"},"src":"1021:42:0","stateMutability":"pure","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) pure"},"visibility":"internal"},"visibility":"internal"}],"src":"1020:44:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":90,"nodeType":"FunctionDefinition","src":"1133:133:0","nodes":[],"body":{"id":89,"nodeType":"Block","src":"1194:72:0","nodes":[],"statements":[{"expression":{"arguments":[{"id":86,"name":"payload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":80,"src":"1251:7:0","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"arguments":[{"id":84,"name":"_sendLogPayloadView","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":106,"src":"1230:19:0","typeDescriptions":{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) view"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) view"}],"id":83,"name":"_castLogPayloadViewToPure","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":78,"src":"1204:25:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_function_internal_view$_t_bytes_memory_ptr_$returns$__$_$returns$_t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$_$","typeString":"function (function (bytes memory) view) pure returns (function (bytes memory) pure)"}},"id":85,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1204:46:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":87,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1204:55:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":88,"nodeType":"ExpressionStatement","src":"1204:55:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"_sendLogPayload","nameLocation":"1142:15:0","parameters":{"id":81,"nodeType":"ParameterList","parameters":[{"constant":false,"id":80,"mutability":"mutable","name":"payload","nameLocation":"1171:7:0","nodeType":"VariableDeclaration","scope":90,"src":"1158:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":79,"name":"bytes","nodeType":"ElementaryTypeName","src":"1158:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"1157:22:0"},"returnParameters":{"id":82,"nodeType":"ParameterList","parameters":[],"src":"1194:0:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":106,"nodeType":"FunctionDefinition","src":"1272:380:0","nodes":[],"body":{"id":105,"nodeType":"Block","src":"1336:316:0","nodes":[],"statements":[{"assignments":[96],"declarations":[{"constant":false,"id":96,"mutability":"mutable","name":"payloadLength","nameLocation":"1354:13:0","nodeType":"VariableDeclaration","scope":105,"src":"1346:21:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":95,"name":"uint256","nodeType":"ElementaryTypeName","src":"1346:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"}],"id":99,"initialValue":{"expression":{"id":97,"name":"payload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":92,"src":"1370:7:0","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}},"id":98,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"length","nodeType":"MemberAccess","src":"1370:14:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"nodeType":"VariableDeclarationStatement","src":"1346:38:0"},{"assignments":[101],"declarations":[{"constant":false,"id":101,"mutability":"mutable","name":"consoleAddress","nameLocation":"1402:14:0","nodeType":"VariableDeclaration","scope":105,"src":"1394:22:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":100,"name":"address","nodeType":"ElementaryTypeName","src":"1394:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"id":103,"initialValue":{"id":102,"name":"CONSOLE_ADDRESS","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":61,"src":"1419:15:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"nodeType":"VariableDeclarationStatement","src":"1394:40:0"},{"AST":{"nodeType":"YulBlock","src":"1496:150:0","statements":[{"nodeType":"YulVariableDeclaration","src":"1510:36:0","value":{"arguments":[{"name":"payload","nodeType":"YulIdentifier","src":"1534:7:0"},{"kind":"number","nodeType":"YulLiteral","src":"1543:2:0","type":"","value":"32"}],"functionName":{"name":"add","nodeType":"YulIdentifier","src":"1530:3:0"},"nodeType":"YulFunctionCall","src":"1530:16:0"},"variables":[{"name":"payloadStart","nodeType":"YulTypedName","src":"1514:12:0","type":""}]},{"nodeType":"YulVariableDeclaration","src":"1559:77:0","value":{"arguments":[{"arguments":[],"functionName":{"name":"gas","nodeType":"YulIdentifier","src":"1579:3:0"},"nodeType":"YulFunctionCall","src":"1579:5:0"},{"name":"consoleAddress","nodeType":"YulIdentifier","src":"1586:14:0"},{"name":"payloadStart","nodeType":"YulIdentifier","src":"1602:12:0"},{"name":"payloadLength","nodeType":"YulIdentifier","src":"1616:13:0"},{"kind":"number","nodeType":"YulLiteral","src":"1631:1:0","type":"","value":"0"},{"kind":"number","nodeType":"YulLiteral","src":"1634:1:0","type":"","value":"0"}],"functionName":{"name":"staticcall","nodeType":"YulIdentifier","src":"1568:10:0"},"nodeType":"YulFunctionCall","src":"1568:68:0"},"variables":[{"name":"r","nodeType":"YulTypedName","src":"1563:1:0","type":""}]}]},"documentation":"@solidity memory-safe-assembly","evmVersion":"london","externalReferences":[{"declaration":101,"isOffset":false,"isSlot":false,"src":"1586:14:0","valueSize":1},{"declaration":92,"isOffset":false,"isSlot":false,"src":"1534:7:0","valueSize":1},{"declaration":96,"isOffset":false,"isSlot":false,"src":"1616:13:0","valueSize":1}],"id":104,"nodeType":"InlineAssembly","src":"1487:159:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"_sendLogPayloadView","nameLocation":"1281:19:0","parameters":{"id":93,"nodeType":"ParameterList","parameters":[{"constant":false,"id":92,"mutability":"mutable","name":"payload","nameLocation":"1314:7:0","nodeType":"VariableDeclaration","scope":106,"src":"1301:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":91,"name":"bytes","nodeType":"ElementaryTypeName","src":"1301:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"1300:22:0"},"returnParameters":{"id":94,"nodeType":"ParameterList","parameters":[],"src":"1336:0:0"},"scope":192,"stateMutability":"view","virtual":false,"visibility":"private"},{"id":120,"nodeType":"FunctionDefinition","src":"1658:121:0","nodes":[],"body":{"id":119,"nodeType":"Block","src":"1703:76:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e6729","id":114,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"1753:13:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_41304facd9323d75b11bcdd609cb38effffdb05710f7caf0e9b16c6d9d709f50","typeString":"literal_string \"log(string)\""},"value":"log(string)"},{"id":115,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":108,"src":"1768:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_41304facd9323d75b11bcdd609cb38effffdb05710f7caf0e9b16c6d9d709f50","typeString":"literal_string \"log(string)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}],"expression":{"id":112,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"1729:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":113,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"1729:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":116,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1729:42:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":111,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":90,"src":"1713:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":117,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1713:59:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":118,"nodeType":"ExpressionStatement","src":"1713:59:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"1667:3:0","parameters":{"id":109,"nodeType":"ParameterList","parameters":[{"constant":false,"id":108,"mutability":"mutable","name":"p0","nameLocation":"1685:2:0","nodeType":"VariableDeclaration","scope":120,"src":"1671:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":107,"name":"string","nodeType":"ElementaryTypeName","src":"1671:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"1670:18:0"},"returnParameters":{"id":110,"nodeType":"ParameterList","parameters":[],"src":"1703:0:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":137,"nodeType":"FunctionDefinition","src":"1785:139:0","nodes":[],"body":{"id":136,"nodeType":"Block","src":"1839:85:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c626f6f6c29","id":130,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"1889:18:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_c3b556354c088fbb43886eb83c2a04bc7089663f964d22be308197a236f5b870","typeString":"literal_string \"log(string,bool)\""},"value":"log(string,bool)"},{"id":131,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":122,"src":"1909:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":132,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":124,"src":"1913:2:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_c3b556354c088fbb43886eb83c2a04bc7089663f964d22be308197a236f5b870","typeString":"literal_string \"log(string,bool)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_bool","typeString":"bool"}],"expression":{"id":128,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"1865:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":129,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"1865:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":133,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1865:51:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":127,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":90,"src":"1849:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":134,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1849:68:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":135,"nodeType":"ExpressionStatement","src":"1849:68:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"1794:3:0","parameters":{"id":125,"nodeType":"ParameterList","parameters":[{"constant":false,"id":122,"mutability":"mutable","name":"p0","nameLocation":"1812:2:0","nodeType":"VariableDeclaration","scope":137,"src":"1798:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":121,"name":"string","nodeType":"ElementaryTypeName","src":"1798:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":124,"mutability":"mutable","name":"p1","nameLocation":"1821:2:0","nodeType":"VariableDeclaration","scope":137,"src":"1816:7:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":123,"name":"bool","nodeType":"ElementaryTypeName","src":"1816:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"src":"1797:27:0"},"returnParameters":{"id":126,"nodeType":"ParameterList","parameters":[],"src":"1839:0:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":154,"nodeType":"FunctionDefinition","src":"1930:145:0","nodes":[],"body":{"id":153,"nodeType":"Block","src":"1987:88:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c75696e7432353629","id":147,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2037:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_b60e72ccf6d57ab53eb84d7e94a9545806ed7f93c4d5673f11a64f03471e584e","typeString":"literal_string \"log(string,uint256)\""},"value":"log(string,uint256)"},{"id":148,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":139,"src":"2060:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":149,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":141,"src":"2064:2:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_b60e72ccf6d57ab53eb84d7e94a9545806ed7f93c4d5673f11a64f03471e584e","typeString":"literal_string \"log(string,uint256)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_uint256","typeString":"uint256"}],"expression":{"id":145,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"2013:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":146,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"2013:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":150,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2013:54:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":144,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":90,"src":"1997:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":151,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1997:71:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":152,"nodeType":"ExpressionStatement","src":"1997:71:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"1939:3:0","parameters":{"id":142,"nodeType":"ParameterList","parameters":[{"constant":false,"id":139,"mutability":"mutable","name":"p0","nameLocation":"1957:2:0","nodeType":"VariableDeclaration","scope":154,"src":"1943:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":138,"name":"string","nodeType":"ElementaryTypeName","src":"1943:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":141,"mutability":"mutable","name":"p1","nameLocation":"1969:2:0","nodeType":"VariableDeclaration","scope":154,"src":"1961:10:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":140,"name":"uint256","nodeType":"ElementaryTypeName","src":"1961:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"}],"src":"1942:30:0"},"returnParameters":{"id":143,"nodeType":"ParameterList","parameters":[],"src":"1987:0:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":171,"nodeType":"FunctionDefinition","src":"2081:145:0","nodes":[],"body":{"id":170,"nodeType":"Block","src":"2138:88:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c6164647265737329","id":164,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2188:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_319af333460570a1937bf195dd33445c0d0951c59127da6f1f038b9fdce3fd72","typeString":"literal_string \"log(string,address)\""},"value":"log(string,address)"},{"id":165,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":156,"src":"2211:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":166,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":158,"src":"2215:2:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_319af333460570a1937bf195dd33445c0d0951c59127da6f1f038b9fdce3fd72","typeString":"literal_string \"log(string,address)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":162,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"2164:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":163,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"2164:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":167,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2164:54:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":161,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":90,"src":"2148:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":168,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2148:71:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":169,"nodeType":"ExpressionStatement","src":"2148:71:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"2090:3:0","parameters":{"id":159,"nodeType":"ParameterList","parameters":[{"constant":false,"id":156,"mutability":"mutable","name":"p0","nameLocation":"2108:2:0","nodeType":"VariableDeclaration","scope":171,"src":"2094:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":155,"name":"string","nodeType":"ElementaryTypeName","src":"2094:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":158,"mutability":"mutable","name":"p1","nameLocation":"2120:2:0","nodeType":"VariableDeclaration","scope":171,"src":"2112:10:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":157,"name":"address","nodeType":"ElementaryTypeName","src":"2112:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"2093:30:0"},"returnParameters":{"id":160,"nodeType":"ParameterList","parameters":[],"src":"2138:0:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":191,"nodeType":"FunctionDefinition","src":"2232:179:0","nodes":[],"body":{"id":190,"nodeType":"Block","src":"2313:98:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c737472696e672c737472696e6729","id":183,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2363:27:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_2ced7cef693312206c21f0e92e3b54e2e16bf33db5eec350c78866822c665e1f","typeString":"literal_string \"log(string,string,string)\""},"value":"log(string,string,string)"},{"id":184,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"2392:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":185,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":175,"src":"2396:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":186,"name":"p2","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":177,"src":"2400:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_2ced7cef693312206c21f0e92e3b54e2e16bf33db5eec350c78866822c665e1f","typeString":"literal_string \"log(string,string,string)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}],"expression":{"id":181,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"2339:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":182,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"2339:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":187,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2339:64:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":180,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":90,"src":"2323:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":188,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2323:81:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":189,"nodeType":"ExpressionStatement","src":"2323:81:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"2241:3:0","parameters":{"id":178,"nodeType":"ParameterList","parameters":[{"constant":false,"id":173,"mutability":"mutable","name":"p0","nameLocation":"2259:2:0","nodeType":"VariableDeclaration","scope":191,"src":"2245:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":172,"name":"string","nodeType":"ElementaryTypeName","src":"2245:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":175,"mutability":"mutable","name":"p1","nameLocation":"2277:2:0","nodeType":"VariableDeclaration","scope":191,"src":"2263:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":174,"name":"string","nodeType":"ElementaryTypeName","src":"2263:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":177,"mutability":"mutable","name":"p2","nameLocation":"2295:2:0","nodeType":"VariableDeclaration","scope":191,"src":"2281:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":176,"name":"string","nodeType":"ElementaryTypeName","src":"2281:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"2244:54:0"},"returnParameters":{"id":179,"nodeType":"ParameterList","parameters":[],"src":"2313:0:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"}],"abstract":false,"baseContracts":[],"canonicalName":"console","contractDependencies":[],"contractKind":"library","fullyImplemented":true,"linearizedBaseContracts":[192],"name":"console","nameLocation":"799:7:0","scope":720,"usedErrors":[]},{"id":706,"nodeType":"ContractDefinition","src":"2541:3359:0","nodes":[{"id":207,"nodeType":"VariableDeclaration","src":"2571:94:0","nodes":[],"constant":true,"mutability":"constant","name":"VM_ADDRESS","nameLocation":"2597:10:0","scope":706,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":194,"name":"address","nodeType":"ElementaryTypeName","src":"2571:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"value":{"arguments":[{"arguments":[{"arguments":[{"arguments":[{"hexValue":"6865766d20636865617420636f6465","id":202,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2644:17:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d","typeString":"literal_string \"hevm cheat code\""},"value":"hevm cheat code"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d","typeString":"literal_string \"hevm cheat code\""}],"id":201,"name":"keccak256","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-8,"src":"2634:9:0","typeDescriptions":{"typeIdentifier":"t_function_keccak256_pure$_t_bytes_memory_ptr_$returns$_t_bytes32_$","typeString":"function (bytes memory) pure returns (bytes32)"}},"id":203,"isConstant":false,"isLValue":false,"isPure":true,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2634:28:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes32","typeString":"bytes32"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes32","typeString":"bytes32"}],"id":200,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2626:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint256_$","typeString":"type(uint256)"},"typeName":{"id":199,"name":"uint256","nodeType":"ElementaryTypeName","src":"2626:7:0","typeDescriptions":{}}},"id":204,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2626:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint256","typeString":"uint256"}],"id":198,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2618:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":197,"name":"uint160","nodeType":"ElementaryTypeName","src":"2618:7:0","typeDescriptions":{}}},"id":205,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2618:46:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":196,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2610:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":195,"name":"address","nodeType":"ElementaryTypeName","src":"2610:7:0","typeDescriptions":{}}},"id":206,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2610:55:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"},{"id":213,"nodeType":"VariableDeclaration","src":"2671:40:0","nodes":[],"constant":true,"mutability":"constant","name":"vm","nameLocation":"2692:2:0","scope":706,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"},"typeName":{"id":209,"nodeType":"UserDefinedTypeName","pathNode":{"id":208,"name":"Vm","nodeType":"IdentifierPath","referencedDeclaration":55,"src":"2671:2:0"},"referencedDeclaration":55,"src":"2671:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"value":{"arguments":[{"id":211,"name":"VM_ADDRESS","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":207,"src":"2700:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":210,"name":"Vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":55,"src":"2697:2:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_Vm_$55_$","typeString":"type(contract Vm)"}},"id":212,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2697:14:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"visibility":"internal"},{"id":215,"nodeType":"VariableDeclaration","src":"2775:22:0","nodes":[],"constant":false,"functionSelector":"61bc221a","mutability":"mutable","name":"counter","nameLocation":"2790:7:0","scope":706,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":214,"name":"uint256","nodeType":"ElementaryTypeName","src":"2775:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"public"},{"id":378,"nodeType":"FunctionDefinition","src":"2887:949:0","nodes":[],"body":{"id":377,"nodeType":"Block","src":"2909:927:0","nodes":[],"statements":[{"assignments":[220],"declarations":[{"constant":false,"id":220,"mutability":"mutable","name":"x","nameLocation":"2924:1:0","nodeType":"VariableDeclaration","scope":377,"src":"2919:6:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":219,"name":"bool","nodeType":"ElementaryTypeName","src":"2919:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"id":226,"initialValue":{"arguments":[{"hexValue":"4558414d504c455f424f4f4c","id":223,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2937:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_a634dae177a0e138ae7aaa2afae347412e148992e88c7aabd33ee71be146cb7f","typeString":"literal_string \"EXAMPLE_BOOL\""},"value":"EXAMPLE_BOOL"},{"hexValue":"66616c7365","id":224,"isConstant":false,"isLValue":false,"isPure":true,"kind":"bool","lValueRequested":false,"nodeType":"Literal","src":"2953:5:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"value":"false"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_a634dae177a0e138ae7aaa2afae347412e148992e88c7aabd33ee71be146cb7f","typeString":"literal_string \"EXAMPLE_BOOL\""},{"typeIdentifier":"t_bool","typeString":"bool"}],"expression":{"id":221,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"2928:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":222,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"envOr","nodeType":"MemberAccess","referencedDeclaration":10,"src":"2928:8:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$_t_bool_$returns$_t_bool_$","typeString":"function (string memory,bool) view external returns (bool)"}},"id":225,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2928:31:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"nodeType":"VariableDeclarationStatement","src":"2919:40:0"},{"expression":{"arguments":[{"hexValue":"626f6f6c2076616c75652066726f6d20656e76","id":230,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2981:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_5a607d0b5a1295325aa8901721d78ba402601bba6f62cebdd5235dd0204a590b","typeString":"literal_string \"bool value from env\""},"value":"bool value from env"},{"id":231,"name":"x","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":220,"src":"3004:1:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_5a607d0b5a1295325aa8901721d78ba402601bba6f62cebdd5235dd0204a590b","typeString":"literal_string \"bool value from env\""},{"typeIdentifier":"t_bool","typeString":"bool"}],"expression":{"id":227,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"2969:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":229,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":137,"src":"2969:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_bool_$returns$__$","typeString":"function (string memory,bool) pure"}},"id":232,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2969:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":233,"nodeType":"ExpressionStatement","src":"2969:37:0"},{"expression":{"arguments":[{"hexValue":"636f6e74726163742061646472","id":237,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3029:15:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_fa50728770d00fe8f6a0592f3565bbfaf063ee4077f1f5bbc003d091d33cd0c4","typeString":"literal_string \"contract addr\""},"value":"contract addr"},{"arguments":[{"id":240,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3054:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}],"id":239,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3046:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":238,"name":"address","nodeType":"ElementaryTypeName","src":"3046:7:0","typeDescriptions":{}}},"id":241,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3046:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_fa50728770d00fe8f6a0592f3565bbfaf063ee4077f1f5bbc003d091d33cd0c4","typeString":"literal_string \"contract addr\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":234,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3017:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":236,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":171,"src":"3017:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":242,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3017:43:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":243,"nodeType":"ExpressionStatement","src":"3017:43:0"},{"expression":{"arguments":[{"hexValue":"636f6e7472616374206e6f6e6365","id":247,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3082:16:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_3a23091615a5de8c0a35ffd8857a37e2c4e0b72f3ef8a34d6caf65efcd562e2f","typeString":"literal_string \"contract nonce\""},"value":"contract nonce"},{"arguments":[{"arguments":[{"id":252,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3120:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}],"id":251,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3112:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":250,"name":"address","nodeType":"ElementaryTypeName","src":"3112:7:0","typeDescriptions":{}}},"id":253,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3112:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":248,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"3100:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":249,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"getNonce","nodeType":"MemberAccess","referencedDeclaration":17,"src":"3100:11:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_address_$returns$_t_uint64_$","typeString":"function (address) view external returns (uint64)"}},"id":254,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3100:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_3a23091615a5de8c0a35ffd8857a37e2c4e0b72f3ef8a34d6caf65efcd562e2f","typeString":"literal_string \"contract nonce\""},{"typeIdentifier":"t_uint64","typeString":"uint64"}],"expression":{"id":244,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3070:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":246,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":154,"src":"3070:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_uint256_$returns$__$","typeString":"function (string memory,uint256) pure"}},"id":255,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3070:57:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":256,"nodeType":"ExpressionStatement","src":"3070:57:0"},{"expression":{"arguments":[{"hexValue":"73656e6465722061646472","id":260,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3149:13:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_8125ca2decf812b25b65606ff16dad37cb198ff0433485a7926e50feafacfc35","typeString":"literal_string \"sender addr\""},"value":"sender addr"},{"arguments":[{"expression":{"id":263,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"3172:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":264,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"3172:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":262,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3164:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":261,"name":"address","nodeType":"ElementaryTypeName","src":"3164:7:0","typeDescriptions":{}}},"id":265,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3164:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_8125ca2decf812b25b65606ff16dad37cb198ff0433485a7926e50feafacfc35","typeString":"literal_string \"sender addr\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":257,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3137:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":259,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":171,"src":"3137:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":266,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3137:47:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":267,"nodeType":"ExpressionStatement","src":"3137:47:0"},{"expression":{"arguments":[{"hexValue":"73656e646572206e6f6e6365","id":271,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3206:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_db7deb43f2f9e0404016de53b7e64c4976b54149581f7534daae2551e8cf4e40","typeString":"literal_string \"sender nonce\""},"value":"sender nonce"},{"arguments":[{"arguments":[{"expression":{"id":276,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"3242:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":277,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"3242:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":275,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3234:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":274,"name":"address","nodeType":"ElementaryTypeName","src":"3234:7:0","typeDescriptions":{}}},"id":278,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3234:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":272,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"3222:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":273,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"getNonce","nodeType":"MemberAccess","referencedDeclaration":17,"src":"3222:11:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_address_$returns$_t_uint64_$","typeString":"function (address) view external returns (uint64)"}},"id":279,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3222:32:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_db7deb43f2f9e0404016de53b7e64c4976b54149581f7534daae2551e8cf4e40","typeString":"literal_string \"sender nonce\""},{"typeIdentifier":"t_uint64","typeString":"uint64"}],"expression":{"id":268,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3194:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":270,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":154,"src":"3194:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_uint256_$returns$__$","typeString":"function (string memory,uint256) pure"}},"id":280,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3194:61:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":281,"nodeType":"ExpressionStatement","src":"3194:61:0"},{"assignments":[283],"declarations":[{"constant":false,"id":283,"mutability":"mutable","name":"json","nameLocation":"3280:4:0","nodeType":"VariableDeclaration","scope":377,"src":"3266:18:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":282,"name":"string","nodeType":"ElementaryTypeName","src":"3266:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"id":285,"initialValue":{"hexValue":"7b22726f6f745f6b6579223a205b7b2261223a20312c202262223a20327d5d7d","id":284,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3287:34:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_e95522e99766888d0261f55bd1eae5e3f3e26eaf009a16e2433eafaf0a4ecdf2","typeString":"literal_string \"{\"root_key\": [{\"a\": 1, \"b\": 2}]}\""},"value":"{\"root_key\": [{\"a\": 1, \"b\": 2}]}"},"nodeType":"VariableDeclarationStatement","src":"3266:55:0"},{"assignments":[290],"declarations":[{"constant":false,"id":290,"mutability":"mutable","name":"keys","nameLocation":"3347:4:0","nodeType":"VariableDeclaration","scope":377,"src":"3331:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string[]"},"typeName":{"baseType":{"id":288,"name":"string","nodeType":"ElementaryTypeName","src":"3331:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"id":289,"nodeType":"ArrayTypeName","src":"3331:8:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_storage_$dyn_storage_ptr","typeString":"string[]"}},"visibility":"internal"}],"id":296,"initialValue":{"arguments":[{"id":293,"name":"json","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":283,"src":"3371:4:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"hexValue":"2e726f6f745f6b65795b305d","id":294,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3377:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_d82f67100edb80050915e1ec4b565c9a8319a22efb1075e1298b7bb60101d266","typeString":"literal_string \".root_key[0]\""},"value":".root_key[0]"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_stringliteral_d82f67100edb80050915e1ec4b565c9a8319a22efb1075e1298b7bb60101d266","typeString":"literal_string \".root_key[0]\""}],"expression":{"id":291,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"3354:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":292,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"parseJsonKeys","nodeType":"MemberAccess","referencedDeclaration":27,"src":"3354:16:0","typeDescriptions":{"typeIdentifier":"t_function_external_pure$_t_string_memory_ptr_$_t_string_memory_ptr_$returns$_t_array$_t_string_memory_ptr_$dyn_memory_ptr_$","typeString":"function (string memory,string memory) pure external returns (string memory[] memory)"}},"id":295,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3354:38:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string memory[] memory"}},"nodeType":"VariableDeclarationStatement","src":"3331:61:0"},{"expression":{"arguments":[{"hexValue":"6b657973","id":300,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3414:6:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_f29790a80c4ce5f42f59892f424f9c92856c6b656c3378e2cf305b260c6f4195","typeString":"literal_string \"keys\""},"value":"keys"},{"baseExpression":{"id":301,"name":"keys","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":290,"src":"3422:4:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string memory[] memory"}},"id":303,"indexExpression":{"hexValue":"30","id":302,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"3427:1:0","typeDescriptions":{"typeIdentifier":"t_rational_0_by_1","typeString":"int_const 0"},"value":"0"},"isConstant":false,"isLValue":true,"isPure":false,"lValueRequested":false,"nodeType":"IndexAccess","src":"3422:7:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"baseExpression":{"id":304,"name":"keys","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":290,"src":"3431:4:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string memory[] memory"}},"id":306,"indexExpression":{"hexValue":"31","id":305,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"3436:1:0","typeDescriptions":{"typeIdentifier":"t_rational_1_by_1","typeString":"int_const 1"},"value":"1"},"isConstant":false,"isLValue":true,"isPure":false,"lValueRequested":false,"nodeType":"IndexAccess","src":"3431:7:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_f29790a80c4ce5f42f59892f424f9c92856c6b656c3378e2cf305b260c6f4195","typeString":"literal_string \"keys\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}],"expression":{"id":297,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3402:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":299,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":191,"src":"3402:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_string_memory_ptr_$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory,string memory,string memory) pure"}},"id":307,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3402:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":308,"nodeType":"ExpressionStatement","src":"3402:37:0"},{"expression":{"arguments":[{"hexValue":"66726f6d206f726967696e616c","id":312,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3461:15:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_77928970c8757d110f3c23e003246f49e0de890480ba9717ba659b2f56f316b2","typeString":"literal_string \"from original\""},"value":"from original"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_77928970c8757d110f3c23e003246f49e0de890480ba9717ba659b2f56f316b2","typeString":"literal_string \"from original\""}],"expression":{"id":309,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3450:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":311,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":633,"src":"3450:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":313,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3450:27:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":314,"nodeType":"ExpressionStatement","src":"3450:27:0"},{"expression":{"arguments":[{"arguments":[{"arguments":[{"hexValue":"30783432","id":322,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"3517:4:0","typeDescriptions":{"typeIdentifier":"t_rational_66_by_1","typeString":"int_const 66"},"value":"0x42"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_66_by_1","typeString":"int_const 66"}],"id":321,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3509:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":320,"name":"uint160","nodeType":"ElementaryTypeName","src":"3509:7:0","typeDescriptions":{}}},"id":323,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3509:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":319,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3501:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":318,"name":"address","nodeType":"ElementaryTypeName","src":"3501:7:0","typeDescriptions":{}}},"id":324,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3501:22:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":315,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"3487:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":317,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"startPrank","nodeType":"MemberAccess","referencedDeclaration":32,"src":"3487:13:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_address_$returns$__$","typeString":"function (address) external"}},"id":325,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3487:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":326,"nodeType":"ExpressionStatement","src":"3487:37:0"},{"expression":{"arguments":[{"hexValue":"66726f6d207072616e6b2031","id":330,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3545:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_42b34abfe37a8b0add910cda7b4a379e6538fa7a1dcafce47a02bd38f6c88e2a","typeString":"literal_string \"from prank 1\""},"value":"from prank 1"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_42b34abfe37a8b0add910cda7b4a379e6538fa7a1dcafce47a02bd38f6c88e2a","typeString":"literal_string \"from prank 1\""}],"expression":{"id":327,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3534:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":329,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":633,"src":"3534:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":331,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3534:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":332,"nodeType":"ExpressionStatement","src":"3534:26:0"},{"expression":{"arguments":[{"hexValue":"706172656e742073636f7065206d73672e73656e646572","id":336,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3582:25:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_83ec9246154d8845de47aafc5c2865c9985d2efe84472c27283879f2fbf5cc94","typeString":"literal_string \"parent scope msg.sender\""},"value":"parent scope msg.sender"},{"arguments":[{"expression":{"id":339,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"3617:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":340,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"3617:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":338,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3609:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":337,"name":"address","nodeType":"ElementaryTypeName","src":"3609:7:0","typeDescriptions":{}}},"id":341,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3609:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_83ec9246154d8845de47aafc5c2865c9985d2efe84472c27283879f2fbf5cc94","typeString":"literal_string \"parent scope msg.sender\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":333,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3570:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":335,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":171,"src":"3570:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":342,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3570:59:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":343,"nodeType":"ExpressionStatement","src":"3570:59:0"},{"expression":{"arguments":[{"hexValue":"706172656e742073636f706520636f6e74726163742e61646472","id":347,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3651:28:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_97df66250e0b2b48f0ec8d0e01eb1b8ca012d95f1572895622aa1ea433e5570f","typeString":"literal_string \"parent scope contract.addr\""},"value":"parent scope contract.addr"},{"arguments":[{"id":350,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3689:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}],"id":349,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3681:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":348,"name":"address","nodeType":"ElementaryTypeName","src":"3681:7:0","typeDescriptions":{}}},"id":351,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3681:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_97df66250e0b2b48f0ec8d0e01eb1b8ca012d95f1572895622aa1ea433e5570f","typeString":"literal_string \"parent scope contract.addr\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":344,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3639:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":346,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":171,"src":"3639:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":352,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3639:56:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":353,"nodeType":"ExpressionStatement","src":"3639:56:0"},{"expression":{"arguments":[{"hexValue":"66726f6d207072616e6b2032","id":357,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3716:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_a38a34f8cad750a79aa097a92971f8f405b51ee9d53d25c5b14fc129ba3684bb","typeString":"literal_string \"from prank 2\""},"value":"from prank 2"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_a38a34f8cad750a79aa097a92971f8f405b51ee9d53d25c5b14fc129ba3684bb","typeString":"literal_string \"from prank 2\""}],"expression":{"id":354,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3705:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":356,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":633,"src":"3705:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":358,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3705:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":359,"nodeType":"ExpressionStatement","src":"3705:26:0"},{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":360,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"3741:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":362,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"stopPrank","nodeType":"MemberAccess","referencedDeclaration":35,"src":"3741:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$__$returns$__$","typeString":"function () external"}},"id":363,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3741:14:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":364,"nodeType":"ExpressionStatement","src":"3741:14:0"},{"expression":{"arguments":[{"hexValue":"66726f6d206f726967696e616c20616761696e","id":368,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3776:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_0c805c6579e20a9c4c8e11aeab23330910a9f2da629191dc119d1730e8ed6860","typeString":"literal_string \"from original again\""},"value":"from original again"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_0c805c6579e20a9c4c8e11aeab23330910a9f2da629191dc119d1730e8ed6860","typeString":"literal_string \"from original again\""}],"expression":{"id":365,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3765:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":367,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":633,"src":"3765:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":369,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3765:33:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":370,"nodeType":"ExpressionStatement","src":"3765:33:0"},{"expression":{"arguments":[{"hexValue":"646f6e6521","id":374,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3821:7:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_080382d5c9e9e7c5e3d1d33f5e7422740375955180fadff167d8130e0c35f3fc","typeString":"literal_string \"done!\""},"value":"done!"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_080382d5c9e9e7c5e3d1d33f5e7422740375955180fadff167d8130e0c35f3fc","typeString":"literal_string \"done!\""}],"expression":{"id":371,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3809:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":373,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"3809:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":375,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3809:20:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":376,"nodeType":"ExpressionStatement","src":"3809:20:0"}]},"documentation":{"id":216,"nodeType":"StructuredDocumentation","src":"2804:78:0","text":"@notice example function, runs through basic cheat-codes and console logs."},"functionSelector":"c0406226","implemented":true,"kind":"function","modifiers":[],"name":"run","nameLocation":"2896:3:0","parameters":{"id":217,"nodeType":"ParameterList","parameters":[],"src":"2899:2:0"},"returnParameters":{"id":218,"nodeType":"ParameterList","parameters":[],"src":"2909:0:0"},"scope":706,"stateMutability":"nonpayable","virtual":false,"visibility":"public"},{"id":609,"nodeType":"FunctionDefinition","src":"3903:1258:0","nodes":[],"body":{"id":608,"nodeType":"Block","src":"3934:1227:0","nodes":[],"statements":[{"expression":{"arguments":[{"hexValue":"6e6f6e6365207374617274","id":385,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3956:13:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_71efc69b9a13b6bc1e9a14d766ff01c79022262c6daa6532fb5dfb14f8511a20","typeString":"literal_string \"nonce start\""},"value":"nonce start"},{"arguments":[{"arguments":[{"arguments":[{"id":392,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3999:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}],"id":391,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3991:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":390,"name":"address","nodeType":"ElementaryTypeName","src":"3991:7:0","typeDescriptions":{}}},"id":393,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3991:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":388,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"3979:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":389,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"getNonce","nodeType":"MemberAccess","referencedDeclaration":17,"src":"3979:11:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_address_$returns$_t_uint64_$","typeString":"function (address) view external returns (uint64)"}},"id":394,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3979:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint64","typeString":"uint64"}],"id":387,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3971:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint256_$","typeString":"type(uint256)"},"typeName":{"id":386,"name":"uint256","nodeType":"ElementaryTypeName","src":"3971:7:0","typeDescriptions":{}}},"id":395,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3971:35:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_71efc69b9a13b6bc1e9a14d766ff01c79022262c6daa6532fb5dfb14f8511a20","typeString":"literal_string \"nonce start\""},{"typeIdentifier":"t_uint256","typeString":"uint256"}],"expression":{"id":382,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3944:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":384,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":154,"src":"3944:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_uint256_$returns$__$","typeString":"function (string memory,uint256) pure"}},"id":396,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3944:63:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":397,"nodeType":"ExpressionStatement","src":"3944:63:0"},{"expression":{"arguments":[{"hexValue":"74657374696e672073696e676c65","id":401,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4030:16:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_b75103528423218e7569082dad569ed0d2ce7c0ac770c0812b220e2d369fe474","typeString":"literal_string \"testing single\""},"value":"testing single"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_b75103528423218e7569082dad569ed0d2ce7c0ac770c0812b220e2d369fe474","typeString":"literal_string \"testing single\""}],"expression":{"id":398,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"4018:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":400,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"4018:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":402,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4018:29:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":403,"nodeType":"ExpressionStatement","src":"4018:29:0"},{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":404,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4057:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":406,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"broadcast","nodeType":"MemberAccess","referencedDeclaration":38,"src":"4057:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$__$returns$__$","typeString":"function () external"}},"id":407,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4057:14:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":408,"nodeType":"ExpressionStatement","src":"4057:14:0"},{"expression":{"arguments":[{"hexValue":"73696e676c655f63616c6c31","id":412,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4092:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_5e1cad6d7a968cfacf2731373e1248ffb11f4886bced66a02a6de1a67ac8f777","typeString":"literal_string \"single_call1\""},"value":"single_call1"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_5e1cad6d7a968cfacf2731373e1248ffb11f4886bced66a02a6de1a67ac8f777","typeString":"literal_string \"single_call1\""}],"expression":{"id":409,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4081:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":411,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"call1","nodeType":"MemberAccess","referencedDeclaration":648,"src":"4081:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":413,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4081:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":414,"nodeType":"ExpressionStatement","src":"4081:26:0"},{"expression":{"arguments":[{"hexValue":"73696e676c655f63616c6c32","id":418,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4128:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_b37ddaf5d00ad9e6371de3fb71b91eef731fae1e86b768666380f7d44e1ada25","typeString":"literal_string \"single_call2\""},"value":"single_call2"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_b37ddaf5d00ad9e6371de3fb71b91eef731fae1e86b768666380f7d44e1ada25","typeString":"literal_string \"single_call2\""}],"expression":{"id":415,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4117:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":417,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"call2","nodeType":"MemberAccess","referencedDeclaration":663,"src":"4117:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":419,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4117:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":420,"nodeType":"ExpressionStatement","src":"4117:26:0"},{"expression":{"arguments":[{"hexValue":"74657374696e672073746172742f73746f70","id":424,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4166:20:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_778e886e3a1c3c5096aca76228832105f3f9269f362effd0e8ce3737787cb784","typeString":"literal_string \"testing start/stop\""},"value":"testing start/stop"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_778e886e3a1c3c5096aca76228832105f3f9269f362effd0e8ce3737787cb784","typeString":"literal_string \"testing start/stop\""}],"expression":{"id":421,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"4154:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":423,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"4154:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":425,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4154:33:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":426,"nodeType":"ExpressionStatement","src":"4154:33:0"},{"expression":{"arguments":[{"arguments":[{"arguments":[{"hexValue":"3078633066666565","id":434,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4231:8:0","typeDescriptions":{"typeIdentifier":"t_rational_12648430_by_1","typeString":"int_const 12648430"},"value":"0xc0ffee"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_12648430_by_1","typeString":"int_const 12648430"}],"id":433,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4223:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":432,"name":"uint160","nodeType":"ElementaryTypeName","src":"4223:7:0","typeDescriptions":{}}},"id":435,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4223:17:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":431,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4215:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":430,"name":"address","nodeType":"ElementaryTypeName","src":"4215:7:0","typeDescriptions":{}}},"id":436,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4215:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":427,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4197:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":429,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"startBroadcast","nodeType":"MemberAccess","referencedDeclaration":48,"src":"4197:17:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_address_$returns$__$","typeString":"function (address) external"}},"id":437,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4197:45:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":438,"nodeType":"ExpressionStatement","src":"4197:45:0"},{"expression":{"arguments":[{"hexValue":"737461727473746f705f63616c6c31","id":442,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4263:17:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_2fc2682edf10ed478ee3b9a190f6b1c88bb492b300935ce44545a1613cf8f041","typeString":"literal_string \"startstop_call1\""},"value":"startstop_call1"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_2fc2682edf10ed478ee3b9a190f6b1c88bb492b300935ce44545a1613cf8f041","typeString":"literal_string \"startstop_call1\""}],"expression":{"id":439,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4252:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":441,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"call1","nodeType":"MemberAccess","referencedDeclaration":648,"src":"4252:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":443,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4252:29:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":444,"nodeType":"ExpressionStatement","src":"4252:29:0"},{"expression":{"arguments":[{"hexValue":"737461727473746f705f63616c6c32","id":448,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4302:17:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_1a6fd77f04b28bf45d6d0e2dd4c65c0bbfeba174f849e43bb67ebca1c019cda4","typeString":"literal_string \"startstop_call2\""},"value":"startstop_call2"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_1a6fd77f04b28bf45d6d0e2dd4c65c0bbfeba174f849e43bb67ebca1c019cda4","typeString":"literal_string \"startstop_call2\""}],"expression":{"id":445,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4291:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":447,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"call2","nodeType":"MemberAccess","referencedDeclaration":663,"src":"4291:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":449,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4291:29:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":450,"nodeType":"ExpressionStatement","src":"4291:29:0"},{"expression":{"arguments":[{"hexValue":"737461727473746f705f70757265","id":454,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4344:16:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_b6e9eb1efd186b1d92b54da45026aa97a178e6eaffdf9dbf9f666fc751fb0ff9","typeString":"literal_string \"startstop_pure\""},"value":"startstop_pure"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_b6e9eb1efd186b1d92b54da45026aa97a178e6eaffdf9dbf9f666fc751fb0ff9","typeString":"literal_string \"startstop_pure\""}],"expression":{"id":451,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4330:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":453,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"callPure","nodeType":"MemberAccess","referencedDeclaration":705,"src":"4330:13:0","typeDescriptions":{"typeIdentifier":"t_function_external_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure external"}},"id":455,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4330:31:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":456,"nodeType":"ExpressionStatement","src":"4330:31:0"},{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":457,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4371:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":459,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"stopBroadcast","nodeType":"MemberAccess","referencedDeclaration":54,"src":"4371:16:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$__$returns$__$","typeString":"function () external"}},"id":460,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4371:18:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":461,"nodeType":"ExpressionStatement","src":"4371:18:0"},{"expression":{"arguments":[{"hexValue":"737461727473746f705f63616c6c33","id":465,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4410:17:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_8eb502bfdc4adda22bd960aa2ae13ce4c0ed8cc3b3791ed65e321a38cdd36f72","typeString":"literal_string \"startstop_call3\""},"value":"startstop_call3"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_8eb502bfdc4adda22bd960aa2ae13ce4c0ed8cc3b3791ed65e321a38cdd36f72","typeString":"literal_string \"startstop_call3\""}],"expression":{"id":462,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4399:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":464,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"call1","nodeType":"MemberAccess","referencedDeclaration":648,"src":"4399:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":466,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4399:29:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":467,"nodeType":"ExpressionStatement","src":"4399:29:0"},{"expression":{"arguments":[{"hexValue":"74657374696e67206e6573746564","id":471,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4451:16:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_f92f19f7a5b5b9ce341188bf4e15925f184cdb5ac135c4846ced718f259dbde5","typeString":"literal_string \"testing nested\""},"value":"testing nested"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_f92f19f7a5b5b9ce341188bf4e15925f184cdb5ac135c4846ced718f259dbde5","typeString":"literal_string \"testing nested\""}],"expression":{"id":468,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"4439:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":470,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"4439:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":472,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4439:29:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":473,"nodeType":"ExpressionStatement","src":"4439:29:0"},{"expression":{"arguments":[{"arguments":[{"arguments":[{"hexValue":"307831323334","id":481,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4512:6:0","typeDescriptions":{"typeIdentifier":"t_rational_4660_by_1","typeString":"int_const 4660"},"value":"0x1234"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_4660_by_1","typeString":"int_const 4660"}],"id":480,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4504:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":479,"name":"uint160","nodeType":"ElementaryTypeName","src":"4504:7:0","typeDescriptions":{}}},"id":482,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4504:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":478,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4496:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":477,"name":"address","nodeType":"ElementaryTypeName","src":"4496:7:0","typeDescriptions":{}}},"id":483,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4496:24:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":474,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4478:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":476,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"startBroadcast","nodeType":"MemberAccess","referencedDeclaration":48,"src":"4478:17:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_address_$returns$__$","typeString":"function (address) external"}},"id":484,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4478:43:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":485,"nodeType":"ExpressionStatement","src":"4478:43:0"},{"expression":{"arguments":[{"hexValue":"6e6573746564","id":489,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4544:8:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_4d5b14044d78fbf0c9dd8b9c49e35f09ee5a6f5b1b3b8117b5d0e15c8dd2cb09","typeString":"literal_string \"nested\""},"value":"nested"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_4d5b14044d78fbf0c9dd8b9c49e35f09ee5a6f5b1b3b8117b5d0e15c8dd2cb09","typeString":"literal_string \"nested\""}],"expression":{"id":486,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4531:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":488,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"nested1","nodeType":"MemberAccess","referencedDeclaration":678,"src":"4531:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":490,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4531:22:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":491,"nodeType":"ExpressionStatement","src":"4531:22:0"},{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":492,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4563:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":494,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"stopBroadcast","nodeType":"MemberAccess","referencedDeclaration":54,"src":"4563:16:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$__$returns$__$","typeString":"function () external"}},"id":495,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4563:18:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":496,"nodeType":"ExpressionStatement","src":"4563:18:0"},{"expression":{"arguments":[{"hexValue":"636f6e7472616374206465706c6f796d656e74","id":500,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4604:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_aaf9be86adf9b6872d87eed3526f7c55f3c5d61f4e4dd6d55ef2fcbb8ad0bd57","typeString":"literal_string \"contract deployment\""},"value":"contract deployment"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_aaf9be86adf9b6872d87eed3526f7c55f3c5d61f4e4dd6d55ef2fcbb8ad0bd57","typeString":"literal_string \"contract deployment\""}],"expression":{"id":497,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"4592:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":499,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"4592:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":501,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4592:34:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":502,"nodeType":"ExpressionStatement","src":"4592:34:0"},{"expression":{"arguments":[{"arguments":[{"arguments":[{"hexValue":"3078313233343536","id":510,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4665:8:0","typeDescriptions":{"typeIdentifier":"t_rational_1193046_by_1","typeString":"int_const 1193046"},"value":"0x123456"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_1193046_by_1","typeString":"int_const 1193046"}],"id":509,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4657:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":508,"name":"uint160","nodeType":"ElementaryTypeName","src":"4657:7:0","typeDescriptions":{}}},"id":511,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4657:17:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":507,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4649:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":506,"name":"address","nodeType":"ElementaryTypeName","src":"4649:7:0","typeDescriptions":{}}},"id":512,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4649:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":503,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4636:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":505,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"broadcast","nodeType":"MemberAccess","referencedDeclaration":43,"src":"4636:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_address_$returns$__$","typeString":"function (address) external"}},"id":513,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4636:40:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":514,"nodeType":"ExpressionStatement","src":"4636:40:0"},{"assignments":[517],"declarations":[{"constant":false,"id":517,"mutability":"mutable","name":"x","nameLocation":"4693:1:0","nodeType":"VariableDeclaration","scope":608,"src":"4686:8:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"},"typeName":{"id":516,"nodeType":"UserDefinedTypeName","pathNode":{"id":515,"name":"FooBar","nodeType":"IdentifierPath","referencedDeclaration":719,"src":"4686:6:0"},"referencedDeclaration":719,"src":"4686:6:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"visibility":"internal"}],"id":523,"initialValue":{"arguments":[{"hexValue":"31323334","id":521,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4708:4:0","typeDescriptions":{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"},"value":"1234"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"}],"id":520,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"NewExpression","src":"4697:10:0","typeDescriptions":{"typeIdentifier":"t_function_creation_nonpayable$_t_uint256_$returns$_t_contract$_FooBar_$719_$","typeString":"function (uint256) returns (contract FooBar)"},"typeName":{"id":519,"nodeType":"UserDefinedTypeName","pathNode":{"id":518,"name":"FooBar","nodeType":"IdentifierPath","referencedDeclaration":719,"src":"4701:6:0"},"referencedDeclaration":719,"src":"4701:6:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}}},"id":522,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4697:16:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"nodeType":"VariableDeclarationStatement","src":"4686:27:0"},{"expression":{"arguments":[{"commonType":{"typeIdentifier":"t_uint256","typeString":"uint256"},"id":529,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"leftExpression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":525,"name":"x","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":517,"src":"4731:1:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"id":526,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"foo","nodeType":"MemberAccess","referencedDeclaration":708,"src":"4731:5:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$__$returns$_t_uint256_$","typeString":"function () view external returns (uint256)"}},"id":527,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4731:7:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"nodeType":"BinaryOperation","operator":"==","rightExpression":{"hexValue":"31323334","id":528,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4742:4:0","typeDescriptions":{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"},"value":"1234"},"src":"4731:15:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bool","typeString":"bool"}],"id":524,"name":"require","nodeType":"Identifier","overloadedDeclarations":[-18,-18],"referencedDeclaration":-18,"src":"4723:7:0","typeDescriptions":{"typeIdentifier":"t_function_require_pure$_t_bool_$returns$__$","typeString":"function (bool) pure"}},"id":530,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4723:24:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":531,"nodeType":"ExpressionStatement","src":"4723:24:0"},{"expression":{"arguments":[{"hexValue":"6372656174652032","id":535,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4770:10:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_4411d6d4ffcd00382a95255a63761e69de9810e1236042a5c64948a7b6c04daa","typeString":"literal_string \"create 2\""},"value":"create 2"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_4411d6d4ffcd00382a95255a63761e69de9810e1236042a5c64948a7b6c04daa","typeString":"literal_string \"create 2\""}],"expression":{"id":532,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"4758:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":534,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"4758:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":536,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4758:23:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":537,"nodeType":"ExpressionStatement","src":"4758:23:0"},{"expression":{"arguments":[{"arguments":[{"arguments":[{"hexValue":"307863616665","id":545,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4820:6:0","typeDescriptions":{"typeIdentifier":"t_rational_51966_by_1","typeString":"int_const 51966"},"value":"0xcafe"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_51966_by_1","typeString":"int_const 51966"}],"id":544,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4812:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":543,"name":"uint160","nodeType":"ElementaryTypeName","src":"4812:7:0","typeDescriptions":{}}},"id":546,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4812:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":542,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4804:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":541,"name":"address","nodeType":"ElementaryTypeName","src":"4804:7:0","typeDescriptions":{}}},"id":547,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4804:24:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":538,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4791:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":540,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"broadcast","nodeType":"MemberAccess","referencedDeclaration":43,"src":"4791:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_address_$returns$__$","typeString":"function (address) external"}},"id":548,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4791:38:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":549,"nodeType":"ExpressionStatement","src":"4791:38:0"},{"assignments":[552],"declarations":[{"constant":false,"id":552,"mutability":"mutable","name":"y","nameLocation":"4846:1:0","nodeType":"VariableDeclaration","scope":608,"src":"4839:8:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"},"typeName":{"id":551,"nodeType":"UserDefinedTypeName","pathNode":{"id":550,"name":"FooBar","nodeType":"IdentifierPath","referencedDeclaration":719,"src":"4839:6:0"},"referencedDeclaration":719,"src":"4839:6:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"visibility":"internal"}],"id":566,"initialValue":{"arguments":[{"hexValue":"31323334","id":564,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4889:4:0","typeDescriptions":{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"},"value":"1234"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"}],"id":555,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"NewExpression","src":"4850:10:0","typeDescriptions":{"typeIdentifier":"t_function_creation_nonpayable$_t_uint256_$returns$_t_contract$_FooBar_$719_$","typeString":"function (uint256) returns (contract FooBar)"},"typeName":{"id":554,"nodeType":"UserDefinedTypeName","pathNode":{"id":553,"name":"FooBar","nodeType":"IdentifierPath","referencedDeclaration":719,"src":"4854:6:0"},"referencedDeclaration":719,"src":"4854:6:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}}},"id":563,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"names":["salt"],"nodeType":"FunctionCallOptions","options":[{"arguments":[{"arguments":[{"hexValue":"3432","id":560,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4883:2:0","typeDescriptions":{"typeIdentifier":"t_rational_42_by_1","typeString":"int_const 42"},"value":"42"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_42_by_1","typeString":"int_const 42"}],"id":559,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4875:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint256_$","typeString":"type(uint256)"},"typeName":{"id":558,"name":"uint256","nodeType":"ElementaryTypeName","src":"4875:7:0","typeDescriptions":{}}},"id":561,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4875:11:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint256","typeString":"uint256"}],"id":557,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4867:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_bytes32_$","typeString":"type(bytes32)"},"typeName":{"id":556,"name":"bytes32","nodeType":"ElementaryTypeName","src":"4867:7:0","typeDescriptions":{}}},"id":562,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4867:20:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes32","typeString":"bytes32"}}],"src":"4850:38:0","typeDescriptions":{"typeIdentifier":"t_function_creation_nonpayable$_t_uint256_$returns$_t_contract$_FooBar_$719_$salt","typeString":"function (uint256) returns (contract FooBar)"}},"id":565,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4850:44:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"nodeType":"VariableDeclarationStatement","src":"4839:55:0"},{"expression":{"arguments":[{"commonType":{"typeIdentifier":"t_uint256","typeString":"uint256"},"id":572,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"leftExpression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":568,"name":"y","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":552,"src":"4912:1:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"id":569,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"foo","nodeType":"MemberAccess","referencedDeclaration":708,"src":"4912:5:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$__$returns$_t_uint256_$","typeString":"function () view external returns (uint256)"}},"id":570,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4912:7:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"nodeType":"BinaryOperation","operator":"==","rightExpression":{"hexValue":"31323334","id":571,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4923:4:0","typeDescriptions":{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"},"value":"1234"},"src":"4912:15:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bool","typeString":"bool"}],"id":567,"name":"require","nodeType":"Identifier","overloadedDeclarations":[-18,-18],"referencedDeclaration":-18,"src":"4904:7:0","typeDescriptions":{"typeIdentifier":"t_function_require_pure$_t_bool_$returns$__$","typeString":"function (bool) pure"}},"id":573,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4904:24:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":574,"nodeType":"ExpressionStatement","src":"4904:24:0"},{"expression":{"arguments":[{"hexValue":"646f6e6521","id":578,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4950:7:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_080382d5c9e9e7c5e3d1d33f5e7422740375955180fadff167d8130e0c35f3fc","typeString":"literal_string \"done!\""},"value":"done!"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_080382d5c9e9e7c5e3d1d33f5e7422740375955180fadff167d8130e0c35f3fc","typeString":"literal_string \"done!\""}],"expression":{"id":575,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"4938:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":577,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"4938:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":579,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4938:20:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":580,"nodeType":"ExpressionStatement","src":"4938:20:0"},{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":581,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"5042:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":583,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"broadcast","nodeType":"MemberAccess","referencedDeclaration":38,"src":"5042:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$__$returns$__$","typeString":"function () external"}},"id":584,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5042:14:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":585,"nodeType":"ExpressionStatement","src":"5042:14:0"},{"expression":{"arguments":[{"hexValue":"31323334","id":589,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"5077:4:0","typeDescriptions":{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"},"value":"1234"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"}],"id":588,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"NewExpression","src":"5066:10:0","typeDescriptions":{"typeIdentifier":"t_function_creation_nonpayable$_t_uint256_$returns$_t_contract$_FooBar_$719_$","typeString":"function (uint256) returns (contract FooBar)"},"typeName":{"id":587,"nodeType":"UserDefinedTypeName","pathNode":{"id":586,"name":"FooBar","nodeType":"IdentifierPath","referencedDeclaration":719,"src":"5070:6:0"},"referencedDeclaration":719,"src":"5070:6:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}}},"id":590,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5066:16:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"id":591,"nodeType":"ExpressionStatement","src":"5066:16:0"},{"expression":{"arguments":[{"hexValue":"6e6f6e636520656e64","id":595,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"5105:11:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_fa629e6661ad2a2bdb09cf9a3a276ce0d722482ae5c2887650751be0938847e8","typeString":"literal_string \"nonce end\""},"value":"nonce end"},{"arguments":[{"arguments":[{"arguments":[{"id":602,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"5146:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}],"id":601,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"5138:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":600,"name":"address","nodeType":"ElementaryTypeName","src":"5138:7:0","typeDescriptions":{}}},"id":603,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5138:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":598,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"5126:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":599,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"getNonce","nodeType":"MemberAccess","referencedDeclaration":17,"src":"5126:11:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_address_$returns$_t_uint64_$","typeString":"function (address) view external returns (uint64)"}},"id":604,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5126:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint64","typeString":"uint64"}],"id":597,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"5118:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint256_$","typeString":"type(uint256)"},"typeName":{"id":596,"name":"uint256","nodeType":"ElementaryTypeName","src":"5118:7:0","typeDescriptions":{}}},"id":605,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5118:35:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_fa629e6661ad2a2bdb09cf9a3a276ce0d722482ae5c2887650751be0938847e8","typeString":"literal_string \"nonce end\""},{"typeIdentifier":"t_uint256","typeString":"uint256"}],"expression":{"id":592,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5093:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":594,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":154,"src":"5093:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_uint256_$returns$__$","typeString":"function (string memory,uint256) pure"}},"id":606,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5093:61:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":607,"nodeType":"ExpressionStatement","src":"5093:61:0"}]},"documentation":{"id":379,"nodeType":"StructuredDocumentation","src":"3842:56:0","text":"@notice example function, to test vm.broadcast with."},"functionSelector":"bef03abc","implemented":true,"kind":"function","modifiers":[],"name":"runBroadcast","nameLocation":"3912:12:0","parameters":{"id":380,"nodeType":"ParameterList","parameters":[],"src":"3924:2:0"},"returnParameters":{"id":381,"nodeType":"ParameterList","parameters":[],"src":"3934:0:0"},"scope":706,"stateMutability":"nonpayable","virtual":false,"visibility":"public"},{"id":633,"nodeType":"FunctionDefinition","src":"5256:143:0","nodes":[],"body":{"id":632,"nodeType":"Block","src":"5305:94:0","nodes":[],"statements":[{"expression":{"arguments":[{"id":618,"name":"_v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":612,"src":"5327:2:0","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}],"expression":{"id":615,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5315:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":617,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"5315:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":619,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5315:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":620,"nodeType":"ExpressionStatement","src":"5315:15:0"},{"expression":{"arguments":[{"hexValue":"68656c6c6f206d73672e73656e646572","id":624,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"5352:18:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_b3cc13bc51228b2c4c4334d82a4772908254dc0e1c512893dd16208ef13efb8e","typeString":"literal_string \"hello msg.sender\""},"value":"hello msg.sender"},{"arguments":[{"expression":{"id":627,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"5380:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":628,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"5380:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":626,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"5372:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":625,"name":"address","nodeType":"ElementaryTypeName","src":"5372:7:0","typeDescriptions":{}}},"id":629,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5372:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_b3cc13bc51228b2c4c4334d82a4772908254dc0e1c512893dd16208ef13efb8e","typeString":"literal_string \"hello msg.sender\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":621,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5340:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":623,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":171,"src":"5340:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":630,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5340:52:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":631,"nodeType":"ExpressionStatement","src":"5340:52:0"}]},"documentation":{"id":610,"nodeType":"StructuredDocumentation","src":"5167:84:0","text":"@notice example external function, to force a CALL, and test vm.startPrank with."},"functionSelector":"a777d0dc","implemented":true,"kind":"function","modifiers":[],"name":"hello","nameLocation":"5265:5:0","parameters":{"id":613,"nodeType":"ParameterList","parameters":[{"constant":false,"id":612,"mutability":"mutable","name":"_v","nameLocation":"5287:2:0","nodeType":"VariableDeclaration","scope":633,"src":"5271:18:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":611,"name":"string","nodeType":"ElementaryTypeName","src":"5271:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"5270:20:0"},"returnParameters":{"id":614,"nodeType":"ParameterList","parameters":[],"src":"5305:0:0"},"scope":706,"stateMutability":"view","virtual":false,"visibility":"external"},{"id":648,"nodeType":"FunctionDefinition","src":"5405:95:0","nodes":[],"body":{"id":647,"nodeType":"Block","src":"5449:51:0","nodes":[],"statements":[{"expression":{"id":639,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"UnaryOperation","operator":"++","prefix":false,"src":"5459:9:0","subExpression":{"id":638,"name":"counter","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":215,"src":"5459:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"id":640,"nodeType":"ExpressionStatement","src":"5459:9:0"},{"expression":{"arguments":[{"id":644,"name":"_v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":635,"src":"5490:2:0","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}],"expression":{"id":641,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5478:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":643,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"5478:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":645,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5478:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":646,"nodeType":"ExpressionStatement","src":"5478:15:0"}]},"functionSelector":"7e79255d","implemented":true,"kind":"function","modifiers":[],"name":"call1","nameLocation":"5414:5:0","parameters":{"id":636,"nodeType":"ParameterList","parameters":[{"constant":false,"id":635,"mutability":"mutable","name":"_v","nameLocation":"5436:2:0","nodeType":"VariableDeclaration","scope":648,"src":"5420:18:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":634,"name":"string","nodeType":"ElementaryTypeName","src":"5420:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"5419:20:0"},"returnParameters":{"id":637,"nodeType":"ParameterList","parameters":[],"src":"5449:0:0"},"scope":706,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":663,"nodeType":"FunctionDefinition","src":"5506:95:0","nodes":[],"body":{"id":662,"nodeType":"Block","src":"5550:51:0","nodes":[],"statements":[{"expression":{"id":654,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"UnaryOperation","operator":"++","prefix":false,"src":"5560:9:0","subExpression":{"id":653,"name":"counter","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":215,"src":"5560:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"id":655,"nodeType":"ExpressionStatement","src":"5560:9:0"},{"expression":{"arguments":[{"id":659,"name":"_v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":650,"src":"5591:2:0","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}],"expression":{"id":656,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5579:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":658,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"5579:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":660,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5579:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":661,"nodeType":"ExpressionStatement","src":"5579:15:0"}]},"functionSelector":"8d3ef7ca","implemented":true,"kind":"function","modifiers":[],"name":"call2","nameLocation":"5515:5:0","parameters":{"id":651,"nodeType":"ParameterList","parameters":[{"constant":false,"id":650,"mutability":"mutable","name":"_v","nameLocation":"5537:2:0","nodeType":"VariableDeclaration","scope":663,"src":"5521:18:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":649,"name":"string","nodeType":"ElementaryTypeName","src":"5521:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"5520:20:0"},"returnParameters":{"id":652,"nodeType":"ParameterList","parameters":[],"src":"5550:0:0"},"scope":706,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":678,"nodeType":"FunctionDefinition","src":"5607:98:0","nodes":[],"body":{"id":677,"nodeType":"Block","src":"5653:52:0","nodes":[],"statements":[{"expression":{"id":669,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"UnaryOperation","operator":"++","prefix":false,"src":"5663:9:0","subExpression":{"id":668,"name":"counter","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":215,"src":"5663:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"id":670,"nodeType":"ExpressionStatement","src":"5663:9:0"},{"expression":{"arguments":[{"id":674,"name":"_v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":665,"src":"5695:2:0","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}],"expression":{"id":671,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"5682:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":673,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"nested2","nodeType":"MemberAccess","referencedDeclaration":693,"src":"5682:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":675,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5682:16:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":676,"nodeType":"ExpressionStatement","src":"5682:16:0"}]},"functionSelector":"a76ccdfa","implemented":true,"kind":"function","modifiers":[],"name":"nested1","nameLocation":"5616:7:0","parameters":{"id":666,"nodeType":"ParameterList","parameters":[{"constant":false,"id":665,"mutability":"mutable","name":"_v","nameLocation":"5640:2:0","nodeType":"VariableDeclaration","scope":678,"src":"5624:18:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":664,"name":"string","nodeType":"ElementaryTypeName","src":"5624:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"5623:20:0"},"returnParameters":{"id":667,"nodeType":"ParameterList","parameters":[],"src":"5653:0:0"},"scope":706,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":693,"nodeType":"FunctionDefinition","src":"5711:97:0","nodes":[],"body":{"id":692,"nodeType":"Block","src":"5757:51:0","nodes":[],"statements":[{"expression":{"id":684,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"UnaryOperation","operator":"++","prefix":false,"src":"5767:9:0","subExpression":{"id":683,"name":"counter","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":215,"src":"5767:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"id":685,"nodeType":"ExpressionStatement","src":"5767:9:0"},{"expression":{"arguments":[{"id":689,"name":"_v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":680,"src":"5798:2:0","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}],"expression":{"id":686,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5786:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":688,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"5786:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":690,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5786:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":691,"nodeType":"ExpressionStatement","src":"5786:15:0"}]},"functionSelector":"dbf1282f","implemented":true,"kind":"function","modifiers":[],"name":"nested2","nameLocation":"5720:7:0","parameters":{"id":681,"nodeType":"ParameterList","parameters":[{"constant":false,"id":680,"mutability":"mutable","name":"_v","nameLocation":"5744:2:0","nodeType":"VariableDeclaration","scope":693,"src":"5728:18:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":679,"name":"string","nodeType":"ElementaryTypeName","src":"5728:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"5727:20:0"},"returnParameters":{"id":682,"nodeType":"ParameterList","parameters":[],"src":"5757:0:0"},"scope":706,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":705,"nodeType":"FunctionDefinition","src":"5814:84:0","nodes":[],"body":{"id":704,"nodeType":"Block","src":"5866:32:0","nodes":[],"statements":[{"expression":{"arguments":[{"id":701,"name":"_v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":695,"src":"5888:2:0","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}],"expression":{"id":698,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5876:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":700,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"5876:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":702,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5876:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":703,"nodeType":"ExpressionStatement","src":"5876:15:0"}]},"functionSelector":"7f8b915c","implemented":true,"kind":"function","modifiers":[],"name":"callPure","nameLocation":"5823:8:0","parameters":{"id":696,"nodeType":"ParameterList","parameters":[{"constant":false,"id":695,"mutability":"mutable","name":"_v","nameLocation":"5848:2:0","nodeType":"VariableDeclaration","scope":705,"src":"5832:18:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":694,"name":"string","nodeType":"ElementaryTypeName","src":"5832:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"5831:20:0"},"returnParameters":{"id":697,"nodeType":"ParameterList","parameters":[],"src":"5866:0:0"},"scope":706,"stateMutability":"pure","virtual":false,"visibility":"external"}],"abstract":false,"baseContracts":[],"canonicalName":"ScriptExample","contractDependencies":[719],"contractKind":"contract","documentation":{"id":193,"nodeType":"StructuredDocumentation","src":"2415:126:0","text":"@title ScriptExample\n @notice ScriptExample is an example script. The Go forge script code tests that it can run this."},"fullyImplemented":true,"linearizedBaseContracts":[706],"name":"ScriptExample","nameLocation":"2550:13:0","scope":720,"usedErrors":[]},{"id":719,"nodeType":"ContractDefinition","src":"5902:96:0","nodes":[{"id":708,"nodeType":"VariableDeclaration","src":"5924:18:0","nodes":[],"constant":false,"functionSelector":"c2985578","mutability":"mutable","name":"foo","nameLocation":"5939:3:0","scope":719,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":707,"name":"uint256","nodeType":"ElementaryTypeName","src":"5924:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"public"},{"id":718,"nodeType":"FunctionDefinition","src":"5949:47:0","nodes":[],"body":{"id":717,"nodeType":"Block","src":"5972:24:0","nodes":[],"statements":[{"expression":{"id":715,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"leftHandSide":{"id":713,"name":"foo","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":708,"src":"5982:3:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"nodeType":"Assignment","operator":"=","rightHandSide":{"id":714,"name":"v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":710,"src":"5988:1:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"src":"5982:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"id":716,"nodeType":"ExpressionStatement","src":"5982:7:0"}]},"implemented":true,"kind":"constructor","modifiers":[],"name":"","nameLocation":"-1:-1:-1","parameters":{"id":711,"nodeType":"ParameterList","parameters":[{"constant":false,"id":710,"mutability":"mutable","name":"v","nameLocation":"5969:1:0","nodeType":"VariableDeclaration","scope":718,"src":"5961:9:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":709,"name":"uint256","nodeType":"ElementaryTypeName","src":"5961:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"}],"src":"5960:11:0"},"returnParameters":{"id":712,"nodeType":"ParameterList","parameters":[],"src":"5972:0:0"},"scope":719,"stateMutability":"nonpayable","virtual":false,"visibility":"public"}],"abstract":false,"baseContracts":[],"canonicalName":"FooBar","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"linearizedBaseContracts":[719],"name":"FooBar","nameLocation":"5911:6:0","scope":720,"usedErrors":[]}],"license":"MIT"},"id":0} \ No newline at end of file diff --git a/op-chain-ops/srcmap/solutil.go b/op-chain-ops/srcmap/solutil.go index 284299762f624..6d1aa4c64a3e7 100644 --- a/op-chain-ops/srcmap/solutil.go +++ b/op-chain-ops/srcmap/solutil.go @@ -120,6 +120,10 @@ type SourceMap struct { // This location is the source file-path, the line number, and column number. // This may return an error, as the source-file is lazy-loaded to calculate the position data. func (s *SourceMap) Info(pc uint64) (source string, line uint32, col uint32, err error) { + if pc >= uint64(len(s.Instr)) { + source = "invalid" + return + } instr := s.Instr[pc] if instr.F < 0 || instr == (InstrMapping{}) { return "generated", 0, 0, nil @@ -235,8 +239,15 @@ func (s *SourceMapTracer) info(codeAddr common.Address, pc uint64) string { func (s *SourceMapTracer) OnOpCode(pc uint64, opcode byte, gas, cost uint64, scope tracing.OpContext, rData []byte, depth int, err error) { op := vm.OpCode(opcode) if op.IsPush() { - start := uint64(op) - uint64(vm.PUSH1) + 1 - val := scope.StackData()[:start] + var val []byte + sc, ok := scope.(*vm.ScopeContext) + if ok { + start := pc + 1 + end := uint64(op) - uint64(vm.PUSH1) + 1 + val = sc.Contract.Code[start : start+end] + } else { + val = []byte("N/A") + } fmt.Fprintf(s.out, "%-40s : pc %x opcode %s (%x)\n", s.info(scope.Address(), pc), pc, op.String(), val) return } diff --git a/op-challenger/cmd/main.go b/op-challenger/cmd/main.go index 50d842592ab5e..dda1fa6417572 100644 --- a/op-challenger/cmd/main.go +++ b/op-challenger/cmd/main.go @@ -15,8 +15,8 @@ import ( "github.com/ethereum-optimism/optimism/op-challenger/version" opservice "github.com/ethereum-optimism/optimism/op-service" "github.com/ethereum-optimism/optimism/op-service/cliapp" + "github.com/ethereum-optimism/optimism/op-service/ctxinterrupt" oplog "github.com/ethereum-optimism/optimism/op-service/log" - "github.com/ethereum-optimism/optimism/op-service/opio" ) var ( @@ -29,7 +29,7 @@ var VersionWithMeta = opservice.FormatVersion(version.Version, GitCommit, GitDat func main() { args := os.Args - ctx := opio.WithInterruptBlocker(context.Background()) + ctx := ctxinterrupt.WithSignalWaiterMain(context.Background()) if err := run(ctx, args, func(ctx context.Context, l log.Logger, config *config.Config) (cliapp.Lifecycle, error) { return challenger.Main(ctx, l, config, metrics.NewMetrics()) }); err != nil { diff --git a/op-challenger/cmd/main_test.go b/op-challenger/cmd/main_test.go index 926f38eced514..529711bbf6605 100644 --- a/op-challenger/cmd/main_test.go +++ b/op-challenger/cmd/main_test.go @@ -264,66 +264,117 @@ func TestPollInterval(t *testing.T) { }) } -func TestAsteriscRequiredArgs(t *testing.T) { - for _, traceType := range []types.TraceType{types.TraceTypeAsterisc} { - traceType := traceType - t.Run(fmt.Sprintf("TestAsteriscBin-%v", traceType), func(t *testing.T) { - t.Run("NotRequiredForAlphabetTrace", func(t *testing.T) { - configForArgs(t, addRequiredArgsExcept(types.TraceTypeAlphabet, "--asterisc-bin")) - }) +func TestAsteriscOpProgramRequiredArgs(t *testing.T) { + traceType := types.TraceTypeAsterisc + t.Run(fmt.Sprintf("TestAsteriscServer-%v", traceType), func(t *testing.T) { + t.Run("NotRequiredForAlphabetTrace", func(t *testing.T) { + configForArgs(t, addRequiredArgsExcept(types.TraceTypeAlphabet, "--asterisc-server")) + }) - t.Run("Required", func(t *testing.T) { - verifyArgsInvalid(t, "flag asterisc-bin is required", addRequiredArgsExcept(traceType, "--asterisc-bin")) - }) + t.Run("Required", func(t *testing.T) { + verifyArgsInvalid(t, "flag asterisc-server is required", addRequiredArgsExcept(traceType, "--asterisc-server")) + }) - t.Run("Valid", func(t *testing.T) { - cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--asterisc-bin", "--asterisc-bin=./asterisc")) - require.Equal(t, "./asterisc", cfg.Asterisc.VmBin) - }) + t.Run("Valid", func(t *testing.T) { + cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--asterisc-server", "--asterisc-server=./op-program")) + require.Equal(t, "./op-program", cfg.Asterisc.Server) }) + }) - t.Run(fmt.Sprintf("TestAsteriscServer-%v", traceType), func(t *testing.T) { - t.Run("NotRequiredForAlphabetTrace", func(t *testing.T) { - configForArgs(t, addRequiredArgsExcept(types.TraceTypeAlphabet, "--asterisc-server")) - }) + t.Run(fmt.Sprintf("TestAsteriscAbsolutePrestate-%v", traceType), func(t *testing.T) { + t.Run("NotRequiredForAlphabetTrace", func(t *testing.T) { + configForArgs(t, addRequiredArgsExcept(types.TraceTypeAlphabet, "--asterisc-prestate")) + }) - t.Run("Required", func(t *testing.T) { - verifyArgsInvalid(t, "flag asterisc-server is required", addRequiredArgsExcept(traceType, "--asterisc-server")) - }) + t.Run("Required", func(t *testing.T) { + verifyArgsInvalid(t, "flag asterisc-prestates-url or asterisc-prestate is required", addRequiredArgsExcept(traceType, "--asterisc-prestate")) + }) - t.Run("Valid", func(t *testing.T) { - cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--asterisc-server", "--asterisc-server=./op-program")) - require.Equal(t, "./op-program", cfg.Asterisc.Server) - }) + t.Run("Valid", func(t *testing.T) { + cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--asterisc-prestate", "--asterisc-prestate=./pre.json")) + require.Equal(t, "./pre.json", cfg.AsteriscAbsolutePreState) }) + }) - t.Run(fmt.Sprintf("TestAsteriscAbsolutePrestate-%v", traceType), func(t *testing.T) { - t.Run("NotRequiredForAlphabetTrace", func(t *testing.T) { - configForArgs(t, addRequiredArgsExcept(types.TraceTypeAlphabet, "--asterisc-prestate")) - }) + t.Run(fmt.Sprintf("TestAsteriscAbsolutePrestateBaseURL-%v", traceType), func(t *testing.T) { + t.Run("NotRequiredForAlphabetTrace", func(t *testing.T) { + configForArgs(t, addRequiredArgsExcept(types.TraceTypeAlphabet, "--asterisc-prestates-url")) + }) - t.Run("Required", func(t *testing.T) { - verifyArgsInvalid(t, "flag asterisc-prestates-url or asterisc-prestate is required", addRequiredArgsExcept(traceType, "--asterisc-prestate")) - }) + t.Run("Required", func(t *testing.T) { + verifyArgsInvalid(t, "flag asterisc-prestates-url or asterisc-prestate is required", addRequiredArgsExcept(traceType, "--asterisc-prestate")) + }) - t.Run("Valid", func(t *testing.T) { - cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--asterisc-prestate", "--asterisc-prestate=./pre.json")) - require.Equal(t, "./pre.json", cfg.AsteriscAbsolutePreState) - }) + t.Run("Valid", func(t *testing.T) { + cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--asterisc-prestates-url", "--asterisc-prestates-url=http://localhost/bar")) + require.Equal(t, "http://localhost/bar", cfg.AsteriscAbsolutePreStateBaseURL.String()) }) + }) +} - t.Run(fmt.Sprintf("TestAsteriscAbsolutePrestateBaseURL-%v", traceType), func(t *testing.T) { +func TestAsteriscKonaRequiredArgs(t *testing.T) { + traceType := types.TraceTypeAsteriscKona + t.Run(fmt.Sprintf("TestAsteriscServer-%v", traceType), func(t *testing.T) { + t.Run("NotRequiredForAlphabetTrace", func(t *testing.T) { + configForArgs(t, addRequiredArgsExcept(types.TraceTypeAlphabet, "--asterisc-kona-server")) + }) + + t.Run("Required", func(t *testing.T) { + verifyArgsInvalid(t, "flag asterisc-kona-server is required", addRequiredArgsExcept(traceType, "--asterisc-kona-server")) + }) + + t.Run("Valid", func(t *testing.T) { + cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--asterisc-kona-server", "--asterisc-kona-server=./kona-host")) + require.Equal(t, "./kona-host", cfg.AsteriscKona.Server) + }) + }) + + t.Run(fmt.Sprintf("TestAsteriscAbsolutePrestate-%v", traceType), func(t *testing.T) { + t.Run("NotRequiredForAlphabetTrace", func(t *testing.T) { + configForArgs(t, addRequiredArgsExcept(types.TraceTypeAlphabet, "--asterisc-kona-prestate")) + }) + + t.Run("Required", func(t *testing.T) { + verifyArgsInvalid(t, "flag asterisc-kona-prestates-url or asterisc-kona-prestate is required", addRequiredArgsExcept(traceType, "--asterisc-kona-prestate")) + }) + + t.Run("Valid", func(t *testing.T) { + cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--asterisc-kona-prestate", "--asterisc-kona-prestate=./pre.json")) + require.Equal(t, "./pre.json", cfg.AsteriscKonaAbsolutePreState) + }) + }) + + t.Run(fmt.Sprintf("TestAsteriscAbsolutePrestateBaseURL-%v", traceType), func(t *testing.T) { + t.Run("NotRequiredForAlphabetTrace", func(t *testing.T) { + configForArgs(t, addRequiredArgsExcept(types.TraceTypeAlphabet, "--asterisc-kona-prestates-url")) + }) + + t.Run("Required", func(t *testing.T) { + verifyArgsInvalid(t, "flag asterisc-kona-prestates-url or asterisc-kona-prestate is required", addRequiredArgsExcept(traceType, "--asterisc-kona-prestate")) + }) + + t.Run("Valid", func(t *testing.T) { + cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--asterisc-kona-prestates-url", "--asterisc-kona-prestates-url=http://localhost/bar")) + require.Equal(t, "http://localhost/bar", cfg.AsteriscKonaAbsolutePreStateBaseURL.String()) + }) + }) +} + +func TestAsteriscBaseRequiredArgs(t *testing.T) { + for _, traceType := range []types.TraceType{types.TraceTypeAsterisc, types.TraceTypeAsteriscKona} { + traceType := traceType + t.Run(fmt.Sprintf("TestAsteriscBin-%v", traceType), func(t *testing.T) { t.Run("NotRequiredForAlphabetTrace", func(t *testing.T) { - configForArgs(t, addRequiredArgsExcept(types.TraceTypeAlphabet, "--asterisc-prestates-url")) + configForArgs(t, addRequiredArgsExcept(types.TraceTypeAlphabet, "--asterisc-bin")) }) t.Run("Required", func(t *testing.T) { - verifyArgsInvalid(t, "flag asterisc-prestates-url or asterisc-prestate is required", addRequiredArgsExcept(traceType, "--asterisc-prestate")) + verifyArgsInvalid(t, "flag asterisc-bin is required", addRequiredArgsExcept(traceType, "--asterisc-bin")) }) t.Run("Valid", func(t *testing.T) { - cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--asterisc-prestates-url", "--asterisc-prestates-url=http://localhost/bar")) - require.Equal(t, "http://localhost/bar", cfg.AsteriscAbsolutePreStateBaseURL.String()) + cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--asterisc-bin", "--asterisc-bin=./asterisc")) + require.Equal(t, "./asterisc", cfg.Asterisc.VmBin) }) }) @@ -853,6 +904,8 @@ func requiredArgs(traceType types.TraceType) map[string]string { addRequiredCannonArgs(args) case types.TraceTypeAsterisc: addRequiredAsteriscArgs(args) + case types.TraceTypeAsteriscKona: + addRequiredAsteriscKonaArgs(args) } return args } @@ -873,6 +926,14 @@ func addRequiredAsteriscArgs(args map[string]string) { args["--l2-eth-rpc"] = l2EthRpc } +func addRequiredAsteriscKonaArgs(args map[string]string) { + args["--asterisc-network"] = asteriscNetwork + args["--asterisc-bin"] = asteriscBin + args["--asterisc-kona-server"] = asteriscServer + args["--asterisc-kona-prestate"] = asteriscPreState + args["--l2-eth-rpc"] = l2EthRpc +} + func toArgList(req map[string]string) []string { var combined []string for name, value := range req { diff --git a/op-challenger/cmd/move.go b/op-challenger/cmd/move.go index 3bc80ae1882a0..cf460d691f3ba 100644 --- a/op-challenger/cmd/move.go +++ b/op-challenger/cmd/move.go @@ -1,7 +1,6 @@ package main import ( - "context" "fmt" "github.com/ethereum-optimism/optimism/op-challenger/flags" @@ -70,7 +69,7 @@ func Move(ctx *cli.Context) error { return fmt.Errorf("either attack or defense flag must be set") } - rct, err := txMgr.Send(context.Background(), tx) + rct, err := txMgr.Send(ctx.Context, tx) if err != nil { return fmt.Errorf("failed to send tx: %w", err) } diff --git a/op-challenger/cmd/run_trace.go b/op-challenger/cmd/run_trace.go index a3438807837b5..c1d2261230f9e 100644 --- a/op-challenger/cmd/run_trace.go +++ b/op-challenger/cmd/run_trace.go @@ -2,10 +2,17 @@ package main import ( "context" + "errors" + "fmt" + "net/url" + "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/trace/vm" "github.com/ethereum-optimism/optimism/op-challenger/runner" + opservice "github.com/ethereum-optimism/optimism/op-service" "github.com/ethereum-optimism/optimism/op-service/cliapp" + "github.com/ethereum/go-ethereum/common" "github.com/urfave/cli/v2" ) @@ -24,11 +31,36 @@ func RunTrace(ctx *cli.Context, _ context.CancelCauseFunc) (cliapp.Lifecycle, er if err := cfg.Check(); err != nil { return nil, err } - return runner.NewRunner(logger, cfg), nil + if err := checkMTCannonFlags(ctx, cfg); err != nil { + return nil, err + } + + var mtPrestate common.Hash + var mtPrestateURL *url.URL + if ctx.IsSet(addMTCannonPrestateFlag.Name) { + mtPrestate = common.HexToHash(ctx.String(addMTCannonPrestateFlag.Name)) + mtPrestateURL, err = url.Parse(ctx.String(addMTCannonPrestateURLFlag.Name)) + if err != nil { + return nil, fmt.Errorf("invalid mt-cannon prestate url (%v): %w", ctx.String(addMTCannonPrestateFlag.Name), err) + } + } + return runner.NewRunner(logger, cfg, mtPrestate, mtPrestateURL), nil +} + +func checkMTCannonFlags(ctx *cli.Context, cfg *config.Config) error { + if ctx.IsSet(addMTCannonPrestateFlag.Name) || ctx.IsSet(addMTCannonPrestateURLFlag.Name) { + if ctx.IsSet(addMTCannonPrestateFlag.Name) != ctx.IsSet(addMTCannonPrestateURLFlag.Name) { + return fmt.Errorf("both flag %v and %v must be set when running MT-Cannon traces", addMTCannonPrestateURLFlag.Name, addMTCannonPrestateFlag.Name) + } + if cfg.Cannon == (vm.Config{}) { + return errors.New("required Cannon vm configuration for mt-cannon traces is missing") + } + } + return nil } func runTraceFlags() []cli.Flag { - return flags.Flags + return append(flags.Flags, addMTCannonPrestateFlag, addMTCannonPrestateURLFlag) } var RunTraceCommand = &cli.Command{ @@ -38,3 +70,16 @@ var RunTraceCommand = &cli.Command{ Action: cliapp.LifecycleCmd(RunTrace), Flags: runTraceFlags(), } + +var ( + addMTCannonPrestateFlag = &cli.StringFlag{ + Name: "add-mt-cannon-prestate", + Usage: "Use this prestate to run MT-Cannon compatibility tests", + EnvVars: opservice.PrefixEnvVar(flags.EnvVarPrefix, "ADD_MT_CANNON_PRESTATE"), + } + addMTCannonPrestateURLFlag = &cli.StringFlag{ + Name: "add-mt-cannon-prestate-url", + Usage: "Use this prestate URL to run MT-Cannon compatibility tests", + EnvVars: opservice.PrefixEnvVar(flags.EnvVarPrefix, "ADD_MT_CANNON_PRESTATE_URL"), + } +) diff --git a/op-challenger/cmd/utils.go b/op-challenger/cmd/utils.go index 110f1dddd6410..82c35f7fa0f5e 100644 --- a/op-challenger/cmd/utils.go +++ b/op-challenger/cmd/utils.go @@ -7,8 +7,8 @@ import ( "github.com/ethereum-optimism/optimism/op-challenger/flags" contractMetrics "github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts/metrics" opservice "github.com/ethereum-optimism/optimism/op-service" + "github.com/ethereum-optimism/optimism/op-service/ctxinterrupt" "github.com/ethereum-optimism/optimism/op-service/dial" - "github.com/ethereum-optimism/optimism/op-service/opio" "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" @@ -20,7 +20,7 @@ type ContractCreator[T any] func(context.Context, contractMetrics.ContractMetric func Interruptible(action cli.ActionFunc) cli.ActionFunc { return func(ctx *cli.Context) error { - ctx.Context = opio.CancelOnInterrupt(ctx.Context) + ctx.Context = ctxinterrupt.WithCancelOnInterrupt(ctx.Context) return action(ctx) } } diff --git a/op-challenger/config/config.go b/op-challenger/config/config.go index a9937a68af869..e8a245936f33f 100644 --- a/op-challenger/config/config.go +++ b/op-challenger/config/config.go @@ -139,13 +139,14 @@ func NewConfig( Datadir: datadir, Cannon: vm.Config{ - VmType: types.TraceTypeCannon, - L1: l1EthRpc, - L1Beacon: l1BeaconApi, - L2: l2EthRpc, - SnapshotFreq: DefaultCannonSnapshotFreq, - InfoFreq: DefaultCannonInfoFreq, - DebugInfo: true, + VmType: types.TraceTypeCannon, + L1: l1EthRpc, + L1Beacon: l1BeaconApi, + L2: l2EthRpc, + SnapshotFreq: DefaultCannonSnapshotFreq, + InfoFreq: DefaultCannonInfoFreq, + DebugInfo: true, + BinarySnapshots: true, }, Asterisc: vm.Config{ VmType: types.TraceTypeAsterisc, diff --git a/op-challenger/flags/flags.go b/op-challenger/flags/flags.go index df62b48aa4132..38e59d350cec4 100644 --- a/op-challenger/flags/flags.go +++ b/op-challenger/flags/flags.go @@ -327,7 +327,7 @@ func CheckCannonFlags(ctx *cli.Context) error { return nil } -func CheckAsteriscFlags(ctx *cli.Context) error { +func CheckAsteriscBaseFlags(ctx *cli.Context) error { if ctx.IsSet(AsteriscNetworkFlag.Name) && ctx.IsSet(flags.NetworkFlagName) { return fmt.Errorf("flag %v can not be used with %v", AsteriscNetworkFlag.Name, flags.NetworkFlagName) } @@ -350,6 +350,13 @@ func CheckAsteriscFlags(ctx *cli.Context) error { if !ctx.IsSet(AsteriscBinFlag.Name) { return fmt.Errorf("flag %s is required", AsteriscBinFlag.Name) } + return nil +} + +func CheckAsteriscFlags(ctx *cli.Context) error { + if err := CheckAsteriscBaseFlags(ctx); err != nil { + return err + } if !ctx.IsSet(AsteriscServerFlag.Name) { return fmt.Errorf("flag %s is required", AsteriscServerFlag.Name) } @@ -359,6 +366,19 @@ func CheckAsteriscFlags(ctx *cli.Context) error { return nil } +func CheckAsteriscKonaFlags(ctx *cli.Context) error { + if err := CheckAsteriscBaseFlags(ctx); err != nil { + return err + } + if !ctx.IsSet(AsteriscKonaServerFlag.Name) { + return fmt.Errorf("flag %s is required", AsteriscKonaServerFlag.Name) + } + if !ctx.IsSet(AsteriscKonaPreStateFlag.Name) && !ctx.IsSet(AsteriscKonaPreStatesURLFlag.Name) { + return fmt.Errorf("flag %s or %s is required", AsteriscKonaPreStatesURLFlag.Name, AsteriscKonaPreStateFlag.Name) + } + return nil +} + func CheckRequired(ctx *cli.Context, traceTypes []types.TraceType) error { for _, f := range requiredFlags { if !ctx.IsSet(f.Names()[0]) { @@ -379,6 +399,10 @@ func CheckRequired(ctx *cli.Context, traceTypes []types.TraceType) error { if err := CheckAsteriscFlags(ctx); err != nil { return err } + case types.TraceTypeAsteriscKona: + if err := CheckAsteriscKonaFlags(ctx); err != nil { + return err + } case types.TraceTypeAlphabet, types.TraceTypeFast: default: return fmt.Errorf("invalid trace type %v. must be one of %v", traceType, types.TraceTypes) @@ -554,6 +578,7 @@ func NewConfigFromCLI(ctx *cli.Context, logger log.Logger) (*config.Config, erro SnapshotFreq: ctx.Uint(CannonSnapshotFreqFlag.Name), InfoFreq: ctx.Uint(CannonInfoFreqFlag.Name), DebugInfo: true, + BinarySnapshots: true, }, CannonAbsolutePreState: ctx.String(CannonPreStateFlag.Name), CannonAbsolutePreStateBaseURL: cannonPrestatesURL, diff --git a/op-challenger/game/fault/player.go b/op-challenger/game/fault/player.go index cede89217c591..5ab1877075576 100644 --- a/op-challenger/game/fault/player.go +++ b/op-challenger/game/fault/player.go @@ -64,6 +64,10 @@ type GameContract interface { GetL1Head(ctx context.Context) (common.Hash, error) } +var actNoop = func(ctx context.Context) error { + return nil +} + type resourceCreator func(ctx context.Context, logger log.Logger, gameDepth types.Depth, dir string) (types.TraceAccessor, error) func NewGamePlayer( @@ -98,9 +102,7 @@ func NewGamePlayer( prestateValidators: validators, status: status, // Act function does nothing because the game is already complete - act: func(ctx context.Context) error { - return nil - }, + act: actNoop, }, nil } @@ -195,6 +197,10 @@ func (g *GamePlayer) ProgressGame(ctx context.Context) gameTypes.GameStatus { } g.logGameStatus(ctx, status) g.status = status + if status != gameTypes.GameStatusInProgress { + // Release the agent as we will no longer need to act on this game. + g.act = actNoop + } return status } diff --git a/op-challenger/game/fault/player_test.go b/op-challenger/game/fault/player_test.go index 0c662ac638836..7c05525a8823d 100644 --- a/op-challenger/game/fault/player_test.go +++ b/op-challenger/game/fault/player_test.go @@ -90,6 +90,11 @@ func TestDoNotActOnCompleteGame(t *testing.T) { fetched = game.ProgressGame(context.Background()) require.Equal(t, 1, gameState.callCount, "does not act after game is complete") require.Equal(t, status, fetched) + + // Should have replaced the act function with a noop so callCount doesn't update even when called directly + // This allows the agent resources to be GC'd + require.NoError(t, game.act(context.Background())) + require.Equal(t, 1, gameState.callCount) }) } } diff --git a/op-challenger/game/fault/register.go b/op-challenger/game/fault/register.go index a76f456f16f3d..08140164a17ce 100644 --- a/op-challenger/game/fault/register.go +++ b/op-challenger/game/fault/register.go @@ -77,7 +77,7 @@ func RegisterGameTypes( registerTasks = append(registerTasks, NewAsteriscRegisterTask(faultTypes.AsteriscGameType, cfg, m, vm.NewOpProgramServerExecutor())) } if cfg.TraceTypeEnabled(faultTypes.TraceTypeAsteriscKona) { - registerTasks = append(registerTasks, NewAsteriscRegisterTask(faultTypes.AsteriscKonaGameType, cfg, m, vm.NewKonaServerExecutor())) + registerTasks = append(registerTasks, NewAsteriscKonaRegisterTask(faultTypes.AsteriscKonaGameType, cfg, m, vm.NewKonaExecutor())) } if cfg.TraceTypeEnabled(faultTypes.TraceTypeFast) { registerTasks = append(registerTasks, NewAlphabetRegisterTask(faultTypes.FastGameType)) diff --git a/op-challenger/game/fault/register_task.go b/op-challenger/game/fault/register_task.go index b9b2db6b49516..3b438ad8eea22 100644 --- a/op-challenger/game/fault/register_task.go +++ b/op-challenger/game/fault/register_task.go @@ -48,16 +48,18 @@ type RegisterTask struct { } func NewCannonRegisterTask(gameType faultTypes.GameType, cfg *config.Config, m caching.Metrics, serverExecutor vm.OracleServerExecutor) *RegisterTask { + stateConverter := cannon.NewStateConverter() return &RegisterTask{ gameType: gameType, getPrestateProvider: cachePrestates( gameType, + stateConverter, m, cfg.CannonAbsolutePreStateBaseURL, cfg.CannonAbsolutePreState, filepath.Join(cfg.Datadir, "cannon-prestates"), func(path string) faultTypes.PrestateProvider { - return cannon.NewPrestateProvider(path) + return vm.NewPrestateProvider(path, stateConverter) }), newTraceAccessor: func( logger log.Logger, @@ -71,23 +73,25 @@ func NewCannonRegisterTask(gameType faultTypes.GameType, cfg *config.Config, m c splitDepth faultTypes.Depth, prestateBlock uint64, poststateBlock uint64) (*trace.Accessor, error) { - provider := vmPrestateProvider.(*cannon.CannonPrestateProvider) + provider := vmPrestateProvider.(*vm.PrestateProvider) return outputs.NewOutputCannonTraceAccessor(logger, m, cfg.Cannon, serverExecutor, l2Client, prestateProvider, provider.PrestatePath(), rollupClient, dir, l1Head, splitDepth, prestateBlock, poststateBlock) }, } } func NewAsteriscRegisterTask(gameType faultTypes.GameType, cfg *config.Config, m caching.Metrics, serverExecutor vm.OracleServerExecutor) *RegisterTask { + stateConverter := asterisc.NewStateConverter() return &RegisterTask{ gameType: gameType, getPrestateProvider: cachePrestates( gameType, + stateConverter, m, cfg.AsteriscAbsolutePreStateBaseURL, cfg.AsteriscAbsolutePreState, filepath.Join(cfg.Datadir, "asterisc-prestates"), func(path string) faultTypes.PrestateProvider { - return asterisc.NewPrestateProvider(path) + return vm.NewPrestateProvider(path, stateConverter) }), newTraceAccessor: func( logger log.Logger, @@ -101,12 +105,44 @@ func NewAsteriscRegisterTask(gameType faultTypes.GameType, cfg *config.Config, m splitDepth faultTypes.Depth, prestateBlock uint64, poststateBlock uint64) (*trace.Accessor, error) { - provider := vmPrestateProvider.(*asterisc.AsteriscPreStateProvider) + provider := vmPrestateProvider.(*vm.PrestateProvider) return outputs.NewOutputAsteriscTraceAccessor(logger, m, cfg.Asterisc, serverExecutor, l2Client, prestateProvider, provider.PrestatePath(), rollupClient, dir, l1Head, splitDepth, prestateBlock, poststateBlock) }, } } +func NewAsteriscKonaRegisterTask(gameType faultTypes.GameType, cfg *config.Config, m caching.Metrics, serverExecutor vm.OracleServerExecutor) *RegisterTask { + stateConverter := asterisc.NewStateConverter() + return &RegisterTask{ + gameType: gameType, + getPrestateProvider: cachePrestates( + gameType, + stateConverter, + m, + cfg.AsteriscKonaAbsolutePreStateBaseURL, + cfg.AsteriscKonaAbsolutePreState, + filepath.Join(cfg.Datadir, "asterisc-kona-prestates"), + func(path string) faultTypes.PrestateProvider { + return vm.NewPrestateProvider(path, stateConverter) + }), + newTraceAccessor: func( + logger log.Logger, + m metrics.Metricer, + l2Client utils.L2HeaderSource, + prestateProvider faultTypes.PrestateProvider, + vmPrestateProvider faultTypes.PrestateProvider, + rollupClient outputs.OutputRollupClient, + dir string, + l1Head eth.BlockID, + splitDepth faultTypes.Depth, + prestateBlock uint64, + poststateBlock uint64) (*trace.Accessor, error) { + provider := vmPrestateProvider.(*vm.PrestateProvider) + return outputs.NewOutputAsteriscTraceAccessor(logger, m, cfg.AsteriscKona, serverExecutor, l2Client, prestateProvider, provider.PrestatePath(), rollupClient, dir, l1Head, splitDepth, prestateBlock, poststateBlock) + }, + } +} + func NewAlphabetRegisterTask(gameType faultTypes.GameType) *RegisterTask { return &RegisterTask{ gameType: gameType, @@ -132,13 +168,14 @@ func NewAlphabetRegisterTask(gameType faultTypes.GameType) *RegisterTask { func cachePrestates( gameType faultTypes.GameType, + stateConverter vm.StateConverter, m caching.Metrics, prestateBaseURL *url.URL, preStatePath string, prestateDir string, newPrestateProvider func(path string) faultTypes.PrestateProvider, ) func(prestateHash common.Hash) (faultTypes.PrestateProvider, error) { - prestateSource := prestates.NewPrestateSource(prestateBaseURL, preStatePath, prestateDir) + prestateSource := prestates.NewPrestateSource(prestateBaseURL, preStatePath, prestateDir, stateConverter) prestateProviderCache := prestates.NewPrestateProviderCache(m, fmt.Sprintf("prestates-%v", gameType), func(prestateHash common.Hash) (faultTypes.PrestateProvider, error) { prestatePath, err := prestateSource.PrestatePath(prestateHash) if err != nil { diff --git a/op-challenger/game/fault/trace/asterisc/prestate.go b/op-challenger/game/fault/trace/asterisc/prestate.go deleted file mode 100644 index f65e4d9c901cd..0000000000000 --- a/op-challenger/game/fault/trace/asterisc/prestate.go +++ /dev/null @@ -1,45 +0,0 @@ -package asterisc - -import ( - "context" - "fmt" - - "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" - "github.com/ethereum/go-ethereum/common" -) - -var _ types.PrestateProvider = (*AsteriscPreStateProvider)(nil) - -type AsteriscPreStateProvider struct { - prestate string - - prestateCommitment common.Hash -} - -func NewPrestateProvider(prestate string) *AsteriscPreStateProvider { - return &AsteriscPreStateProvider{prestate: prestate} -} - -func (p *AsteriscPreStateProvider) absolutePreState() (*VMState, error) { - state, err := parseState(p.prestate) - if err != nil { - return nil, fmt.Errorf("cannot load absolute pre-state: %w", err) - } - return state, nil -} - -func (p *AsteriscPreStateProvider) 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) - } - p.prestateCommitment = state.StateHash - return state.StateHash, nil -} - -func (p *AsteriscPreStateProvider) PrestatePath() string { - return p.prestate -} diff --git a/op-challenger/game/fault/trace/asterisc/prestate_test.go b/op-challenger/game/fault/trace/asterisc/prestate_test.go deleted file mode 100644 index 38bc6d360e7b2..0000000000000 --- a/op-challenger/game/fault/trace/asterisc/prestate_test.go +++ /dev/null @@ -1,59 +0,0 @@ -package asterisc - -import ( - "context" - "os" - "path/filepath" - "testing" - - "github.com/stretchr/testify/require" -) - -func newAsteriscPrestateProvider(dataDir string, prestate string) *AsteriscPreStateProvider { - return &AsteriscPreStateProvider{ - prestate: filepath.Join(dataDir, prestate), - } -} - -func TestAbsolutePreStateCommitment(t *testing.T) { - dataDir := t.TempDir() - - prestate := "state.json" - - t.Run("StateUnavailable", func(t *testing.T) { - provider := newAsteriscPrestateProvider("/dir/does/not/exist", prestate) - _, err := provider.AbsolutePreStateCommitment(context.Background()) - require.ErrorIs(t, err, os.ErrNotExist) - }) - - t.Run("InvalidStateFile", func(t *testing.T) { - setupPreState(t, dataDir, "invalid.json") - provider := newAsteriscPrestateProvider(dataDir, prestate) - _, err := provider.AbsolutePreStateCommitment(context.Background()) - require.ErrorContains(t, err, "invalid asterisc VM state") - }) - - t.Run("CacheAbsolutePreState", func(t *testing.T) { - setupPreState(t, dataDir, prestate) - provider := newAsteriscPrestateProvider(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) { - srcDir := filepath.Join("test_data") - path := filepath.Join(srcDir, filename) - file, err := testData.ReadFile(path) - require.NoErrorf(t, err, "reading %v", path) - err = os.WriteFile(filepath.Join(dataDir, "state.json"), file, 0o644) - require.NoErrorf(t, err, "writing %v", path) -} diff --git a/op-challenger/game/fault/trace/asterisc/provider.go b/op-challenger/game/fault/trace/asterisc/provider.go index c4647234c64f4..2ea1b729709e9 100644 --- a/op-challenger/game/fault/trace/asterisc/provider.go +++ b/op-challenger/game/fault/trace/asterisc/provider.go @@ -15,6 +15,7 @@ import ( "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/vm" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" "github.com/ethereum-optimism/optimism/op-program/host/kvstore" + kvtypes "github.com/ethereum-optimism/optimism/op-program/host/types" "github.com/ethereum-optimism/optimism/op-service/ioutil" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" @@ -27,6 +28,8 @@ type AsteriscTraceProvider struct { generator utils.ProofGenerator gameDepth types.Depth preimageLoader *utils.PreimageLoader + stateConverter vm.StateConverter + cfg vm.Config types.PrestateProvider @@ -37,13 +40,17 @@ type AsteriscTraceProvider struct { func NewTraceProvider(logger log.Logger, m vm.Metricer, cfg vm.Config, vmCfg vm.OracleServerExecutor, prestateProvider types.PrestateProvider, asteriscPrestate string, localInputs utils.LocalGameInputs, dir string, gameDepth types.Depth) *AsteriscTraceProvider { return &AsteriscTraceProvider{ - logger: logger, - dir: dir, - prestate: asteriscPrestate, - generator: vm.NewExecutor(logger, m, cfg, vmCfg, asteriscPrestate, localInputs), - gameDepth: gameDepth, - preimageLoader: utils.NewPreimageLoader(kvstore.NewDiskKV(vm.PreimageDir(dir)).Get), + logger: logger, + dir: dir, + prestate: asteriscPrestate, + generator: vm.NewExecutor(logger, m, cfg, vmCfg, asteriscPrestate, localInputs), + gameDepth: gameDepth, + preimageLoader: utils.NewPreimageLoader(func() (utils.PreimageSource, error) { + return kvstore.NewDiskKV(logger, vm.PreimageDir(dir), kvtypes.DataFormatFile) + }), PrestateProvider: prestateProvider, + stateConverter: NewStateConverter(), + cfg: cfg, } } @@ -118,31 +125,23 @@ func (p *AsteriscTraceProvider) loadProof(ctx context.Context, i uint64) (*utils 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 := p.finalState() + proof, step, exited, err := p.stateConverter.ConvertStateToProof(vm.FinalStatePath(p.dir, p.cfg.BinarySnapshots)) if err != nil { return nil, err } - if state.Exited && state.Step <= i { - p.logger.Warn("Requested proof was after the program exited", "proof", i, "last", state.Step) + if exited && step <= i { + p.logger.Warn("Requested proof was after the program exited", "proof", i, "last", step) // The final instruction has already been applied to this state, so the last step we can execute // is one before its Step value. - p.lastStep = state.Step - 1 + p.lastStep = step - 1 // Extend the trace out to the full length using a no-op instruction that doesn't change any state // No execution is done, so no proof-data or oracle values are required. - proof := &utils.ProofData{ - ClaimValue: state.StateHash, - StateData: state.Witness, - ProofData: []byte{}, - OracleKey: nil, - OracleValue: nil, - OracleOffset: 0, - } if err := utils.WriteLastStep(p.dir, proof, p.lastStep); err != nil { p.logger.Warn("Failed to write last step to disk cache", "step", p.lastStep) } return proof, nil } else { - return nil, fmt.Errorf("expected proof not generated but final state was not exited, requested step %v, final state at step %v", i, state.Step) + return nil, fmt.Errorf("expected proof not generated but final state was not exited, requested step %v, final state at step %v", i, step) } } } @@ -158,14 +157,6 @@ func (p *AsteriscTraceProvider) loadProof(ctx context.Context, i uint64) (*utils return &proof, nil } -func (c *AsteriscTraceProvider) finalState() (*VMState, error) { - state, err := parseState(filepath.Join(c.dir, vm.FinalState)) - if err != nil { - return nil, fmt.Errorf("cannot read final state: %w", err) - } - return state, nil -} - // AsteriscTraceProviderForTest is a AsteriscTraceProvider that can find the step referencing the preimage read // Only to be used for testing type AsteriscTraceProviderForTest struct { @@ -174,12 +165,16 @@ type AsteriscTraceProviderForTest struct { func NewTraceProviderForTest(logger log.Logger, m vm.Metricer, cfg *config.Config, localInputs utils.LocalGameInputs, dir string, gameDepth types.Depth) *AsteriscTraceProviderForTest { p := &AsteriscTraceProvider{ - logger: logger, - dir: dir, - prestate: cfg.AsteriscAbsolutePreState, - generator: vm.NewExecutor(logger, m, cfg.Asterisc, vm.NewOpProgramServerExecutor(), cfg.AsteriscAbsolutePreState, localInputs), - gameDepth: gameDepth, - preimageLoader: utils.NewPreimageLoader(kvstore.NewDiskKV(vm.PreimageDir(dir)).Get), + logger: logger, + dir: dir, + prestate: cfg.AsteriscAbsolutePreState, + generator: vm.NewExecutor(logger, m, cfg.Asterisc, vm.NewOpProgramServerExecutor(), cfg.AsteriscAbsolutePreState, localInputs), + gameDepth: gameDepth, + preimageLoader: utils.NewPreimageLoader(func() (utils.PreimageSource, error) { + return kvstore.NewDiskKV(logger, vm.PreimageDir(dir), kvtypes.DataFormatFile) + }), + stateConverter: NewStateConverter(), + cfg: cfg.Asterisc, } return &AsteriscTraceProviderForTest{p} } @@ -190,14 +185,14 @@ func (p *AsteriscTraceProviderForTest) FindStep(ctx context.Context, start uint6 return 0, fmt.Errorf("generate asterisc trace (until preimage read): %w", err) } // Load the step from the state asterisc finished with - state, err := p.finalState() + _, step, exited, err := p.stateConverter.ConvertStateToProof(vm.FinalStatePath(p.dir, p.cfg.BinarySnapshots)) 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 { + if 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 + return step - 1, nil } diff --git a/op-challenger/game/fault/trace/asterisc/provider_test.go b/op-challenger/game/fault/trace/asterisc/provider_test.go index 939a27decc304..ce80b3403dac7 100644 --- a/op-challenger/game/fault/trace/asterisc/provider_test.go +++ b/op-challenger/game/fault/trace/asterisc/provider_test.go @@ -221,11 +221,12 @@ func setupTestData(t *testing.T) (string, string) { func setupWithTestData(t *testing.T, dataDir string, prestate string) (*AsteriscTraceProvider, *stubGenerator) { generator := &stubGenerator{} return &AsteriscTraceProvider{ - logger: testlog.Logger(t, log.LevelInfo), - dir: dataDir, - generator: generator, - prestate: filepath.Join(dataDir, prestate), - gameDepth: 63, + logger: testlog.Logger(t, log.LevelInfo), + dir: dataDir, + generator: generator, + prestate: filepath.Join(dataDir, prestate), + gameDepth: 63, + stateConverter: &StateConverter{}, }, generator } @@ -242,7 +243,7 @@ func (e *stubGenerator) GenerateProof(ctx context.Context, dir string, i uint64) var err error if e.finalState != nil && e.finalState.Step <= i { // Requesting a trace index past the end of the trace - proofFile = filepath.Join(dir, vm.FinalState) + proofFile = vm.FinalStatePath(dir, false) data, err = json.Marshal(e.finalState) if err != nil { return err diff --git a/op-challenger/game/fault/trace/asterisc/state.go b/op-challenger/game/fault/trace/asterisc/state_converter.go similarity index 73% rename from op-challenger/game/fault/trace/asterisc/state.go rename to op-challenger/game/fault/trace/asterisc/state_converter.go index e30ebf8702d82..29c9f8b2ea50d 100644 --- a/op-challenger/game/fault/trace/asterisc/state.go +++ b/op-challenger/game/fault/trace/asterisc/state_converter.go @@ -8,6 +8,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum-optimism/optimism/cannon/mipsevm" + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils" "github.com/ethereum-optimism/optimism/op-service/ioutil" ) @@ -74,3 +75,27 @@ func parseStateFromReader(in io.ReadCloser) (*VMState, error) { } return &state, nil } + +type StateConverter struct { +} + +func NewStateConverter() *StateConverter { + return &StateConverter{} +} + +func (c *StateConverter) ConvertStateToProof(statePath string) (*utils.ProofData, uint64, bool, error) { + state, err := parseState(statePath) + if err != nil { + return nil, 0, false, fmt.Errorf("cannot read final state: %w", err) + } + // Extend the trace out to the full length using a no-op instruction that doesn't change any state + // No execution is done, so no proof-data or oracle values are required. + return &utils.ProofData{ + ClaimValue: state.StateHash, + StateData: state.Witness, + ProofData: []byte{}, + OracleKey: nil, + OracleValue: nil, + OracleOffset: 0, + }, state.Step, state.Exited, nil +} diff --git a/op-challenger/game/fault/trace/asterisc/state_test.go b/op-challenger/game/fault/trace/asterisc/state_converter_test.go similarity index 100% rename from op-challenger/game/fault/trace/asterisc/state_test.go rename to op-challenger/game/fault/trace/asterisc/state_converter_test.go diff --git a/op-challenger/game/fault/trace/cannon/prestate.go b/op-challenger/game/fault/trace/cannon/prestate.go deleted file mode 100644 index 6fcb8f50f6628..0000000000000 --- a/op-challenger/game/fault/trace/cannon/prestate.go +++ /dev/null @@ -1,47 +0,0 @@ -package cannon - -import ( - "context" - "fmt" - - "github.com/ethereum/go-ethereum/common" - - "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" -) - -var _ types.PrestateProvider = (*CannonPrestateProvider)(nil) - -type CannonPrestateProvider struct { - prestate string - - prestateCommitment common.Hash -} - -func NewPrestateProvider(prestate string) *CannonPrestateProvider { - return &CannonPrestateProvider{prestate: prestate} -} - -func (p *CannonPrestateProvider) absolutePreState() ([]byte, common.Hash, error) { - state, err := parseState(p.prestate) - if err != nil { - return nil, common.Hash{}, fmt.Errorf("cannot load absolute pre-state: %w", err) - } - witness, hash := state.EncodeWitness() - return witness, hash, nil -} - -func (p *CannonPrestateProvider) AbsolutePreStateCommitment(_ context.Context) (common.Hash, error) { - if p.prestateCommitment != (common.Hash{}) { - return p.prestateCommitment, nil - } - _, hash, err := p.absolutePreState() - if err != nil { - return common.Hash{}, fmt.Errorf("cannot load absolute pre-state: %w", err) - } - p.prestateCommitment = hash - return hash, nil -} - -func (p *CannonPrestateProvider) PrestatePath() string { - return p.prestate -} diff --git a/op-challenger/game/fault/trace/cannon/prestate_test.go b/op-challenger/game/fault/trace/cannon/prestate_test.go deleted file mode 100644 index 9566e9d0664cc..0000000000000 --- a/op-challenger/game/fault/trace/cannon/prestate_test.go +++ /dev/null @@ -1,89 +0,0 @@ -package cannon - -import ( - "context" - "os" - "path/filepath" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/stretchr/testify/require" - - "github.com/ethereum-optimism/optimism/cannon/mipsevm" - "github.com/ethereum-optimism/optimism/cannon/mipsevm/memory" - "github.com/ethereum-optimism/optimism/cannon/mipsevm/singlethreaded" -) - -func newCannonPrestateProvider(dataDir string, prestate string) *CannonPrestateProvider { - return &CannonPrestateProvider{ - prestate: filepath.Join(dataDir, prestate), - } -} - -func TestAbsolutePreStateCommitment(t *testing.T) { - dataDir := t.TempDir() - - prestate := "state.json" - - t.Run("StateUnavailable", func(t *testing.T) { - provider := newCannonPrestateProvider("/dir/does/not/exist", prestate) - _, err := provider.AbsolutePreStateCommitment(context.Background()) - require.ErrorIs(t, err, os.ErrNotExist) - }) - - t.Run("InvalidStateFile", func(t *testing.T) { - setupPreState(t, dataDir, "invalid.json") - provider := newCannonPrestateProvider(dataDir, prestate) - _, err := provider.AbsolutePreStateCommitment(context.Background()) - require.ErrorContains(t, err, "invalid mipsevm state") - }) - - t.Run("ExpectedAbsolutePreState", func(t *testing.T) { - setupPreState(t, dataDir, "state.json") - provider := newCannonPrestateProvider(dataDir, prestate) - actual, err := provider.AbsolutePreStateCommitment(context.Background()) - require.NoError(t, err) - state := singlethreaded.State{ - Memory: memory.NewMemory(), - PreimageKey: common.HexToHash("cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"), - PreimageOffset: 0, - Cpu: mipsevm.CpuScalars{ - PC: 0, - NextPC: 1, - LO: 0, - HI: 0, - }, - Heap: 0, - ExitCode: 0, - Exited: false, - Step: 0, - Registers: [32]uint32{}, - } - _, expected := state.EncodeWitness() - require.Equal(t, expected, actual) - }) - - t.Run("CacheAbsolutePreState", func(t *testing.T) { - setupPreState(t, dataDir, prestate) - 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) { - srcDir := filepath.Join("test_data") - path := filepath.Join(srcDir, filename) - file, err := testData.ReadFile(path) - require.NoErrorf(t, err, "reading %v", path) - err = os.WriteFile(filepath.Join(dataDir, "state.json"), file, 0o644) - require.NoErrorf(t, err, "writing %v", path) -} diff --git a/op-challenger/game/fault/trace/cannon/provider.go b/op-challenger/game/fault/trace/cannon/provider.go index 7262ec918040e..823f8c6d814b1 100644 --- a/op-challenger/game/fault/trace/cannon/provider.go +++ b/op-challenger/game/fault/trace/cannon/provider.go @@ -10,11 +10,10 @@ import ( "os" "path/filepath" + kvtypes "github.com/ethereum-optimism/optimism/op-program/host/types" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/log" - "github.com/ethereum-optimism/optimism/cannon/mipsevm/singlethreaded" "github.com/ethereum-optimism/optimism/op-challenger/config" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/vm" @@ -30,6 +29,8 @@ type CannonTraceProvider struct { generator utils.ProofGenerator gameDepth types.Depth preimageLoader *utils.PreimageLoader + stateConverter vm.StateConverter + cfg vm.Config types.PrestateProvider @@ -40,13 +41,17 @@ type CannonTraceProvider struct { func NewTraceProvider(logger log.Logger, m vm.Metricer, cfg vm.Config, vmCfg vm.OracleServerExecutor, prestateProvider types.PrestateProvider, prestate string, localInputs utils.LocalGameInputs, dir string, gameDepth types.Depth) *CannonTraceProvider { return &CannonTraceProvider{ - logger: logger, - dir: dir, - prestate: prestate, - generator: vm.NewExecutor(logger, m, cfg, vmCfg, prestate, localInputs), - gameDepth: gameDepth, - preimageLoader: utils.NewPreimageLoader(kvstore.NewDiskKV(vm.PreimageDir(dir)).Get), + logger: logger, + dir: dir, + prestate: prestate, + generator: vm.NewExecutor(logger, m, cfg, vmCfg, prestate, localInputs), + gameDepth: gameDepth, + preimageLoader: utils.NewPreimageLoader(func() (utils.PreimageSource, error) { + return kvstore.NewDiskKV(logger, vm.PreimageDir(dir), kvtypes.DataFormatFile) + }), PrestateProvider: prestateProvider, + stateConverter: &StateConverter{}, + cfg: cfg, } } @@ -120,33 +125,22 @@ func (p *CannonTraceProvider) loadProof(ctx context.Context, i uint64) (*utils.P // Try opening the file again now and it should exist. 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 := p.finalState() + proof, stateStep, exited, err := p.stateConverter.ConvertStateToProof(vm.FinalStatePath(p.dir, p.cfg.BinarySnapshots)) if err != nil { - return nil, err + return nil, fmt.Errorf("cannot create proof from final state: %w", err) } - if state.Exited && state.Step <= i { - p.logger.Warn("Requested proof was after the program exited", "proof", i, "last", state.Step) + + if exited && stateStep <= i { + p.logger.Warn("Requested proof was after the program exited", "proof", i, "last", stateStep) // The final instruction has already been applied to this state, so the last step we can execute // is one before its Step value. - p.lastStep = state.Step - 1 - // Extend the trace out to the full length using a no-op instruction that doesn't change any state - // No execution is done, so no proof-data or oracle values are required. - witness, witnessHash := state.EncodeWitness() - proof := &utils.ProofData{ - ClaimValue: witnessHash, - StateData: hexutil.Bytes(witness), - ProofData: []byte{}, - OracleKey: nil, - OracleValue: nil, - OracleOffset: 0, - } + p.lastStep = stateStep - 1 if err := utils.WriteLastStep(p.dir, proof, p.lastStep); err != nil { p.logger.Warn("Failed to write last step to disk cache", "step", p.lastStep) } return proof, nil } else { - return nil, fmt.Errorf("expected proof not generated but final state was not exited, requested step %v, final state at step %v", i, state.Step) + return nil, fmt.Errorf("expected proof not generated but final state was not exited, requested step %v, final state at step %v", i, stateStep) } } } @@ -162,14 +156,6 @@ func (p *CannonTraceProvider) loadProof(ctx context.Context, i uint64) (*utils.P return &proof, nil } -func (c *CannonTraceProvider) finalState() (*singlethreaded.State, error) { - state, err := parseState(filepath.Join(c.dir, vm.FinalState)) - if err != nil { - return nil, fmt.Errorf("cannot read final state: %w", err) - } - return state, nil -} - // CannonTraceProviderForTest is a CannonTraceProvider that can find the step referencing the preimage read // Only to be used for testing type CannonTraceProviderForTest struct { @@ -178,12 +164,16 @@ type CannonTraceProviderForTest struct { func NewTraceProviderForTest(logger log.Logger, m vm.Metricer, cfg *config.Config, localInputs utils.LocalGameInputs, dir string, gameDepth types.Depth) *CannonTraceProviderForTest { p := &CannonTraceProvider{ - logger: logger, - dir: dir, - prestate: cfg.CannonAbsolutePreState, - generator: vm.NewExecutor(logger, m, cfg.Cannon, vm.NewOpProgramServerExecutor(), cfg.CannonAbsolutePreState, localInputs), - gameDepth: gameDepth, - preimageLoader: utils.NewPreimageLoader(kvstore.NewDiskKV(vm.PreimageDir(dir)).Get), + logger: logger, + dir: dir, + prestate: cfg.CannonAbsolutePreState, + generator: vm.NewExecutor(logger, m, cfg.Cannon, vm.NewOpProgramServerExecutor(), cfg.CannonAbsolutePreState, localInputs), + gameDepth: gameDepth, + preimageLoader: utils.NewPreimageLoader(func() (utils.PreimageSource, error) { + return kvstore.NewDiskKV(logger, vm.PreimageDir(dir), kvtypes.DataFormatFile) + }), + stateConverter: NewStateConverter(), + cfg: cfg.Cannon, } return &CannonTraceProviderForTest{p} } @@ -194,14 +184,15 @@ func (p *CannonTraceProviderForTest) FindStep(ctx context.Context, start uint64, 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() + + _, step, exited, err := p.stateConverter.ConvertStateToProof(vm.FinalStatePath(p.dir, p.cfg.BinarySnapshots)) 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 { + if 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 + return 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 3343b581f1c16..82edc5562623d 100644 --- a/op-challenger/game/fault/trace/cannon/provider_test.go +++ b/op-challenger/game/fault/trace/cannon/provider_test.go @@ -239,11 +239,12 @@ 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.LevelInfo), - dir: dataDir, - generator: generator, - prestate: filepath.Join(dataDir, prestate), - gameDepth: 63, + logger: testlog.Logger(t, log.LevelInfo), + dir: dataDir, + generator: generator, + prestate: filepath.Join(dataDir, prestate), + gameDepth: 63, + stateConverter: &StateConverter{}, }, generator } @@ -260,7 +261,7 @@ func (e *stubGenerator) GenerateProof(ctx context.Context, dir string, i uint64) var err error if e.finalState != nil && e.finalState.Step <= i { // Requesting a trace index past the end of the trace - proofFile = filepath.Join(dir, vm.FinalState) + proofFile = vm.FinalStatePath(dir, false) data, err = json.Marshal(e.finalState) if err != nil { return err diff --git a/op-challenger/game/fault/trace/cannon/state.go b/op-challenger/game/fault/trace/cannon/state.go deleted file mode 100644 index cf781c8bd428b..0000000000000 --- a/op-challenger/game/fault/trace/cannon/state.go +++ /dev/null @@ -1,27 +0,0 @@ -package cannon - -import ( - "encoding/json" - "fmt" - "io" - - "github.com/ethereum-optimism/optimism/cannon/mipsevm/singlethreaded" - "github.com/ethereum-optimism/optimism/op-service/ioutil" -) - -func parseState(path string) (*singlethreaded.State, error) { - file, err := ioutil.OpenDecompressed(path) - if err != nil { - return nil, fmt.Errorf("cannot open state file (%v): %w", path, err) - } - return parseStateFromReader(file) -} - -func parseStateFromReader(in io.ReadCloser) (*singlethreaded.State, error) { - defer in.Close() - var state singlethreaded.State - if err := json.NewDecoder(in).Decode(&state); err != nil { - return nil, fmt.Errorf("invalid mipsevm state: %w", err) - } - return &state, nil -} diff --git a/op-challenger/game/fault/trace/cannon/state_converter.go b/op-challenger/game/fault/trace/cannon/state_converter.go new file mode 100644 index 0000000000000..248676cc326e4 --- /dev/null +++ b/op-challenger/game/fault/trace/cannon/state_converter.go @@ -0,0 +1,38 @@ +package cannon + +import ( + "fmt" + + "github.com/ethereum-optimism/optimism/cannon/mipsevm" + "github.com/ethereum-optimism/optimism/cannon/mipsevm/versions" + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils" +) + +type StateConverter struct { +} + +func NewStateConverter() *StateConverter { + return &StateConverter{} +} + +func (c *StateConverter) ConvertStateToProof(statePath string) (*utils.ProofData, uint64, bool, error) { + state, err := parseState(statePath) + if err != nil { + return nil, 0, false, fmt.Errorf("cannot read final state: %w", err) + } + // Extend the trace out to the full length using a no-op instruction that doesn't change any state + // No execution is done, so no proof-data or oracle values are required. + witness, witnessHash := state.EncodeWitness() + return &utils.ProofData{ + ClaimValue: witnessHash, + StateData: witness, + ProofData: []byte{}, + OracleKey: nil, + OracleValue: nil, + OracleOffset: 0, + }, state.GetStep(), state.GetExited(), nil +} + +func parseState(path string) (mipsevm.FPVMState, error) { + return versions.LoadStateFromFile(path) +} diff --git a/op-challenger/game/fault/trace/cannon/state_converter_test.go b/op-challenger/game/fault/trace/cannon/state_converter_test.go new file mode 100644 index 0000000000000..c0c0182529ff6 --- /dev/null +++ b/op-challenger/game/fault/trace/cannon/state_converter_test.go @@ -0,0 +1,96 @@ +package cannon + +import ( + _ "embed" + "path/filepath" + "testing" + + "github.com/ethereum-optimism/optimism/cannon/mipsevm" + "github.com/ethereum-optimism/optimism/cannon/mipsevm/multithreaded" + "github.com/ethereum-optimism/optimism/cannon/mipsevm/versions" + "github.com/ethereum-optimism/optimism/cannon/serialize" + "github.com/stretchr/testify/require" + + "github.com/ethereum-optimism/optimism/cannon/mipsevm/singlethreaded" +) + +func TestLoadState(t *testing.T) { + tests := []struct { + name string + creator func() mipsevm.FPVMState + supportsJSON bool + }{ + { + name: "singlethreaded", + creator: func() mipsevm.FPVMState { return singlethreaded.CreateInitialState(234, 82) }, + supportsJSON: true, + }, + { + name: "multithreaded", + creator: func() mipsevm.FPVMState { return multithreaded.CreateInitialState(982, 492) }, + supportsJSON: false, + }, + } + for _, test := range tests { + test := test + loadExpectedState := func(t *testing.T) *versions.VersionedState { + state, err := versions.NewFromState(test.creator()) + require.NoError(t, err) + return state + } + t.Run(test.name, func(t *testing.T) { + t.Run("Uncompressed", func(t *testing.T) { + if !test.supportsJSON { + t.Skip("JSON not supported by state version") + } + expected := loadExpectedState(t) + path := writeState(t, "state.json", expected) + + state, err := parseState(path) + require.NoError(t, err) + + require.Equal(t, expected, state) + }) + + t.Run("Gzipped", func(t *testing.T) { + if !test.supportsJSON { + t.Skip("JSON not supported by state version") + } + expected := loadExpectedState(t) + path := writeState(t, "state.json.gz", expected) + + state, err := parseState(path) + require.NoError(t, err) + + require.Equal(t, expected, state) + }) + + t.Run("Binary", func(t *testing.T) { + expected := loadExpectedState(t) + + path := writeState(t, "state.bin", expected) + + state, err := parseState(path) + require.NoError(t, err) + require.Equal(t, expected, state) + }) + + t.Run("BinaryGzip", func(t *testing.T) { + expected := loadExpectedState(t) + + path := writeState(t, "state.bin.gz", expected) + + state, err := parseState(path) + require.NoError(t, err) + require.Equal(t, expected, state) + }) + }) + } +} + +func writeState(t *testing.T, filename string, state *versions.VersionedState) string { + dir := t.TempDir() + path := filepath.Join(dir, filename) + require.NoError(t, serialize.Write(path, state, 0644)) + return path +} diff --git a/op-challenger/game/fault/trace/cannon/state_test.go b/op-challenger/game/fault/trace/cannon/state_test.go deleted file mode 100644 index ce4757a356713..0000000000000 --- a/op-challenger/game/fault/trace/cannon/state_test.go +++ /dev/null @@ -1,51 +0,0 @@ -package cannon - -import ( - "compress/gzip" - _ "embed" - "encoding/json" - "os" - "path/filepath" - "testing" - - "github.com/stretchr/testify/require" - - "github.com/ethereum-optimism/optimism/cannon/mipsevm/singlethreaded" -) - -//go:embed test_data/state.json -var testState []byte - -func TestLoadState(t *testing.T) { - t.Run("Uncompressed", func(t *testing.T) { - dir := t.TempDir() - path := filepath.Join(dir, "state.json") - require.NoError(t, os.WriteFile(path, testState, 0644)) - - state, err := parseState(path) - require.NoError(t, err) - - var expected singlethreaded.State - require.NoError(t, json.Unmarshal(testState, &expected)) - require.Equal(t, &expected, state) - }) - - t.Run("Gzipped", func(t *testing.T) { - dir := t.TempDir() - path := filepath.Join(dir, "state.json.gz") - f, err := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644) - require.NoError(t, err) - defer f.Close() - writer := gzip.NewWriter(f) - _, err = writer.Write(testState) - require.NoError(t, err) - require.NoError(t, writer.Close()) - - state, err := parseState(path) - require.NoError(t, err) - - var expected singlethreaded.State - require.NoError(t, json.Unmarshal(testState, &expected)) - require.Equal(t, &expected, state) - }) -} diff --git a/op-challenger/game/fault/trace/cannon/test_data/invalid.json b/op-challenger/game/fault/trace/cannon/test_data/invalid.json deleted file mode 100644 index 06a76bf5b23de..0000000000000 --- a/op-challenger/game/fault/trace/cannon/test_data/invalid.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "preimageKey": 1 -} diff --git a/op-challenger/game/fault/trace/cannon/test_data/state.json b/op-challenger/game/fault/trace/cannon/test_data/state.json deleted file mode 100644 index 30cd1ccdcf0c8..0000000000000 --- a/op-challenger/game/fault/trace/cannon/test_data/state.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "memory": [], - "preimageKey": "0xcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc", - "preimageOffset": 0, - "pc": 0, - "nextPC": 1, - "lo": 0, - "hi": 0, - "heap": 0, - "exit": 0, - "exited": false, - "step": 0, - "registers": [] -} diff --git a/op-challenger/game/fault/trace/outputs/output_asterisc.go b/op-challenger/game/fault/trace/outputs/output_asterisc.go index 726b57e551d7b..82dac14f8453f 100644 --- a/op-challenger/game/fault/trace/outputs/output_asterisc.go +++ b/op-challenger/game/fault/trace/outputs/output_asterisc.go @@ -41,7 +41,7 @@ func NewOutputAsteriscTraceAccessor( if err != nil { return nil, fmt.Errorf("failed to fetch asterisc local inputs: %w", err) } - provider := asterisc.NewTraceProvider(logger, m, cfg, vmCfg, prestateProvider, asteriscPrestate, localInputs, subdir, depth) + provider := asterisc.NewTraceProvider(logger, m.VmMetrics(cfg.VmType.String()), cfg, vmCfg, prestateProvider, asteriscPrestate, localInputs, subdir, 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 1f9c4285a3542..49b6631b5a7f0 100644 --- a/op-challenger/game/fault/trace/outputs/output_cannon.go +++ b/op-challenger/game/fault/trace/outputs/output_cannon.go @@ -41,7 +41,7 @@ func NewOutputCannonTraceAccessor( if err != nil { return nil, fmt.Errorf("failed to fetch cannon local inputs: %w", err) } - provider := cannon.NewTraceProvider(logger, m, cfg, serverExecutor, prestateProvider, cannonPrestate, localInputs, subdir, depth) + provider := cannon.NewTraceProvider(logger, m.VmMetrics(cfg.VmType.String()), cfg, serverExecutor, prestateProvider, cannonPrestate, localInputs, subdir, depth) return provider, nil } diff --git a/op-challenger/game/fault/trace/prestates/multi.go b/op-challenger/game/fault/trace/prestates/multi.go index ccc22c6d5d4a3..03abbbc564866 100644 --- a/op-challenger/game/fault/trace/prestates/multi.go +++ b/op-challenger/game/fault/trace/prestates/multi.go @@ -9,43 +9,64 @@ import ( "os" "path/filepath" + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/vm" "github.com/ethereum-optimism/optimism/op-service/ioutil" "github.com/ethereum/go-ethereum/common" ) var ( ErrPrestateUnavailable = errors.New("prestate unavailable") + + // supportedFileTypes lists, in preferred order, the prestate file types to attempt to download + supportedFileTypes = []string{".bin.gz", ".json.gz", ".json"} ) type MultiPrestateProvider struct { - baseUrl *url.URL - dataDir string + baseUrl *url.URL + dataDir string + stateConverter vm.StateConverter } -func NewMultiPrestateProvider(baseUrl *url.URL, dataDir string) *MultiPrestateProvider { +func NewMultiPrestateProvider(baseUrl *url.URL, dataDir string, stateConverter vm.StateConverter) *MultiPrestateProvider { return &MultiPrestateProvider{ - baseUrl: baseUrl, - dataDir: dataDir, + baseUrl: baseUrl, + dataDir: dataDir, + stateConverter: stateConverter, } } func (m *MultiPrestateProvider) PrestatePath(hash common.Hash) (string, error) { - path := filepath.Join(m.dataDir, hash.Hex()+".json.gz") - if _, err := os.Stat(path); errors.Is(err, os.ErrNotExist) { - if err := m.fetchPrestate(hash, path); err != nil { - return "", fmt.Errorf("failed to fetch prestate: %w", err) + // First try to find a previously downloaded prestate + for _, fileType := range supportedFileTypes { + path := filepath.Join(m.dataDir, hash.Hex()+fileType) + if _, err := os.Stat(path); errors.Is(err, os.ErrNotExist) { + continue // File doesn't exist, try the next file type + } else if err != nil { + return "", fmt.Errorf("error checking for existing prestate %v in file %v: %w", hash, path, err) + } + return path, nil // Found an existing file so use it + } + + // Didn't find any available files, try to download one + var combinedErr error // Keep a track of each download attempt so we can report them if none work + for _, fileType := range supportedFileTypes { + path := filepath.Join(m.dataDir, hash.Hex()+fileType) + if err := m.fetchPrestate(hash, fileType, path); errors.Is(err, ErrPrestateUnavailable) { + combinedErr = errors.Join(combinedErr, err) + continue // Didn't find prestate in this format, try the next + } else if err != nil { + return "", fmt.Errorf("error downloading prestate %v to file %v: %w", hash, path, err) } - } else if err != nil { - return "", fmt.Errorf("error checking for existing prestate %v: %w", hash, err) + return path, nil // Successfully downloaded a prestate so use it } - return path, nil + return "", errors.Join(ErrPrestateUnavailable, combinedErr) } -func (m *MultiPrestateProvider) fetchPrestate(hash common.Hash, dest string) error { +func (m *MultiPrestateProvider) fetchPrestate(hash common.Hash, fileType string, dest string) error { if err := os.MkdirAll(m.dataDir, 0755); err != nil { return fmt.Errorf("error creating prestate dir: %w", err) } - prestateUrl := m.baseUrl.JoinPath(hash.Hex() + ".json") + prestateUrl := m.baseUrl.JoinPath(hash.Hex() + fileType) resp, err := http.Get(prestateUrl.String()) if err != nil { return fmt.Errorf("failed to fetch prestate from %v: %w", prestateUrl, err) @@ -54,7 +75,8 @@ func (m *MultiPrestateProvider) fetchPrestate(hash common.Hash, dest string) err if resp.StatusCode != http.StatusOK { return fmt.Errorf("%w from url %v: status %v", ErrPrestateUnavailable, prestateUrl, resp.StatusCode) } - out, err := ioutil.NewAtomicWriterCompressed(dest, 0o644) + tmpFile := dest + ".tmp" + fileType // Preserve the file type extension so state decoding is applied correctly + out, err := ioutil.NewAtomicWriter(tmpFile, 0o644) if err != nil { return fmt.Errorf("failed to open atomic writer for %v: %w", dest, err) } @@ -68,5 +90,15 @@ func (m *MultiPrestateProvider) fetchPrestate(hash common.Hash, dest string) err if err := out.Close(); err != nil { return fmt.Errorf("failed to close file %v: %w", dest, err) } + // Verify the prestate actually matches the expected hash before moving it into the final destination + proof, _, _, err := m.stateConverter.ConvertStateToProof(tmpFile) + if err != nil || proof.ClaimValue != hash { + // Treat invalid prestates as unavailable. Often servers return a 404 page with 200 status code + _ = os.Remove(tmpFile) // Best effort attempt to clean up the temporary file + return fmt.Errorf("invalid prestate from url: %v, ignoring: %w", prestateUrl, errors.Join(ErrPrestateUnavailable, err)) + } + if err := os.Rename(tmpFile, dest); err != nil { + return fmt.Errorf("failed to move temp file to final destination: %w", err) + } return nil } diff --git a/op-challenger/game/fault/trace/prestates/multi_test.go b/op-challenger/game/fault/trace/prestates/multi_test.go index 2f825d98da4e0..7b09b81bdc676 100644 --- a/op-challenger/game/fault/trace/prestates/multi_test.go +++ b/op-challenger/game/fault/trace/prestates/multi_test.go @@ -1,60 +1,67 @@ package prestates import ( + "errors" "io" "net/http" "net/http/httptest" "net/url" "os" "path/filepath" + "strings" "testing" + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils" "github.com/ethereum-optimism/optimism/op-service/ioutil" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" ) func TestDownloadPrestate(t *testing.T) { - dir := t.TempDir() - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - _, _ = w.Write([]byte(r.URL.Path)) - })) - defer server.Close() - provider := NewMultiPrestateProvider(parseURL(t, server.URL), dir) - hash := common.Hash{0xaa} - path, err := provider.PrestatePath(hash) - require.NoError(t, err) - in, err := ioutil.OpenDecompressed(path) - require.NoError(t, err) - defer in.Close() - content, err := io.ReadAll(in) - require.NoError(t, err) - require.Equal(t, "/"+hash.Hex()+".json", string(content)) + for _, ext := range supportedFileTypes { + t.Run(ext, func(t *testing.T) { + dir := t.TempDir() + server := prestateHTTPServer(ext) + defer server.Close() + hash := common.Hash{0xaa} + provider := NewMultiPrestateProvider(parseURL(t, server.URL), dir, &stubStateConverter{hash: hash}) + path, err := provider.PrestatePath(hash) + require.NoError(t, err) + in, err := os.Open(path) + require.NoError(t, err) + defer in.Close() + content, err := io.ReadAll(in) + require.NoError(t, err) + require.Equal(t, "/"+hash.Hex()+ext, string(content)) + }) + } } func TestCreateDirectory(t *testing.T) { - dir := t.TempDir() - dir = filepath.Join(dir, "test") - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - _, _ = w.Write([]byte(r.URL.Path)) - })) - defer server.Close() - provider := NewMultiPrestateProvider(parseURL(t, server.URL), dir) - hash := common.Hash{0xaa} - path, err := provider.PrestatePath(hash) - require.NoError(t, err) - in, err := ioutil.OpenDecompressed(path) - require.NoError(t, err) - defer in.Close() - content, err := io.ReadAll(in) - require.NoError(t, err) - require.Equal(t, "/"+hash.Hex()+".json", string(content)) + for _, ext := range supportedFileTypes { + t.Run(ext, func(t *testing.T) { + dir := t.TempDir() + dir = filepath.Join(dir, "test") + server := prestateHTTPServer(ext) + defer server.Close() + hash := common.Hash{0xaa} + provider := NewMultiPrestateProvider(parseURL(t, server.URL), dir, &stubStateConverter{hash: hash}) + path, err := provider.PrestatePath(hash) + require.NoError(t, err) + in, err := os.Open(path) + require.NoError(t, err) + defer in.Close() + content, err := io.ReadAll(in) + require.NoError(t, err) + require.Equal(t, "/"+hash.Hex()+ext, string(content)) + }) + } } func TestExistingPrestate(t *testing.T) { dir := t.TempDir() - provider := NewMultiPrestateProvider(parseURL(t, "http://127.0.0.1:1"), dir) hash := common.Hash{0xaa} + provider := NewMultiPrestateProvider(parseURL(t, "http://127.0.0.1:1"), dir, &stubStateConverter{hash: hash}) expectedFile := filepath.Join(dir, hash.Hex()+".json.gz") err := ioutil.WriteCompressedBytes(expectedFile, []byte("expected content"), os.O_WRONLY|os.O_CREATE, 0o644) require.NoError(t, err) @@ -72,16 +79,84 @@ func TestExistingPrestate(t *testing.T) { func TestMissingPrestate(t *testing.T) { dir := t.TempDir() + var requests []string server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + requests = append(requests, r.URL.Path) w.WriteHeader(404) })) defer server.Close() - provider := NewMultiPrestateProvider(parseURL(t, server.URL), dir) hash := common.Hash{0xaa} + provider := NewMultiPrestateProvider(parseURL(t, server.URL), dir, &stubStateConverter{hash: hash}) path, err := provider.PrestatePath(hash) require.ErrorIs(t, err, ErrPrestateUnavailable) _, err = os.Stat(path) require.ErrorIs(t, err, os.ErrNotExist) + expectedRequests := []string{ + "/" + hash.Hex() + ".bin.gz", + "/" + hash.Hex() + ".json.gz", + "/" + hash.Hex() + ".json", + } + require.Equal(t, expectedRequests, requests) +} + +func TestStorePrestateWithCorrectExtension(t *testing.T) { + extensions := []string{".bin.gz", ".json.gz", ".json"} + for _, ext := range extensions { + ext := ext + t.Run(ext, func(t *testing.T) { + dir := t.TempDir() + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if !strings.HasSuffix(r.URL.Path, ext) { + w.WriteHeader(404) + return + } + _, _ = w.Write([]byte("content")) + })) + defer server.Close() + hash := common.Hash{0xaa} + provider := NewMultiPrestateProvider(parseURL(t, server.URL), dir, &stubStateConverter{hash: hash}) + path, err := provider.PrestatePath(hash) + require.NoError(t, err) + require.Truef(t, strings.HasSuffix(path, ext), "Expected path %v to have extension %v", path, ext) + in, err := os.Open(path) + require.NoError(t, err) + defer in.Close() + content, err := io.ReadAll(in) + require.NoError(t, err) + require.Equal(t, "content", string(content)) + }) + } +} + +func TestDetectInvalidPrestate(t *testing.T) { + dir := t.TempDir() + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + _, _ = w.Write([]byte("content")) + })) + defer server.Close() + hash := common.Hash{0xaa} + provider := NewMultiPrestateProvider(parseURL(t, server.URL), dir, &stubStateConverter{hash: hash, err: errors.New("boom")}) + _, err := provider.PrestatePath(hash) + require.ErrorIs(t, err, ErrPrestateUnavailable) + entries, err := os.ReadDir(dir) + require.NoError(t, err) + require.Empty(t, entries, "should not leave any files in temp dir") +} + +func TestDetectPrestateWithWrongHash(t *testing.T) { + dir := t.TempDir() + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + _, _ = w.Write([]byte("content")) + })) + defer server.Close() + hash := common.Hash{0xaa} + actualHash := common.Hash{0xbb} + provider := NewMultiPrestateProvider(parseURL(t, server.URL), dir, &stubStateConverter{hash: actualHash}) + _, err := provider.PrestatePath(hash) + require.ErrorIs(t, err, ErrPrestateUnavailable) + entries, err := os.ReadDir(dir) + require.NoError(t, err) + require.Empty(t, entries, "should not leave any files in temp dir") } func parseURL(t *testing.T, str string) *url.URL { @@ -89,3 +164,26 @@ func parseURL(t *testing.T, str string) *url.URL { require.NoError(t, err) return parsed } + +func prestateHTTPServer(ext string) *httptest.Server { + return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if strings.HasSuffix(r.URL.Path, ext) { + _, _ = w.Write([]byte(r.URL.Path)) + } else { + w.WriteHeader(http.StatusNotFound) + } + })) +} + +type stubStateConverter struct { + err error + hash common.Hash +} + +func (s *stubStateConverter) ConvertStateToProof(path string) (*utils.ProofData, uint64, bool, error) { + // Return an error if we're given the wrong path + if _, err := os.Stat(path); err != nil { + return nil, 0, false, err + } + return &utils.ProofData{ClaimValue: s.hash}, 0, false, s.err +} diff --git a/op-challenger/game/fault/trace/prestates/source.go b/op-challenger/game/fault/trace/prestates/source.go index c59763560b114..a4c9839ad1e5d 100644 --- a/op-challenger/game/fault/trace/prestates/source.go +++ b/op-challenger/game/fault/trace/prestates/source.go @@ -1,10 +1,14 @@ package prestates -import "net/url" +import ( + "net/url" -func NewPrestateSource(baseURL *url.URL, path string, localDir string) PrestateSource { + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/vm" +) + +func NewPrestateSource(baseURL *url.URL, path string, localDir string, stateConverter vm.StateConverter) PrestateSource { if baseURL != nil { - return NewMultiPrestateProvider(baseURL, localDir) + return NewMultiPrestateProvider(baseURL, localDir, stateConverter) } else { return NewSinglePrestateSource(path) } diff --git a/op-challenger/game/fault/trace/utils/preimage.go b/op-challenger/game/fault/trace/utils/preimage.go index 09a48ee912f67..5b61a70adb9f7 100644 --- a/op-challenger/game/fault/trace/utils/preimage.go +++ b/op-challenger/game/fault/trace/utils/preimage.go @@ -23,19 +23,23 @@ const ( ) var ( - ErrInvalidScalarValue = errors.New("invalid scalar value") ErrInvalidBlobKeyPreimage = errors.New("invalid blob key preimage") ) -type preimageSource func(key common.Hash) ([]byte, error) +type PreimageSource interface { + Get(key common.Hash) ([]byte, error) + Close() error +} + +type PreimageSourceCreator func() (PreimageSource, error) type PreimageLoader struct { - getPreimage preimageSource + makeSource PreimageSourceCreator } -func NewPreimageLoader(getPreimage preimageSource) *PreimageLoader { +func NewPreimageLoader(makeSource PreimageSourceCreator) *PreimageLoader { return &PreimageLoader{ - getPreimage: getPreimage, + makeSource: makeSource, } } @@ -57,7 +61,12 @@ func (l *PreimageLoader) loadBlobPreimage(proof *ProofData) (*types.PreimageOrac // 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) + source, err := l.makeSource() + if err != nil { + return nil, fmt.Errorf("failed to open preimage store: %w", err) + } + defer source.Close() + inputs, err := source.Get(inputsKey) if err != nil { return nil, fmt.Errorf("failed to get key preimage: %w", err) } @@ -74,7 +83,7 @@ func (l *PreimageLoader) loadBlobPreimage(proof *ProofData) (*types.PreimageOrac 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) + fieldElement, err := source.Get(key) if err != nil { return nil, fmt.Errorf("failed to load field element %v with key %v: %w", i, common.Hash(key), err) } @@ -105,7 +114,12 @@ func (l *PreimageLoader) loadBlobPreimage(proof *ProofData) (*types.PreimageOrac func (l *PreimageLoader) loadPrecompilePreimage(proof *ProofData) (*types.PreimageOracleData, error) { inputKey := preimage.Keccak256Key(proof.OracleKey).PreimageKey() - input, err := l.getPreimage(inputKey) + source, err := l.makeSource() + if err != nil { + return nil, fmt.Errorf("failed to open preimage store: %w", err) + } + defer source.Close() + input, err := source.Get(inputKey) if err != nil { return nil, fmt.Errorf("failed to get key preimage: %w", err) } diff --git a/op-challenger/game/fault/trace/utils/preimage_test.go b/op-challenger/game/fault/trace/utils/preimage_test.go index 46778f080c374..2b5552f28e0cb 100644 --- a/op-challenger/game/fault/trace/utils/preimage_test.go +++ b/op-challenger/game/fault/trace/utils/preimage_test.go @@ -20,14 +20,20 @@ import ( ) func TestPreimageLoader_NoPreimage(t *testing.T) { - loader := NewPreimageLoader(kvstore.NewMemKV().Get) + kv := kvstore.NewMemKV() + loader := NewPreimageLoader(func() (PreimageSource, error) { + return kv, nil + }) actual, err := loader.LoadPreimage(&ProofData{}) require.NoError(t, err) require.Nil(t, actual) } func TestPreimageLoader_LocalPreimage(t *testing.T) { - loader := NewPreimageLoader(kvstore.NewMemKV().Get) + kv := kvstore.NewMemKV() + loader := NewPreimageLoader(func() (PreimageSource, error) { + return kv, nil + }) proof := &ProofData{ OracleKey: common.Hash{byte(preimage.LocalKeyType), 0xaa, 0xbb}.Bytes(), OracleValue: nil, @@ -48,7 +54,10 @@ func TestPreimageLoader_SimpleTypes(t *testing.T) { for _, keyType := range tests { keyType := keyType t.Run(fmt.Sprintf("type-%v", keyType), func(t *testing.T) { - loader := NewPreimageLoader(kvstore.NewMemKV().Get) + kv := kvstore.NewMemKV() + loader := NewPreimageLoader(func() (PreimageSource, error) { + return kv, nil + }) proof := &ProofData{ OracleKey: common.Hash{byte(keyType), 0xaa, 0xbb}.Bytes(), OracleValue: []byte{1, 2, 3, 4, 5, 6}, @@ -90,7 +99,9 @@ func TestPreimageLoader_BlobPreimage(t *testing.T) { t.Run("NoKeyPreimage", func(t *testing.T) { kv := kvstore.NewMemKV() - loader := NewPreimageLoader(kv.Get) + loader := NewPreimageLoader(func() (PreimageSource, error) { + return kv, nil + }) proof := &ProofData{ OracleKey: common.Hash{byte(preimage.BlobKeyType), 0xaf}.Bytes(), OracleValue: proof.OracleValue, @@ -102,7 +113,9 @@ func TestPreimageLoader_BlobPreimage(t *testing.T) { t.Run("InvalidKeyPreimage", func(t *testing.T) { kv := kvstore.NewMemKV() - loader := NewPreimageLoader(kv.Get) + loader := NewPreimageLoader(func() (PreimageSource, error) { + return kv, nil + }) proof := &ProofData{ OracleKey: common.Hash{byte(preimage.BlobKeyType), 0xad}.Bytes(), OracleValue: proof.OracleValue, @@ -115,7 +128,9 @@ func TestPreimageLoader_BlobPreimage(t *testing.T) { t.Run("MissingBlobs", func(t *testing.T) { kv := kvstore.NewMemKV() - loader := NewPreimageLoader(kv.Get) + loader := NewPreimageLoader(func() (PreimageSource, error) { + return kv, nil + }) proof := &ProofData{ OracleKey: common.Hash{byte(preimage.BlobKeyType), 0xae}.Bytes(), OracleValue: proof.OracleValue, @@ -128,7 +143,9 @@ func TestPreimageLoader_BlobPreimage(t *testing.T) { t.Run("Valid", func(t *testing.T) { kv := kvstore.NewMemKV() - loader := NewPreimageLoader(kv.Get) + loader := NewPreimageLoader(func() (PreimageSource, error) { + return kv, nil + }) storeBlob(t, kv, gokzg4844.KZGCommitment(commitment), gokzg4844.Blob(blob)) actual, err := loader.LoadPreimage(proof) require.NoError(t, err) @@ -161,13 +178,17 @@ func TestPreimageLoader_PrecompilePreimage(t *testing.T) { t.Run("NoInputPreimage", func(t *testing.T) { kv := kvstore.NewMemKV() - loader := NewPreimageLoader(kv.Get) + loader := NewPreimageLoader(func() (PreimageSource, error) { + return kv, nil + }) _, err := loader.LoadPreimage(proof) require.ErrorIs(t, err, kvstore.ErrNotFound) }) t.Run("Valid", func(t *testing.T) { kv := kvstore.NewMemKV() - loader := NewPreimageLoader(kv.Get) + loader := NewPreimageLoader(func() (PreimageSource, error) { + return kv, nil + }) require.NoError(t, kv.Put(preimage.Keccak256Key(proof.OracleKey).PreimageKey(), input)) actual, err := loader.LoadPreimage(proof) require.NoError(t, err) diff --git a/op-challenger/game/fault/trace/vm/executor.go b/op-challenger/game/fault/trace/vm/executor.go index 65c18d67d221e..9e2cd0d29e93e 100644 --- a/op-challenger/game/fault/trace/vm/executor.go +++ b/op-challenger/game/fault/trace/vm/executor.go @@ -22,17 +22,18 @@ const ( ) type Metricer interface { - RecordVmExecutionTime(vmType string, t time.Duration) - RecordVmMemoryUsed(vmType string, memoryUsed uint64) + RecordExecutionTime(t time.Duration) + RecordMemoryUsed(memoryUsed uint64) } type Config struct { // VM Configuration - VmType types.TraceType - VmBin string // Path to the vm executable to run when generating trace data - SnapshotFreq uint // Frequency of snapshots to create when executing (in VM instructions) - InfoFreq uint // Frequency of progress log messages (in VM instructions) - DebugInfo bool + VmType types.TraceType + VmBin string // Path to the vm executable to run when generating trace data + SnapshotFreq uint // Frequency of snapshots to create when executing (in VM instructions) + InfoFreq uint // Frequency of progress log messages (in VM instructions) + DebugInfo bool // Whether to record debug info from the execution + BinarySnapshots bool // Whether to use binary snapshots instead of JSON // Host Configuration L1 string @@ -82,13 +83,13 @@ func (e *Executor) GenerateProof(ctx context.Context, dir string, i uint64) erro // The proof is stored at the specified directory. func (e *Executor) DoGenerateProof(ctx context.Context, dir string, begin uint64, end uint64, extraVmArgs ...string) error { snapshotDir := filepath.Join(dir, SnapsDir) - start, err := e.selectSnapshot(e.logger, snapshotDir, e.absolutePreState, begin) + start, err := e.selectSnapshot(e.logger, snapshotDir, e.absolutePreState, begin, e.cfg.BinarySnapshots) if err != nil { return fmt.Errorf("find starting snapshot: %w", err) } proofDir := filepath.Join(dir, utils.ProofsDir) dataDir := PreimageDir(dir) - lastGeneratedState := filepath.Join(dir, FinalState) + lastGeneratedState := FinalStatePath(dir, e.cfg.BinarySnapshots) args := []string{ "run", "--input", start, @@ -98,7 +99,11 @@ func (e *Executor) DoGenerateProof(ctx context.Context, dir string, begin uint64 "--proof-at", "=" + strconv.FormatUint(end, 10), "--proof-fmt", filepath.Join(proofDir, "%d.json.gz"), "--snapshot-at", "%" + strconv.FormatUint(uint64(e.cfg.SnapshotFreq), 10), - "--snapshot-fmt", filepath.Join(snapshotDir, "%d.json.gz"), + } + if e.cfg.BinarySnapshots { + args = append(args, "--snapshot-fmt", filepath.Join(snapshotDir, "%d.bin.gz")) + } else { + args = append(args, "--snapshot-fmt", filepath.Join(snapshotDir, "%d.json.gz")) } if end < math.MaxUint64 { args = append(args, "--stop-at", "="+strconv.FormatUint(end+1, 10)) @@ -128,12 +133,12 @@ func (e *Executor) DoGenerateProof(ctx context.Context, dir string, begin uint64 err = e.cmdExecutor(ctx, e.logger.New("proof", end), e.cfg.VmBin, args...) execTime := time.Since(execStart) memoryUsed := "unknown" - e.metrics.RecordVmExecutionTime(e.cfg.VmType.String(), execTime) + e.metrics.RecordExecutionTime(execTime) if e.cfg.DebugInfo && err == nil { if info, err := jsonutil.LoadJSON[debugInfo](filepath.Join(dataDir, debugFilename)); err != nil { e.logger.Warn("Failed to load debug metrics", "err", err) } else { - e.metrics.RecordVmMemoryUsed(e.cfg.VmType.String(), uint64(info.MemoryUsed)) + e.metrics.RecordMemoryUsed(uint64(info.MemoryUsed)) memoryUsed = fmt.Sprintf("%d", uint64(info.MemoryUsed)) } } diff --git a/op-challenger/game/fault/trace/vm/executor_test.go b/op-challenger/game/fault/trace/vm/executor_test.go index 695f9bf9fceb9..ff4a8ba7e1ab2 100644 --- a/op-challenger/game/fault/trace/vm/executor_test.go +++ b/op-challenger/game/fault/trace/vm/executor_test.go @@ -9,7 +9,6 @@ import ( "time" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils" - "github.com/ethereum-optimism/optimism/op-challenger/metrics" "github.com/ethereum-optimism/optimism/op-service/testlog" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" @@ -43,7 +42,7 @@ func TestGenerateProof(t *testing.T) { captureExec := func(t *testing.T, cfg Config, proofAt uint64) (string, string, map[string]string) { m := &stubVmMetrics{} executor := NewExecutor(testlog.Logger(t, log.LevelInfo), m, cfg, NewOpProgramServerExecutor(), prestate, inputs) - executor.selectSnapshot = func(logger log.Logger, dir string, absolutePreState string, i uint64) (string, error) { + executor.selectSnapshot = func(logger log.Logger, dir string, absolutePreState string, i uint64, binary bool) (string, error) { return input, nil } var binary string @@ -82,7 +81,7 @@ func TestGenerateProof(t *testing.T) { require.Equal(t, input, args["--input"]) require.Contains(t, args, "--meta") require.Equal(t, "", args["--meta"]) - require.Equal(t, filepath.Join(dir, FinalState), args["--output"]) + require.Equal(t, FinalStatePath(dir, cfg.BinarySnapshots), args["--output"]) require.Equal(t, "=150000000", args["--proof-at"]) require.Equal(t, "=150000001", args["--stop-at"]) require.Equal(t, "%500", args["--snapshot-at"]) @@ -128,13 +127,29 @@ func TestGenerateProof(t *testing.T) { // so expect that it will be omitted. We'll ultimately want asterisc to execute until the program exits. require.NotContains(t, args, "--stop-at") }) + + t.Run("BinarySnapshots", func(t *testing.T) { + cfg.Network = "mainnet" + cfg.BinarySnapshots = true + _, _, args := captureExec(t, cfg, 100) + require.Equal(t, filepath.Join(dir, SnapsDir, "%d.bin.gz"), args["--snapshot-fmt"]) + }) + + t.Run("JsonSnapshots", func(t *testing.T) { + cfg.Network = "mainnet" + cfg.BinarySnapshots = false + _, _, args := captureExec(t, cfg, 100) + require.Equal(t, filepath.Join(dir, SnapsDir, "%d.json.gz"), args["--snapshot-fmt"]) + }) } type stubVmMetrics struct { - metrics.NoopMetricsImpl executionTimeRecordCount int } -func (c *stubVmMetrics) RecordVmExecutionTime(_ string, _ time.Duration) { +func (c *stubVmMetrics) RecordExecutionTime(_ time.Duration) { c.executionTimeRecordCount++ } + +func (c *stubVmMetrics) RecordMemoryUsed(_ uint64) { +} diff --git a/op-challenger/game/fault/trace/vm/iface.go b/op-challenger/game/fault/trace/vm/iface.go new file mode 100644 index 0000000000000..188f19e0c8e27 --- /dev/null +++ b/op-challenger/game/fault/trace/vm/iface.go @@ -0,0 +1,9 @@ +package vm + +import "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils" + +type StateConverter interface { + // ConvertStateToProof reads the state snapshot at the specified path and converts it to ProofData. + // Returns the proof data, the VM step the state is from and whether or not the VM had exited. + ConvertStateToProof(statePath string) (*utils.ProofData, uint64, bool, error) +} diff --git a/op-challenger/game/fault/trace/vm/kona_server_executor.go b/op-challenger/game/fault/trace/vm/kona_server_executor.go index ac5b0fbb0fe07..a8be1c7bc5620 100644 --- a/op-challenger/game/fault/trace/vm/kona_server_executor.go +++ b/op-challenger/game/fault/trace/vm/kona_server_executor.go @@ -8,32 +8,52 @@ import ( "github.com/ethereum-optimism/optimism/op-node/chaincfg" ) -type KonaServerExecutor struct { +type KonaExecutor struct { + nativeMode bool + clientBinPath string } -var _ OracleServerExecutor = (*KonaServerExecutor)(nil) +var _ OracleServerExecutor = (*KonaExecutor)(nil) -func NewKonaServerExecutor() *KonaServerExecutor { - return &KonaServerExecutor{} +func NewKonaExecutor() *KonaExecutor { + return &KonaExecutor{nativeMode: false} } -func (s *KonaServerExecutor) OracleCommand(cfg Config, dataDir string, inputs utils.LocalGameInputs) ([]string, error) { - if cfg.Network == "" { - return nil, errors.New("network is not defined") - } +func NewNativeKonaExecutor(clientBinPath string) *KonaExecutor { + return &KonaExecutor{nativeMode: true, clientBinPath: clientBinPath} +} - chainCfg := chaincfg.ChainByName(cfg.Network) - return []string{ - cfg.Server, "--server", +func (s *KonaExecutor) OracleCommand(cfg Config, dataDir string, inputs utils.LocalGameInputs) ([]string, error) { + args := []string{ + cfg.Server, "--l1-node-address", cfg.L1, "--l1-beacon-address", cfg.L1Beacon, "--l2-node-address", cfg.L2, - "--data-dir", dataDir, - "--l2-chain-id", strconv.FormatUint(chainCfg.ChainID, 10), "--l1-head", inputs.L1Head.Hex(), "--l2-head", inputs.L2Head.Hex(), "--l2-output-root", inputs.L2OutputRoot.Hex(), "--l2-claim", inputs.L2Claim.Hex(), "--l2-block-number", inputs.L2BlockNumber.Text(10), - }, nil + "-v", + } + + if s.nativeMode { + args = append(args, "--exec", s.clientBinPath) + } else { + args = append(args, "--server") + args = append(args, "--data-dir", dataDir) + } + + if cfg.RollupConfigPath != "" { + args = append(args, "--rollup-config-path", cfg.RollupConfigPath) + } else { + if cfg.Network == "" { + return nil, errors.New("network is not defined") + } + + chainCfg := chaincfg.ChainByName(cfg.Network) + args = append(args, "--l2-chain-id", strconv.FormatUint(chainCfg.ChainID, 10)) + } + + return args, nil } diff --git a/op-challenger/game/fault/trace/vm/kona_server_executor_test.go b/op-challenger/game/fault/trace/vm/kona_server_executor_test.go index 45fb5faa90408..ba690b5c08818 100644 --- a/op-challenger/game/fault/trace/vm/kona_server_executor_test.go +++ b/op-challenger/game/fault/trace/vm/kona_server_executor_test.go @@ -26,7 +26,7 @@ func TestKonaFillHostCommand(t *testing.T) { L2Claim: common.Hash{0x44}, L2BlockNumber: big.NewInt(3333), } - vmConfig := NewKonaServerExecutor() + vmConfig := NewKonaExecutor() args, err := vmConfig.OracleCommand(cfg, dir, inputs) require.NoError(t, err) diff --git a/op-challenger/game/fault/trace/vm/prestate.go b/op-challenger/game/fault/trace/vm/prestate.go new file mode 100644 index 0000000000000..bbb4a9437d9aa --- /dev/null +++ b/op-challenger/game/fault/trace/vm/prestate.go @@ -0,0 +1,42 @@ +package vm + +import ( + "context" + "fmt" + + "github.com/ethereum/go-ethereum/common" + + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" +) + +var _ types.PrestateProvider = (*PrestateProvider)(nil) + +type PrestateProvider struct { + prestate string + stateConverter StateConverter + + prestateCommitment common.Hash +} + +func NewPrestateProvider(prestate string, converter StateConverter) *PrestateProvider { + return &PrestateProvider{ + prestate: prestate, + stateConverter: converter, + } +} + +func (p *PrestateProvider) AbsolutePreStateCommitment(_ context.Context) (common.Hash, error) { + if p.prestateCommitment != (common.Hash{}) { + return p.prestateCommitment, nil + } + proof, _, _, err := p.stateConverter.ConvertStateToProof(p.prestate) + if err != nil { + return common.Hash{}, fmt.Errorf("cannot load absolute pre-state: %w", err) + } + p.prestateCommitment = proof.ClaimValue + return proof.ClaimValue, nil +} + +func (p *PrestateProvider) PrestatePath() string { + return p.prestate +} diff --git a/op-challenger/game/fault/trace/vm/prestate_test.go b/op-challenger/game/fault/trace/vm/prestate_test.go new file mode 100644 index 0000000000000..69498e323c59d --- /dev/null +++ b/op-challenger/game/fault/trace/vm/prestate_test.go @@ -0,0 +1,63 @@ +package vm + +import ( + "context" + "errors" + "path/filepath" + "testing" + + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" +) + +type stubConverter struct { + err error + hash common.Hash +} + +func (s *stubConverter) ConvertStateToProof(statePath string) (*utils.ProofData, uint64, bool, error) { + if s.err != nil { + return nil, 0, false, s.err + } + return &utils.ProofData{ + ClaimValue: s.hash, + }, 0, false, nil +} + +func newPrestateProvider(prestate common.Hash) *PrestateProvider { + return NewPrestateProvider("state.json", &stubConverter{hash: prestate}) +} + +func TestAbsolutePreStateCommitment(t *testing.T) { + prestate := common.Hash{0xaa, 0xbb} + + t.Run("StateUnavailable", func(t *testing.T) { + expectedErr := errors.New("kaboom") + provider := NewPrestateProvider("foo", &stubConverter{err: expectedErr}) + _, err := provider.AbsolutePreStateCommitment(context.Background()) + require.ErrorIs(t, err, expectedErr) + }) + + t.Run("ExpectedAbsolutePreState", func(t *testing.T) { + provider := newPrestateProvider(prestate) + actual, err := provider.AbsolutePreStateCommitment(context.Background()) + require.NoError(t, err) + require.Equal(t, prestate, actual) + }) + + t.Run("CacheAbsolutePreState", func(t *testing.T) { + converter := &stubConverter{hash: prestate} + provider := NewPrestateProvider(filepath.Join("state.json"), converter) + first, err := provider.AbsolutePreStateCommitment(context.Background()) + require.NoError(t, err) + + // Remove the prestate from disk + converter.err = errors.New("no soup for you") + + // Value should still be available from cache + cached, err := provider.AbsolutePreStateCommitment(context.Background()) + require.NoError(t, err) + require.Equal(t, first, cached) + }) +} diff --git a/op-challenger/game/fault/trace/vm/prestates.go b/op-challenger/game/fault/trace/vm/prestates.go index c51dda7de1e5b..b54d86ed9ccaf 100644 --- a/op-challenger/game/fault/trace/vm/prestates.go +++ b/op-challenger/game/fault/trace/vm/prestates.go @@ -14,16 +14,26 @@ import ( "github.com/ethereum/go-ethereum/log" ) -type SnapshotSelect func(logger log.Logger, dir string, absolutePreState string, i uint64) (string, error) +type SnapshotSelect func(logger log.Logger, dir string, absolutePreState string, i uint64, binary bool) (string, error) type CmdExecutor func(ctx context.Context, l log.Logger, binary string, args ...string) error const ( - SnapsDir = "snapshots" - PreimagesDir = "preimages" - FinalState = "final.json.gz" + SnapsDir = "snapshots" + PreimagesDir = "preimages" + finalStateJson = "final.json.gz" + finalStateBinary = "final.bin.gz" ) -var snapshotNameRegexp = regexp.MustCompile(`^[0-9]+\.json.gz$`) +func FinalStatePath(dir string, binarySnapshots bool) string { + filename := finalStateJson + if binarySnapshots { + filename = finalStateBinary + } + return filepath.Join(dir, filename) +} + +var snapshotJsonNameRegexp = regexp.MustCompile(`^[0-9]+\.json\.gz$`) +var snapshotBinaryNameRegexp = regexp.MustCompile(`^[0-9]+\.bin\.gz$`) func PreimageDir(dir string) string { return filepath.Join(dir, PreimagesDir) @@ -43,7 +53,13 @@ func RunCmd(ctx context.Context, l log.Logger, binary string, args ...string) er // FindStartingSnapshot finds the closest snapshot before the specified traceIndex in snapDir. // If no suitable snapshot can be found it returns absolutePreState. -func FindStartingSnapshot(logger log.Logger, snapDir string, absolutePreState string, traceIndex uint64) (string, error) { +func FindStartingSnapshot(logger log.Logger, snapDir string, absolutePreState string, traceIndex uint64, binarySnapshots bool) (string, error) { + suffix := ".json.gz" + nameRegexp := snapshotJsonNameRegexp + if binarySnapshots { + suffix = ".bin.gz" + nameRegexp = snapshotBinaryNameRegexp + } // Find the closest snapshot to start from entries, err := os.ReadDir(snapDir) if err != nil { @@ -59,11 +75,11 @@ func FindStartingSnapshot(logger log.Logger, snapDir string, absolutePreState st continue } name := entry.Name() - if !snapshotNameRegexp.MatchString(name) { + if !nameRegexp.MatchString(name) { logger.Warn("Unexpected file in snapshots dir", "parent", snapDir, "child", entry.Name()) continue } - index, err := strconv.ParseUint(name[0:len(name)-len(".json.gz")], 10, 64) + index, err := strconv.ParseUint(name[0:len(name)-len(suffix)], 10, 64) if err != nil { logger.Error("Unable to parse trace index of snapshot file", "parent", snapDir, "child", entry.Name()) continue @@ -75,7 +91,7 @@ func FindStartingSnapshot(logger log.Logger, snapDir string, absolutePreState st if bestSnap == 0 { return absolutePreState, nil } - startFrom := fmt.Sprintf("%v/%v.json.gz", snapDir, bestSnap) + startFrom := fmt.Sprintf("%v/%v%v", snapDir, bestSnap, suffix) return startFrom, nil } diff --git a/op-challenger/game/fault/types/types.go b/op-challenger/game/fault/types/types.go index 93c8b19bd5425..46227668e9285 100644 --- a/op-challenger/game/fault/types/types.go +++ b/op-challenger/game/fault/types/types.go @@ -67,7 +67,7 @@ const ( TraceTypePermissioned TraceType = "permissioned" ) -var TraceTypes = []TraceType{TraceTypeAlphabet, TraceTypeCannon, TraceTypePermissioned, TraceTypeAsterisc, TraceTypeFast} +var TraceTypes = []TraceType{TraceTypeAlphabet, TraceTypeCannon, TraceTypePermissioned, TraceTypeAsterisc, TraceTypeAsteriscKona, TraceTypeFast} func (t TraceType) String() string { return string(t) @@ -104,6 +104,8 @@ func (t TraceType) GameType() GameType { return PermissionedGameType case TraceTypeAsterisc: return AsteriscGameType + case TraceTypeAsteriscKona: + return AsteriscKonaGameType case TraceTypeFast: return FastGameType case TraceTypeAlphabet: diff --git a/op-challenger/metrics/metrics.go b/op-challenger/metrics/metrics.go index fdea90841a043..c6acc2b2f7bbf 100644 --- a/op-challenger/metrics/metrics.go +++ b/op-challenger/metrics/metrics.go @@ -38,8 +38,6 @@ type Metricer interface { RecordGameStep() RecordGameMove() RecordGameL2Challenge() - RecordVmExecutionTime(vmType string, t time.Duration) - RecordVmMemoryUsed(vmType string, memoryUsed uint64) RecordClaimResolutionTime(t float64) RecordGameActTime(t float64) @@ -60,6 +58,10 @@ type Metricer interface { DecActiveExecutors() IncIdleExecutors() DecIdleExecutors() + + // Record vm execution metrics + VmMetricer + VmMetrics(vmType string) *VmMetrics } // Metrics implementation must implement RegistryMetricer to allow the metrics server to work. @@ -339,3 +341,7 @@ func (m *Metrics) RecordGameUpdateScheduled() { func (m *Metrics) RecordGameUpdateCompleted() { m.inflightGames.Sub(1) } + +func (m *Metrics) VmMetrics(vmType string) *VmMetrics { + return NewVmMetrics(m, vmType) +} diff --git a/op-challenger/metrics/noop.go b/op-challenger/metrics/noop.go index 99a89965aa213..84b5923a33d98 100644 --- a/op-challenger/metrics/noop.go +++ b/op-challenger/metrics/noop.go @@ -56,3 +56,7 @@ func (*NoopMetricsImpl) DecIdleExecutors() {} func (*NoopMetricsImpl) CacheAdd(_ string, _ int, _ bool) {} func (*NoopMetricsImpl) CacheGet(_ string, _ bool) {} + +func (m *NoopMetricsImpl) VmMetrics(vmType string) *VmMetrics { + return NewVmMetrics(m, vmType) +} diff --git a/op-challenger/metrics/vm.go b/op-challenger/metrics/vm.go new file mode 100644 index 0000000000000..70e9a363cb368 --- /dev/null +++ b/op-challenger/metrics/vm.go @@ -0,0 +1,28 @@ +package metrics + +import "time" + +type VmMetricer interface { + RecordVmExecutionTime(vmType string, t time.Duration) + RecordVmMemoryUsed(vmType string, memoryUsed uint64) +} + +type VmMetrics struct { + m VmMetricer + vmType string +} + +func NewVmMetrics(m VmMetricer, vmType string) *VmMetrics { + return &VmMetrics{ + m: m, + vmType: vmType, + } +} + +func (m *VmMetrics) RecordExecutionTime(dur time.Duration) { + m.m.RecordVmExecutionTime(m.vmType, dur) +} + +func (m *VmMetrics) RecordMemoryUsed(memoryUsed uint64) { + m.m.RecordVmMemoryUsed(m.vmType, memoryUsed) +} diff --git a/op-challenger/runner/factory.go b/op-challenger/runner/factory.go index dae0a3fce1460..898afdbbf1b7a 100644 --- a/op-challenger/runner/factory.go +++ b/op-challenger/runner/factory.go @@ -29,37 +29,63 @@ func createTraceProvider( switch traceType { case types.TraceTypeCannon: vmConfig := vm.NewOpProgramServerExecutor() - prestate, err := getPrestate(prestateHash, cfg.CannonAbsolutePreStateBaseURL, cfg.CannonAbsolutePreState, dir) + stateConverter := cannon.NewStateConverter() + prestate, err := getPrestate(prestateHash, cfg.CannonAbsolutePreStateBaseURL, cfg.CannonAbsolutePreState, dir, stateConverter) if err != nil { return nil, err } - prestateProvider := cannon.NewPrestateProvider(prestate) + prestateProvider := vm.NewPrestateProvider(prestate, stateConverter) return cannon.NewTraceProvider(logger, m, cfg.Cannon, vmConfig, prestateProvider, prestate, localInputs, dir, 42), nil case types.TraceTypeAsterisc: vmConfig := vm.NewOpProgramServerExecutor() - prestate, err := getPrestate(prestateHash, cfg.AsteriscAbsolutePreStateBaseURL, cfg.AsteriscAbsolutePreState, dir) + stateConverter := asterisc.NewStateConverter() + prestate, err := getPrestate(prestateHash, cfg.AsteriscAbsolutePreStateBaseURL, cfg.AsteriscAbsolutePreState, dir, stateConverter) if err != nil { return nil, err } - prestateProvider := asterisc.NewPrestateProvider(prestate) + prestateProvider := vm.NewPrestateProvider(prestate, stateConverter) return asterisc.NewTraceProvider(logger, m, cfg.Asterisc, vmConfig, prestateProvider, prestate, localInputs, dir, 42), nil case types.TraceTypeAsteriscKona: - vmConfig := vm.NewKonaServerExecutor() - prestate, err := getPrestate(prestateHash, cfg.AsteriscAbsolutePreStateBaseURL, cfg.AsteriscAbsolutePreState, dir) + vmConfig := vm.NewKonaExecutor() + stateConverter := asterisc.NewStateConverter() + prestate, err := getPrestate(prestateHash, cfg.AsteriscKonaAbsolutePreStateBaseURL, cfg.AsteriscKonaAbsolutePreState, dir, stateConverter) if err != nil { return nil, err } - prestateProvider := asterisc.NewPrestateProvider(prestate) - return asterisc.NewTraceProvider(logger, m, cfg.Asterisc, vmConfig, prestateProvider, prestate, localInputs, dir, 42), nil + prestateProvider := vm.NewPrestateProvider(prestate, stateConverter) + return asterisc.NewTraceProvider(logger, m, cfg.AsteriscKona, vmConfig, prestateProvider, prestate, localInputs, dir, 42), nil } return nil, errors.New("invalid trace type") } -func getPrestate(prestateHash common.Hash, prestateBaseUrl *url.URL, prestatePath string, dataDir string) (string, error) { +func createMTTraceProvider( + logger log.Logger, + m vm.Metricer, + vmConfig vm.Config, + prestateHash common.Hash, + absolutePrestateBaseURL *url.URL, + traceType types.TraceType, + localInputs utils.LocalGameInputs, + dir string, +) (types.TraceProvider, error) { + executor := vm.NewOpProgramServerExecutor() + stateConverter := cannon.NewStateConverter() + + prestateSource := prestates.NewMultiPrestateProvider(absolutePrestateBaseURL, filepath.Join(dir, "prestates"), cannon.NewStateConverter()) + prestatePath, err := prestateSource.PrestatePath(prestateHash) + if err != nil { + return nil, fmt.Errorf("failed to get prestate %v: %w", prestateHash, err) + } + prestateProvider := vm.NewPrestateProvider(prestatePath, stateConverter) + return cannon.NewTraceProvider(logger, m, vmConfig, executor, prestateProvider, prestatePath, localInputs, dir, 42), nil +} + +func getPrestate(prestateHash common.Hash, prestateBaseUrl *url.URL, prestatePath string, dataDir string, stateConverter vm.StateConverter) (string, error) { prestateSource := prestates.NewPrestateSource( prestateBaseUrl, prestatePath, - filepath.Join(dataDir, "prestates")) + filepath.Join(dataDir, "prestates"), + stateConverter) prestate, err := prestateSource.PrestatePath(prestateHash) if err != nil { diff --git a/op-challenger/runner/metrics.go b/op-challenger/runner/metrics.go index e15ad95adc1bf..1f347b62aa685 100644 --- a/op-challenger/runner/metrics.go +++ b/op-challenger/runner/metrics.go @@ -4,7 +4,6 @@ import ( "time" contractMetrics "github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts/metrics" - "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" opmetrics "github.com/ethereum-optimism/optimism/op-service/metrics" "github.com/prometheus/client_golang/prometheus" ) @@ -100,14 +99,14 @@ func (m *Metrics) RecordVmMemoryUsed(vmType string, memoryUsed uint64) { m.vmLastMemoryUsed.WithLabelValues(vmType).Set(float64(memoryUsed)) } -func (m *Metrics) RecordSuccess(vmType types.TraceType) { - m.successTotal.WithLabelValues(vmType.String()).Inc() +func (m *Metrics) RecordSuccess(vmType string) { + m.successTotal.WithLabelValues(vmType).Inc() } -func (m *Metrics) RecordFailure(vmType types.TraceType) { - m.failuresTotal.WithLabelValues(vmType.String()).Inc() +func (m *Metrics) RecordFailure(vmType string) { + m.failuresTotal.WithLabelValues(vmType).Inc() } -func (m *Metrics) RecordInvalid(vmType types.TraceType) { - m.invalidTotal.WithLabelValues(vmType.String()).Inc() +func (m *Metrics) RecordInvalid(vmType string) { + m.invalidTotal.WithLabelValues(vmType).Inc() } diff --git a/op-challenger/runner/runner.go b/op-challenger/runner/runner.go index 8c46f0f0a6bf5..61fc8180905f6 100644 --- a/op-challenger/runner/runner.go +++ b/op-challenger/runner/runner.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "math/big" + "net/url" "os" "path/filepath" "sync" @@ -16,8 +17,8 @@ import ( "github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts" contractMetrics "github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts/metrics" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils" - "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/vm" "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/cliapp" "github.com/ethereum-optimism/optimism/op-service/dial" "github.com/ethereum-optimism/optimism/op-service/httputil" @@ -28,23 +29,28 @@ import ( "github.com/ethereum/go-ethereum/log" ) +const mtCannonType = "mt-cannon" + var ( ErrUnexpectedStatusCode = errors.New("unexpected status code") ) type Metricer interface { - vm.Metricer contractMetrics.ContractMetricer - RecordFailure(vmType types.TraceType) - RecordInvalid(vmType types.TraceType) - RecordSuccess(vmType types.TraceType) + RecordVmExecutionTime(vmType string, t time.Duration) + RecordVmMemoryUsed(vmType string, memoryUsed uint64) + RecordFailure(vmType string) + RecordInvalid(vmType string) + RecordSuccess(vmType string) } type Runner struct { - log log.Logger - cfg *config.Config - m Metricer + log log.Logger + cfg *config.Config + addMTCannonPrestate common.Hash + addMTCannonPrestateURL *url.URL + m Metricer running atomic.Bool ctx context.Context @@ -53,11 +59,13 @@ type Runner struct { metricsSrv *httputil.HTTPServer } -func NewRunner(logger log.Logger, cfg *config.Config) *Runner { +func NewRunner(logger log.Logger, cfg *config.Config, mtCannonPrestate common.Hash, mtCannonPrestateURL *url.URL) *Runner { return &Runner{ - log: logger, - cfg: cfg, - m: NewMetrics(), + log: logger, + cfg: cfg, + addMTCannonPrestate: mtCannonPrestate, + addMTCannonPrestateURL: mtCannonPrestateURL, + m: NewMetrics(), } } @@ -97,16 +105,7 @@ func (r *Runner) loop(ctx context.Context, traceType types.TraceType, client *so t := time.NewTicker(1 * time.Minute) defer t.Stop() for { - if err := r.runOnce(ctx, traceType, client, caller); errors.Is(err, ErrUnexpectedStatusCode) { - r.log.Error("Incorrect status code", "type", traceType, "err", err) - r.m.RecordInvalid(traceType) - } else if err != nil { - r.log.Error("Failed to run", "type", traceType, "err", err) - r.m.RecordFailure(traceType) - } else { - r.log.Info("Successfully verified output root", "type", traceType) - r.m.RecordSuccess(traceType) - } + r.runAndRecordOnce(ctx, traceType, client, caller) select { case <-t.C: case <-ctx.Done(): @@ -115,22 +114,80 @@ func (r *Runner) loop(ctx context.Context, traceType types.TraceType, client *so } } -func (r *Runner) runOnce(ctx context.Context, traceType types.TraceType, client *sources.RollupClient, caller *batching.MultiCaller) error { +func (r *Runner) runAndRecordOnce(ctx context.Context, traceType types.TraceType, client *sources.RollupClient, caller *batching.MultiCaller) { + recordError := func(err error, traceType string, m Metricer, log log.Logger) { + if errors.Is(err, ErrUnexpectedStatusCode) { + log.Error("Incorrect status code", "type", traceType, "err", err) + m.RecordInvalid(traceType) + } else if err != nil { + log.Error("Failed to run", "type", traceType, "err", err) + m.RecordFailure(traceType) + } else { + log.Info("Successfully verified output root", "type", traceType) + m.RecordSuccess(traceType) + } + } + prestateHash, err := r.getPrestateHash(ctx, traceType, caller) if err != nil { - return err + recordError(err, traceType.String(), r.m, r.log) + return } localInputs, err := r.createGameInputs(ctx, client) if err != nil { - return err + recordError(err, traceType.String(), r.m, r.log) + return } - dir, err := r.prepDatadir(traceType) + + inputsLogger := r.log.New("l1", localInputs.L1Head, "l2", localInputs.L2Head, "l2Block", localInputs.L2BlockNumber, "claim", localInputs.L2Claim) + var wg sync.WaitGroup + wg.Add(1) + go func() { + defer wg.Done() + dir, err := r.prepDatadir(traceType.String()) + if err != nil { + recordError(err, traceType.String(), r.m, r.log) + return + } + err = r.runOnce(ctx, inputsLogger.With("type", traceType), traceType, prestateHash, localInputs, dir) + recordError(err, traceType.String(), r.m, r.log) + }() + + if traceType == types.TraceTypeCannon && r.addMTCannonPrestate != (common.Hash{}) && r.addMTCannonPrestateURL != nil { + wg.Add(1) + go func() { + defer wg.Done() + dir, err := r.prepDatadir(mtCannonType) + if err != nil { + recordError(err, mtCannonType, r.m, r.log) + return + } + logger := inputsLogger.With("type", mtCannonType) + err = r.runMTOnce(ctx, logger, localInputs, dir) + recordError(err, mtCannonType, r.m, r.log.With(mtCannonType, true)) + }() + } + wg.Wait() +} + +func (r *Runner) runOnce(ctx context.Context, logger log.Logger, traceType types.TraceType, prestateHash common.Hash, localInputs utils.LocalGameInputs, dir string) error { + provider, err := createTraceProvider(logger, metrics.NewVmMetrics(r.m, traceType.String()), r.cfg, prestateHash, traceType, localInputs, dir) if err != nil { - return err + return fmt.Errorf("failed to create trace provider: %w", err) + } + hash, err := provider.Get(ctx, types.RootPosition) + if err != nil { + return fmt.Errorf("failed to execute trace provider: %w", err) } - logger := r.log.New("l1", localInputs.L1Head, "l2", localInputs.L2Head, "l2Block", localInputs.L2BlockNumber, "claim", localInputs.L2Claim, "type", traceType) - provider, err := createTraceProvider(logger, r.m, r.cfg, prestateHash, traceType, localInputs, dir) + if hash[0] != mipsevm.VMStatusValid { + return fmt.Errorf("%w: %v", ErrUnexpectedStatusCode, hash) + } + return nil +} + +func (r *Runner) runMTOnce(ctx context.Context, logger log.Logger, localInputs utils.LocalGameInputs, dir string) error { + provider, err := createMTTraceProvider(logger, metrics.NewVmMetrics(r.m, mtCannonType), r.cfg.Cannon, r.addMTCannonPrestate, r.addMTCannonPrestateURL, types.TraceTypeCannon, localInputs, dir) if err != nil { return fmt.Errorf("failed to create trace provider: %w", err) } @@ -144,8 +201,8 @@ func (r *Runner) runOnce(ctx context.Context, traceType types.TraceType, client return nil } -func (r *Runner) prepDatadir(traceType types.TraceType) (string, error) { - dir := filepath.Join(r.cfg.Datadir, traceType.String()) +func (r *Runner) prepDatadir(traceType string) (string, error) { + dir := filepath.Join(r.cfg.Datadir, traceType) if err := os.RemoveAll(dir); err != nil { return "", fmt.Errorf("failed to remove old dir: %w", err) } diff --git a/op-challenger/sender/sender_test.go b/op-challenger/sender/sender_test.go index 2e0f09830605c..5169ae67192ad 100644 --- a/op-challenger/sender/sender_test.go +++ b/op-challenger/sender/sender_test.go @@ -3,6 +3,7 @@ package sender import ( "context" "fmt" + "math/big" "sync" "testing" "time" @@ -128,6 +129,10 @@ func (s *stubTxMgr) Send(ctx context.Context, candidate txmgr.TxCandidate) (*typ return <-ch, nil } +func (s *stubTxMgr) SendAsync(ctx context.Context, candidate txmgr.TxCandidate, ch chan txmgr.SendResponse) { + panic("unimplemented") +} + func (s *stubTxMgr) recordTx(candidate txmgr.TxCandidate) chan *types.Receipt { s.m.Lock() defer s.m.Unlock() @@ -177,3 +182,7 @@ func (s *stubTxMgr) API() rpc.API { func (s *stubTxMgr) Close() { } + +func (s *stubTxMgr) SuggestGasPriceCaps(context.Context) (*big.Int, *big.Int, *big.Int, error) { + panic("unimplemented") +} diff --git a/op-conductor/cmd/main.go b/op-conductor/cmd/main.go index 508ffe220df02..3497e85f7917a 100644 --- a/op-conductor/cmd/main.go +++ b/op-conductor/cmd/main.go @@ -12,8 +12,8 @@ import ( "github.com/ethereum-optimism/optimism/op-conductor/flags" opservice "github.com/ethereum-optimism/optimism/op-service" "github.com/ethereum-optimism/optimism/op-service/cliapp" + "github.com/ethereum-optimism/optimism/op-service/ctxinterrupt" oplog "github.com/ethereum-optimism/optimism/op-service/log" - "github.com/ethereum-optimism/optimism/op-service/opio" ) var ( @@ -34,7 +34,7 @@ func main() { app.Action = cliapp.LifecycleCmd(OpConductorMain) app.Commands = []*cli.Command{} - ctx := opio.WithInterruptBlocker(context.Background()) + ctx := ctxinterrupt.WithSignalWaiterMain(context.Background()) err := app.RunContext(ctx, os.Args) if err != nil { log.Crit("Application failed", "message", err) diff --git a/op-conductor/conductor/config.go b/op-conductor/conductor/config.go index 2d356a6553e1b..ca18de7d1a18f 100644 --- a/op-conductor/conductor/config.go +++ b/op-conductor/conductor/config.go @@ -3,6 +3,7 @@ package conductor import ( "fmt" "math" + "time" "github.com/ethereum/go-ethereum/log" "github.com/pkg/errors" @@ -33,6 +34,15 @@ type Config struct { // RaftBootstrap is true if this node should bootstrap a new raft cluster. RaftBootstrap bool + // RaftSnapshotInterval is the interval to check if a snapshot should be taken. + RaftSnapshotInterval time.Duration + + // RaftSnapshotThreshold is the number of logs to trigger a snapshot. + RaftSnapshotThreshold uint64 + + // RaftTrailingLogs is the number of logs to keep after a snapshot. + RaftTrailingLogs uint64 + // NodeRPC is the HTTP provider URL for op-node. NodeRPC string @@ -107,14 +117,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), + 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), + RaftSnapshotInterval: ctx.Duration(flags.RaftSnapshotInterval.Name), + RaftSnapshotThreshold: ctx.Uint64(flags.RaftSnapshotThreshold.Name), + RaftTrailingLogs: ctx.Uint64(flags.RaftTrailingLogs.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), UnsafeInterval: ctx.Uint64(flags.HealthCheckUnsafeInterval.Name), diff --git a/op-conductor/conductor/service.go b/op-conductor/conductor/service.go index a1ccef871538a..d2eb4fe89d9dc 100644 --- a/op-conductor/conductor/service.go +++ b/op-conductor/conductor/service.go @@ -149,7 +149,17 @@ func (c *OpConductor) initConsensus(ctx context.Context) error { } serverAddr := fmt.Sprintf("%s:%d", c.cfg.ConsensusAddr, c.cfg.ConsensusPort) - cons, err := consensus.NewRaftConsensus(c.log, c.cfg.RaftServerID, serverAddr, c.cfg.RaftStorageDir, c.cfg.RaftBootstrap, &c.cfg.RollupCfg) + raftConsensusConfig := &consensus.RaftConsensusConfig{ + ServerID: c.cfg.RaftServerID, + ServerAddr: serverAddr, + StorageDir: c.cfg.RaftStorageDir, + Bootstrap: c.cfg.RaftBootstrap, + RollupCfg: &c.cfg.RollupCfg, + SnapshotInterval: c.cfg.RaftSnapshotInterval, + SnapshotThreshold: c.cfg.RaftSnapshotThreshold, + TrailingLogs: c.cfg.RaftTrailingLogs, + } + cons, err := consensus.NewRaftConsensus(c.log, raftConsensusConfig) if err != nil { return errors.Wrap(err, "failed to create raft consensus") } @@ -647,9 +657,12 @@ func (oc *OpConductor) action() { 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, "status", status) - time.Sleep(oc.retryBackoff()) - oc.queueAction() + select { + case <-oc.shutdownCtx.Done(): + case <-time.After(oc.retryBackoff()): + oc.log.Error("failed to execute step, queueing another one to retry", "err", err, "status", status) + oc.queueAction() + } return } @@ -683,18 +696,33 @@ 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()) - - _, err := oc.ctrl.StopSequencer(context.Background()) - if err != nil { + oc.log.Info( + "stopping sequencer", + "server", oc.cons.ServerID(), + "leader", oc.leader.Load(), + "healthy", oc.healthy.Load(), + "active", oc.seqActive.Load()) + + // Quoting (@zhwrd): StopSequencer is called after conductor loses leadership. In the event that + // the StopSequencer call fails, it actually has little real consequences because the sequencer + // cant produce a block and gossip / commit it to the raft log (requires leadership). Once + // conductor comes back up it will check its leader and sequencer state and attempt to stop the + // sequencer again. So it is "okay" to fail to stop a sequencer, the state will eventually be + // rectified and we won't have two active sequencers that are actually producing blocks. + // + // To that end we allow to cancel the StopSequencer call if we're shutting down. + latestHead, err := oc.ctrl.StopSequencer(oc.shutdownCtx) + if err == nil { + // None of the consensus state should have changed here so don't log it again. + oc.log.Info("stopped sequencer", "latestHead", latestHead) + } else { if strings.Contains(err.Error(), driver.ErrSequencerAlreadyStopped.Error()) { - oc.log.Warn("sequencer already stopped.", "err", err) + oc.log.Warn("sequencer already stopped", "err", err) } else { return errors.Wrap(err, "failed to stop sequencer") } } oc.metrics.RecordStopSequencer(err == nil) - oc.seqActive.Store(false) return nil } diff --git a/op-conductor/consensus/raft.go b/op-conductor/consensus/raft.go index c534d03058478..f6acc0fb76f17 100644 --- a/op-conductor/consensus/raft.go +++ b/op-conductor/consensus/raft.go @@ -32,6 +32,17 @@ type RaftConsensus struct { unsafeTracker *unsafeHeadTracker } +type RaftConsensusConfig struct { + ServerID string + ServerAddr string + StorageDir string + Bootstrap bool + RollupCfg *rollup.Config + SnapshotInterval time.Duration + SnapshotThreshold uint64 + TrailingLogs uint64 +} + // checkTCPPortOpen attempts to connect to the specified address and returns an error if the connection fails. func checkTCPPortOpen(address string) error { conn, err := net.DialTimeout("tcp", address, 5*time.Second) @@ -43,11 +54,14 @@ func checkTCPPortOpen(address string) error { } // NewRaftConsensus creates a new RaftConsensus instance. -func NewRaftConsensus(log log.Logger, serverID, serverAddr, storageDir string, bootstrap bool, rollupCfg *rollup.Config) (*RaftConsensus, error) { +func NewRaftConsensus(log log.Logger, cfg *RaftConsensusConfig) (*RaftConsensus, error) { rc := raft.DefaultConfig() - rc.LocalID = raft.ServerID(serverID) + rc.SnapshotInterval = cfg.SnapshotInterval + rc.TrailingLogs = cfg.TrailingLogs + rc.SnapshotThreshold = cfg.SnapshotThreshold + rc.LocalID = raft.ServerID(cfg.ServerID) - baseDir := filepath.Join(storageDir, serverID) + baseDir := filepath.Join(cfg.StorageDir, cfg.ServerID) if _, err := os.Stat(baseDir); os.IsNotExist(err) { if err := os.MkdirAll(baseDir, 0o755); err != nil { return nil, fmt.Errorf("error creating storage dir: %w", err) @@ -72,7 +86,7 @@ func NewRaftConsensus(log log.Logger, serverID, serverAddr, storageDir string, b return nil, fmt.Errorf(`raft.NewFileSnapshotStore(%q): %w`, baseDir, err) } - addr, err := net.ResolveTCPAddr("tcp", serverAddr) + addr, err := net.ResolveTCPAddr("tcp", cfg.ServerAddr) if err != nil { return nil, errors.Wrap(err, "failed to resolve tcp address") } @@ -95,18 +109,18 @@ func NewRaftConsensus(log log.Logger, serverID, serverAddr, storageDir string, b // 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{ + if cfg.Bootstrap { + raftCfg := raft.Configuration{ Servers: []raft.Server{ { ID: rc.LocalID, - Address: raft.ServerAddress(serverAddr), + Address: raft.ServerAddress(cfg.ServerAddr), Suffrage: raft.Voter, }, }, } - f := r.BootstrapCluster(cfg) + f := r.BootstrapCluster(raftCfg) if err := f.Error(); err != nil { return nil, errors.Wrap(err, "failed to bootstrap raft cluster") } @@ -115,9 +129,9 @@ func NewRaftConsensus(log log.Logger, serverID, serverAddr, storageDir string, b return &RaftConsensus{ log: log, r: r, - serverID: raft.ServerID(serverID), + serverID: raft.ServerID(cfg.ServerID), unsafeTracker: fsm, - rollupCfg: rollupCfg, + rollupCfg: cfg.RollupCfg, }, nil } diff --git a/op-conductor/consensus/raft_fsm.go b/op-conductor/consensus/raft_fsm.go index 31631d2c91e61..28c85c36d904b 100644 --- a/op-conductor/consensus/raft_fsm.go +++ b/op-conductor/consensus/raft_fsm.go @@ -29,7 +29,7 @@ func NewUnsafeHeadTracker(log log.Logger) *unsafeHeadTracker { // Apply implements raft.FSM, it applies the latest change (latest unsafe head payload) to FSM. func (t *unsafeHeadTracker) Apply(l *raft.Log) interface{} { - if l.Data == nil || len(l.Data) == 0 { + if len(l.Data) == 0 { return fmt.Errorf("log data is nil or empty") } diff --git a/op-conductor/consensus/raft_test.go b/op-conductor/consensus/raft_test.go index 332bbd203e7e6..fbd9c7cb3bc81 100644 --- a/op-conductor/consensus/raft_test.go +++ b/op-conductor/consensus/raft_test.go @@ -18,9 +18,6 @@ import ( func TestCommitAndRead(t *testing.T) { log := testlog.Logger(t, log.LevelInfo) - serverID := "SequencerA" - serverAddr := "127.0.0.1:0" - bootstrap := true now := uint64(time.Now().Unix()) rollupCfg := &rollup.Config{ CanyonTime: &now, @@ -29,8 +26,18 @@ func TestCommitAndRead(t *testing.T) { if err := os.RemoveAll(storageDir); err != nil { t.Fatal(err) } + raftConsensusConfig := &RaftConsensusConfig{ + ServerID: "SequencerA", + ServerAddr: "127.0.0.1:0", + StorageDir: storageDir, + Bootstrap: true, + RollupCfg: rollupCfg, + SnapshotInterval: 120 * time.Second, + SnapshotThreshold: 10240, + TrailingLogs: 8192, + } - cons, err := NewRaftConsensus(log, serverID, serverAddr, storageDir, bootstrap, rollupCfg) + cons, err := NewRaftConsensus(log, raftConsensusConfig) require.NoError(t, err) // wait till it became leader diff --git a/op-conductor/flags/flags.go b/op-conductor/flags/flags.go index 4870ba4a3ab03..249e8a676e079 100644 --- a/op-conductor/flags/flags.go +++ b/op-conductor/flags/flags.go @@ -2,6 +2,7 @@ package flags import ( "fmt" + "time" "github.com/urfave/cli/v2" @@ -44,6 +45,24 @@ var ( Usage: "Directory to store raft data", EnvVars: opservice.PrefixEnvVar(EnvVarPrefix, "RAFT_STORAGE_DIR"), } + RaftSnapshotInterval = &cli.DurationFlag{ + Name: "raft.snapshot-interval", + Usage: "The interval to check if a snapshot should be taken.", + EnvVars: opservice.PrefixEnvVar(EnvVarPrefix, "RAFT_SNAPSHOT_INTERVAL"), + Value: 120 * time.Second, + } + RaftSnapshotThreshold = &cli.Uint64Flag{ + Name: "raft.snapshot-threshold", + Usage: "Number of logs to trigger a snapshot", + EnvVars: opservice.PrefixEnvVar(EnvVarPrefix, "RAFT_SNAPSHOT_THRESHOLD"), + Value: 8192, + } + RaftTrailingLogs = &cli.Uint64Flag{ + Name: "raft.trailing-logs", + Usage: "Number of logs to keep after a snapshot", + EnvVars: opservice.PrefixEnvVar(EnvVarPrefix, "RAFT_TRAILING_LOGS"), + Value: 10240, + } NodeRPC = &cli.StringFlag{ Name: "node.rpc", Usage: "HTTP provider URL for op-node", @@ -113,6 +132,9 @@ var optionalFlags = []cli.Flag{ RaftBootstrap, HealthCheckSafeEnabled, HealthCheckSafeInterval, + RaftSnapshotInterval, + RaftSnapshotThreshold, + RaftTrailingLogs, } func init() { diff --git a/op-dispute-mon/cmd/main.go b/op-dispute-mon/cmd/main.go index 4b2c1f46bd173..619fad23592e7 100644 --- a/op-dispute-mon/cmd/main.go +++ b/op-dispute-mon/cmd/main.go @@ -14,8 +14,8 @@ import ( "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" + "github.com/ethereum-optimism/optimism/op-service/ctxinterrupt" oplog "github.com/ethereum-optimism/optimism/op-service/log" - "github.com/ethereum-optimism/optimism/op-service/opio" ) var ( @@ -28,7 +28,7 @@ var VersionWithMeta = opservice.FormatVersion(version.Version, GitCommit, GitDat func main() { args := os.Args - ctx := opio.WithInterruptBlocker(context.Background()) + ctx := ctxinterrupt.WithSignalWaiterMain(context.Background()) if err := run(ctx, args, monitor.Main); err != nil { log.Crit("Application failed", "err", err) } diff --git a/op-dispute-mon/mon/bonds/monitor.go b/op-dispute-mon/mon/bonds/monitor.go index efa7804d34085..2ce23dc472e74 100644 --- a/op-dispute-mon/mon/bonds/monitor.go +++ b/op-dispute-mon/mon/bonds/monitor.go @@ -17,22 +17,19 @@ type RClock interface { type BondMetrics interface { RecordCredit(expectation metrics.CreditExpectation, count int) RecordBondCollateral(addr common.Address, required *big.Int, available *big.Int) - RecordHonestWithdrawableAmounts(map[common.Address]*big.Int) } type Bonds struct { - logger log.Logger - clock RClock - metrics BondMetrics - honestActors types.HonestActors + logger log.Logger + clock RClock + metrics BondMetrics } -func NewBonds(logger log.Logger, metrics BondMetrics, honestActors types.HonestActors, clock RClock) *Bonds { +func NewBonds(logger log.Logger, metrics BondMetrics, clock RClock) *Bonds { return &Bonds{ - logger: logger, - clock: clock, - metrics: metrics, - honestActors: honestActors, + logger: logger, + clock: clock, + metrics: metrics, } } @@ -50,10 +47,6 @@ func (b *Bonds) CheckBonds(games []*types.EnrichedGameData) { func (b *Bonds) checkCredits(games []*types.EnrichedGameData) { creditMetrics := make(map[metrics.CreditExpectation]int) - honestWithdrawableAmounts := make(map[common.Address]*big.Int) - for address := range b.honestActors { - honestWithdrawableAmounts[address] = big.NewInt(0) - } for _, game := range games { // Check if the max duration has been reached for this game @@ -101,12 +94,6 @@ func (b *Bonds) checkCredits(games []*types.EnrichedGameData) { } comparison := actual.Cmp(expected) if maxDurationReached { - if actual.Cmp(big.NewInt(0)) > 0 && b.honestActors.Contains(recipient) { - total := honestWithdrawableAmounts[recipient] - total = new(big.Int).Add(total, actual) - honestWithdrawableAmounts[recipient] = total - b.logger.Warn("Found unclaimed credit", "recipient", recipient, "game", game.Proxy, "amount", actual) - } if comparison > 0 { creditMetrics[metrics.CreditAboveWithdrawable] += 1 b.logger.Warn("Credit above expected amount", "recipient", recipient, "expected", expected, "actual", actual, "game", game.Proxy, "withdrawable", "withdrawable") @@ -136,5 +123,4 @@ func (b *Bonds) checkCredits(games []*types.EnrichedGameData) { b.metrics.RecordCredit(metrics.CreditBelowNonWithdrawable, creditMetrics[metrics.CreditBelowNonWithdrawable]) b.metrics.RecordCredit(metrics.CreditEqualNonWithdrawable, creditMetrics[metrics.CreditEqualNonWithdrawable]) b.metrics.RecordCredit(metrics.CreditAboveNonWithdrawable, creditMetrics[metrics.CreditAboveNonWithdrawable]) - b.metrics.RecordHonestWithdrawableAmounts(honestWithdrawableAmounts) } diff --git a/op-dispute-mon/mon/bonds/monitor_test.go b/op-dispute-mon/mon/bonds/monitor_test.go index 5fd766b870613..dbeddd74d9c71 100644 --- a/op-dispute-mon/mon/bonds/monitor_test.go +++ b/op-dispute-mon/mon/bonds/monitor_test.go @@ -17,10 +17,7 @@ import ( ) var ( - frozen = time.Unix(int64(time.Hour.Seconds()), 0) - honestActor1 = common.Address{0x11, 0xaa} - honestActor2 = common.Address{0x22, 0xbb} - honestActor3 = common.Address{0x33, 0xcc} + frozen = time.Unix(int64(time.Hour.Seconds()), 0) ) func TestCheckBonds(t *testing.T) { @@ -64,8 +61,8 @@ func TestCheckBonds(t *testing.T) { } func TestCheckRecipientCredit(t *testing.T) { - addr1 := honestActor1 - addr2 := honestActor2 + addr1 := common.Address{0x11, 0xaa} + addr2 := common.Address{0x22, 0xbb} addr3 := common.Address{0x3c} addr4 := common.Address{0x4d} notRootPosition := types.NewPositionFromGIndex(big.NewInt(2)) @@ -349,14 +346,6 @@ func TestCheckRecipientCredit(t *testing.T) { require.Equal(t, 2, m.credits[metrics.CreditEqualNonWithdrawable], "CreditEqualNonWithdrawable") require.Equal(t, 2, m.credits[metrics.CreditAboveNonWithdrawable], "CreditAboveNonWithdrawable") - require.Len(t, m.honestWithdrawable, 3) - requireBigInt := func(name string, expected, actual *big.Int) { - require.Truef(t, expected.Cmp(actual) == 0, "Expected %v withdrawable to be %v but was %v", name, expected, actual) - } - requireBigInt("honest addr1", m.honestWithdrawable[addr1], big.NewInt(19)) - requireBigInt("honest addr2", m.honestWithdrawable[addr2], big.NewInt(13)) - requireBigInt("honest addr3", m.honestWithdrawable[honestActor3], big.NewInt(0)) - // Logs from game1 // addr1 is correct so has no logs // addr2 is below expected before max duration, so warn about early withdrawal @@ -382,18 +371,8 @@ func TestCheckRecipientCredit(t *testing.T) { testlog.NewAttributesFilter("withdrawable", "non_withdrawable"))) // Logs from game 2 - // addr1 is below expected - no warning as withdrawals may now be possible, but has unclaimed credit - require.NotNil(t, logs.FindLog( - testlog.NewLevelFilter(log.LevelWarn), - testlog.NewMessageFilter("Found unclaimed credit"), - testlog.NewAttributesFilter("game", game2.Proxy.Hex()), - testlog.NewAttributesFilter("recipient", addr1.Hex()))) - // addr2 is correct but has unclaimed credit - require.NotNil(t, logs.FindLog( - testlog.NewLevelFilter(log.LevelWarn), - testlog.NewMessageFilter("Found unclaimed credit"), - testlog.NewAttributesFilter("game", game2.Proxy.Hex()), - testlog.NewAttributesFilter("recipient", addr2.Hex()))) + // addr1 is below expected - no warning as withdrawals may now be possible + // addr2 is correct // addr3 is above expected - warn require.NotNil(t, logs.FindLog( testlog.NewLevelFilter(log.LevelWarn), @@ -422,18 +401,8 @@ func TestCheckRecipientCredit(t *testing.T) { testlog.NewAttributesFilter("withdrawable", "non_withdrawable"))) // Logs from game 4 - // addr1 is correct but has unclaimed credit - require.NotNil(t, logs.FindLog( - testlog.NewLevelFilter(log.LevelWarn), - testlog.NewMessageFilter("Found unclaimed credit"), - testlog.NewAttributesFilter("game", game4.Proxy.Hex()), - testlog.NewAttributesFilter("recipient", addr1.Hex()))) - // addr2 is below expected before max duration, no log because withdrawals may be possible but warn about unclaimed - require.NotNil(t, logs.FindLog( - testlog.NewLevelFilter(log.LevelWarn), - testlog.NewMessageFilter("Found unclaimed credit"), - testlog.NewAttributesFilter("game", game4.Proxy.Hex()), - testlog.NewAttributesFilter("recipient", addr2.Hex()))) + // addr1 is correct + // addr2 is below expected before max duration, no log because withdrawals may be possible // addr3 is not involved so no logs // addr4 is above expected before max duration, so warn require.NotNil(t, logs.FindLog( @@ -450,19 +419,13 @@ func setupBondMetricsTest(t *testing.T) (*Bonds, *stubBondMetrics, *testlog.Capt credits: make(map[metrics.CreditExpectation]int), recorded: make(map[common.Address]Collateral), } - honestActors := monTypes.NewHonestActors([]common.Address{honestActor1, honestActor2, honestActor3}) - bonds := NewBonds(logger, metrics, honestActors, clock.NewDeterministicClock(frozen)) + bonds := NewBonds(logger, metrics, clock.NewDeterministicClock(frozen)) return bonds, metrics, logs } type stubBondMetrics struct { - credits map[metrics.CreditExpectation]int - recorded map[common.Address]Collateral - honestWithdrawable map[common.Address]*big.Int -} - -func (s *stubBondMetrics) RecordHonestWithdrawableAmounts(values map[common.Address]*big.Int) { - s.honestWithdrawable = values + credits map[metrics.CreditExpectation]int + recorded map[common.Address]Collateral } func (s *stubBondMetrics) RecordBondCollateral(addr common.Address, required *big.Int, available *big.Int) { diff --git a/op-dispute-mon/mon/service.go b/op-dispute-mon/mon/service.go index e637b23d63b0d..8ce97b7b8dd92 100644 --- a/op-dispute-mon/mon/service.go +++ b/op-dispute-mon/mon/service.go @@ -116,7 +116,7 @@ func (s *Service) initResolutionMonitor() { } func (s *Service) initWithdrawalMonitor() { - s.withdrawals = NewWithdrawalMonitor(s.logger, s.metrics) + s.withdrawals = NewWithdrawalMonitor(s.logger, s.cl, s.metrics, s.honestActors) } func (s *Service) initGameCallerCreator() { @@ -145,7 +145,7 @@ func (s *Service) initForecast(cfg *config.Config) { } func (s *Service) initBonds() { - s.bonds = bonds.NewBonds(s.logger, s.metrics, s.honestActors, s.cl) + s.bonds = bonds.NewBonds(s.logger, s.metrics, s.cl) } func (s *Service) initOutputRollupClient(ctx context.Context, cfg *config.Config) error { diff --git a/op-dispute-mon/mon/withdrawals.go b/op-dispute-mon/mon/withdrawals.go index 5563b099afe5a..1c7e9da2f9af0 100644 --- a/op-dispute-mon/mon/withdrawals.go +++ b/op-dispute-mon/mon/withdrawals.go @@ -1,6 +1,9 @@ package mon import ( + "math/big" + "time" + "github.com/ethereum-optimism/optimism/op-dispute-mon/mon/types" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" @@ -8,25 +11,35 @@ import ( type WithdrawalMetrics interface { RecordWithdrawalRequests(delayedWeth common.Address, matches bool, count int) + RecordHonestWithdrawableAmounts(map[common.Address]*big.Int) } type WithdrawalMonitor struct { - logger log.Logger - metrics WithdrawalMetrics + logger log.Logger + clock RClock + metrics WithdrawalMetrics + honestActors types.HonestActors } -func NewWithdrawalMonitor(logger log.Logger, metrics WithdrawalMetrics) *WithdrawalMonitor { +func NewWithdrawalMonitor(logger log.Logger, clock RClock, metrics WithdrawalMetrics, honestActors types.HonestActors) *WithdrawalMonitor { return &WithdrawalMonitor{ - logger: logger, - metrics: metrics, + logger: logger, + clock: clock, + metrics: metrics, + honestActors: honestActors, } } func (w *WithdrawalMonitor) CheckWithdrawals(games []*types.EnrichedGameData) { + now := w.clock.Now() // Use a consistent time for all checks matching := make(map[common.Address]int) divergent := make(map[common.Address]int) + honestWithdrawableAmounts := make(map[common.Address]*big.Int) + for address := range w.honestActors { + honestWithdrawableAmounts[address] = big.NewInt(0) + } for _, game := range games { - matches, diverges := w.validateGameWithdrawals(game) + matches, diverges := w.validateGameWithdrawals(game, now, honestWithdrawableAmounts) matching[game.WETHContract] += matches divergent[game.WETHContract] += diverges } @@ -36,9 +49,10 @@ func (w *WithdrawalMonitor) CheckWithdrawals(games []*types.EnrichedGameData) { for contract, count := range divergent { w.metrics.RecordWithdrawalRequests(contract, false, count) } + w.metrics.RecordHonestWithdrawableAmounts(honestWithdrawableAmounts) } -func (w *WithdrawalMonitor) validateGameWithdrawals(game *types.EnrichedGameData) (int, int) { +func (w *WithdrawalMonitor) validateGameWithdrawals(game *types.EnrichedGameData, now time.Time, honestWithdrawableAmounts map[common.Address]*big.Int) (int, int) { matching := 0 divergent := 0 for recipient, withdrawalAmount := range game.WithdrawalRequests { @@ -48,6 +62,16 @@ func (w *WithdrawalMonitor) validateGameWithdrawals(game *types.EnrichedGameData divergent++ w.logger.Error("Withdrawal request amount does not match credit", "game", game.Proxy, "recipient", recipient, "credit", game.Credits[recipient], "withdrawal", game.WithdrawalRequests[recipient].Amount) } + + if withdrawalAmount.Amount.Cmp(big.NewInt(0)) > 0 && w.honestActors.Contains(recipient) { + if time.Unix(withdrawalAmount.Timestamp.Int64(), 0).Add(game.WETHDelay).Before(now) { + // Credits are withdrawable + total := honestWithdrawableAmounts[recipient] + total = new(big.Int).Add(total, withdrawalAmount.Amount) + honestWithdrawableAmounts[recipient] = total + w.logger.Warn("Found unclaimed credit", "recipient", recipient, "game", game.Proxy, "amount", withdrawalAmount.Amount) + } + } } return matching, divergent } diff --git a/op-dispute-mon/mon/withdrawals_test.go b/op-dispute-mon/mon/withdrawals_test.go index f598ea38df97a..ad17493adf656 100644 --- a/op-dispute-mon/mon/withdrawals_test.go +++ b/op-dispute-mon/mon/withdrawals_test.go @@ -3,9 +3,12 @@ package mon import ( "math/big" "testing" + "time" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts" + "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" @@ -15,58 +18,76 @@ import ( var ( weth1 = common.Address{0x1a} weth2 = common.Address{0x2b} + + honestActor1 = common.Address{0x11, 0xaa} + honestActor2 = common.Address{0x22, 0xbb} + honestActor3 = common.Address{0x33, 0xcc} + dishonestActor4 = common.Address{0x44, 0xdd} + + nowUnix = int64(10_000) ) func makeGames() []*monTypes.EnrichedGameData { weth1Balance := big.NewInt(4200) weth2Balance := big.NewInt(6000) + game1 := &monTypes.EnrichedGameData{ + GameMetadata: types.GameMetadata{Proxy: common.Address{0x11, 0x11, 0x11}}, Credits: map[common.Address]*big.Int{ - common.Address{0x01}: big.NewInt(3), - common.Address{0x02}: big.NewInt(1), + honestActor1: big.NewInt(3), + honestActor2: big.NewInt(1), }, WithdrawalRequests: map[common.Address]*contracts.WithdrawalRequest{ - common.Address{0x01}: &contracts.WithdrawalRequest{Amount: big.NewInt(3)}, - common.Address{0x02}: &contracts.WithdrawalRequest{Amount: big.NewInt(1)}, + honestActor1: {Amount: big.NewInt(3), Timestamp: big.NewInt(nowUnix - 101)}, // Claimable + honestActor2: {Amount: big.NewInt(1), Timestamp: big.NewInt(nowUnix - 99)}, // Not claimable }, WETHContract: weth1, ETHCollateral: weth1Balance, + WETHDelay: 100 * time.Second, } game2 := &monTypes.EnrichedGameData{ + GameMetadata: types.GameMetadata{Proxy: common.Address{0x22, 0x22, 0x22}}, Credits: map[common.Address]*big.Int{ - common.Address{0x01}: big.NewInt(46), - common.Address{0x02}: big.NewInt(1), + honestActor1: big.NewInt(46), + honestActor2: big.NewInt(1), }, WithdrawalRequests: map[common.Address]*contracts.WithdrawalRequest{ - common.Address{0x01}: &contracts.WithdrawalRequest{Amount: big.NewInt(3)}, - common.Address{0x02}: &contracts.WithdrawalRequest{Amount: big.NewInt(1)}, + honestActor1: {Amount: big.NewInt(3), Timestamp: big.NewInt(nowUnix - 501)}, // Claimable + honestActor2: {Amount: big.NewInt(1), Timestamp: big.NewInt(nowUnix)}, // Not claimable }, WETHContract: weth2, ETHCollateral: weth2Balance, + WETHDelay: 500 * time.Second, } game3 := &monTypes.EnrichedGameData{ + GameMetadata: types.GameMetadata{Proxy: common.Address{0x33, 0x33, 0x33}}, Credits: map[common.Address]*big.Int{ - common.Address{0x03}: big.NewInt(2), - common.Address{0x04}: big.NewInt(4), + honestActor3: big.NewInt(2), + dishonestActor4: big.NewInt(4), }, WithdrawalRequests: map[common.Address]*contracts.WithdrawalRequest{ - common.Address{0x03}: &contracts.WithdrawalRequest{Amount: big.NewInt(2)}, - common.Address{0x04}: &contracts.WithdrawalRequest{Amount: big.NewInt(4)}, + honestActor3: {Amount: big.NewInt(2), Timestamp: big.NewInt(nowUnix - 1)}, // Claimable + dishonestActor4: {Amount: big.NewInt(4), Timestamp: big.NewInt(nowUnix - 5)}, // Claimable }, WETHContract: weth2, ETHCollateral: weth2Balance, + WETHDelay: 0 * time.Second, } return []*monTypes.EnrichedGameData{game1, game2, game3} } func TestCheckWithdrawals(t *testing.T) { - logger := testlog.Logger(t, log.LvlInfo) + now := time.Unix(nowUnix, 0) + cl := clock.NewDeterministicClock(now) + logger, logs := testlog.CaptureLogger(t, log.LvlInfo) metrics := &stubWithdrawalsMetrics{ matching: make(map[common.Address]int), divergent: make(map[common.Address]int), } - withdrawals := NewWithdrawalMonitor(logger, metrics) - withdrawals.CheckWithdrawals(makeGames()) + honestActors := monTypes.NewHonestActors([]common.Address{honestActor1, honestActor2, honestActor3}) + withdrawals := NewWithdrawalMonitor(logger, cl, metrics, honestActors) + games := makeGames() + withdrawals.CheckWithdrawals(games) require.Equal(t, metrics.matchCalls, 2) require.Equal(t, metrics.divergeCalls, 2) @@ -80,13 +101,59 @@ func TestCheckWithdrawals(t *testing.T) { require.Equal(t, metrics.matching[weth2], 3) require.Equal(t, metrics.divergent[weth1], 0) require.Equal(t, metrics.divergent[weth2], 1) + + require.Len(t, metrics.honestWithdrawable, 3) + requireBigInt := func(name string, expected, actual *big.Int) { + require.Truef(t, expected.Cmp(actual) == 0, "Expected %v withdrawable to be %v but was %v", name, expected, actual) + } + requireBigInt("honest addr1", big.NewInt(6), metrics.honestWithdrawable[honestActor1]) + requireBigInt("honest addr2", big.NewInt(0), metrics.honestWithdrawable[honestActor2]) + requireBigInt("honest addr3", big.NewInt(2), metrics.honestWithdrawable[honestActor3]) + require.Nil(t, metrics.honestWithdrawable[dishonestActor4], "should only report withdrawable credits for honest actors") + + findUnclaimedCreditWarning := func(game common.Address, actor common.Address) *testlog.CapturedRecord { + return logs.FindLog( + testlog.NewLevelFilter(log.LevelWarn), + testlog.NewMessageFilter("Found unclaimed credit"), + testlog.NewAttributesFilter("game", game.Hex()), + testlog.NewAttributesFilter("recipient", actor.Hex())) + } + requireUnclaimedWarning := func(game common.Address, actor common.Address) { + require.NotNil(t, findUnclaimedCreditWarning(game, actor)) + } + noUnclaimedWarning := func(game common.Address, actor common.Address) { + require.Nil(t, findUnclaimedCreditWarning(game, actor)) + } + // Game 1, unclaimed for honestActor1 only + requireUnclaimedWarning(games[0].Proxy, honestActor1) + noUnclaimedWarning(games[0].Proxy, honestActor2) + noUnclaimedWarning(games[0].Proxy, honestActor3) + noUnclaimedWarning(games[0].Proxy, dishonestActor4) + + // Game 2, unclaimed for honestActor1 only + requireUnclaimedWarning(games[1].Proxy, honestActor1) + noUnclaimedWarning(games[1].Proxy, honestActor2) + noUnclaimedWarning(games[1].Proxy, honestActor3) + noUnclaimedWarning(games[1].Proxy, dishonestActor4) + + // Game 3, unclaimed for honestActor3 only + // dishonestActor4 has unclaimed credits but we don't track them + noUnclaimedWarning(games[2].Proxy, honestActor1) + noUnclaimedWarning(games[2].Proxy, honestActor2) + requireUnclaimedWarning(games[2].Proxy, honestActor3) + noUnclaimedWarning(games[2].Proxy, dishonestActor4) } type stubWithdrawalsMetrics struct { - matchCalls int - divergeCalls int - matching map[common.Address]int - divergent map[common.Address]int + matchCalls int + divergeCalls int + matching map[common.Address]int + divergent map[common.Address]int + honestWithdrawable map[common.Address]*big.Int +} + +func (s *stubWithdrawalsMetrics) RecordHonestWithdrawableAmounts(honestWithdrawable map[common.Address]*big.Int) { + s.honestWithdrawable = honestWithdrawable } func (s *stubWithdrawalsMetrics) RecordWithdrawalRequests(addr common.Address, matches bool, count int) { diff --git a/op-e2e/Makefile b/op-e2e/Makefile index bd0cdba73bef9..f3f67f8050da2 100644 --- a/op-e2e/Makefile +++ b/op-e2e/Makefile @@ -17,15 +17,15 @@ test-external-%: pre-test $(go_test) $(go_test_flags) --externalL2 ./external_$*/ test-ws: pre-test - $(go_test) $(go_test_flags) . ./e2eutils/... + $(go_test) $(go_test_flags) ./system/... ./e2eutils/... ./opgeth/... ./interop/... .PHONY: test-ws test-actions: pre-test - $(go_test) $(go_test_flags) ./actions + $(go_test) $(go_test_flags) ./actions/... .PHONY: test-actions test-http: pre-test - OP_E2E_USE_HTTP=true $(go_test) $(go_test_flags) . ./e2eutils/... + OP_E2E_USE_HTTP=true $(go_test) $(go_test_flags) ./system/... ./e2eutils/... ./opgeth/... ./interop/... .PHONY: test-http test-cannon: pre-test @@ -40,8 +40,9 @@ test-devnet: pre-test $(go_test) $(go_test_flags) ./devnet .PHONY: test-devnet -cannon-prestate: +cannon-prestates: make -C .. cannon-prestate + make -C .. cannon-prestate-mt .PHONY: cannon-prestate # We depend on the absolute pre-state generated by cannon to deploy the dispute game contracts. @@ -54,7 +55,7 @@ pre-test: pre-test-cannon pre-test-allocs pre-test-cannon: @if [ ! -e ../op-program/bin ]; then \ - make cannon-prestate; \ + make cannon-prestates; \ fi .PHONY: pre-test-cannon @@ -70,7 +71,7 @@ clean: .PHONY: clean fuzz: - go test -run NOTAREALTEST -tags cgo_test -v -fuzztime 10s -fuzz FuzzFjordCostFunction ./ - go test -run NOTAREALTEST -tags cgo_test -v -fuzztime 10s -fuzz FuzzFastLzGethSolidity ./ - go test -run NOTAREALTEST -tags cgo_test -v -fuzztime 10s -fuzz FuzzFastLzCgo ./ + go test -run NOTAREALTEST -tags cgo_test -v -fuzztime 10s -fuzz FuzzFjordCostFunction ./opgeth + go test -run NOTAREALTEST -tags cgo_test -v -fuzztime 10s -fuzz FuzzFastLzGethSolidity ./opgeth + go test -run NOTAREALTEST -tags cgo_test -v -fuzztime 10s -fuzz FuzzFastLzCgo ./opgeth diff --git a/op-e2e/actions/altda_test.go b/op-e2e/actions/altda/altda_test.go similarity index 87% rename from op-e2e/actions/altda_test.go rename to op-e2e/actions/altda/altda_test.go index 14889edabc889..ac122d9d999a5 100644 --- a/op-e2e/actions/altda_test.go +++ b/op-e2e/actions/altda/altda_test.go @@ -1,10 +1,11 @@ -package actions +package altda import ( "math/big" "math/rand" "testing" + "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" "github.com/stretchr/testify/require" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -32,21 +33,21 @@ type L2AltDA struct { daMgr *altda.DA altDACfg altda.Config contract *bindings.DataAvailabilityChallenge - batcher *L2Batcher - sequencer *L2Sequencer - engine *L2Engine + batcher *helpers.L2Batcher + sequencer *helpers.L2Sequencer + engine *helpers.L2Engine engCl *sources.EngineClient sd *e2eutils.SetupData dp *e2eutils.DeployParams - miner *L1Miner - alice *CrossLayerUser + miner *helpers.L1Miner + alice *helpers.CrossLayerUser lastComm []byte lastCommBn uint64 } type AltDAParam func(p *e2eutils.TestParams) -func NewL2AltDA(t Testing, params ...AltDAParam) *L2AltDA { +func NewL2AltDA(t helpers.Testing, params ...AltDAParam) *L2AltDA { p := &e2eutils.TestParams{ MaxSequencerDrift: 40, SequencerWindowSize: 12, @@ -60,15 +61,15 @@ func NewL2AltDA(t Testing, params ...AltDAParam) *L2AltDA { log := testlog.Logger(t, log.LvlDebug) dp := e2eutils.MakeDeployParams(t, p) - sd := e2eutils.Setup(t, dp, defaultAlloc) + sd := e2eutils.Setup(t, dp, helpers.DefaultAlloc) require.True(t, sd.RollupCfg.AltDAEnabled()) - miner := NewL1Miner(t, log, sd.L1Cfg) + miner := helpers.NewL1Miner(t, log, sd.L1Cfg) l1Client := miner.EthClient() jwtPath := e2eutils.WriteDefaultJWT(t) - engine := NewL2Engine(t, log, sd.L2Cfg, sd.RollupCfg.Genesis.L1, jwtPath) + engine := helpers.NewL2Engine(t, log, sd.L2Cfg, sd.RollupCfg.Genesis.L1, jwtPath) engCl := engine.EngineClient(t, sd.RollupCfg) storage := &altda.DAErrFaker{Client: altda.NewMockDAClient(log)} @@ -81,21 +82,21 @@ func NewL2AltDA(t Testing, params ...AltDAParam) *L2AltDA { daMgr := altda.NewAltDAWithStorage(log, altDACfg, storage, &altda.NoopMetrics{}) - sequencer := NewL2Sequencer(t, log, l1F, miner.BlobStore(), daMgr, engCl, sd.RollupCfg, 0) + sequencer := helpers.NewL2Sequencer(t, log, l1F, miner.BlobStore(), daMgr, engCl, sd.RollupCfg, 0, nil) miner.ActL1SetFeeRecipient(common.Address{'A'}) sequencer.ActL2PipelineFull(t) - batcher := NewL2Batcher(log, sd.RollupCfg, AltDABatcherCfg(dp, storage), sequencer.RollupClient(), l1Client, engine.EthClient(), engCl) + batcher := helpers.NewL2Batcher(log, sd.RollupCfg, helpers.AltDABatcherCfg(dp, storage), sequencer.RollupClient(), l1Client, engine.EthClient(), engCl) addresses := e2eutils.CollectAddresses(sd, dp) cl := engine.EthClient() - l2UserEnv := &BasicUserEnv[*L2Bindings]{ + l2UserEnv := &helpers.BasicUserEnv[*helpers.L2Bindings]{ EthCl: cl, Signer: types.LatestSigner(sd.L2Cfg.Config), AddressCorpora: addresses, - Bindings: NewL2Bindings(t, cl, engine.GethClient()), + Bindings: helpers.NewL2Bindings(t, cl, engine.GethClient()), } - alice := NewCrossLayerUser(log, dp.Secrets.Alice, rand.New(rand.NewSource(0xa57b))) + alice := helpers.NewCrossLayerUser(log, dp.Secrets.Alice, rand.New(rand.NewSource(0xa57b))) alice.L2.SetUserEnv(l2UserEnv) contract, err := bindings.NewDataAvailabilityChallenge(sd.RollupCfg.AltDAConfig.DAChallengeAddress, l1Client) @@ -130,21 +131,21 @@ func (a *L2AltDA) StorageClient() *altda.DAErrFaker { return a.storage } -func (a *L2AltDA) NewVerifier(t Testing) *L2Verifier { +func (a *L2AltDA) NewVerifier(t helpers.Testing) *helpers.L2Verifier { jwtPath := e2eutils.WriteDefaultJWT(t) - engine := NewL2Engine(t, a.log, a.sd.L2Cfg, a.sd.RollupCfg.Genesis.L1, jwtPath) + engine := helpers.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 := altda.NewAltDAWithStorage(a.log, a.altDACfg, a.storage, &altda.NoopMetrics{}) - verifier := NewL2Verifier(t, a.log, l1F, a.miner.BlobStore(), daMgr, engCl, a.sd.RollupCfg, &sync.Config{}, safedb.Disabled) + verifier := helpers.NewL2Verifier(t, a.log, l1F, a.miner.BlobStore(), daMgr, engCl, a.sd.RollupCfg, &sync.Config{}, safedb.Disabled, nil) return verifier } -func (a *L2AltDA) ActSequencerIncludeTx(t Testing) { +func (a *L2AltDA) ActSequencerIncludeTx(t helpers.Testing) { a.alice.L2.ActResetTxOpts(t) a.alice.L2.ActSetTxToAddr(&a.dp.Addresses.Bob)(t) a.alice.L2.ActMakeTx(t) @@ -156,7 +157,7 @@ func (a *L2AltDA) ActSequencerIncludeTx(t Testing) { a.sequencer.ActL2EndBlock(t) } -func (a *L2AltDA) ActNewL2Tx(t Testing) { +func (a *L2AltDA) ActNewL2Tx(t helpers.Testing) { a.ActSequencerIncludeTx(t) a.batcher.ActL2BatchBuffer(t) @@ -170,20 +171,20 @@ func (a *L2AltDA) ActNewL2Tx(t Testing) { a.miner.ActL1IncludeTx(a.dp.Addresses.Batcher)(t) a.miner.ActL1EndBlock(t) - a.lastCommBn = a.miner.l1Chain.CurrentBlock().Number.Uint64() + a.lastCommBn = a.miner.L1Chain().CurrentBlock().Number.Uint64() } -func (a *L2AltDA) ActDeleteLastInput(t Testing) { +func (a *L2AltDA) ActDeleteLastInput(t helpers.Testing) { require.NoError(t, a.storage.Client.DeleteData(a.lastComm)) } -func (a *L2AltDA) ActChallengeLastInput(t Testing) { +func (a *L2AltDA) ActChallengeLastInput(t helpers.Testing) { a.ActChallengeInput(t, a.lastComm, a.lastCommBn) a.log.Info("challenged last input", "block", a.lastCommBn) } -func (a *L2AltDA) ActChallengeInput(t Testing, comm []byte, bn uint64) { +func (a *L2AltDA) ActChallengeInput(t helpers.Testing, comm []byte, bn uint64) { bondValue, err := a.contract.BondSize(&bind.CallOpts{}) require.NoError(t, err) @@ -209,15 +210,15 @@ func (a *L2AltDA) ActChallengeInput(t Testing, comm []byte, bn uint64) { a.miner.ActL1EndBlock(t) } -func (a *L2AltDA) ActExpireLastInput(t Testing) { +func (a *L2AltDA) ActExpireLastInput(t helpers.Testing) { reorgWindow := a.altDACfg.ResolveWindow + a.altDACfg.ChallengeWindow - for a.miner.l1Chain.CurrentBlock().Number.Uint64() <= a.lastCommBn+reorgWindow { + for a.miner.L1Chain().CurrentBlock().Number.Uint64() <= a.lastCommBn+reorgWindow { a.miner.ActL1StartBlock(12)(t) a.miner.ActL1EndBlock(t) } } -func (a *L2AltDA) ActResolveInput(t Testing, comm []byte, input []byte, bn uint64) { +func (a *L2AltDA) ActResolveInput(t helpers.Testing, comm []byte, input []byte, bn uint64) { txOpts, err := bind.NewKeyedTransactorWithChainID(a.dp.Secrets.Alice, a.sd.L1Cfg.Config.ChainID) require.NoError(t, err) @@ -229,7 +230,7 @@ func (a *L2AltDA) ActResolveInput(t Testing, comm []byte, input []byte, bn uint6 a.miner.ActL1EndBlock(t) } -func (a *L2AltDA) ActResolveLastChallenge(t Testing) { +func (a *L2AltDA) ActResolveLastChallenge(t helpers.Testing) { // remove derivation byte prefix input, err := a.storage.GetInput(t.Ctx(), altda.Keccak256Commitment(a.lastComm[1:])) require.NoError(t, err) @@ -237,23 +238,22 @@ func (a *L2AltDA) ActResolveLastChallenge(t Testing) { a.ActResolveInput(t, a.lastComm, input, a.lastCommBn) } -func (a *L2AltDA) ActL1Blocks(t Testing, n uint64) { +func (a *L2AltDA) ActL1Blocks(t helpers.Testing, n uint64) { for i := uint64(0); i < n; i++ { a.miner.ActL1StartBlock(12)(t) a.miner.ActL1EndBlock(t) } } -func (a *L2AltDA) GetLastTxBlock(t Testing) *types.Block { - rcpt, err := a.engine.EthClient().TransactionReceipt(t.Ctx(), a.alice.L2.lastTxHash) - require.NoError(t, err) +func (a *L2AltDA) GetLastTxBlock(t helpers.Testing) *types.Block { + rcpt := a.alice.L2.LastTxReceipt(t) blk, err := a.engine.EthClient().BlockByHash(t.Ctx(), rcpt.BlockHash) require.NoError(t, err) return blk } -func (a *L2AltDA) ActL1Finalized(t Testing) { - latest := a.miner.l1Chain.CurrentBlock().Number.Uint64() +func (a *L2AltDA) ActL1Finalized(t helpers.Testing) { + latest := a.miner.L1Chain().CurrentBlock().Number.Uint64() a.miner.ActL1Safe(t, latest) a.miner.ActL1Finalize(t, latest) a.sequencer.ActL1FinalizedSignal(t) @@ -265,7 +265,7 @@ func TestAltDA_ChallengeExpired(gt *testing.T) { gt.Skip("AltDA is not enabled") } - t := NewDefaultTesting(gt) + t := helpers.NewDefaultTesting(gt) harness := NewL2AltDA(t) // generate enough initial l1 blocks to have a finalized head. @@ -325,7 +325,7 @@ func TestAltDA_ChallengeResolved(gt *testing.T) { gt.Skip("AltDA is not enabled") } - t := NewDefaultTesting(gt) + t := helpers.NewDefaultTesting(gt) harness := NewL2AltDA(t) // include a new l2 transaction, submitting an input commitment to the l1. @@ -373,7 +373,7 @@ func TestAltDA_StorageError(gt *testing.T) { gt.Skip("AltDA is not enabled") } - t := NewDefaultTesting(gt) + t := helpers.NewDefaultTesting(gt) harness := NewL2AltDA(t) // include a new l2 transaction, submitting an input commitment to the l1. @@ -402,7 +402,7 @@ func TestAltDA_ChallengeReorg(gt *testing.T) { gt.Skip("AltDA is not enabled") } - t := NewDefaultTesting(gt) + t := helpers.NewDefaultTesting(gt) harness := NewL2AltDA(t) // New L2 tx added to a batch and committed to L1 @@ -450,7 +450,7 @@ func TestAltDA_SequencerStalledMultiChallenges(gt *testing.T) { gt.Skip("AltDA is not enabled") } - t := NewDefaultTesting(gt) + t := helpers.NewDefaultTesting(gt) a := NewL2AltDA(t) // create a new tx on l2 and commit it to l1 @@ -509,7 +509,7 @@ func TestAltDA_SequencerStalledMultiChallenges(gt *testing.T) { comm2 := a.lastComm _, err = a.storage.GetInput(t.Ctx(), altda.Keccak256Commitment(comm2[1:])) require.NoError(t, err) - a.lastCommBn = a.miner.l1Chain.CurrentBlock().Number.Uint64() + a.lastCommBn = a.miner.L1Chain().CurrentBlock().Number.Uint64() // ensure the second commitment is distinct from the first require.NotEqual(t, comm1, comm2) @@ -545,7 +545,7 @@ func TestAltDA_Finalization(gt *testing.T) { if !e2eutils.UseAltDA() { gt.Skip("AltDA is not enabled") } - t := NewDefaultTesting(gt) + t := helpers.NewDefaultTesting(gt) a := NewL2AltDA(t) // build L1 block #1 diff --git a/op-e2e/actions/eip4844_test.go b/op-e2e/actions/batcher/eip4844_test.go similarity index 85% rename from op-e2e/actions/eip4844_test.go rename to op-e2e/actions/batcher/eip4844_test.go index ddab21d48b47d..6d77a3961788d 100644 --- a/op-e2e/actions/eip4844_test.go +++ b/op-e2e/actions/batcher/eip4844_test.go @@ -1,8 +1,9 @@ -package actions +package batcher import ( "testing" + "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" "github.com/stretchr/testify/require" "github.com/ethereum/go-ethereum/common" @@ -16,26 +17,26 @@ import ( "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) +func setupEIP4844Test(t helpers.Testing, log log.Logger) (*e2eutils.SetupData, *e2eutils.DeployParams, *helpers.L1Miner, *helpers.L2Sequencer, *helpers.L2Engine, *helpers.L2Verifier, *helpers.L2Engine) { + dp := e2eutils.MakeDeployParams(t, helpers.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) + sd := e2eutils.Setup(t, dp, helpers.DefaultAlloc) + miner, seqEngine, sequencer := helpers.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{}) + verifEngine, verifier := helpers.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{ +func setupBatcher(t helpers.Testing, log log.Logger, sd *e2eutils.SetupData, dp *e2eutils.DeployParams, miner *helpers.L1Miner, + sequencer *helpers.L2Sequencer, engine *helpers.L2Engine, daType batcherFlags.DataAvailabilityType, +) *helpers.L2Batcher { + return helpers.NewL2Batcher(log, sd.RollupCfg, &helpers.BatcherCfg{ MinL1TxSize: 0, MaxL1TxSize: 128_000, BatcherKey: dp.Secrets.Batcher, @@ -44,7 +45,7 @@ func setupBatcher(t Testing, log log.Logger, sd *e2eutils.SetupData, dp *e2eutil } func TestEIP4844DataAvailability(gt *testing.T) { - t := NewDefaultTesting(gt) + t := helpers.NewDefaultTesting(gt) log := testlog.Logger(t, log.LevelDebug) sd, dp, miner, sequencer, seqEngine, verifier, _ := setupEIP4844Test(t, log) @@ -82,7 +83,7 @@ func TestEIP4844DataAvailability(gt *testing.T) { } func TestEIP4844MultiBlobs(gt *testing.T) { - t := NewDefaultTesting(gt) + t := helpers.NewDefaultTesting(gt) log := testlog.Logger(t, log.LevelDebug) sd, dp, miner, sequencer, seqEngine, verifier, _ := setupEIP4844Test(t, log) @@ -121,7 +122,7 @@ func TestEIP4844MultiBlobs(gt *testing.T) { } func TestEIP4844DataAvailabilitySwitch(gt *testing.T) { - t := NewDefaultTesting(gt) + t := helpers.NewDefaultTesting(gt) log := testlog.Logger(t, log.LevelDebug) sd, dp, miner, sequencer, seqEngine, verifier, _ := setupEIP4844Test(t, log) diff --git a/op-e2e/actions/l2_batcher_test.go b/op-e2e/actions/batcher/l2_batcher_test.go similarity index 80% rename from op-e2e/actions/l2_batcher_test.go rename to op-e2e/actions/batcher/l2_batcher_test.go index 6235c7482326b..e0605f3fb1216 100644 --- a/op-e2e/actions/l2_batcher_test.go +++ b/op-e2e/actions/batcher/l2_batcher_test.go @@ -1,4 +1,4 @@ -package actions +package batcher import ( "errors" @@ -6,6 +6,8 @@ import ( "math/rand" "testing" + actionsHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" + upgradesHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/upgrades/helpers" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" @@ -50,29 +52,8 @@ func TestL2BatcherBatchType(t *testing.T) { } } -// applyDeltaTimeOffset adjusts fork configuration to not conflict with the delta overrides -func applyDeltaTimeOffset(dp *e2eutils.DeployParams, deltaTimeOffset *hexutil.Uint64) { - dp.DeployConfig.L2GenesisDeltaTimeOffset = deltaTimeOffset - // configure Ecotone to not be before Delta accidentally - if dp.DeployConfig.L2GenesisEcotoneTimeOffset != nil { - if deltaTimeOffset == nil { - dp.DeployConfig.L2GenesisEcotoneTimeOffset = nil - } else if *dp.DeployConfig.L2GenesisEcotoneTimeOffset < *deltaTimeOffset { - dp.DeployConfig.L2GenesisEcotoneTimeOffset = deltaTimeOffset - } - } - // configure Fjord to not be before Delta accidentally - if dp.DeployConfig.L2GenesisFjordTimeOffset != nil { - if deltaTimeOffset == nil { - dp.DeployConfig.L2GenesisFjordTimeOffset = nil - } else if *dp.DeployConfig.L2GenesisFjordTimeOffset < *deltaTimeOffset { - dp.DeployConfig.L2GenesisFjordTimeOffset = deltaTimeOffset - } - } -} - func NormalBatcher(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { - t := NewDefaultTesting(gt) + t := actionsHelpers.NewDefaultTesting(gt) p := &e2eutils.TestParams{ MaxSequencerDrift: 20, // larger than L1 block time we simulate in this test (12) SequencerWindowSize: 24, @@ -80,14 +61,14 @@ func NormalBatcher(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { L1BlockTime: 12, } dp := e2eutils.MakeDeployParams(t, p) - applyDeltaTimeOffset(dp, deltaTimeOffset) - sd := e2eutils.Setup(t, dp, defaultAlloc) + upgradesHelpers.ApplyDeltaTimeOffset(dp, deltaTimeOffset) + sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) log := testlog.Logger(t, log.LevelDebug) - miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) - verifEngine, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) + miner, seqEngine, sequencer := actionsHelpers.SetupSequencerTest(t, sd, log) + verifEngine, verifier := actionsHelpers.SetupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) rollupSeqCl := sequencer.RollupClient() - batcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp), + batcher := actionsHelpers.NewL2Batcher(log, sd.RollupCfg, actionsHelpers.DefaultBatcherCfg(dp), rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) // Alice makes a L2 tx @@ -99,7 +80,7 @@ func NormalBatcher(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { 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)), + 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), @@ -123,8 +104,8 @@ func NormalBatcher(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { miner.ActL1StartBlock(12)(t) miner.ActL1IncludeTx(dp.Addresses.Batcher)(t) miner.ActL1EndBlock(t) - bl := miner.l1Chain.CurrentBlock() - log.Info("bl", "txs", len(miner.l1Chain.GetBlockByHash(bl.Hash()).Transactions())) + bl := miner.L1Chain().CurrentBlock() + log.Info("bl", "txs", len(miner.L1Chain().GetBlockByHash(bl.Hash()).Transactions())) // Now make enough L1 blocks that the verifier will have to derive a L2 block // It will also eagerly derive the block from the batcher @@ -147,12 +128,12 @@ func NormalBatcher(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { } func L2Finalization(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { - t := NewDefaultTesting(gt) - dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) - applyDeltaTimeOffset(dp, deltaTimeOffset) - sd := e2eutils.Setup(t, dp, defaultAlloc) + t := actionsHelpers.NewDefaultTesting(gt) + dp := e2eutils.MakeDeployParams(t, actionsHelpers.DefaultRollupTestParams) + upgradesHelpers.ApplyDeltaTimeOffset(dp, deltaTimeOffset) + sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) log := testlog.Logger(t, log.LevelDebug) - miner, engine, sequencer := setupSequencerTest(t, sd, log) + miner, engine, sequencer := actionsHelpers.SetupSequencerTest(t, sd, log) sequencer.ActL2PipelineFull(t) @@ -184,7 +165,7 @@ 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, DefaultBatcherCfg(dp), + batcher := actionsHelpers.NewL2Batcher(log, sd.RollupCfg, actionsHelpers.DefaultBatcherCfg(dp), sequencer.RollupClient(), miner.EthClient(), engine.EthClient(), engine.EngineClient(t, sd.RollupCfg)) heightToSubmit := sequencer.SyncStatus().UnsafeL2.Number @@ -244,12 +225,12 @@ func L2Finalization(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { // L2FinalizationWithSparseL1 tests that safe L2 blocks can be finalized even if we do not regularly get a L1 finalization signal func L2FinalizationWithSparseL1(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { - t := NewDefaultTesting(gt) - dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) - applyDeltaTimeOffset(dp, deltaTimeOffset) - sd := e2eutils.Setup(t, dp, defaultAlloc) + t := actionsHelpers.NewDefaultTesting(gt) + dp := e2eutils.MakeDeployParams(t, actionsHelpers.DefaultRollupTestParams) + upgradesHelpers.ApplyDeltaTimeOffset(dp, deltaTimeOffset) + sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) log := testlog.Logger(t, log.LevelDebug) - miner, engine, sequencer := setupSequencerTest(t, sd, log) + miner, engine, sequencer := actionsHelpers.SetupSequencerTest(t, sd, log) sequencer.ActL2PipelineFull(t) @@ -260,7 +241,7 @@ 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, DefaultBatcherCfg(dp), + batcher := actionsHelpers.NewL2Batcher(log, sd.RollupCfg, actionsHelpers.DefaultBatcherCfg(dp), sequencer.RollupClient(), miner.EthClient(), engine.EthClient(), engine.EngineClient(t, sd.RollupCfg)) batcher.ActSubmitAll(t) @@ -300,29 +281,29 @@ func L2FinalizationWithSparseL1(gt *testing.T, deltaTimeOffset *hexutil.Uint64) // valid batches being submitted to the batch inbox. These batches should always be rejected // and the safe L2 head should remain unaltered. func GarbageBatch(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { - t := NewDefaultTesting(gt) - p := defaultRollupTestParams + t := actionsHelpers.NewDefaultTesting(gt) + p := actionsHelpers.DefaultRollupTestParams dp := e2eutils.MakeDeployParams(t, p) - applyDeltaTimeOffset(dp, deltaTimeOffset) - for _, garbageKind := range GarbageKinds { - sd := e2eutils.Setup(t, dp, defaultAlloc) + upgradesHelpers.ApplyDeltaTimeOffset(dp, deltaTimeOffset) + for _, garbageKind := range actionsHelpers.GarbageKinds { + sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) log := testlog.Logger(t, log.LevelError) - miner, engine, sequencer := setupSequencerTest(t, sd, log) + miner, engine, sequencer := actionsHelpers.SetupSequencerTest(t, sd, log) - _, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) + _, verifier := actionsHelpers.SetupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) - batcherCfg := DefaultBatcherCfg(dp) + batcherCfg := actionsHelpers.DefaultBatcherCfg(dp) - if garbageKind == MALFORM_RLP || garbageKind == INVALID_COMPRESSION { + if garbageKind == actionsHelpers.MALFORM_RLP || garbageKind == actionsHelpers.INVALID_COMPRESSION { // If the garbage kind is `INVALID_COMPRESSION` or `MALFORM_RLP`, use the `actions` packages // modified `ChannelOut`. - batcherCfg.GarbageCfg = &GarbageChannelCfg{ - useInvalidCompression: garbageKind == INVALID_COMPRESSION, - malformRLP: garbageKind == MALFORM_RLP, + batcherCfg.GarbageCfg = &actionsHelpers.GarbageChannelCfg{ + UseInvalidCompression: garbageKind == actionsHelpers.INVALID_COMPRESSION, + MalformRLP: garbageKind == actionsHelpers.MALFORM_RLP, } } - batcher := NewL2Batcher(log, sd.RollupCfg, batcherCfg, sequencer.RollupClient(), miner.EthClient(), engine.EthClient(), engine.EngineClient(t, sd.RollupCfg)) + batcher := actionsHelpers.NewL2Batcher(log, sd.RollupCfg, batcherCfg, sequencer.RollupClient(), miner.EthClient(), engine.EthClient(), engine.EngineClient(t, sd.RollupCfg)) sequencer.ActL2PipelineFull(t) verifier.ActL2PipelineFull(t) @@ -376,7 +357,7 @@ func GarbageBatch(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { } func ExtendedTimeWithoutL1Batches(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { - t := NewDefaultTesting(gt) + t := actionsHelpers.NewDefaultTesting(gt) p := &e2eutils.TestParams{ MaxSequencerDrift: 20, // larger than L1 block time we simulate in this test (12) SequencerWindowSize: 24, @@ -384,14 +365,14 @@ func ExtendedTimeWithoutL1Batches(gt *testing.T, deltaTimeOffset *hexutil.Uint64 L1BlockTime: 12, } dp := e2eutils.MakeDeployParams(t, p) - applyDeltaTimeOffset(dp, deltaTimeOffset) - sd := e2eutils.Setup(t, dp, defaultAlloc) + upgradesHelpers.ApplyDeltaTimeOffset(dp, deltaTimeOffset) + sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) log := testlog.Logger(t, log.LevelError) - miner, engine, sequencer := setupSequencerTest(t, sd, log) + miner, engine, sequencer := actionsHelpers.SetupSequencerTest(t, sd, log) - _, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) + _, verifier := actionsHelpers.SetupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) - batcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp), + batcher := actionsHelpers.NewL2Batcher(log, sd.RollupCfg, actionsHelpers.DefaultBatcherCfg(dp), sequencer.RollupClient(), miner.EthClient(), engine.EthClient(), engine.EngineClient(t, sd.RollupCfg)) sequencer.ActL2PipelineFull(t) @@ -432,7 +413,7 @@ func ExtendedTimeWithoutL1Batches(gt *testing.T, deltaTimeOffset *hexutil.Uint64 // This does not test the batcher code, but is really focused at testing the batcher utils // and channel-decoding verifier code in the derive package. func BigL2Txs(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { - t := NewDefaultTesting(gt) + t := actionsHelpers.NewDefaultTesting(gt) p := &e2eutils.TestParams{ MaxSequencerDrift: 100, SequencerWindowSize: 1000, @@ -440,14 +421,14 @@ func BigL2Txs(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { L1BlockTime: 12, } dp := e2eutils.MakeDeployParams(t, p) - applyDeltaTimeOffset(dp, deltaTimeOffset) - sd := e2eutils.Setup(t, dp, defaultAlloc) + upgradesHelpers.ApplyDeltaTimeOffset(dp, deltaTimeOffset) + sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) log := testlog.Logger(t, log.LevelInfo) - miner, engine, sequencer := setupSequencerTest(t, sd, log) + miner, engine, sequencer := actionsHelpers.SetupSequencerTest(t, sd, log) - _, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) + _, verifier := actionsHelpers.SetupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) - batcher := NewL2Batcher(log, sd.RollupCfg, &BatcherCfg{ + batcher := actionsHelpers.NewL2Batcher(log, sd.RollupCfg, &actionsHelpers.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, @@ -478,7 +459,7 @@ func BigL2Txs(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { } sequencer.ActL1HeadSignal(t) sequencer.ActL2StartBlock(t) - baseFee := engine.l2Chain.CurrentBlock().BaseFee // this will go quite high, since so many consecutive blocks are filled at capacity. + baseFee := engine.L2Chain().CurrentBlock().BaseFee // this will go quite high, since so many consecutive blocks are filled at capacity. // fill the block with large L2 txs from alice for n := aliceNonce; ; n++ { require.NoError(t, err) @@ -488,7 +469,7 @@ func BigL2Txs(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { require.NoError(t, err) gas, err := core.IntrinsicGas(data, nil, false, true, true, false) require.NoError(t, err) - if gas > engine.engineApi.RemainingBlockGas() { + if gas > engine.EngineApi.RemainingBlockGas() { break } tx := types.MustSignNewTx(dp.Secrets.Alice, signer, &types.DynamicFeeTx{ @@ -505,12 +486,12 @@ func BigL2Txs(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { engine.ActL2IncludeTx(dp.Addresses.Alice)(t) } sequencer.ActL2EndBlock(t) - for batcher.l2BufferedBlock.Number < sequencer.SyncStatus().UnsafeL2.Number { + for batcher.L2BufferedBlock.Number < sequencer.SyncStatus().UnsafeL2.Number { // if we run out of space, close the channel and submit all the txs if err := batcher.Buffer(t); errors.Is(err, derive.ErrTooManyRLPBytes) || errors.Is(err, derive.ErrCompressorFull) { - log.Info("flushing filled channel to batch txs", "id", batcher.l2ChannelOut.ID()) + log.Info("flushing filled channel to batch txs", "id", batcher.L2ChannelOut.ID()) batcher.ActL2ChannelClose(t) - for batcher.l2ChannelOut != nil { + for batcher.L2ChannelOut != nil { batcher.ActL2BatchSubmit(t, batcherTxOpts) } } @@ -518,16 +499,16 @@ func BigL2Txs(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { } // if anything is left in the channel, submit it - if batcher.l2ChannelOut != nil { - log.Info("flushing trailing channel to batch txs", "id", batcher.l2ChannelOut.ID()) + if batcher.L2ChannelOut != nil { + log.Info("flushing trailing channel to batch txs", "id", batcher.L2ChannelOut.ID()) batcher.ActL2ChannelClose(t) - for batcher.l2ChannelOut != nil { + for batcher.L2ChannelOut != nil { batcher.ActL2BatchSubmit(t, batcherTxOpts) } } // build L1 blocks until we're out of txs - txs, _ := miner.eth.TxPool().ContentFrom(dp.Addresses.Batcher) + txs, _ := miner.Eth.TxPool().ContentFrom(dp.Addresses.Batcher) for { if len(txs) == 0 { break @@ -538,7 +519,7 @@ func BigL2Txs(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { break } tx := txs[0] - if miner.l1GasPool.Gas() < tx.Gas() { // fill the L1 block with batcher txs until we run out of gas + if miner.L1GasPool.Gas() < tx.Gas() { // fill the L1 block with batcher txs until we run out of gas break } log.Info("including batcher tx", "nonce", tx.Nonce()) diff --git a/op-e2e/actions/derivation/batch_queue_test.go b/op-e2e/actions/derivation/batch_queue_test.go new file mode 100644 index 0000000000000..af5b7231b8849 --- /dev/null +++ b/op-e2e/actions/derivation/batch_queue_test.go @@ -0,0 +1,102 @@ +package derivation + +import ( + "testing" + + altda "github.com/ethereum-optimism/optimism/op-alt-da" + batcherFlags "github.com/ethereum-optimism/optimism/op-batcher/flags" + "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" + upgradesHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/upgrades/helpers" + "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/derive" + "github.com/ethereum-optimism/optimism/op-node/rollup/sync" + "github.com/ethereum-optimism/optimism/op-service/sources" + "github.com/ethereum-optimism/optimism/op-service/testlog" + "github.com/ethereum/go-ethereum/log" + "github.com/stretchr/testify/require" +) + +// TestDeriveChainFromNearL1Genesis tests a corner case where when the derivation pipeline starts, the +// safe head has an L1 origin of block 1. The derivation then starts with pipeline origin of L1 genesis, +// just one block prior to the origin of the safe head. +// This is a regression test, previously the pipeline encountered got stuck in a reset loop with the error: +// buffered L1 chain epoch %s in batch queue does not match safe head origin %s +func TestDeriveChainFromNearL1Genesis(gt *testing.T) { + t := helpers.NewDefaultTesting(gt) + p := &e2eutils.TestParams{ + MaxSequencerDrift: 20, // larger than L1 block time we simulate in this test (12) + SequencerWindowSize: 24, + ChannelTimeout: 20, + L1BlockTime: 12, + } + dp := e2eutils.MakeDeployParams(t, p) + // do not activate Delta hardfork for verifier + upgradesHelpers.ApplyDeltaTimeOffset(dp, nil) + sd := e2eutils.Setup(t, dp, helpers.DefaultAlloc) + logger := testlog.Logger(t, log.LevelInfo) + miner, seqEngine, sequencer := helpers.SetupSequencerTest(t, sd, logger) + + miner.ActEmptyBlock(t) + require.EqualValues(gt, 1, miner.L1Chain().CurrentBlock().Number.Uint64()) + + ref, err := derive.L2BlockToBlockRef(sequencer.RollupCfg, seqEngine.L2Chain().Genesis()) + require.NoError(gt, err) + require.EqualValues(gt, 0, ref.L1Origin.Number) + + sequencer.ActL1HeadSignal(t) + sequencer.ActBuildToL1Head(t) + l2BlockNum := seqEngine.L2Chain().CurrentBlock().Number.Uint64() + ref, err = derive.L2BlockToBlockRef(sequencer.RollupCfg, seqEngine.L2Chain().GetBlockByNumber(l2BlockNum)) + require.NoError(gt, err) + require.EqualValues(gt, 1, ref.L1Origin.Number) + + miner.ActEmptyBlock(t) + + rollupSeqCl := sequencer.RollupClient() + // Force batcher to submit SingularBatches to L1. + batcher := helpers.NewL2Batcher(logger, sd.RollupCfg, &helpers.BatcherCfg{ + MinL1TxSize: 0, + MaxL1TxSize: 128_000, + BatcherKey: dp.Secrets.Batcher, + DataAvailabilityType: batcherFlags.CalldataType, + }, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) + + batcher.ActSubmitAll(t) + require.EqualValues(gt, l2BlockNum, batcher.L2BufferedBlock.Number) + + // confirm batch on L1 + miner.ActL1StartBlock(12)(t) + miner.ActL1IncludeTx(dp.Addresses.Batcher)(t) + miner.ActL1EndBlock(t) + bl := miner.L1Chain().CurrentBlock() + logger.Info("Produced L1 block with batch", + "num", miner.L1Chain().CurrentBlock().Number.Uint64(), + "txs", len(miner.L1Chain().GetBlockByHash(bl.Hash()).Transactions())) + + // Process batches so safe head updates + sequencer.ActL1HeadSignal(t) + sequencer.ActL2PipelineFull(t) + require.EqualValues(gt, l2BlockNum, seqEngine.L2Chain().CurrentSafeBlock().Number.Uint64()) + + // Finalize L1 and process so L2 finalized updates + miner.ActL1Safe(t, miner.L1Chain().CurrentBlock().Number.Uint64()) + miner.ActL1Finalize(t, miner.L1Chain().CurrentBlock().Number.Uint64()) + sequencer.ActL1SafeSignal(t) + sequencer.ActL1FinalizedSignal(t) + sequencer.ActL2PipelineFull(t) + require.EqualValues(gt, l2BlockNum, seqEngine.L2Chain().CurrentFinalBlock().Number.Uint64()) + + // Create a new verifier using the existing engine so it already has the safe and finalized heads set. + // This is the same situation as if op-node restarted at this point. + l2Cl, err := sources.NewEngineClient(seqEngine.RPCClient(), logger, nil, sources.EngineClientDefaultConfig(sd.RollupCfg)) + require.NoError(gt, err) + verifier := helpers.NewL2Verifier(t, logger, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), altda.Disabled, + l2Cl, sequencer.RollupCfg, &sync.Config{}, safedb.Disabled, nil) + verifier.ActL2PipelineFull(t) // Should not get stuck in a reset loop forever + require.EqualValues(gt, l2BlockNum, seqEngine.L2Chain().CurrentSafeBlock().Number.Uint64()) + require.EqualValues(gt, l2BlockNum, seqEngine.L2Chain().CurrentFinalBlock().Number.Uint64()) + syncStatus := verifier.SyncStatus() + require.EqualValues(gt, l2BlockNum, syncStatus.SafeL2.Number) + require.EqualValues(gt, l2BlockNum, syncStatus.FinalizedL2.Number) +} diff --git a/op-e2e/actions/blocktime_test.go b/op-e2e/actions/derivation/blocktime_test.go similarity index 89% rename from op-e2e/actions/blocktime_test.go rename to op-e2e/actions/derivation/blocktime_test.go index 7bf34e103cc7d..ec192d08ad782 100644 --- a/op-e2e/actions/blocktime_test.go +++ b/op-e2e/actions/derivation/blocktime_test.go @@ -1,9 +1,11 @@ -package actions +package derivation import ( "math/big" "testing" + actionsHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" + upgradesHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/upgrades/helpers" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" "github.com/ethereum-optimism/optimism/op-service/testlog" "github.com/ethereum/go-ethereum/common/hexutil" @@ -44,16 +46,16 @@ func TestBlockTimeBatchType(t *testing.T) { // window. // This is a regression test against the bug fixed in PR #4566 func BatchInLastPossibleBlocks(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { - t := NewDefaultTesting(gt) - dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) - applyDeltaTimeOffset(dp, deltaTimeOffset) + t := actionsHelpers.NewDefaultTesting(gt) + dp := e2eutils.MakeDeployParams(t, actionsHelpers.DefaultRollupTestParams) + upgradesHelpers.ApplyDeltaTimeOffset(dp, deltaTimeOffset) dp.DeployConfig.SequencerWindowSize = 4 dp.DeployConfig.L2BlockTime = 2 - sd := e2eutils.Setup(t, dp, defaultAlloc) + sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) log := testlog.Logger(t, log.LevelDebug) - sd, _, miner, sequencer, sequencerEngine, _, _, batcher := setupReorgTestActors(t, dp, sd, log) + sd, _, miner, sequencer, sequencerEngine, _, _, batcher := actionsHelpers.SetupReorgTestActors(t, dp, sd, log) signer := types.LatestSigner(sd.L2Cfg.Config) cl := sequencerEngine.EthClient() @@ -63,7 +65,7 @@ func BatchInLastPossibleBlocks(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { ChainID: sd.L2Cfg.Config.ChainID, Nonce: aliceNonce, GasTipCap: big.NewInt(2 * params.GWei), - GasFeeCap: new(big.Int).Add(miner.l1Chain.CurrentBlock().BaseFee, 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), @@ -78,7 +80,7 @@ func BatchInLastPossibleBlocks(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { sequencer.ActL2EndBlock(t) } verifyChainStateOnSequencer := func(l1Number, unsafeHead, unsafeHeadOrigin, safeHead, safeHeadOrigin uint64) { - require.Equal(t, l1Number, miner.l1Chain.CurrentHeader().Number.Uint64()) + require.Equal(t, l1Number, miner.L1Chain().CurrentHeader().Number.Uint64()) require.Equal(t, unsafeHead, sequencer.L2Unsafe().Number) require.Equal(t, unsafeHeadOrigin, sequencer.L2Unsafe().L1Origin.Number) require.Equal(t, safeHead, sequencer.L2Safe().Number) @@ -155,8 +157,8 @@ func BatchInLastPossibleBlocks(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { // At this point it can verify that the batches where properly generated. // Note: It batches submits when possible. func LargeL1Gaps(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { - t := NewDefaultTesting(gt) - dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) + t := actionsHelpers.NewDefaultTesting(gt) + dp := e2eutils.MakeDeployParams(t, actionsHelpers.DefaultRollupTestParams) dp.DeployConfig.L1BlockTime = 4 dp.DeployConfig.L2BlockTime = 2 dp.DeployConfig.SequencerWindowSize = 4 @@ -165,11 +167,11 @@ func LargeL1Gaps(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { dp.DeployConfig.L2GenesisFjordTimeOffset = nil // TODO(client-pod#831): The Ecotone (and Fjord) activation blocks don't include user txs, // so disabling these forks for now. - applyDeltaTimeOffset(dp, deltaTimeOffset) - sd := e2eutils.Setup(t, dp, defaultAlloc) + upgradesHelpers.ApplyDeltaTimeOffset(dp, deltaTimeOffset) + sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) log := testlog.Logger(t, log.LevelDebug) - sd, _, miner, sequencer, sequencerEngine, verifier, _, batcher := setupReorgTestActors(t, dp, sd, log) + sd, _, miner, sequencer, sequencerEngine, verifier, _, batcher := actionsHelpers.SetupReorgTestActors(t, dp, sd, log) signer := types.LatestSigner(sd.L2Cfg.Config) cl := sequencerEngine.EthClient() @@ -180,7 +182,7 @@ func LargeL1Gaps(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { ChainID: sd.L2Cfg.Config.ChainID, Nonce: aliceNonce, GasTipCap: big.NewInt(2 * params.GWei), - GasFeeCap: new(big.Int).Add(miner.l1Chain.CurrentBlock().BaseFee, 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), @@ -196,7 +198,7 @@ func LargeL1Gaps(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { } verifyChainStateOnSequencer := func(l1Number, unsafeHead, unsafeHeadOrigin, safeHead, safeHeadOrigin uint64) { - require.Equal(t, l1Number, miner.l1Chain.CurrentHeader().Number.Uint64()) + require.Equal(t, l1Number, miner.L1Chain().CurrentHeader().Number.Uint64()) require.Equal(t, unsafeHead, sequencer.L2Unsafe().Number) require.Equal(t, unsafeHeadOrigin, sequencer.L2Unsafe().L1Origin.Number) require.Equal(t, safeHead, sequencer.L2Safe().Number) @@ -204,7 +206,7 @@ func LargeL1Gaps(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { } verifyChainStateOnVerifier := func(l1Number, unsafeHead, unsafeHeadOrigin, safeHead, safeHeadOrigin uint64) { - require.Equal(t, l1Number, miner.l1Chain.CurrentHeader().Number.Uint64()) + require.Equal(t, l1Number, miner.L1Chain().CurrentHeader().Number.Uint64()) require.Equal(t, unsafeHead, verifier.L2Unsafe().Number) require.Equal(t, unsafeHeadOrigin, verifier.L2Unsafe().L1Origin.Number) require.Equal(t, safeHead, verifier.L2Safe().Number) diff --git a/op-e2e/actions/l2_verifier_test.go b/op-e2e/actions/derivation/l2_verifier_test.go similarity index 51% rename from op-e2e/actions/l2_verifier_test.go rename to op-e2e/actions/derivation/l2_verifier_test.go index 328801214e04a..2f4fce628d534 100644 --- a/op-e2e/actions/l2_verifier_test.go +++ b/op-e2e/actions/derivation/l2_verifier_test.go @@ -1,59 +1,19 @@ -package actions +package derivation import ( "testing" - altda "github.com/ethereum-optimism/optimism/op-alt-da" - "github.com/ethereum-optimism/optimism/op-node/node/safedb" + "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" "github.com/stretchr/testify/require" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" - "github.com/ethereum-optimism/optimism/op-node/rollup/derive" - "github.com/ethereum-optimism/optimism/op-node/rollup/sync" "github.com/ethereum-optimism/optimism/op-service/testlog" ) -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.New("role", "verifier-engine"), sd.L2Cfg, sd.RollupCfg.Genesis.L1, jwtPath, EngineWithP2P()) - engCl := engine.EngineClient(t, sd.RollupCfg) - verifier := NewL2Verifier(t, log.New("role", "verifier"), l1F, blobSrc, altda.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, miner.BlobStore(), &sync.Config{}) - return miner, engine, verifier -} - func TestL2Verifier_SequenceWindow(gt *testing.T) { - t := NewDefaultTesting(gt) + t := helpers.NewDefaultTesting(gt) p := &e2eutils.TestParams{ MaxSequencerDrift: 10, SequencerWindowSize: 24, @@ -61,26 +21,26 @@ func TestL2Verifier_SequenceWindow(gt *testing.T) { L1BlockTime: 15, } dp := e2eutils.MakeDeployParams(t, p) - sd := e2eutils.Setup(t, dp, defaultAlloc) + sd := e2eutils.Setup(t, dp, helpers.DefaultAlloc) log := testlog.Logger(t, log.LevelDebug) - miner, engine, verifier := setupVerifierOnlyTest(t, sd, log) + miner, engine, verifier := helpers.SetupVerifierOnlyTest(t, sd, log) miner.ActL1SetFeeRecipient(common.Address{'A'}) // Make two sequence windows worth of empty L1 blocks. After we pass the first sequence window, the L2 chain should get blocks - for miner.l1Chain.CurrentBlock().Number.Uint64() < sd.RollupCfg.SeqWindowSize*2 { + for miner.L1Chain().CurrentBlock().Number.Uint64() < sd.RollupCfg.SeqWindowSize*2 { miner.ActL1StartBlock(10)(t) miner.ActL1EndBlock(t) verifier.ActL2PipelineFull(t) - l1Head := miner.l1Chain.CurrentBlock().Number.Uint64() + l1Head := miner.L1Chain().CurrentBlock().Number.Uint64() expectedL1Origin := uint64(0) // as soon as we complete the sequence window, we force-adopt the L1 origin if l1Head >= sd.RollupCfg.SeqWindowSize { expectedL1Origin = l1Head - sd.RollupCfg.SeqWindowSize } require.Equal(t, expectedL1Origin, verifier.SyncStatus().SafeL2.L1Origin.Number, "L1 origin is forced in, given enough L1 blocks pass by") - require.LessOrEqual(t, miner.l1Chain.GetBlockByNumber(expectedL1Origin).Time(), engine.l2Chain.CurrentBlock().Time, "L2 time higher than L1 origin time") + require.LessOrEqual(t, miner.L1Chain().GetBlockByNumber(expectedL1Origin).Time(), engine.L2Chain().CurrentBlock().Time, "L2 time higher than L1 origin time") } tip2N := verifier.SyncStatus() @@ -95,13 +55,13 @@ func TestL2Verifier_SequenceWindow(gt *testing.T) { miner.ActL1SetFeeRecipient(common.Address{'B'}) miner.ActL1StartBlock(10)(t) miner.ActL1EndBlock(t) - reorgL1Block := miner.l1Chain.CurrentBlock() + reorgL1Block := miner.L1Chain().CurrentBlock() // Still no reorg, we need more L1 blocks first, before the reorged L1 block is forced in by sequence window verifier.ActL2PipelineFull(t) require.Equal(t, tip2N.SafeL2, verifier.SyncStatus().SafeL2) - for miner.l1Chain.CurrentBlock().Number.Uint64() < sd.RollupCfg.SeqWindowSize*2 { + for miner.L1Chain().CurrentBlock().Number.Uint64() < sd.RollupCfg.SeqWindowSize*2 { miner.ActL1StartBlock(10)(t) miner.ActL1EndBlock(t) } @@ -113,6 +73,6 @@ func TestL2Verifier_SequenceWindow(gt *testing.T) { // Now it will reorg verifier.ActL2PipelineFull(t) - got := miner.l1Chain.GetBlockByHash(miner.l1Chain.GetBlockByHash(verifier.SyncStatus().SafeL2.L1Origin.Hash).Hash()) + got := miner.L1Chain().GetBlockByHash(miner.L1Chain().GetBlockByHash(verifier.SyncStatus().SafeL2.L1Origin.Hash).Hash()) require.Equal(t, reorgL1Block.Hash(), got.Hash(), "must have reorged L2 chain to the new L1 chain") } diff --git a/op-e2e/actions/reorg_test.go b/op-e2e/actions/derivation/reorg_test.go similarity index 89% rename from op-e2e/actions/reorg_test.go rename to op-e2e/actions/derivation/reorg_test.go index 4036d9fb131cd..6551b314c1ea6 100644 --- a/op-e2e/actions/reorg_test.go +++ b/op-e2e/actions/derivation/reorg_test.go @@ -1,4 +1,4 @@ -package actions +package derivation import ( "math/big" @@ -6,6 +6,8 @@ import ( "path" "testing" + actionsHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" + upgradesHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/upgrades/helpers" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" @@ -16,34 +18,12 @@ import ( altda "github.com/ethereum-optimism/optimism/op-alt-da" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" - "github.com/ethereum-optimism/optimism/op-node/rollup/sync" "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" ) -func setupReorgTest(t Testing, config *e2eutils.TestParams, deltaTimeOffset *hexutil.Uint64) (*e2eutils.SetupData, *e2eutils.DeployParams, *L1Miner, *L2Sequencer, *L2Engine, *L2Verifier, *L2Engine, *L2Batcher) { - dp := e2eutils.MakeDeployParams(t, config) - applyDeltaTimeOffset(dp, deltaTimeOffset) - - sd := e2eutils.Setup(t, dp, defaultAlloc) - log := testlog.Logger(t, log.LevelDebug) - - return setupReorgTestActors(t, dp, sd, log) -} - -func setupReorgTestActors(t Testing, dp *e2eutils.DeployParams, sd *e2eutils.SetupData, log log.Logger) (*e2eutils.SetupData, *e2eutils.DeployParams, *L1Miner, *L2Sequencer, *L2Engine, *L2Verifier, *L2Engine, *L2Batcher) { - 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{}) - rollupSeqCl := sequencer.RollupClient() - 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 -} - // TestReorgBatchType run each reorg-related test case in singular batch mode and span batch mode. func TestReorgBatchType(t *testing.T) { tests := []struct { @@ -74,8 +54,8 @@ func TestReorgBatchType(t *testing.T) { } func ReorgOrphanBlock(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { - t := NewDefaultTesting(gt) - sd, _, miner, sequencer, _, verifier, verifierEng, batcher := setupReorgTest(t, defaultRollupTestParams, deltaTimeOffset) + t := actionsHelpers.NewDefaultTesting(gt) + sd, _, miner, sequencer, _, verifier, verifierEng, batcher := actionsHelpers.SetupReorgTest(t, actionsHelpers.DefaultRollupTestParams, deltaTimeOffset) verifEngClient := verifierEng.EngineClient(t, sd.RollupCfg) sequencer.ActL2PipelineFull(t) @@ -94,7 +74,7 @@ func ReorgOrphanBlock(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { // new L1 block with L2 batch miner.ActL1StartBlock(12)(t) miner.ActL1IncludeTx(sd.RollupCfg.Genesis.SystemConfig.BatcherAddr)(t) - batchTx := miner.l1Transactions[0] + batchTx := miner.L1Transactions[0] miner.ActL1EndBlock(t) // verifier picks up the L2 chain that was submitted @@ -123,7 +103,7 @@ func ReorgOrphanBlock(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { 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]) + 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) @@ -142,8 +122,8 @@ func ReorgOrphanBlock(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { } func ReorgFlipFlop(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { - t := NewDefaultTesting(gt) - sd, _, miner, sequencer, _, verifier, verifierEng, batcher := setupReorgTest(t, defaultRollupTestParams, deltaTimeOffset) + t := actionsHelpers.NewDefaultTesting(gt) + sd, _, miner, sequencer, _, verifier, verifierEng, batcher := actionsHelpers.SetupReorgTest(t, actionsHelpers.DefaultRollupTestParams, deltaTimeOffset) minerCl := miner.L1Client(t, sd.RollupCfg) verifEngClient := verifierEng.EngineClient(t, sd.RollupCfg) checkVerifEngine := func() { @@ -172,7 +152,7 @@ func ReorgFlipFlop(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { miner.ActL1SetFeeRecipient(common.Address{'A', 1}) miner.ActL1StartBlock(12)(t) miner.ActL1IncludeTx(sd.RollupCfg.Genesis.SystemConfig.BatcherAddr)(t) - batchTxA := miner.l1Transactions[0] + batchTxA := miner.L1Transactions[0] miner.ActL1EndBlock(t) // verifier picks up the L2 chain that was submitted @@ -195,7 +175,7 @@ func ReorgFlipFlop(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { // re-include the batch tx that submitted L2 chain data that pointed to A0, in the new block B1 miner.ActL1SetFeeRecipient(common.Address{'B', 1}) miner.ActL1StartBlock(12)(t) - require.NoError(t, miner.eth.TxPool().Add([]*types.Transaction{batchTxA}, true, true)[0]) + require.NoError(t, miner.Eth.TxPool().Add([]*types.Transaction{batchTxA}, true, true)[0]) miner.ActL1IncludeTx(sd.RollupCfg.Genesis.SystemConfig.BatcherAddr)(t) miner.ActL1EndBlock(t) @@ -219,7 +199,7 @@ func ReorgFlipFlop(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { // after delta hard fork require.Zero(t, verifier.L2Safe().Number, "safe head is at genesis block because span batch referenced reorged L1 chain is not accepted") require.Equal(t, verifier.L2Unsafe().ID(), sequencer.L2Unsafe().ParentID(), "head is at the highest unsafe block that references canonical L1 chain(genesis block)") - batcher.l2BufferedBlock = eth.L2BlockRef{} // must reset batcher to resubmit blocks included in the last batch + batcher.L2BufferedBlock = eth.L2BlockRef{} // must reset batcher to resubmit blocks included in the last batch } checkVerifEngine() @@ -260,7 +240,7 @@ func ReorgFlipFlop(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { miner.ActL1SetFeeRecipient(common.Address{'A', 2}) miner.ActL1StartBlock(12)(t) - require.NoError(t, miner.eth.TxPool().Add([]*types.Transaction{batchTxA}, true, true)[0]) // replay chain A batches, but now in A2 instead of A1 + require.NoError(t, miner.Eth.TxPool().Add([]*types.Transaction{batchTxA}, true, true)[0]) // replay chain A batches, but now in A2 instead of A1 miner.ActL1IncludeTx(sd.RollupCfg.Genesis.SystemConfig.BatcherAddr)(t) miner.ActL1EndBlock(t) @@ -356,10 +336,10 @@ func ReorgFlipFlop(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { // - Unsafe head is 62 // - Safe head is 42 func DeepReorg(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { - t := NewDefaultTesting(gt) + t := actionsHelpers.NewDefaultTesting(gt) // Create actor and verification engine client - sd, dp, miner, sequencer, seqEngine, verifier, verifierEng, batcher := setupReorgTest(t, &e2eutils.TestParams{ + sd, dp, miner, sequencer, seqEngine, verifier, verifierEng, batcher := actionsHelpers.SetupReorgTest(t, &e2eutils.TestParams{ MaxSequencerDrift: 40, SequencerWindowSize: 20, ChannelTimeout: 120, @@ -377,13 +357,13 @@ func DeepReorg(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { // Set up alice log := testlog.Logger(t, log.LevelDebug) addresses := e2eutils.CollectAddresses(sd, dp) - l2UserEnv := &BasicUserEnv[*L2Bindings]{ + l2UserEnv := &actionsHelpers.BasicUserEnv[*actionsHelpers.L2Bindings]{ EthCl: l2Client, Signer: types.LatestSigner(sd.L2Cfg.Config), AddressCorpora: addresses, - Bindings: NewL2Bindings(t, l2Client, seqEngine.GethClient()), + Bindings: actionsHelpers.NewL2Bindings(t, l2Client, seqEngine.GethClient()), } - alice := NewCrossLayerUser(log, dp.Secrets.Alice, rand.New(rand.NewSource(0xa57b))) + alice := actionsHelpers.NewCrossLayerUser(log, dp.Secrets.Alice, rand.New(rand.NewSource(0xa57b))) alice.L2.SetUserEnv(l2UserEnv) // Run one iteration of the L2 derivation pipeline @@ -593,29 +573,29 @@ type rpcWrapper struct { // RestartOpGeth tests that the sequencer can restart its execution engine without rollup-node restart, // including recovering the finalized/safe state of L2 chain without reorging. func RestartOpGeth(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { - t := NewDefaultTesting(gt) + t := actionsHelpers.NewDefaultTesting(gt) dbPath := path.Join(t.TempDir(), "testdb") dbOption := func(_ *ethconfig.Config, nodeCfg *node.Config) error { nodeCfg.DataDir = dbPath return nil } - dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) - applyDeltaTimeOffset(dp, deltaTimeOffset) - sd := e2eutils.Setup(t, dp, defaultAlloc) + dp := e2eutils.MakeDeployParams(t, actionsHelpers.DefaultRollupTestParams) + upgradesHelpers.ApplyDeltaTimeOffset(dp, deltaTimeOffset) + sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) log := testlog.Logger(t, log.LevelDebug) jwtPath := e2eutils.WriteDefaultJWT(t) // L1 - miner := NewL1Miner(t, log, sd.L1Cfg) + miner := actionsHelpers.NewL1Miner(t, log, sd.L1Cfg) l1F, err := sources.NewL1Client(miner.RPCClient(), log, nil, sources.L1ClientDefaultConfig(sd.RollupCfg, false, sources.RPCKindStandard)) require.NoError(t, err) // Sequencer - seqEng := NewL2Engine(t, log, sd.L2Cfg, sd.RollupCfg.Genesis.L1, jwtPath, dbOption) + seqEng := actionsHelpers.NewL2Engine(t, log, sd.L2Cfg, sd.RollupCfg.Genesis.L1, jwtPath, dbOption) engRpc := &rpcWrapper{seqEng.RPCClient()} l2Cl, err := sources.NewEngineClient(engRpc, log, nil, sources.EngineClientDefaultConfig(sd.RollupCfg)) require.NoError(t, err) - sequencer := NewL2Sequencer(t, log, l1F, miner.BlobStore(), altda.Disabled, l2Cl, sd.RollupCfg, 0) + sequencer := actionsHelpers.NewL2Sequencer(t, log, l1F, miner.BlobStore(), altda.Disabled, l2Cl, sd.RollupCfg, 0, nil) - batcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp), + batcher := actionsHelpers.NewL2Batcher(log, sd.RollupCfg, actionsHelpers.DefaultBatcherCfg(dp), sequencer.RollupClient(), miner.EthClient(), seqEng.EthClient(), seqEng.EngineClient(t, sd.RollupCfg)) // start @@ -664,7 +644,7 @@ func RestartOpGeth(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { // close the sequencer engine require.NoError(t, seqEng.Close()) // and start a new one with same db path - seqEngNew := NewL2Engine(t, log, sd.L2Cfg, sd.RollupCfg.Genesis.L1, jwtPath, dbOption) + seqEngNew := actionsHelpers.NewL2Engine(t, log, sd.L2Cfg, sd.RollupCfg.Genesis.L1, jwtPath, dbOption) // swap in the new rpc. This is as close as we can get to reconnecting to a new in-memory rpc connection engRpc.RPC = seqEngNew.RPCClient() @@ -686,35 +666,35 @@ func RestartOpGeth(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { // L2 block (compared to something already secured by the first sequencer): // the alt block is not synced by the verifier, in unsafe and safe sync modes. func ConflictingL2Blocks(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { - t := NewDefaultTesting(gt) - dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) - applyDeltaTimeOffset(dp, deltaTimeOffset) - sd := e2eutils.Setup(t, dp, defaultAlloc) + t := actionsHelpers.NewDefaultTesting(gt) + dp := e2eutils.MakeDeployParams(t, actionsHelpers.DefaultRollupTestParams) + upgradesHelpers.ApplyDeltaTimeOffset(dp, deltaTimeOffset) + sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) log := testlog.Logger(t, log.LevelDebug) - sd, _, miner, sequencer, seqEng, verifier, _, batcher := setupReorgTestActors(t, dp, sd, log) + sd, _, miner, sequencer, seqEng, verifier, _, batcher := actionsHelpers.SetupReorgTestActors(t, dp, sd, log) // Extra setup: a full alternative sequencer, sequencer engine, and batcher jwtPath := e2eutils.WriteDefaultJWT(t) - altSeqEng := NewL2Engine(t, log, sd.L2Cfg, sd.RollupCfg.Genesis.L1, jwtPath) + altSeqEng := actionsHelpers.NewL2Engine(t, log, sd.L2Cfg, sd.RollupCfg.Genesis.L1, jwtPath) altSeqEngCl, err := sources.NewEngineClient(altSeqEng.RPCClient(), log, nil, sources.EngineClientDefaultConfig(sd.RollupCfg)) 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, miner.BlobStore(), altda.Disabled, altSeqEngCl, sd.RollupCfg, 0) - altBatcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp), + altSequencer := actionsHelpers.NewL2Sequencer(t, log, l1F, miner.BlobStore(), altda.Disabled, altSeqEngCl, sd.RollupCfg, 0, nil) + altBatcher := actionsHelpers.NewL2Batcher(log, sd.RollupCfg, actionsHelpers.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() addresses := e2eutils.CollectAddresses(sd, dp) - l2UserEnv := &BasicUserEnv[*L2Bindings]{ + l2UserEnv := &actionsHelpers.BasicUserEnv[*actionsHelpers.L2Bindings]{ EthCl: l2Cl, Signer: types.LatestSigner(sd.L2Cfg.Config), AddressCorpora: addresses, - Bindings: NewL2Bindings(t, l2Cl, altSeqEng.GethClient()), + Bindings: actionsHelpers.NewL2Bindings(t, l2Cl, altSeqEng.GethClient()), } - alice := NewCrossLayerUser(log, dp.Secrets.Alice, rand.New(rand.NewSource(1234))) + alice := actionsHelpers.NewCrossLayerUser(log, dp.Secrets.Alice, rand.New(rand.NewSource(1234))) alice.L2.SetUserEnv(l2UserEnv) sequencer.ActL2PipelineFull(t) @@ -756,7 +736,7 @@ func ConflictingL2Blocks(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { altSeqEng.ActL2IncludeTx(alice.Address())(t) altSequencer.ActL2EndBlock(t) - conflictBlock := seqEng.l2Chain.GetBlockByNumber(altSequencer.L2Unsafe().Number) + conflictBlock := seqEng.L2Chain().GetBlockByNumber(altSequencer.L2Unsafe().Number) require.NotEqual(t, conflictBlock.Hash(), altSequencer.L2Unsafe().Hash, "alt sequencer has built a conflicting block") // give the unsafe block to the verifier, and see if it reorgs because of any unsafe inputs @@ -776,7 +756,7 @@ func ConflictingL2Blocks(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { miner.ActL1StartBlock(12)(t) miner.ActL1IncludeTx(sd.RollupCfg.Genesis.SystemConfig.BatcherAddr)(t) miner.ActL1EndBlock(t) - l1Number := miner.l1Chain.CurrentHeader().Number.Uint64() + l1Number := miner.L1Chain().CurrentHeader().Number.Uint64() // show latest L1 block with new batch data to verifier, and make it sync. verifier.ActL1HeadSignal(t) @@ -793,24 +773,24 @@ func ConflictingL2Blocks(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { } func SyncAfterReorg(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { - t := NewDefaultTesting(gt) + t := actionsHelpers.NewDefaultTesting(gt) testingParams := e2eutils.TestParams{ MaxSequencerDrift: 60, SequencerWindowSize: 4, ChannelTimeout: 2, L1BlockTime: 12, } - sd, dp, miner, sequencer, seqEngine, verifier, _, batcher := setupReorgTest(t, &testingParams, deltaTimeOffset) + sd, dp, miner, sequencer, seqEngine, verifier, _, batcher := actionsHelpers.SetupReorgTest(t, &testingParams, deltaTimeOffset) l2Client := seqEngine.EthClient() log := testlog.Logger(t, log.LevelDebug) addresses := e2eutils.CollectAddresses(sd, dp) - l2UserEnv := &BasicUserEnv[*L2Bindings]{ + l2UserEnv := &actionsHelpers.BasicUserEnv[*actionsHelpers.L2Bindings]{ EthCl: l2Client, Signer: types.LatestSigner(sd.L2Cfg.Config), AddressCorpora: addresses, - Bindings: NewL2Bindings(t, l2Client, seqEngine.GethClient()), + Bindings: actionsHelpers.NewL2Bindings(t, l2Client, seqEngine.GethClient()), } - alice := NewCrossLayerUser(log, dp.Secrets.Alice, rand.New(rand.NewSource(0xa57b))) + alice := actionsHelpers.NewCrossLayerUser(log, dp.Secrets.Alice, rand.New(rand.NewSource(0xa57b))) alice.L2.SetUserEnv(l2UserEnv) sequencer.ActL2PipelineFull(t) @@ -820,11 +800,11 @@ func SyncAfterReorg(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { miner.ActL1SetFeeRecipient(common.Address{'A', 0}) miner.ActEmptyBlock(t) sequencer.ActL1HeadSignal(t) - for sequencer.engine.UnsafeL2Head().L1Origin.Number < sequencer.syncStatus.L1Head().Number { + for sequencer.L2Unsafe().L1Origin.Number < sequencer.SyncStatus().HeadL1.Number { // build L2 blocks until the L1 origin is the current L1 head(A0) sequencer.ActL2PipelineFull(t) sequencer.ActL2StartBlock(t) - if sequencer.engine.UnsafeL2Head().Number == 11 { + if sequencer.L2Unsafe().Number == 11 { // include a user tx at L2 block #12 to make a state transition alice.L2.ActResetTxOpts(t) alice.L2.ActSetTxToAddr(&dp.Addresses.Bob)(t) diff --git a/op-e2e/actions/system_config_test.go b/op-e2e/actions/derivation/system_config_test.go similarity index 87% rename from op-e2e/actions/system_config_test.go rename to op-e2e/actions/derivation/system_config_test.go index 452d5dbc300b4..bb62001de4a20 100644 --- a/op-e2e/actions/system_config_test.go +++ b/op-e2e/actions/derivation/system_config_test.go @@ -1,10 +1,12 @@ -package actions +package derivation import ( "math/big" "math/rand" "testing" + actionsHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" + upgradesHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/upgrades/helpers" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" @@ -49,27 +51,27 @@ func TestSystemConfigBatchType(t *testing.T) { // BatcherKeyRotation tests that batcher A can operate, then be replaced with batcher B, then ignore old batcher A, // and that the change to batcher B is reverted properly upon reorg of L1. func BatcherKeyRotation(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { - t := NewDefaultTesting(gt) + t := actionsHelpers.NewDefaultTesting(gt) - dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) + dp := e2eutils.MakeDeployParams(t, actionsHelpers.DefaultRollupTestParams) dp.DeployConfig.L2BlockTime = 2 - applyDeltaTimeOffset(dp, deltaTimeOffset) - sd := e2eutils.Setup(t, dp, defaultAlloc) + upgradesHelpers.ApplyDeltaTimeOffset(dp, deltaTimeOffset) + sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) log := testlog.Logger(t, log.LevelDebug) - miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) + miner, seqEngine, sequencer := actionsHelpers.SetupSequencerTest(t, sd, log) miner.ActL1SetFeeRecipient(common.Address{'A'}) sequencer.ActL2PipelineFull(t) - _, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) + _, verifier := actionsHelpers.SetupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) rollupSeqCl := sequencer.RollupClient() // the default batcher - batcherA := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp), + batcherA := actionsHelpers.NewL2Batcher(log, sd.RollupCfg, actionsHelpers.DefaultBatcherCfg(dp), rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) // a batcher with a new key - altCfg := *DefaultBatcherCfg(dp) + altCfg := *actionsHelpers.DefaultBatcherCfg(dp) altCfg.BatcherKey = dp.Secrets.Bob - batcherB := NewL2Batcher(log, sd.RollupCfg, &altCfg, + batcherB := actionsHelpers.NewL2Batcher(log, sd.RollupCfg, &altCfg, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) sequencer.ActL2PipelineFull(t) @@ -114,7 +116,7 @@ func BatcherKeyRotation(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { receipt, err := miner.EthClient().TransactionReceipt(t.Ctx(), tx.Hash()) require.NoError(t, err) - cfgChangeL1BlockNum := miner.l1Chain.CurrentBlock().Number.Uint64() + cfgChangeL1BlockNum := miner.L1Chain().CurrentBlock().Number.Uint64() require.Equal(t, cfgChangeL1BlockNum, receipt.BlockNumber.Uint64()) // sequence L2 blocks, and submit with new batcher @@ -225,9 +227,9 @@ func BatcherKeyRotation(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { // GPOParamsChange tests that the GPO params can be updated to adjust fees of L2 transactions, // and that the L1 data fees to the L2 transaction are applied correctly before, during and after the GPO update in L2. func GPOParamsChange(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { - t := NewDefaultTesting(gt) - dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) - applyDeltaTimeOffset(dp, deltaTimeOffset) + t := actionsHelpers.NewDefaultTesting(gt) + dp := e2eutils.MakeDeployParams(t, actionsHelpers.DefaultRollupTestParams) + upgradesHelpers.ApplyDeltaTimeOffset(dp, deltaTimeOffset) // activating Delta only, not Ecotone and further: // the GPO change assertions here all apply only for the Delta transition. @@ -236,14 +238,14 @@ func GPOParamsChange(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { dp.DeployConfig.L2GenesisFjordTimeOffset = nil dp.DeployConfig.L2GenesisGraniteTimeOffset = nil - sd := e2eutils.Setup(t, dp, defaultAlloc) + sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) log := testlog.Logger(t, log.LevelDebug) - miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) - batcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp), + miner, seqEngine, sequencer := actionsHelpers.SetupSequencerTest(t, sd, log) + batcher := actionsHelpers.NewL2Batcher(log, sd.RollupCfg, actionsHelpers.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]{ + alice := actionsHelpers.NewBasicUser[any](log, dp.Secrets.Alice, rand.New(rand.NewSource(1234))) + alice.SetUserEnv(&actionsHelpers.BasicUserEnv[any]{ EthCl: seqEngine.EthClient(), Signer: types.LatestSigner(sd.L2Cfg.Config), }) @@ -254,7 +256,7 @@ func GPOParamsChange(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { miner.ActEmptyBlock(t) sequencer.ActL1HeadSignal(t) sequencer.ActBuildToL1Head(t) - basefee := miner.l1Chain.CurrentBlock().BaseFee + basefee := miner.L1Chain().CurrentBlock().BaseFee // alice makes a L2 tx, sequencer includes it alice.ActResetTxOpts(t) @@ -299,7 +301,7 @@ func GPOParamsChange(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { miner.ActL1StartBlock(12)(t) miner.ActL1IncludeTx(dp.Addresses.SysCfgOwner)(t) miner.ActL1EndBlock(t) - basefeeGPOUpdate := miner.l1Chain.CurrentBlock().BaseFee + basefeeGPOUpdate := miner.L1Chain().CurrentBlock().BaseFee // build empty L2 chain, up to but excluding the L2 block with the L1 origin that processes the GPO change sequencer.ActL1HeadSignal(t) @@ -336,7 +338,7 @@ func GPOParamsChange(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { // build more L2 blocks, with new L1 origin miner.ActEmptyBlock(t) - basefee = miner.l1Chain.CurrentBlock().BaseFee + basefee = miner.L1Chain().CurrentBlock().BaseFee sequencer.ActL1HeadSignal(t) sequencer.ActBuildToL1Head(t) // and Alice makes a tx again @@ -360,13 +362,13 @@ func GPOParamsChange(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { // and that the L2 changes the gas limit instantly at the exact block that adopts the L1 origin with // the gas limit change event. And checks if a verifier node can reproduce the same gas limit change. func GasLimitChange(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { - t := NewDefaultTesting(gt) - dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) - applyDeltaTimeOffset(dp, deltaTimeOffset) - sd := e2eutils.Setup(t, dp, defaultAlloc) + t := actionsHelpers.NewDefaultTesting(gt) + dp := e2eutils.MakeDeployParams(t, actionsHelpers.DefaultRollupTestParams) + upgradesHelpers.ApplyDeltaTimeOffset(dp, deltaTimeOffset) + sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) log := testlog.Logger(t, log.LevelDebug) - miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) - batcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp), + miner, seqEngine, sequencer := actionsHelpers.SetupSequencerTest(t, sd, log) + batcher := actionsHelpers.NewL2Batcher(log, sd.RollupCfg, actionsHelpers.DefaultBatcherCfg(dp), sequencer.RollupClient(), miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) sequencer.ActL2PipelineFull(t) @@ -374,7 +376,7 @@ func GasLimitChange(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { sequencer.ActL1HeadSignal(t) sequencer.ActBuildToL1Head(t) - oldGasLimit := seqEngine.l2Chain.CurrentBlock().GasLimit + oldGasLimit := seqEngine.L2Chain().CurrentBlock().GasLimit require.Equal(t, oldGasLimit, uint64(dp.DeployConfig.L2GenesisBlockGasLimit)) // change gas limit on L1 to triple what it was @@ -396,12 +398,12 @@ func GasLimitChange(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { sequencer.ActL1HeadSignal(t) sequencer.ActBuildToL1HeadExcl(t) - require.Equal(t, oldGasLimit, seqEngine.l2Chain.CurrentBlock().GasLimit) + require.Equal(t, oldGasLimit, seqEngine.L2Chain().CurrentBlock().GasLimit) require.Equal(t, uint64(1), sequencer.SyncStatus().UnsafeL2.L1Origin.Number) // now include the L1 block with the gaslimit change, and see if it changes as expected sequencer.ActBuildToL1Head(t) - require.Equal(t, oldGasLimit*3, seqEngine.l2Chain.CurrentBlock().GasLimit) + require.Equal(t, oldGasLimit*3, seqEngine.L2Chain().CurrentBlock().GasLimit) require.Equal(t, uint64(2), sequencer.SyncStatus().UnsafeL2.L1Origin.Number) // now submit all this to L1, and see if a verifier can sync and reproduce it @@ -410,7 +412,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), miner.BlobStore(), &sync.Config{}) + _, verifier := actionsHelpers.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/action.go b/op-e2e/actions/helpers/action.go similarity index 99% rename from op-e2e/actions/action.go rename to op-e2e/actions/helpers/action.go index 551ab58d96322..3f8bba669242d 100644 --- a/op-e2e/actions/action.go +++ b/op-e2e/actions/helpers/action.go @@ -1,4 +1,4 @@ -package actions +package helpers import ( "context" diff --git a/op-e2e/actions/garbage_channel_out.go b/op-e2e/actions/helpers/garbage_channel_out.go similarity index 94% rename from op-e2e/actions/garbage_channel_out.go rename to op-e2e/actions/helpers/garbage_channel_out.go index a24cca7c2c03f..6d813520a10a9 100644 --- a/op-e2e/actions/garbage_channel_out.go +++ b/op-e2e/actions/helpers/garbage_channel_out.go @@ -1,4 +1,4 @@ -package actions +package helpers import ( "bytes" @@ -36,10 +36,29 @@ var GarbageKinds = []GarbageKind{ MALFORM_RLP, } +func (gk GarbageKind) String() string { + switch gk { + case STRIP_VERSION: + return "STRIP_VERSION" + case RANDOM: + return "RANDOM" + case TRUNCATE_END: + return "TRUNCATE_END" + case DIRTY_APPEND: + return "DIRTY_APPEND" + case INVALID_COMPRESSION: + return "INVALID_COMPRESSION" + case MALFORM_RLP: + return "MALFORM_RLP" + default: + return "UNKNOWN" + } +} + // GarbageChannelCfg is the configuration for a `GarbageChannelOut` type GarbageChannelCfg struct { - useInvalidCompression bool - malformRLP bool + UseInvalidCompression bool + MalformRLP bool } // Writer is the interface shared between `zlib.Writer` and `gzip.Writer` @@ -109,7 +128,7 @@ func NewGarbageChannelOut(cfg *GarbageChannelCfg) (*GarbageChannelOut, error) { // Optionally use zlib or gzip compression var compress Writer - if cfg.useInvalidCompression { + if cfg.UseInvalidCompression { compress, err = gzip.NewWriterLevel(&c.buf, gzip.BestCompression) } else { compress, err = zlib.NewWriterLevel(&c.buf, zlib.BestCompression) @@ -152,7 +171,7 @@ func (co *GarbageChannelOut) AddBlock(rollupCfg *rollup.Config, block *types.Blo if err := rlp.Encode(&buf, batch); err != nil { return err } - if co.cfg.malformRLP { + if co.cfg.MalformRLP { // Malform the RLP by incrementing the length prefix by 1. bufBytes := buf.Bytes() bufBytes[0] += 1 diff --git a/op-e2e/actions/l1_miner.go b/op-e2e/actions/helpers/l1_miner.go similarity index 89% rename from op-e2e/actions/l1_miner.go rename to op-e2e/actions/helpers/l1_miner.go index 9026d74db1780..5fe5c762d5c9f 100644 --- a/op-e2e/actions/l1_miner.go +++ b/op-e2e/actions/helpers/l1_miner.go @@ -1,8 +1,9 @@ -package actions +package helpers import ( "math/big" + "github.com/ethereum-optimism/optimism/op-program/host/prefetcher" "github.com/stretchr/testify/require" "github.com/ethereum/go-ethereum/common" @@ -17,7 +18,6 @@ import ( "github.com/ethereum/go-ethereum/trie" "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" ) @@ -33,9 +33,9 @@ type L1Miner struct { // L1 block building data l1BuildingHeader *types.Header // block header that we add txs to for block building l1BuildingState *state.StateDB // state used for block building - l1GasPool *core.GasPool // track gas used of ongoing building + L1GasPool *core.GasPool // track gas used of ongoing building pendingIndices map[common.Address]uint64 // per account, how many txs from the pool were already included in the block, since the pool is lagging behind block mining. - l1Transactions []*types.Transaction // collects txs that were successfully included into current block build + L1Transactions []*types.Transaction // collects txs that were successfully included into current block build l1Receipts []*types.Receipt // collect receipts of ongoing building l1Building bool l1TxFailed []*types.Transaction // log of failed transactions which could not be included @@ -52,7 +52,11 @@ func NewL1Miner(t Testing, log log.Logger, genesis *core.Genesis) *L1Miner { } } -func (s *L1Miner) BlobStore() derive.L1BlobsFetcher { +func (s *L1Miner) BlobSource() prefetcher.L1BlobSource { + return s.blobStore +} + +func (s *L1Miner) BlobStore() *e2eutils.BlobsStore { return s.blobStore } @@ -120,11 +124,11 @@ func (s *L1Miner) ActL1StartBlock(timeDelta uint64) Action { s.l1BuildingHeader = header s.l1BuildingState = statedb s.l1Receipts = make([]*types.Receipt, 0) - s.l1Transactions = make([]*types.Transaction, 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) + s.L1GasPool = new(core.GasPool).AddGas(header.GasLimit) } } @@ -138,7 +142,7 @@ func (s *L1Miner) ActL1IncludeTx(from common.Address) Action { getPendingIndex := func(from common.Address) uint64 { return s.pendingIndices[from] } - tx := firstValidTx(t, from, getPendingIndex, s.eth.TxPool().ContentFrom, s.EthClient().NonceAt) + tx := firstValidTx(t, from, getPendingIndex, s.Eth.TxPool().ContentFrom, s.EthClient().NonceAt) s.IncludeTx(t, tx) s.pendingIndices[from] = s.pendingIndices[from] + 1 // won't retry the tx } @@ -151,7 +155,7 @@ func (s *L1Miner) ActL1IncludeTxByHash(txHash common.Hash) Action { t.InvalidAction("no tx inclusion when not building l1 block") return } - tx := s.eth.TxPool().Get(txHash) + 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) @@ -167,19 +171,19 @@ func (s *L1Miner) IncludeTx(t Testing, tx *types.Transaction) { if tx.Gas() > s.l1BuildingHeader.GasLimit { t.Fatalf("tx consumes %d gas, more than available in L1 block %d", tx.Gas(), s.l1BuildingHeader.GasLimit) } - if tx.Gas() > uint64(*s.l1GasPool) { - t.InvalidAction("action takes too much gas: %d, only have %d", tx.Gas(), uint64(*s.l1GasPool)) + if tx.Gas() > uint64(*s.L1GasPool) { + t.InvalidAction("action takes too much gas: %d, only have %d", tx.Gas(), uint64(*s.L1GasPool)) return } - s.l1BuildingState.SetTxContext(tx.Hash(), len(s.l1Transactions)) + 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.WithoutBlobTxSidecar(), &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) + 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.WithoutBlobTxSidecar()) + 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() @@ -205,7 +209,7 @@ func (s *L1Miner) ActL1EndBlock(t Testing) { } s.l1Building = false - s.l1BuildingHeader.GasUsed = s.l1BuildingHeader.GasLimit - uint64(*s.l1GasPool) + s.l1BuildingHeader.GasUsed = s.l1BuildingHeader.GasLimit - uint64(*s.L1GasPool) s.l1BuildingHeader.Root = s.l1BuildingState.IntermediateRoot(s.l1Cfg.Config.IsEIP158(s.l1BuildingHeader.Number)) var withdrawals []*types.Withdrawal @@ -213,7 +217,7 @@ func (s *L1Miner) ActL1EndBlock(t Testing) { withdrawals = make([]*types.Withdrawal, 0) } - block := types.NewBlock(s.l1BuildingHeader, &types.Body{Transactions: s.l1Transactions, Withdrawals: withdrawals}, s.l1Receipts, trie.NewStackTrie(nil)) + block := types.NewBlock(s.l1BuildingHeader, &types.Body{Transactions: s.L1Transactions, Withdrawals: withdrawals}, s.l1Receipts, trie.NewStackTrie(nil)) if s.l1Cfg.Config.IsCancun(s.l1BuildingHeader.Number, s.l1BuildingHeader.Time) { parent := s.l1Chain.GetHeaderByHash(s.l1BuildingHeader.ParentHash) var ( @@ -240,7 +244,8 @@ func (s *L1Miner) ActL1EndBlock(t Testing) { for _, sidecar := range s.l1BuildingBlobSidecars { for i, h := range sidecar.BlobHashes() { blob := (*eth.Blob)(&sidecar.Blobs[i]) - s.blobStore.StoreBlob(block.Hash(), h, blob) + indexedHash := eth.IndexedBlobHash{Index: uint64(i), Hash: h} + s.blobStore.StoreBlob(block.Time(), indexedHash, blob) } } _, err = s.l1Chain.InsertChain(types.Blocks{block}) diff --git a/op-e2e/actions/l1_miner_test.go b/op-e2e/actions/helpers/l1_miner_test.go similarity index 94% rename from op-e2e/actions/l1_miner_test.go rename to op-e2e/actions/helpers/l1_miner_test.go index 10e4c0c5498cd..b102dcaf84f0e 100644 --- a/op-e2e/actions/l1_miner_test.go +++ b/op-e2e/actions/helpers/l1_miner_test.go @@ -1,4 +1,4 @@ -package actions +package helpers import ( "math/big" @@ -15,8 +15,8 @@ import ( func TestL1Miner_BuildBlock(gt *testing.T) { t := NewDefaultTesting(gt) - dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) - sd := e2eutils.Setup(t, dp, defaultAlloc) + dp := e2eutils.MakeDeployParams(t, DefaultRollupTestParams) + sd := e2eutils.Setup(t, dp, DefaultAlloc) log := testlog.Logger(t, log.LevelDebug) miner := NewL1Miner(t, log, sd.L1Cfg) t.Cleanup(func() { diff --git a/op-e2e/actions/l1_replica.go b/op-e2e/actions/helpers/l1_replica.go similarity index 96% rename from op-e2e/actions/l1_replica.go rename to op-e2e/actions/helpers/l1_replica.go index fb042757065e2..7b089a4f7fa98 100644 --- a/op-e2e/actions/l1_replica.go +++ b/op-e2e/actions/helpers/l1_replica.go @@ -1,4 +1,4 @@ -package actions +package helpers import ( "errors" @@ -38,7 +38,7 @@ type L1Replica struct { log log.Logger node *node.Node - eth *eth.Ethereum + Eth *eth.Ethereum // L1 evm / chain l1Chain *core.BlockChain @@ -67,6 +67,8 @@ func NewL1Replica(t Testing, log log.Logger, genesis *core.Genesis) *L1Replica { Name: "l1-geth", WSHost: "127.0.0.1", WSPort: 0, + HTTPHost: "127.0.0.1", + HTTPPort: 0, WSModules: []string{"debug", "admin", "eth", "txpool", "net", "rpc", "web3", "personal"}, HTTPModules: []string{"debug", "admin", "eth", "txpool", "net", "rpc", "web3", "personal"}, DataDir: "", // in-memory @@ -90,7 +92,7 @@ func NewL1Replica(t Testing, log log.Logger, genesis *core.Genesis) *L1Replica { return &L1Replica{ log: log, node: n, - eth: backend, + Eth: backend, l1Chain: backend.BlockChain(), l1Database: backend.ChainDb(), l1Cfg: genesis, @@ -168,6 +170,10 @@ func (s *L1Replica) MockL1RPCErrors(fn func() error) { } } +func (s *L1Replica) HTTPEndpoint() string { + return s.node.HTTPEndpoint() +} + func (s *L1Replica) EthClient() *ethclient.Client { cl := s.node.Attach() return ethclient.NewClient(cl) @@ -192,6 +198,10 @@ func (s *L1Replica) L1Client(t Testing, cfg *rollup.Config) *sources.L1Client { return l1F } +func (s *L1Replica) L1Chain() *core.BlockChain { + return s.l1Chain +} + func (s *L1Replica) UnsafeNum() uint64 { head := s.l1Chain.CurrentBlock() headNum := uint64(0) diff --git a/op-e2e/actions/l1_replica_test.go b/op-e2e/actions/helpers/l1_replica_test.go similarity index 90% rename from op-e2e/actions/l1_replica_test.go rename to op-e2e/actions/helpers/l1_replica_test.go index ab918a619644e..5bfe2212f59e8 100644 --- a/op-e2e/actions/l1_replica_test.go +++ b/op-e2e/actions/helpers/l1_replica_test.go @@ -1,4 +1,4 @@ -package actions +package helpers import ( "encoding/binary" @@ -21,20 +21,11 @@ import ( "github.com/ethereum-optimism/optimism/op-service/testlog" ) -var defaultRollupTestParams = &e2eutils.TestParams{ - MaxSequencerDrift: 40, - SequencerWindowSize: 120, - ChannelTimeout: 120, - L1BlockTime: 15, -} - -var defaultAlloc = &e2eutils.AllocParams{PrefundTestUsers: true} - // Test if we can mock an RPC failure func TestL1Replica_ActL1RPCFail(gt *testing.T) { t := NewDefaultTesting(gt) - dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) - sd := e2eutils.Setup(t, dp, defaultAlloc) + dp := e2eutils.MakeDeployParams(t, DefaultRollupTestParams) + sd := e2eutils.Setup(t, dp, DefaultAlloc) log := testlog.Logger(t, log.LevelDebug) replica := NewL1Replica(t, log, sd.L1Cfg) t.Cleanup(func() { @@ -55,9 +46,9 @@ func TestL1Replica_ActL1RPCFail(gt *testing.T) { // Test if we can make the replica sync an artificial L1 chain, rewind it, and reorg it func TestL1Replica_ActL1Sync(gt *testing.T) { t := NewDefaultTesting(gt) - dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) + dp := e2eutils.MakeDeployParams(t, DefaultRollupTestParams) dp.DeployConfig.L1CancunTimeOffset = nil - sd := e2eutils.Setup(t, dp, defaultAlloc) + sd := e2eutils.Setup(t, dp, DefaultAlloc) log := testlog.Logger(t, log.LevelDebug) genesisBlock := sd.L1Cfg.ToBlock() consensus := beacon.New(ethash.NewFaker()) diff --git a/op-e2e/actions/l2_batcher.go b/op-e2e/actions/helpers/l2_batcher.go similarity index 82% rename from op-e2e/actions/l2_batcher.go rename to op-e2e/actions/helpers/l2_batcher.go index 42fe7c8b2bcdb..d9e6fe3dbec50 100644 --- a/op-e2e/actions/l2_batcher.go +++ b/op-e2e/actions/helpers/l2_batcher.go @@ -1,4 +1,4 @@ -package actions +package helpers import ( "bytes" @@ -106,12 +106,12 @@ type L2Batcher struct { l1Signer types.Signer - l2ChannelOut ChannelOutIface + L2ChannelOut ChannelOutIface l2Submitting bool // when the channel out is being submitted, and not safe to write to without resetting - l2BufferedBlock eth.L2BlockRef + L2BufferedBlock eth.L2BlockRef l2SubmittedBlock eth.L2BlockRef l2BatcherCfg *BatcherCfg - batcherAddr common.Address + BatcherAddr common.Address LastSubmitted *types.Transaction } @@ -126,7 +126,7 @@ func NewL2Batcher(log log.Logger, rollupCfg *rollup.Config, batcherCfg *BatcherC engCl: engCl, l2BatcherCfg: batcherCfg, l1Signer: types.LatestSignerForChainID(rollupCfg.L1ChainID), - batcherAddr: crypto.PubkeyToAddress(batcherCfg.BatcherKey.PublicKey), + BatcherAddr: crypto.PubkeyToAddress(batcherCfg.BatcherKey.PublicKey), } } @@ -136,15 +136,25 @@ func (s *L2Batcher) SubmittingData() bool { return s.l2Submitting } +// Reset the batcher state, clearing any buffered data. +func (s *L2Batcher) Reset() { + s.L2ChannelOut = nil + s.l2Submitting = false + s.L2BufferedBlock = eth.L2BlockRef{} + s.l2SubmittedBlock = eth.L2BlockRef{} +} + // ActL2BatchBuffer adds the next L2 block to the batch buffer. // If the buffer is being submitted, the buffer is wiped. func (s *L2Batcher) ActL2BatchBuffer(t Testing) { require.NoError(t, s.Buffer(t), "failed to add block to channel") } -func (s *L2Batcher) Buffer(t Testing) error { +type BlockModifier = func(block *types.Block) + +func (s *L2Batcher) Buffer(t Testing, opts ...BlockModifier) error { if s.l2Submitting { // break ongoing submitting work if necessary - s.l2ChannelOut = nil + s.L2ChannelOut = nil s.l2Submitting = false } syncStatus, err := s.syncStatusAPI.SyncStatus(t.Ctx()) @@ -153,38 +163,45 @@ func (s *L2Batcher) Buffer(t Testing) error { if s.l2SubmittedBlock == (eth.L2BlockRef{}) { s.log.Info("Starting batch-submitter work at safe-head", "safe", syncStatus.SafeL2) s.l2SubmittedBlock = syncStatus.SafeL2 - s.l2BufferedBlock = syncStatus.SafeL2 - s.l2ChannelOut = nil + s.L2BufferedBlock = syncStatus.SafeL2 + s.L2ChannelOut = nil } // If it's lagging behind, catch it up. if s.l2SubmittedBlock.Number < syncStatus.SafeL2.Number { s.log.Warn("last submitted block lagged behind L2 safe head: batch submission will continue from the safe head now", "last", s.l2SubmittedBlock, "safe", syncStatus.SafeL2) s.l2SubmittedBlock = syncStatus.SafeL2 - s.l2BufferedBlock = syncStatus.SafeL2 - s.l2ChannelOut = nil + s.L2BufferedBlock = syncStatus.SafeL2 + s.L2ChannelOut = nil } // Add the next unsafe block to the channel - if s.l2BufferedBlock.Number >= syncStatus.UnsafeL2.Number { - if s.l2BufferedBlock.Number > syncStatus.UnsafeL2.Number || s.l2BufferedBlock.Hash != syncStatus.UnsafeL2.Hash { + if s.L2BufferedBlock.Number >= syncStatus.UnsafeL2.Number { + if s.L2BufferedBlock.Number > syncStatus.UnsafeL2.Number || s.L2BufferedBlock.Hash != syncStatus.UnsafeL2.Hash { s.log.Error("detected a reorg in L2 chain vs previous buffered information, resetting to safe head now", "safe_head", syncStatus.SafeL2) s.l2SubmittedBlock = syncStatus.SafeL2 - s.l2BufferedBlock = syncStatus.SafeL2 - s.l2ChannelOut = nil + s.L2BufferedBlock = syncStatus.SafeL2 + s.L2ChannelOut = nil } else { s.log.Info("nothing left to submit") return nil } } - block, err := s.l2.BlockByNumber(t.Ctx(), big.NewInt(int64(s.l2BufferedBlock.Number+1))) + + block, err := s.l2.BlockByNumber(t.Ctx(), big.NewInt(int64(s.L2BufferedBlock.Number+1))) require.NoError(t, err, "need l2 block %d from sync status", s.l2SubmittedBlock.Number+1) - if block.ParentHash() != s.l2BufferedBlock.Hash { + if block.ParentHash() != s.L2BufferedBlock.Hash { s.log.Error("detected a reorg in L2 chain vs previous submitted information, resetting to safe head now", "safe_head", syncStatus.SafeL2) s.l2SubmittedBlock = syncStatus.SafeL2 - s.l2BufferedBlock = syncStatus.SafeL2 - s.l2ChannelOut = nil + s.L2BufferedBlock = syncStatus.SafeL2 + s.L2ChannelOut = nil + } + + // Apply modifications to the block + for _, f := range opts { + f(block) } + // Create channel if we don't have one yet - if s.l2ChannelOut == nil { + if s.L2ChannelOut == nil { var ch ChannelOutIface if s.l2BatcherCfg.GarbageCfg != nil { ch, err = NewGarbageChannelOut(s.l2BatcherCfg.GarbageCfg) @@ -202,7 +219,7 @@ func (s *L2Batcher) Buffer(t Testing) error { chainSpec := rollup.NewChainSpec(s.rollupCfg) // use span batch if we're forcing it or if we're at/beyond delta if s.l2BatcherCfg.ForceSubmitSpanBatch || s.rollupCfg.IsDelta(block.Time()) { - ch, err = derive.NewSpanChannelOut(s.rollupCfg.Genesis.L2Time, s.rollupCfg.L2ChainID, target, derive.Zlib, chainSpec) + ch, err = derive.NewSpanChannelOut(target, derive.Zlib, chainSpec) // use singular batches in all other cases } else { ch, err = derive.NewSingularChannelOut(c, chainSpec) @@ -210,53 +227,60 @@ func (s *L2Batcher) Buffer(t Testing) error { } } require.NoError(t, err, "failed to create channel") - s.l2ChannelOut = ch + s.L2ChannelOut = ch } - if err := s.l2ChannelOut.AddBlock(s.rollupCfg, block); err != nil { + if err := s.L2ChannelOut.AddBlock(s.rollupCfg, block); err != nil { return err } ref, err := s.engCl.L2BlockRefByHash(t.Ctx(), block.Hash()) require.NoError(t, err, "failed to get L2BlockRef") - s.l2BufferedBlock = ref + s.L2BufferedBlock = ref return nil } func (s *L2Batcher) ActL2ChannelClose(t Testing) { // Don't run this action if there's no data to submit - if s.l2ChannelOut == nil { + if s.L2ChannelOut == nil { t.InvalidAction("need to buffer data first, cannot batch submit with empty buffer") return } - require.NoError(t, s.l2ChannelOut.Close(), "must close channel before submitting it") + require.NoError(t, s.L2ChannelOut.Close(), "must close channel before submitting it") } -// ActL2BatchSubmit constructs a batch tx from previous buffered L2 blocks, and submits it to L1 -func (s *L2Batcher) ActL2BatchSubmit(t Testing, txOpts ...func(tx *types.DynamicFeeTx)) { +func (s *L2Batcher) ReadNextOutputFrame(t Testing) []byte { // Don't run this action if there's no data to submit - if s.l2ChannelOut == nil { + if s.L2ChannelOut == nil { t.InvalidAction("need to buffer data first, cannot batch submit with empty buffer") - return + return nil } // Collect the output frame data := new(bytes.Buffer) data.WriteByte(derive.DerivationVersion0) // subtract one, to account for the version byte - if _, err := s.l2ChannelOut.OutputFrame(data, s.l2BatcherCfg.MaxL1TxSize-1); err == io.EOF { - s.l2ChannelOut = nil + if _, err := s.L2ChannelOut.OutputFrame(data, s.l2BatcherCfg.MaxL1TxSize-1); err == io.EOF { + s.L2ChannelOut = nil s.l2Submitting = false } else if err != nil { s.l2Submitting = false t.Fatalf("failed to output channel data to frame: %v", err) } - payload := data.Bytes() + return data.Bytes() +} + +// ActL2BatchSubmit constructs a batch tx from previous buffered L2 blocks, and submits it to L1 +func (s *L2Batcher) ActL2BatchSubmit(t Testing, txOpts ...func(tx *types.DynamicFeeTx)) { + s.ActL2BatchSubmitRaw(t, s.ReadNextOutputFrame(t), txOpts...) +} + +func (s *L2Batcher) ActL2BatchSubmitRaw(t Testing, payload []byte, txOpts ...func(tx *types.DynamicFeeTx)) { if s.l2BatcherCfg.UseAltDA { comm, err := s.l2BatcherCfg.AltDA.SetInput(t.Ctx(), payload) require.NoError(t, err, "failed to set input for altda") payload = comm.TxData() } - nonce, err := s.l1.PendingNonceAt(t.Ctx(), s.batcherAddr) + nonce, err := s.l1.PendingNonceAt(t.Ctx(), s.BatcherAddr) require.NoError(t, err, "need batcher nonce") gasTipCap := big.NewInt(2 * params.GWei) @@ -327,7 +351,7 @@ func (s *L2Batcher) ActL2BatchSubmitMultiBlob(t Testing, numBlobs int) { } // Don't run this action if there's no data to submit - if s.l2ChannelOut == nil { + if s.L2ChannelOut == nil { t.InvalidAction("need to buffer data first, cannot batch submit with empty buffer") return } @@ -344,12 +368,12 @@ func (s *L2Batcher) ActL2BatchSubmitMultiBlob(t Testing, numBlobs int) { // subtract one, to account for the version byte l = s.l2BatcherCfg.MaxL1TxSize - 1 } - if _, err := s.l2ChannelOut.OutputFrame(data, l); err == io.EOF { + 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 + s.L2ChannelOut = nil } else if err != nil { s.l2Submitting = false t.Fatalf("failed to output channel data to frame: %v", err) @@ -359,7 +383,7 @@ func (s *L2Batcher) ActL2BatchSubmitMultiBlob(t Testing, numBlobs int) { require.NoError(t, blobs[i].FromData(data.Bytes()), "must turn data into blob") } - nonce, err := s.l1.PendingNonceAt(t.Ctx(), s.batcherAddr) + nonce, err := s.l1.PendingNonceAt(t.Ctx(), s.BatcherAddr) require.NoError(t, err, "need batcher nonce") gasTipCap := big.NewInt(2 * params.GWei) @@ -401,27 +425,14 @@ func (s *L2Batcher) ActL2BatchSubmitMultiBlob(t Testing, numBlobs int) { // batch inbox. This *should* cause the batch inbox to reject the blocks // encoded within the frame, even if the blocks themselves are valid. func (s *L2Batcher) ActL2BatchSubmitGarbage(t Testing, kind GarbageKind) { - // 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 frame - data := new(bytes.Buffer) - data.WriteByte(derive.DerivationVersion0) - - // subtract one, to account for the version byte - if _, err := s.l2ChannelOut.OutputFrame(data, s.l2BatcherCfg.MaxL1TxSize-1); err == io.EOF { - s.l2ChannelOut = nil - s.l2Submitting = false - } else if err != nil { - s.l2Submitting = false - t.Fatalf("failed to output channel data to frame: %v", err) - } - - outputFrame := data.Bytes() + outputFrame := s.ReadNextOutputFrame(t) + s.ActL2BatchSubmitGarbageRaw(t, outputFrame, kind) +} +// ActL2BatchSubmitGarbageRaw constructs a malformed channel frame from `outputFrame` and submits it to the +// batch inbox. This *should* cause the batch inbox to reject the blocks +// encoded within the frame, even if the blocks themselves are valid. +func (s *L2Batcher) ActL2BatchSubmitGarbageRaw(t Testing, outputFrame []byte, kind GarbageKind) { // Malform the output frame switch kind { // Strip the derivation version byte from the output frame @@ -453,37 +464,13 @@ func (s *L2Batcher) ActL2BatchSubmitGarbage(t Testing, kind GarbageKind) { t.Fatalf("Unexpected garbage kind: %v", kind) } - 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))) - - rawTx := &types.DynamicFeeTx{ - ChainID: s.rollupCfg.L1ChainID, - Nonce: nonce, - To: &s.rollupCfg.BatchInboxAddress, - GasTipCap: gasTipCap, - GasFeeCap: gasFeeCap, - Data: outputFrame, - } - 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) - require.NoError(t, err, "need to sign tx") - - err = s.l1.SendTransaction(t.Ctx(), tx) - require.NoError(t, err, "need to send tx") + s.ActL2BatchSubmitRaw(t, outputFrame) } func (s *L2Batcher) ActBufferAll(t Testing) { stat, err := s.syncStatusAPI.SyncStatus(t.Ctx()) require.NoError(t, err) - for s.l2BufferedBlock.Number < stat.UnsafeL2.Number { + for s.L2BufferedBlock.Number < stat.UnsafeL2.Number { s.ActL2BatchBuffer(t) } } diff --git a/op-e2e/actions/l2_engine.go b/op-e2e/actions/helpers/l2_engine.go similarity index 88% rename from op-e2e/actions/l2_engine.go rename to op-e2e/actions/helpers/l2_engine.go index 54267ee9da589..5839a20798d31 100644 --- a/op-e2e/actions/l2_engine.go +++ b/op-e2e/actions/helpers/l2_engine.go @@ -1,4 +1,4 @@ -package actions +package helpers import ( "errors" @@ -35,7 +35,7 @@ type L2Engine struct { log log.Logger node *node.Node - eth *geth.Ethereum + Eth *geth.Ethereum rollupGenesis *rollup.Genesis @@ -43,9 +43,9 @@ type L2Engine struct { l2Chain *core.BlockChain l2Signer types.Signer - engineApi *engineapi.L2EngineAPI + EngineApi *engineapi.L2EngineAPI - failL2RPC func(call []rpc.BatchElem) error // mock error + FailL2RPC func(call []rpc.BatchElem) error // mock error } type EngineOption func(ethCfg *ethconfig.Config, nodeCfg *node.Config) error @@ -58,7 +58,7 @@ func NewL2Engine(t Testing, log log.Logger, genesis *core.Genesis, rollupGenesis eng := &L2Engine{ log: log, node: n, - eth: ethBackend, + Eth: ethBackend, rollupGenesis: &rollup.Genesis{ L1: rollupGenesisL1, L2: eth.BlockID{Hash: genesisBlock.Hash(), Number: genesisBlock.NumberU64()}, @@ -66,14 +66,14 @@ func NewL2Engine(t Testing, log log.Logger, genesis *core.Genesis, rollupGenesis }, l2Chain: chain, l2Signer: types.LatestSigner(genesis.Config), - engineApi: engineApi, + EngineApi: engineApi, } // register the custom engine API, so we can serve engine requests while having more control // over sequencing of individual txs. n.RegisterAPIs([]rpc.API{ { Namespace: "engine", - Service: eng.engineApi, + Service: eng.EngineApi, Authenticated: true, }, }) @@ -93,6 +93,8 @@ func newBackend(t e2eutils.TestingBase, genesis *core.Genesis, jwtPath string, o Name: "l2-geth", WSHost: "127.0.0.1", WSPort: 0, + HTTPHost: "127.0.0.1", + HTTPPort: 0, AuthAddr: "127.0.0.1", AuthPort: 0, WSModules: []string{"debug", "admin", "eth", "txpool", "net", "rpc", "web3", "personal"}, @@ -135,6 +137,10 @@ func (e *engineApiBackend) Genesis() *core.Genesis { return e.genesis } +func (s *L2Engine) L2Chain() *core.BlockChain { + return s.l2Chain +} + func (s *L2Engine) Enode() *enode.Node { return s.node.Server().LocalNode().Node() } @@ -149,6 +155,10 @@ func (s *L2Engine) PeerCount() int { return s.node.Server().PeerCount() } +func (s *L2Engine) HTTPEndpoint() string { + return s.node.HTTPEndpoint() +} + func (s *L2Engine) EthClient() *ethclient.Client { cl := s.node.Attach() return ethclient.NewClient(cl) @@ -164,10 +174,10 @@ func (e *L2Engine) RPCClient() client.RPC { return testutils.RPCErrFaker{ RPC: client.NewBaseRPCClient(cl), ErrFn: func(call []rpc.BatchElem) error { - if e.failL2RPC == nil { + if e.FailL2RPC == nil { return nil } - return e.failL2RPC(call) + return e.FailL2RPC(call) }, } } @@ -180,12 +190,12 @@ func (e *L2Engine) EngineClient(t Testing, cfg *rollup.Config) *sources.EngineCl // 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? + if e.FailL2RPC != nil { // already set to fail? t.InvalidAction("already set a mock L2 rpc error") return } - e.failL2RPC = func(call []rpc.BatchElem) error { - e.failL2RPC = nil + e.FailL2RPC = func(call []rpc.BatchElem) error { + e.FailL2RPC = nil return err } } @@ -193,13 +203,13 @@ func (e *L2Engine) ActL2RPCFail(t Testing, err error) { // ActL2IncludeTx includes the next transaction from the given address in the block that is being built func (e *L2Engine) ActL2IncludeTx(from common.Address) Action { return func(t Testing) { - if e.engineApi.ForcedEmpty() { + if e.EngineApi.ForcedEmpty() { e.log.Info("Skipping including a transaction because e.L2ForceEmpty is true") return } - tx := firstValidTx(t, from, e.engineApi.PendingIndices, e.eth.TxPool().ContentFrom, e.EthClient().NonceAt) - err := e.engineApi.IncludeTx(tx, from) + tx := firstValidTx(t, from, e.EngineApi.PendingIndices, e.Eth.TxPool().ContentFrom, e.EthClient().NonceAt) + err := e.EngineApi.IncludeTx(tx, from) if errors.Is(err, engineapi.ErrNotBuildingBlock) { t.InvalidAction(err.Error()) } else if errors.Is(err, engineapi.ErrUsesTooMuchGas) { diff --git a/op-e2e/actions/l2_engine_test.go b/op-e2e/actions/helpers/l2_engine_test.go similarity index 95% rename from op-e2e/actions/l2_engine_test.go rename to op-e2e/actions/helpers/l2_engine_test.go index 5d7a537b5d03b..d74595d316213 100644 --- a/op-e2e/actions/l2_engine_test.go +++ b/op-e2e/actions/helpers/l2_engine_test.go @@ -1,4 +1,4 @@ -package actions +package helpers import ( "encoding/binary" @@ -31,8 +31,8 @@ import ( func TestL2EngineAPI(gt *testing.T) { t := NewDefaultTesting(gt) jwtPath := e2eutils.WriteDefaultJWT(t) - dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) - sd := e2eutils.Setup(t, dp, defaultAlloc) + dp := e2eutils.MakeDeployParams(t, DefaultRollupTestParams) + sd := e2eutils.Setup(t, dp, DefaultAlloc) log := testlog.Logger(t, log.LevelDebug) genesisBlock := sd.L2Cfg.ToBlock() consensus := beacon.New(ethash.NewFaker()) @@ -107,8 +107,8 @@ func TestL2EngineAPI(gt *testing.T) { func TestL2EngineAPIBlockBuilding(gt *testing.T) { t := NewDefaultTesting(gt) jwtPath := e2eutils.WriteDefaultJWT(t) - dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) - sd := e2eutils.Setup(t, dp, defaultAlloc) + dp := e2eutils.MakeDeployParams(t, DefaultRollupTestParams) + sd := e2eutils.Setup(t, dp, DefaultAlloc) log := testlog.Logger(t, log.LevelDebug) genesisBlock := sd.L2Cfg.ToBlock() db := rawdb.NewMemoryDatabase() @@ -208,8 +208,8 @@ func TestL2EngineAPIBlockBuilding(gt *testing.T) { func TestL2EngineAPIFail(gt *testing.T) { t := NewDefaultTesting(gt) jwtPath := e2eutils.WriteDefaultJWT(t) - dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) - sd := e2eutils.Setup(t, dp, defaultAlloc) + dp := e2eutils.MakeDeployParams(t, DefaultRollupTestParams) + sd := e2eutils.Setup(t, dp, DefaultAlloc) log := testlog.Logger(t, log.LevelDebug) engine := NewL2Engine(t, log, sd.L2Cfg, sd.RollupCfg.Genesis.L1, jwtPath) // mock an RPC failure @@ -228,8 +228,8 @@ func TestL2EngineAPIFail(gt *testing.T) { func TestEngineAPITests(t *testing.T) { test.RunEngineAPITests(t, func(t *testing.T) engineapi.EngineBackend { jwtPath := e2eutils.WriteDefaultJWT(t) - dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) - sd := e2eutils.Setup(t, dp, defaultAlloc) + dp := e2eutils.MakeDeployParams(t, DefaultRollupTestParams) + sd := e2eutils.Setup(t, dp, DefaultAlloc) n, _, apiBackend := newBackend(t, sd.L2Cfg, jwtPath, nil) err := n.Start() require.NoError(t, err) diff --git a/op-e2e/actions/l2_proposer.go b/op-e2e/actions/helpers/l2_proposer.go similarity index 96% rename from op-e2e/actions/l2_proposer.go rename to op-e2e/actions/helpers/l2_proposer.go index 9298548f0abf0..f1a0c4d0d6344 100644 --- a/op-e2e/actions/l2_proposer.go +++ b/op-e2e/actions/helpers/l2_proposer.go @@ -1,4 +1,4 @@ -package actions +package helpers import ( "context" @@ -69,6 +69,10 @@ func (f fakeTxMgr) Send(_ context.Context, _ txmgr.TxCandidate) (*types.Receipt, panic("unimplemented") } +func (f fakeTxMgr) SendAsync(ctx context.Context, candidate txmgr.TxCandidate, ch chan txmgr.SendResponse) { + panic("unimplemented") +} + func (f fakeTxMgr) Close() { } @@ -80,6 +84,10 @@ func (f fakeTxMgr) API() rpc.API { panic("unimplemented") } +func (f fakeTxMgr) SuggestGasPriceCaps(context.Context) (*big.Int, *big.Int, *big.Int, error) { + panic("unimplemented") +} + func NewL2Proposer(t Testing, log log.Logger, cfg *ProposerCfg, l1 *ethclient.Client, rollupCl *sources.RollupClient) *L2Proposer { proposerConfig := proposer.ProposerConfig{ PollInterval: time.Second, diff --git a/op-e2e/actions/l2_sequencer.go b/op-e2e/actions/helpers/l2_sequencer.go similarity index 93% rename from op-e2e/actions/l2_sequencer.go rename to op-e2e/actions/helpers/l2_sequencer.go index 7211537bc50cc..98becdcc87a4a 100644 --- a/op-e2e/actions/l2_sequencer.go +++ b/op-e2e/actions/helpers/l2_sequencer.go @@ -1,4 +1,4 @@ -package actions +package helpers import ( "context" @@ -19,6 +19,7 @@ import ( "github.com/ethereum-optimism/optimism/op-node/rollup/driver" "github.com/ethereum-optimism/optimism/op-node/rollup/engine" "github.com/ethereum-optimism/optimism/op-node/rollup/event" + "github.com/ethereum-optimism/optimism/op-node/rollup/interop" "github.com/ethereum-optimism/optimism/op-node/rollup/sequencing" "github.com/ethereum-optimism/optimism/op-node/rollup/sync" "github.com/ethereum-optimism/optimism/op-service/eth" @@ -50,8 +51,9 @@ type L2Sequencer struct { } func NewL2Sequencer(t Testing, log log.Logger, l1 derive.L1Fetcher, blobSrc derive.L1BlobsFetcher, - altDASrc driver.AltDAIface, eng L2API, cfg *rollup.Config, seqConfDepth uint64) *L2Sequencer { - ver := NewL2Verifier(t, log, l1, blobSrc, altDASrc, eng, cfg, &sync.Config{}, safedb.Disabled) + altDASrc driver.AltDAIface, eng L2API, cfg *rollup.Config, seqConfDepth uint64, + interopBackend interop.InteropBackend) *L2Sequencer { + ver := NewL2Verifier(t, log, l1, blobSrc, altDASrc, eng, cfg, &sync.Config{}, safedb.Disabled, interopBackend) attrBuilder := derive.NewFetchingAttributesBuilder(cfg, l1, eng) seqConfDepthL1 := confdepth.NewConfDepth(seqConfDepth, ver.syncStatus.L1Head, l1) l1OriginSelector := &MockL1OriginSelector{ @@ -87,7 +89,7 @@ func NewL2Sequencer(t Testing, log log.Logger, l1 derive.L1Fetcher, blobSrc deri // ActL2StartBlock starts building of a new L2 block on top of the head func (s *L2Sequencer) ActL2StartBlock(t Testing) { - if !s.l2PipelineIdle { + if !s.L2PipelineIdle { t.InvalidAction("cannot start L2 build when derivation is not idle") return } @@ -189,22 +191,22 @@ func (s *L2Sequencer) ActBuildL2ToTime(t Testing, target uint64) { } func (s *L2Sequencer) ActBuildL2ToEcotone(t Testing) { - require.NotNil(t, s.rollupCfg.EcotoneTime, "cannot activate Ecotone when it is not scheduled") - for s.L2Unsafe().Time < *s.rollupCfg.EcotoneTime { + require.NotNil(t, s.RollupCfg.EcotoneTime, "cannot activate Ecotone when it is not scheduled") + for s.L2Unsafe().Time < *s.RollupCfg.EcotoneTime { s.ActL2StartBlock(t) s.ActL2EndBlock(t) } } func (s *L2Sequencer) ActBuildL2ToFjord(t Testing) { - require.NotNil(t, s.rollupCfg.FjordTime, "cannot activate FjordTime when it is not scheduled") - for s.L2Unsafe().Time < *s.rollupCfg.FjordTime { + require.NotNil(t, s.RollupCfg.FjordTime, "cannot activate FjordTime when it is not scheduled") + for s.L2Unsafe().Time < *s.RollupCfg.FjordTime { s.ActL2StartBlock(t) s.ActL2EndBlock(t) } } func (s *L2Sequencer) ActBuildL2ToGranite(t Testing) { - require.NotNil(t, s.rollupCfg.GraniteTime, "cannot activate GraniteTime when it is not scheduled") - for s.L2Unsafe().Time < *s.rollupCfg.GraniteTime { + require.NotNil(t, s.RollupCfg.GraniteTime, "cannot activate GraniteTime when it is not scheduled") + for s.L2Unsafe().Time < *s.RollupCfg.GraniteTime { s.ActL2StartBlock(t) s.ActL2EndBlock(t) } diff --git a/op-e2e/actions/l2_verifier.go b/op-e2e/actions/helpers/l2_verifier.go similarity index 90% rename from op-e2e/actions/l2_verifier.go rename to op-e2e/actions/helpers/l2_verifier.go index 5cc09c76c4e42..1594e1eb368cf 100644 --- a/op-e2e/actions/l2_verifier.go +++ b/op-e2e/actions/helpers/l2_verifier.go @@ -1,4 +1,4 @@ -package actions +package helpers import ( "context" @@ -23,6 +23,7 @@ import ( "github.com/ethereum-optimism/optimism/op-node/rollup/engine" "github.com/ethereum-optimism/optimism/op-node/rollup/event" "github.com/ethereum-optimism/optimism/op-node/rollup/finality" + "github.com/ethereum-optimism/optimism/op-node/rollup/interop" "github.com/ethereum-optimism/optimism/op-node/rollup/status" "github.com/ethereum-optimism/optimism/op-node/rollup/sync" "github.com/ethereum-optimism/optimism/op-service/client" @@ -39,7 +40,7 @@ type L2Verifier struct { log log.Logger - eng L2API + Eng L2API syncStatus driver.SyncStatusTracker @@ -48,18 +49,19 @@ type L2Verifier struct { drainer event.Drainer // L2 rollup - engine *engine.EngineController - derivation *derive.DerivationPipeline + engine *engine.EngineController + derivationMetrics *testutils.TestDerivationMetrics + derivation *derive.DerivationPipeline safeHeadListener rollup.SafeHeadListener syncCfg *sync.Config l1 derive.L1Fetcher - l2PipelineIdle bool + L2PipelineIdle bool l2Building bool - rollupCfg *rollup.Config + RollupCfg *rollup.Config rpc *rpc.Server @@ -84,7 +86,11 @@ type safeDB interface { node.SafeDBReader } -func NewL2Verifier(t Testing, log log.Logger, l1 derive.L1Fetcher, blobsSrc derive.L1BlobsFetcher, altDASrc driver.AltDAIface, eng L2API, cfg *rollup.Config, syncCfg *sync.Config, safeHeadListener safeDB) *L2Verifier { +func NewL2Verifier(t Testing, log log.Logger, l1 derive.L1Fetcher, + blobsSrc derive.L1BlobsFetcher, altDASrc driver.AltDAIface, + eng L2API, cfg *rollup.Config, syncCfg *sync.Config, safeHeadListener safeDB, + interopBackend interop.InteropBackend, +) *L2Verifier { ctx, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) @@ -104,6 +110,10 @@ func NewL2Verifier(t Testing, log log.Logger, l1 derive.L1Fetcher, blobsSrc deri }, } + if interopBackend != nil { + sys.Register("interop", interop.NewInteropDeriver(log, cfg, ctx, interopBackend, eng), opts) + } + metrics := &testutils.TestDerivationMetrics{} ec := engine.NewEngineController(eng, log, metrics, cfg, syncCfg, sys.Register("engine-controller", nil, opts)) @@ -152,17 +162,18 @@ func NewL2Verifier(t Testing, log log.Logger, l1 derive.L1Fetcher, blobsSrc deri rollupNode := &L2Verifier{ eventSys: sys, log: log, - eng: eng, + Eng: eng, engine: ec, + derivationMetrics: metrics, derivation: pipeline, safeHeadListener: safeHeadListener, syncCfg: syncCfg, drainer: executor, l1: l1, syncStatus: syncStatusTracker, - l2PipelineIdle: true, + L2PipelineIdle: true, l2Building: false, - rollupCfg: cfg, + RollupCfg: cfg, rpc: rpc.NewServer(), synchronousEvents: testActionEmitter, } @@ -197,7 +208,7 @@ type l2VerifierBackend struct { } func (s *l2VerifierBackend) BlockRefWithStatus(ctx context.Context, num uint64) (eth.L2BlockRef, *eth.SyncStatus, error) { - ref, err := s.verifier.eng.L2BlockRefByNumber(ctx, num) + ref, err := s.verifier.Eng.L2BlockRefByNumber(ctx, num) return ref, s.verifier.SyncStatus(), err } @@ -230,6 +241,10 @@ func (s *l2VerifierBackend) OnUnsafeL2Payload(ctx context.Context, envelope *eth return nil } +func (s *L2Verifier) DerivationMetricsTracer() *testutils.TestDerivationMetrics { + return s.derivationMetrics +} + func (s *L2Verifier) L2Finalized() eth.L2BlockRef { return s.engine.Finalized() } @@ -316,6 +331,13 @@ func (s *L2Verifier) ActL1FinalizedSignal(t Testing) { require.Equal(t, finalized, s.syncStatus.SyncStatus().FinalizedL1) } +func (s *L2Verifier) ActInteropBackendCheck(t Testing) { + s.synchronousEvents.Emit(engine.CrossUpdateRequestEvent{ + CrossUnsafe: true, + CrossSafe: true, + }) +} + func (s *L2Verifier) OnEvent(ev event.Event) bool { switch x := ev.(type) { case rollup.L1TemporaryErrorEvent: @@ -330,9 +352,9 @@ func (s *L2Verifier) OnEvent(ev event.Event) bool { case rollup.CriticalErrorEvent: panic(fmt.Errorf("derivation failed critically: %w", x.Err)) case derive.DeriverIdleEvent: - s.l2PipelineIdle = true + s.L2PipelineIdle = true case derive.PipelineStepEvent: - s.l2PipelineIdle = false + s.L2PipelineIdle = false case driver.StepReqEvent: s.synchronousEvents.Emit(driver.StepEvent{}) default: @@ -381,7 +403,7 @@ func (s *L2Verifier) ActL2UnsafeGossipReceive(payload *eth.ExecutionPayloadEnvel // ActL2InsertUnsafePayload creates an action that can insert an unsafe execution payload func (s *L2Verifier) ActL2InsertUnsafePayload(payload *eth.ExecutionPayloadEnvelope) Action { return func(t Testing) { - ref, err := derive.PayloadToBlockRef(s.rollupCfg, payload.ExecutionPayload) + ref, err := derive.PayloadToBlockRef(s.RollupCfg, payload.ExecutionPayload) require.NoError(t, err) err = s.engine.InsertUnsafePayload(t.Ctx(), payload, ref) require.NoError(t, err) diff --git a/op-e2e/actions/helpers/setups.go b/op-e2e/actions/helpers/setups.go new file mode 100644 index 0000000000000..26e19eae82a05 --- /dev/null +++ b/op-e2e/actions/helpers/setups.go @@ -0,0 +1,75 @@ +package helpers + +import ( + altda "github.com/ethereum-optimism/optimism/op-alt-da" + "github.com/ethereum-optimism/optimism/op-e2e/actions/upgrades/helpers" + "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" + "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/stretchr/testify/require" +) + +func SetupSequencerTest(t Testing, sd *e2eutils.SetupData, log log.Logger, opts ...SequencerOpt) (*L1Miner, *L2Engine, *L2Sequencer) { + jwtPath := e2eutils.WriteDefaultJWT(t) + cfg := DefaultSequencerConfig() + for _, opt := range opts { + opt(cfg) + } + + miner := NewL1Miner(t, log.New("role", "l1-miner"), sd.L1Cfg) + + l1F, err := sources.NewL1Client(miner.RPCClient(), log, nil, sources.L1ClientDefaultConfig(sd.RollupCfg, false, sources.RPCKindStandard)) + require.NoError(t, err) + engine := NewL2Engine(t, log.New("role", "sequencer-engine"), sd.L2Cfg, sd.RollupCfg.Genesis.L1, jwtPath, EngineWithP2P()) + l2Cl, err := sources.NewEngineClient(engine.RPCClient(), log, nil, sources.EngineClientDefaultConfig(sd.RollupCfg)) + require.NoError(t, err) + + sequencer := NewL2Sequencer(t, log.New("role", "sequencer"), l1F, miner.BlobStore(), altda.Disabled, l2Cl, sd.RollupCfg, 0, cfg.InteropBackend) + return miner, engine, sequencer +} + +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.New("role", "verifier-engine"), sd.L2Cfg, sd.RollupCfg.Genesis.L1, jwtPath, EngineWithP2P()) + engCl := engine.EngineClient(t, sd.RollupCfg) + verifier := NewL2Verifier(t, log.New("role", "verifier"), l1F, blobSrc, altda.Disabled, engCl, sd.RollupCfg, syncCfg, cfg.SafeHeadListener, cfg.InteropBackend) + 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, miner.BlobStore(), &sync.Config{}) + return miner, engine, verifier +} + +func SetupReorgTest(t Testing, config *e2eutils.TestParams, deltaTimeOffset *hexutil.Uint64) (*e2eutils.SetupData, *e2eutils.DeployParams, *L1Miner, *L2Sequencer, *L2Engine, *L2Verifier, *L2Engine, *L2Batcher) { + dp := e2eutils.MakeDeployParams(t, config) + helpers.ApplyDeltaTimeOffset(dp, deltaTimeOffset) + + sd := e2eutils.Setup(t, dp, DefaultAlloc) + log := testlog.Logger(t, log.LevelDebug) + + return SetupReorgTestActors(t, dp, sd, log) +} + +func SetupReorgTestActors(t Testing, dp *e2eutils.DeployParams, sd *e2eutils.SetupData, log log.Logger) (*e2eutils.SetupData, *e2eutils.DeployParams, *L1Miner, *L2Sequencer, *L2Engine, *L2Verifier, *L2Engine, *L2Batcher) { + 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{}) + rollupSeqCl := sequencer.RollupClient() + 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 +} diff --git a/op-e2e/actions/tx_helper.go b/op-e2e/actions/helpers/tx_helper.go similarity index 99% rename from op-e2e/actions/tx_helper.go rename to op-e2e/actions/helpers/tx_helper.go index e63c1a2248223..8174563102c81 100644 --- a/op-e2e/actions/tx_helper.go +++ b/op-e2e/actions/helpers/tx_helper.go @@ -1,4 +1,4 @@ -package actions +package helpers import ( "context" diff --git a/op-e2e/actions/user.go b/op-e2e/actions/helpers/user.go similarity index 96% rename from op-e2e/actions/user.go rename to op-e2e/actions/helpers/user.go index dabc9c1d89802..2acd6ccaf8e72 100644 --- a/op-e2e/actions/user.go +++ b/op-e2e/actions/helpers/user.go @@ -1,4 +1,4 @@ -package actions +package helpers import ( "context" @@ -24,10 +24,10 @@ import ( "github.com/stretchr/testify/require" "github.com/ethereum-optimism/optimism/op-chain-ops/crossdomain" - e2e "github.com/ethereum-optimism/optimism/op-e2e" legacybindings "github.com/ethereum-optimism/optimism/op-e2e/bindings" "github.com/ethereum-optimism/optimism/op-e2e/config" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" + e2ehelpers "github.com/ethereum-optimism/optimism/op-e2e/system/helpers" "github.com/ethereum-optimism/optimism/op-node/bindings" bindingspreview "github.com/ethereum-optimism/optimism/op-node/bindings/preview" "github.com/ethereum-optimism/optimism/op-node/rollup/derive" @@ -130,6 +130,10 @@ func (s *BasicUser[B]) SetUserEnv(env *BasicUserEnv[B]) { s.env = env } +func (s *BasicUser[B]) Signer() types.Signer { + return s.env.Signer +} + func (s *BasicUser[B]) signerFn(address common.Address, tx *types.Transaction) (*types.Transaction, error) { if address != s.address { return nil, bind.ErrNotAuthorized @@ -231,9 +235,7 @@ func (s *BasicUser[B]) LastTxReceipt(t Testing) *types.Receipt { return receipt } -// ActMakeTx makes a tx with the predetermined contents (see randomization and other actions) -// and sends it to the tx pool -func (s *BasicUser[B]) ActMakeTx(t Testing) { +func (s *BasicUser[B]) MakeTransaction(t Testing) *types.Transaction { gas, err := s.env.EthCl.EstimateGas(t.Ctx(), ethereum.CallMsg{ From: s.address, To: s.txToAddr, @@ -243,7 +245,7 @@ func (s *BasicUser[B]) ActMakeTx(t Testing) { Data: s.txCallData, }) require.NoError(t, err, "gas estimation should pass") - tx := types.MustSignNewTx(s.account, s.env.Signer, &types.DynamicFeeTx{ + return types.MustSignNewTx(s.account, s.env.Signer, &types.DynamicFeeTx{ To: s.txToAddr, GasFeeCap: s.txOpts.GasFeeCap, GasTipCap: s.txOpts.GasTipCap, @@ -253,7 +255,13 @@ func (s *BasicUser[B]) ActMakeTx(t Testing) { Gas: gas, Data: s.txCallData, }) - err = s.env.EthCl.SendTransaction(t.Ctx(), tx) +} + +// ActMakeTx makes a tx with the predetermined contents (see randomization and other actions) +// and sends it to the tx pool +func (s *BasicUser[B]) ActMakeTx(t Testing) { + tx := s.MakeTransaction(t) + err := s.env.EthCl.SendTransaction(t.Ctx(), tx) require.NoError(t, err, "must send tx") s.lastTxHash = tx.Hash() // reset the calldata @@ -449,7 +457,7 @@ func (s *CrossLayerUser) getLatestWithdrawalParams(t Testing) (*withdrawals.Prov header, err := s.L2.env.EthCl.HeaderByNumber(t.Ctx(), l2OutputBlockNr) require.NoError(t, err) - 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) + params, err := e2ehelpers.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 diff --git a/op-e2e/actions/user_test.go b/op-e2e/actions/helpers/user_test.go similarity index 97% rename from op-e2e/actions/user_test.go rename to op-e2e/actions/helpers/user_test.go index 3a0b079cb3e4c..8ee60aa680e3d 100644 --- a/op-e2e/actions/user_test.go +++ b/op-e2e/actions/helpers/user_test.go @@ -1,4 +1,4 @@ -package actions +package helpers import ( "fmt" @@ -109,7 +109,7 @@ func TestCrossLayerUser(t *testing.T) { func runCrossLayerUserTest(gt *testing.T, test hardforkScheduledTest) { t := NewDefaultTesting(gt) - dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) + dp := e2eutils.MakeDeployParams(t, DefaultRollupTestParams) // This overwrites all deploy-config settings, // so even when the deploy-config defaults change, we test the right transitions. dp.DeployConfig.L2GenesisRegolithTimeOffset = test.regolithTime @@ -125,13 +125,13 @@ func runCrossLayerUserTest(gt *testing.T, test hardforkScheduledTest) { require.Zero(t, uint64(*test.ecotoneTime)%uint64(dp.DeployConfig.L2BlockTime), "ecotone fork must be aligned") } - sd := e2eutils.Setup(t, dp, defaultAlloc) + sd := e2eutils.Setup(t, dp, DefaultAlloc) 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) + miner, seqEngine, seq := SetupSequencerTest(t, sd, log) batcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp), seq.RollupClient(), miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) @@ -199,7 +199,7 @@ func runCrossLayerUserTest(gt *testing.T, test hardforkScheduledTest) { require.NoError(t, err) require.True(t, infoTx.IsDepositTx()) // Should only be a system tx if regolith is not enabled - require.Equal(t, !seq.rollupCfg.IsRegolith(seq.L2Unsafe().Time), infoTx.IsSystemTx()) + require.Equal(t, !seq.RollupCfg.IsRegolith(seq.L2Unsafe().Time), infoTx.IsSystemTx()) // regular L2 tx, in new L2 block alice.L2.ActResetTxOpts(t) @@ -320,5 +320,5 @@ func runCrossLayerUserTest(gt *testing.T, test hardforkScheduledTest) { require.NoError(t, err) require.True(t, infoTx.IsDepositTx()) // Should only be a system tx if regolith is not enabled - require.Equal(t, !seq.rollupCfg.IsRegolith(seq.L2Unsafe().Time), infoTx.IsSystemTx()) + require.Equal(t, !seq.RollupCfg.IsRegolith(seq.L2Unsafe().Time), infoTx.IsSystemTx()) } diff --git a/op-e2e/actions/helpers/utils.go b/op-e2e/actions/helpers/utils.go new file mode 100644 index 0000000000000..f4f1b812cbaa9 --- /dev/null +++ b/op-e2e/actions/helpers/utils.go @@ -0,0 +1,79 @@ +package helpers + +import ( + "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/interop" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/eth/ethconfig" + "github.com/ethereum/go-ethereum/node" + "github.com/ethereum/go-ethereum/p2p" +) + +var DefaultRollupTestParams = &e2eutils.TestParams{ + MaxSequencerDrift: 40, + SequencerWindowSize: 120, + ChannelTimeout: 120, + L1BlockTime: 15, +} + +var DefaultAlloc = &e2eutils.AllocParams{PrefundTestUsers: true} + +type VerifierCfg struct { + SafeHeadListener safeDB + InteropBackend interop.InteropBackend +} + +type VerifierOpt func(opts *VerifierCfg) + +func WithSafeHeadListener(l safeDB) VerifierOpt { + return func(opts *VerifierCfg) { + opts.SafeHeadListener = l + } +} + +func WithInteropBackend(b interop.InteropBackend) VerifierOpt { + return func(opts *VerifierCfg) { + opts.InteropBackend = b + } +} + +func DefaultVerifierCfg() *VerifierCfg { + return &VerifierCfg{ + SafeHeadListener: safedb.Disabled, + } +} + +func EngineWithP2P() EngineOption { + return func(ethCfg *ethconfig.Config, nodeCfg *node.Config) error { + p2pKey, err := crypto.GenerateKey() + if err != nil { + return err + } + nodeCfg.P2P = p2p.Config{ + MaxPeers: 100, + NoDiscovery: true, + ListenAddr: "127.0.0.1:0", + PrivateKey: p2pKey, + } + return nil + } +} + +type SequencerCfg struct { + VerifierCfg +} + +func DefaultSequencerConfig() *SequencerCfg { + return &SequencerCfg{VerifierCfg: *DefaultVerifierCfg()} +} + +type SequencerOpt func(opts *SequencerCfg) + +func WithVerifierOpts(opts ...VerifierOpt) SequencerOpt { + return func(cfg *SequencerCfg) { + for _, opt := range opts { + opt(&cfg.VerifierCfg) + } + } +} diff --git a/op-e2e/actions/interop/interop_test.go b/op-e2e/actions/interop/interop_test.go new file mode 100644 index 0000000000000..4015ffa29ce95 --- /dev/null +++ b/op-e2e/actions/interop/interop_test.go @@ -0,0 +1,124 @@ +package interop + +import ( + "testing" + + "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" + "github.com/stretchr/testify/require" + + "github.com/ethereum/go-ethereum/log" + + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" + "github.com/ethereum-optimism/optimism/op-node/rollup/interop" + "github.com/ethereum-optimism/optimism/op-node/rollup/sync" + "github.com/ethereum-optimism/optimism/op-service/testlog" + "github.com/ethereum-optimism/optimism/op-service/testutils" + "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" +) + +var _ interop.InteropBackend = (*testutils.MockInteropBackend)(nil) + +func TestInteropVerifier(gt *testing.T) { + t := helpers.NewDefaultTesting(gt) + dp := e2eutils.MakeDeployParams(t, helpers.DefaultRollupTestParams) + sd := e2eutils.Setup(t, dp, helpers.DefaultAlloc) + // Temporary work-around: interop needs to be active, for cross-safety to not be instant. + // The state genesis in this test is pre-interop however. + sd.RollupCfg.InteropTime = new(uint64) + logger := testlog.Logger(t, log.LevelDebug) + seqMockBackend := &testutils.MockInteropBackend{} + l1Miner, seqEng, seq := helpers.SetupSequencerTest(t, sd, logger, + helpers.WithVerifierOpts(helpers.WithInteropBackend(seqMockBackend))) + + batcher := helpers.NewL2Batcher(logger, sd.RollupCfg, helpers.DefaultBatcherCfg(dp), + seq.RollupClient(), l1Miner.EthClient(), seqEng.EthClient(), seqEng.EngineClient(t, sd.RollupCfg)) + + verMockBackend := &testutils.MockInteropBackend{} + _, ver := helpers.SetupVerifier(t, sd, logger, + l1Miner.L1Client(t, sd.RollupCfg), l1Miner.BlobStore(), &sync.Config{}, + helpers.WithInteropBackend(verMockBackend)) + + seq.ActL2PipelineFull(t) + ver.ActL2PipelineFull(t) + + l2ChainID := types.ChainIDFromBig(sd.RollupCfg.L2ChainID) + seqMockBackend.ExpectCheckBlock(l2ChainID, 1, types.Unsafe, nil) + // create an unsafe L2 block + seq.ActL2StartBlock(t) + seq.ActL2EndBlock(t) + seq.ActL2PipelineFull(t) + seqMockBackend.AssertExpectations(t) + status := seq.SyncStatus() + require.Equal(t, uint64(1), status.UnsafeL2.Number) + require.Equal(t, uint64(0), status.CrossUnsafeL2.Number) + require.Equal(t, uint64(0), status.LocalSafeL2.Number) + require.Equal(t, uint64(0), status.SafeL2.Number) + + // promote it to cross-unsafe in the backend + // and see if the node picks up on it + seqMockBackend.ExpectCheckBlock(l2ChainID, 1, types.CrossUnsafe, nil) + seq.ActInteropBackendCheck(t) + seq.ActL2PipelineFull(t) + seqMockBackend.AssertExpectations(t) + status = seq.SyncStatus() + require.Equal(t, uint64(1), status.UnsafeL2.Number) + require.Equal(t, uint64(1), status.CrossUnsafeL2.Number, "cross unsafe now") + require.Equal(t, uint64(0), status.LocalSafeL2.Number) + require.Equal(t, uint64(0), status.SafeL2.Number) + + // submit all new L2 blocks + batcher.ActSubmitAll(t) + // new L1 block with L2 batch + l1Miner.ActL1StartBlock(12)(t) + l1Miner.ActL1IncludeTx(sd.RollupCfg.Genesis.SystemConfig.BatcherAddr)(t) + l1Miner.ActL1EndBlock(t) + + // Sync the L1 block, to verify the L2 block as local-safe. + seqMockBackend.ExpectCheckBlock(l2ChainID, 1, types.CrossUnsafe, nil) // not cross-safe yet + seq.ActL1HeadSignal(t) + seq.ActL2PipelineFull(t) + seqMockBackend.AssertExpectations(t) + + status = seq.SyncStatus() + require.Equal(t, uint64(1), status.UnsafeL2.Number) + require.Equal(t, uint64(1), status.CrossUnsafeL2.Number) + require.Equal(t, uint64(1), status.LocalSafeL2.Number, "local safe changed") + require.Equal(t, uint64(0), status.SafeL2.Number) + + // Now mark it as cross-safe + seqMockBackend.ExpectCheckBlock(l2ChainID, 1, types.CrossSafe, nil) + seq.ActInteropBackendCheck(t) + seq.ActL2PipelineFull(t) + seqMockBackend.AssertExpectations(t) + + status = seq.SyncStatus() + require.Equal(t, uint64(1), status.UnsafeL2.Number) + require.Equal(t, uint64(1), status.CrossUnsafeL2.Number) + require.Equal(t, uint64(1), status.LocalSafeL2.Number) + require.Equal(t, uint64(1), status.SafeL2.Number, "cross-safe reached") + require.Equal(t, uint64(0), status.FinalizedL2.Number) + + // The verifier might not see the L2 block that was just derived from L1 as cross-verified yet. + verMockBackend.ExpectCheckBlock(l2ChainID, 1, types.Unsafe, nil) // for the local unsafe check + verMockBackend.ExpectCheckBlock(l2ChainID, 1, types.Unsafe, nil) // for the local safe check + ver.ActL1HeadSignal(t) + ver.ActL2PipelineFull(t) + verMockBackend.AssertExpectations(t) + status = ver.SyncStatus() + require.Equal(t, uint64(1), status.UnsafeL2.Number, "synced the block") + require.Equal(t, uint64(0), status.CrossUnsafeL2.Number, "not cross-verified yet") + require.Equal(t, uint64(1), status.LocalSafeL2.Number, "derived from L1, thus local-safe") + require.Equal(t, uint64(0), status.SafeL2.Number, "not yet cross-safe") + require.Equal(t, uint64(0), status.FinalizedL2.Number) + + // signal that L1 finalized; the cross-safe block we have should get finalized too + l1Miner.ActL1SafeNext(t) + l1Miner.ActL1FinalizeNext(t) + seq.ActL1SafeSignal(t) + seq.ActL1FinalizedSignal(t) + seq.ActL2PipelineFull(t) + seqMockBackend.AssertExpectations(t) + + status = seq.SyncStatus() + require.Equal(t, uint64(1), status.FinalizedL2.Number, "finalized the block") +} diff --git a/op-e2e/actions/proofs/bad_tx_in_batch_test.go b/op-e2e/actions/proofs/bad_tx_in_batch_test.go new file mode 100644 index 0000000000000..f67e216f76cb0 --- /dev/null +++ b/op-e2e/actions/proofs/bad_tx_in_batch_test.go @@ -0,0 +1,174 @@ +package proofs + +import ( + "testing" + + actionsHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" + "github.com/ethereum-optimism/optimism/op-e2e/actions/proofs/helpers" + "github.com/ethereum-optimism/optimism/op-program/client/claim" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/stretchr/testify/require" +) + +func runBadTxInBatchTest(gt *testing.T, testCfg *helpers.TestCfg[any]) { + t := actionsHelpers.NewDefaultTesting(gt) + env := helpers.NewL2FaultProofEnv(t, testCfg, helpers.NewTestParams(), helpers.NewBatcherCfg()) + + // Build a block on L2 with 1 tx. + env.Alice.L2.ActResetTxOpts(t) + env.Alice.L2.ActSetTxToAddr(&env.Dp.Addresses.Bob) + env.Alice.L2.ActMakeTx(t) + + env.Sequencer.ActL2StartBlock(t) + env.Engine.ActL2IncludeTx(env.Alice.Address())(t) + env.Sequencer.ActL2EndBlock(t) + env.Alice.L2.ActCheckReceiptStatusOfLastTx(true)(t) + + // Instruct the batcher to submit a faulty channel, with an invalid tx. + err := env.Batcher.Buffer(t, func(block *types.Block) { + // Replace the tx with one that has a bad signature. + txs := block.Transactions() + newTx, err := txs[1].WithSignature(env.Alice.L2.Signer(), make([]byte, 65)) + txs[1] = newTx + require.NoError(t, err) + }) + require.NoError(t, err) + env.Batcher.ActL2ChannelClose(t) + env.Batcher.ActL2BatchSubmit(t) + + // Include the batcher transaction. + env.Miner.ActL1StartBlock(12)(t) + env.Miner.ActL1IncludeTxByHash(env.Batcher.LastSubmitted.Hash())(t) + env.Miner.ActL1EndBlock(t) + env.Miner.ActL1SafeNext(t) + + // Instruct the sequencer to derive the L2 chain from the data on L1 that the batcher just posted. + env.Sequencer.ActL1HeadSignal(t) + env.Sequencer.ActL2PipelineFull(t) + + // Ensure the safe head has not advanced - the batch is invalid. + l2SafeHead := env.Engine.L2Chain().CurrentSafeBlock() + require.Equal(t, uint64(0), l2SafeHead.Number.Uint64()) + + // Reset the batcher and submit a valid batch. + env.Batcher.Reset() + env.Batcher.ActSubmitAll(t) + env.Miner.ActL1StartBlock(12)(t) + env.Miner.ActL1IncludeTxByHash(env.Batcher.LastSubmitted.Hash())(t) + env.Miner.ActL1EndBlock(t) + env.Miner.ActL1SafeNext(t) + + // Instruct the sequencer to derive the L2 chain from the data on L1 that the batcher just posted. + env.Sequencer.ActL1HeadSignal(t) + env.Sequencer.ActL2PipelineFull(t) + + // Ensure the safe head has advanced. + l1Head := env.Miner.L1Chain().CurrentBlock() + l2SafeHead = env.Engine.L2Chain().CurrentSafeBlock() + require.Equal(t, uint64(2), l1Head.Number.Uint64()) + require.Equal(t, uint64(1), l2SafeHead.Number.Uint64()) + + env.RunFaultProofProgram(t, l2SafeHead.Number.Uint64(), testCfg.CheckResult, testCfg.InputParams...) +} + +func runBadTxInBatch_ResubmitBadFirstFrame_Test(gt *testing.T, testCfg *helpers.TestCfg[any]) { + t := actionsHelpers.NewDefaultTesting(gt) + env := helpers.NewL2FaultProofEnv(t, testCfg, helpers.NewTestParams(), helpers.NewBatcherCfg()) + + // Build 2 blocks on L2 with 1 tx each. + for i := 0; i < 2; i++ { + env.Alice.L2.ActResetTxOpts(t) + env.Alice.L2.ActSetTxToAddr(&env.Dp.Addresses.Bob) + env.Alice.L2.ActMakeTx(t) + + env.Sequencer.ActL2StartBlock(t) + env.Engine.ActL2IncludeTx(env.Alice.Address())(t) + env.Sequencer.ActL2EndBlock(t) + env.Alice.L2.ActCheckReceiptStatusOfLastTx(true)(t) + } + + // Instruct the batcher to submit a faulty channel, with an invalid tx in the second block + // within the span batch. + env.Batcher.ActL2BatchBuffer(t) + err := env.Batcher.Buffer(t, func(block *types.Block) { + // Replace the tx with one that has a bad signature. + txs := block.Transactions() + newTx, err := txs[1].WithSignature(env.Alice.L2.Signer(), make([]byte, 65)) + txs[1] = newTx + require.NoError(t, err) + }) + require.NoError(t, err) + env.Batcher.ActL2ChannelClose(t) + env.Batcher.ActL2BatchSubmit(t) + + // Include the batcher transaction. + env.Miner.ActL1StartBlock(12)(t) + env.Miner.ActL1IncludeTxByHash(env.Batcher.LastSubmitted.Hash())(t) + env.Miner.ActL1EndBlock(t) + env.Miner.ActL1SafeNext(t) + + // Instruct the sequencer to derive the L2 chain from the data on L1 that the batcher just posted. + env.Sequencer.ActL1HeadSignal(t) + env.Sequencer.ActL2PipelineFull(t) + + // Ensure the safe head has not advanced - the batch is invalid. + l2SafeHead := env.Engine.L2Chain().CurrentSafeBlock() + require.Equal(t, uint64(0), l2SafeHead.Number.Uint64()) + + // Reset the batcher and submit a valid batch. + env.Batcher.Reset() + env.Batcher.ActSubmitAll(t) + env.Miner.ActL1StartBlock(12)(t) + env.Miner.ActL1IncludeTxByHash(env.Batcher.LastSubmitted.Hash())(t) + env.Miner.ActL1EndBlock(t) + env.Miner.ActL1SafeNext(t) + + // Instruct the sequencer to derive the L2 chain from the data on L1 that the batcher just posted. + env.Sequencer.ActL1HeadSignal(t) + env.Sequencer.ActL2PipelineFull(t) + + // Ensure the safe head has advanced. + l1Head := env.Miner.L1Chain().CurrentBlock() + l2SafeHead = env.Engine.L2Chain().CurrentSafeBlock() + require.Equal(t, uint64(2), l1Head.Number.Uint64()) + require.Equal(t, uint64(2), l2SafeHead.Number.Uint64()) + + env.RunFaultProofProgram(t, l2SafeHead.Number.Uint64()-1, testCfg.CheckResult, testCfg.InputParams...) +} + +func Test_ProgramAction_BadTxInBatch(gt *testing.T) { + matrix := helpers.NewMatrix[any]() + defer matrix.Run(gt) + + matrix.AddTestCase( + "HonestClaim", + nil, + helpers.LatestForkOnly, + runBadTxInBatchTest, + helpers.ExpectNoError(), + ) + matrix.AddTestCase( + "JunkClaim", + nil, + helpers.LatestForkOnly, + runBadTxInBatchTest, + helpers.ExpectError(claim.ErrClaimNotValid), + helpers.WithL2Claim(common.HexToHash("0xdeadbeef")), + ) + matrix.AddTestCase( + "ResubmitBadFirstFrame-HonestClaim", + nil, + helpers.LatestForkOnly, + runBadTxInBatch_ResubmitBadFirstFrame_Test, + helpers.ExpectNoError(), + ) + matrix.AddTestCase( + "ResubmitBadFirstFrame-JunkClaim", + nil, + helpers.LatestForkOnly, + runBadTxInBatch_ResubmitBadFirstFrame_Test, + helpers.ExpectError(claim.ErrClaimNotValid), + helpers.WithL2Claim(common.HexToHash("0xdeadbeef")), + ) +} diff --git a/op-e2e/actions/proofs/channel_timeout_test.go b/op-e2e/actions/proofs/channel_timeout_test.go new file mode 100644 index 0000000000000..09ff333922abf --- /dev/null +++ b/op-e2e/actions/proofs/channel_timeout_test.go @@ -0,0 +1,250 @@ +package proofs + +import ( + "testing" + + actionsHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" + "github.com/ethereum-optimism/optimism/op-e2e/actions/proofs/helpers" + "github.com/ethereum-optimism/optimism/op-program/client/claim" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" +) + +// Run a test that submits the first channel frame, times out the channel, and then resubmits the full channel. +func runChannelTimeoutTest(gt *testing.T, testCfg *helpers.TestCfg[any]) { + t := actionsHelpers.NewDefaultTesting(gt) + tp := helpers.NewTestParams() + env := helpers.NewL2FaultProofEnv(t, testCfg, tp, helpers.NewBatcherCfg()) + channelTimeout := env.Sd.ChainSpec.ChannelTimeout(0) + + var timedOutChannels uint + env.Sequencer.DerivationMetricsTracer().FnRecordChannelTimedOut = func() { + timedOutChannels++ + } + + const NumL2Blocks = 10 + + // Build NumL2Blocks empty blocks on L2 + for i := 0; i < NumL2Blocks; i++ { + env.Sequencer.ActL2StartBlock(t) + env.Sequencer.ActL2EndBlock(t) + } + + // Buffer the first half of L2 blocks in the batcher, and submit it. + for i := 0; i < NumL2Blocks/2; i++ { + env.Batcher.ActL2BatchBuffer(t) + } + firstFrame := env.Batcher.ReadNextOutputFrame(t) + env.Batcher.ActL2BatchSubmitRaw(t, firstFrame) + + // Include the batcher transaction. + env.Miner.ActL1StartBlock(12)(t) + env.Miner.ActL1IncludeTxByHash(env.Batcher.LastSubmitted.Hash())(t) + env.Miner.ActL1EndBlock(t) + + // Finalize the block with the first channel frame on L1. + env.Miner.ActL1SafeNext(t) + + // Instruct the sequencer to derive the L2 chain from the data on L1 that the batcher just posted. + env.Sequencer.ActL1HeadSignal(t) + env.Sequencer.ActL2PipelineFull(t) + + // Ensure that the safe head has not advanced - the channel is incomplete. + l2SafeHead := env.Engine.L2Chain().CurrentSafeBlock() + require.Equal(t, uint64(0), l2SafeHead.Number.Uint64()) + + // Time out the channel by mining `channelTimeout + 1` empty blocks on L1. + for i := uint64(0); i < channelTimeout+1; i++ { + env.Miner.ActEmptyBlock(t) + env.Miner.ActL1SafeNext(t) + } + + // Instruct the sequencer to derive the L2 chain - the channel should now be timed out. + env.Sequencer.ActL1HeadSignal(t) + env.Sequencer.ActL2PipelineFull(t) + + // Ensure the safe head has still not advanced. + l2SafeHead = env.Engine.L2Chain().CurrentSafeBlock() + require.Equal(t, uint64(0), l2SafeHead.Number.Uint64()) + + // Ensure that the channel was timed out. + require.EqualValues(t, 1, timedOutChannels) + + // Instruct the batcher to submit the blocks to L1 in a new channel, + // submitted across 2 transactions. + for i := 0; i < 2; i++ { + if i == 0 { + // Re-submit the first frame + env.Batcher.ActL2BatchSubmitRaw(t, firstFrame) + } else { + // Buffer half of the L2 chain's blocks. + for j := 0; j < NumL2Blocks/2; j++ { + env.Batcher.ActL2BatchBuffer(t) + } + env.Batcher.ActL2ChannelClose(t) + env.Batcher.ActL2BatchSubmit(t) + } + + env.Miner.ActL1StartBlock(12)(t) + env.Miner.ActL1IncludeTxByHash(env.Batcher.LastSubmitted.Hash())(t) + env.Miner.ActL1EndBlock(t) + + // Finalize the block with the frame data on L1. + env.Miner.ActL1SafeNext(t) + } + + // Instruct the sequencer to derive the L2 chain. + env.Sequencer.ActL1HeadSignal(t) + env.Sequencer.ActL2PipelineFull(t) + + // Ensure the safe head has still advanced to L2 block # NumL2Blocks. + l2SafeHead = env.Engine.L2Chain().CurrentSafeBlock() + require.EqualValues(t, NumL2Blocks, l2SafeHead.Number.Uint64()) + + // Run the FPP on L2 block # NumL2Blocks/2. + env.RunFaultProofProgram(t, NumL2Blocks/2, testCfg.CheckResult, testCfg.InputParams...) +} + +func runChannelTimeoutTest_CloseChannelLate(gt *testing.T, testCfg *helpers.TestCfg[any]) { + t := actionsHelpers.NewDefaultTesting(gt) + tp := helpers.NewTestParams() + env := helpers.NewL2FaultProofEnv(t, testCfg, tp, helpers.NewBatcherCfg()) + channelTimeout := env.Sd.ChainSpec.ChannelTimeout(0) + + var timedOutChannels uint + env.Sequencer.DerivationMetricsTracer().FnRecordChannelTimedOut = func() { + timedOutChannels++ + } + + const NumL2Blocks = 10 + + // Build NumL2Blocks empty blocks on L2 + for i := 0; i < NumL2Blocks; i++ { + env.Sequencer.ActL2StartBlock(t) + env.Sequencer.ActL2EndBlock(t) + } + + // Buffer the first half of L2 blocks in the batcher, and submit it. + for i := 0; i < NumL2Blocks/2; i++ { + env.Batcher.ActL2BatchBuffer(t) + } + firstFrame := env.Batcher.ReadNextOutputFrame(t) + env.Batcher.ActL2BatchSubmitRaw(t, firstFrame) + + // Instruct the batcher to submit the first channel frame to L1, and include the transaction. + env.Miner.ActL1StartBlock(12)(t) + env.Miner.ActL1IncludeTxByHash(env.Batcher.LastSubmitted.Hash())(t) + env.Miner.ActL1EndBlock(t) + + // Finalize the block with the first channel frame on L1. + env.Miner.ActL1SafeNext(t) + + // Instruct the sequencer to derive the L2 chain from the data on L1 that the batcher just posted. + env.Sequencer.ActL1HeadSignal(t) + env.Sequencer.ActL2PipelineFull(t) + + // Ensure that the safe head has not advanced - the channel is incomplete. + l2SafeHead := env.Engine.L2Chain().CurrentSafeBlock() + require.Equal(t, uint64(0), l2SafeHead.Number.Uint64()) + + // Time out the channel by mining `channelTimeout + 1` empty blocks on L1. + for i := uint64(0); i < channelTimeout+1; i++ { + env.Miner.ActEmptyBlock(t) + env.Miner.ActL1SafeNext(t) + } + + // Instruct the sequencer to derive the L2 chain. + env.Sequencer.ActL1HeadSignal(t) + env.Sequencer.ActL2PipelineFull(t) + + // Ensure the safe head has still not advanced. + l2SafeHead = env.Engine.L2Chain().CurrentSafeBlock() + require.Equal(t, uint64(0), l2SafeHead.Number.Uint64()) + + // Ensure that the channel was timed out. + require.EqualValues(t, 1, timedOutChannels) + + // Cache the second and final frame of the channel from the batcher, but do not submit it yet. + for i := 0; i < NumL2Blocks/2; i++ { + env.Batcher.ActL2BatchBuffer(t) + } + env.Batcher.ActL2ChannelClose(t) + finalFrame := env.Batcher.ReadNextOutputFrame(t) + + // Submit the final frame of the timed out channel, now that the channel has timed out. + env.Batcher.ActL2BatchSubmitRaw(t, finalFrame) + + // Instruct the batcher to submit the second channel frame to L1, and include the transaction. + env.Miner.ActL1StartBlock(12)(t) + env.Miner.ActL1IncludeTxByHash(env.Batcher.LastSubmitted.Hash())(t) + env.Miner.ActL1EndBlock(t) + + // Finalize the block with the second channel frame on L1. + env.Miner.ActL1SafeNext(t) + + // Instruct the sequencer to derive the L2 chain from the data on L1 that the batcher just posted. + env.Sequencer.ActL1HeadSignal(t) + env.Sequencer.ActL2PipelineFull(t) + + // Ensure the safe head has still not advanced. + l2SafeHead = env.Engine.L2Chain().CurrentSafeBlock() + require.Equal(t, uint64(0), l2SafeHead.Number.Uint64()) + + // Instruct the batcher to submit the blocks to L1 in a new channel. + for _, frame := range [][]byte{firstFrame, finalFrame} { + env.Batcher.ActL2BatchSubmitRaw(t, frame) + env.Miner.ActL1StartBlock(12)(t) + env.Miner.ActL1IncludeTxByHash(env.Batcher.LastSubmitted.Hash())(t) + env.Miner.ActL1EndBlock(t) + + // Finalize the block with the resubmitted channel frames on L1. + env.Miner.ActL1SafeNext(t) + } + + // Instruct the sequencer to derive the L2 chain. + env.Sequencer.ActL1HeadSignal(t) + env.Sequencer.ActL2PipelineFull(t) + + // Ensure the safe head has still advanced to L2 block # NumL2Blocks. + l2SafeHead = env.Engine.L2Chain().CurrentSafeBlock() + require.EqualValues(t, NumL2Blocks, l2SafeHead.Number.Uint64()) + + // Run the FPP on L2 block # NumL2Blocks/2. + env.RunFaultProofProgram(t, NumL2Blocks/2, testCfg.CheckResult, testCfg.InputParams...) +} + +func Test_ProgramAction_ChannelTimeout(gt *testing.T) { + matrix := helpers.NewMatrix[any]() + defer matrix.Run(gt) + + matrix.AddTestCase( + "HonestClaim", + nil, + helpers.LatestForkOnly, + runChannelTimeoutTest, + helpers.ExpectNoError(), + ) + matrix.AddTestCase( + "JunkClaim", + nil, + helpers.LatestForkOnly, + runChannelTimeoutTest, + helpers.ExpectError(claim.ErrClaimNotValid), + helpers.WithL2Claim(common.HexToHash("0xdeadbeef")), + ) + matrix.AddTestCase( + "CloseChannelLate-HonestClaim", + nil, + helpers.LatestForkOnly, + runChannelTimeoutTest_CloseChannelLate, + helpers.ExpectNoError(), + ) + matrix.AddTestCase( + "CloseChannelLate-JunkClaim", + nil, + helpers.LatestForkOnly, + runChannelTimeoutTest_CloseChannelLate, + helpers.ExpectError(claim.ErrClaimNotValid), + helpers.WithL2Claim(common.HexToHash("0xdeadbeef")), + ) +} diff --git a/op-e2e/actions/proofs/garbage_channel_test.go b/op-e2e/actions/proofs/garbage_channel_test.go new file mode 100644 index 0000000000000..f112a1a71bdaa --- /dev/null +++ b/op-e2e/actions/proofs/garbage_channel_test.go @@ -0,0 +1,123 @@ +package proofs + +import ( + "fmt" + "testing" + + actionsHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" + "github.com/ethereum-optimism/optimism/op-e2e/actions/proofs/helpers" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" + "github.com/ethereum-optimism/optimism/op-program/client/claim" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" +) + +// garbageKinds is a list of garbage kinds to test. We don't use `INVALID_COMPRESSION` and `MALFORM_RLP` because +// they submit malformed frames always, and this test models a valid channel with a single invalid frame in the +// middle. +var garbageKinds = []actionsHelpers.GarbageKind{ + actionsHelpers.STRIP_VERSION, + actionsHelpers.RANDOM, + actionsHelpers.TRUNCATE_END, + actionsHelpers.DIRTY_APPEND, +} + +// Run a test that submits garbage channel data in the middle of a channel. +// +// channel format ([]Frame): +// [f[0 - correct] f_x[1 - bad frame] f[1 - correct]] +func runGarbageChannelTest(gt *testing.T, testCfg *helpers.TestCfg[actionsHelpers.GarbageKind]) { + t := actionsHelpers.NewDefaultTesting(gt) + tp := helpers.NewTestParams(func(tp *e2eutils.TestParams) { + // Set the channel timeout to 10 blocks, 12x lower than the sequencing window. + tp.ChannelTimeout = 10 + }) + env := helpers.NewL2FaultProofEnv(t, testCfg, tp, helpers.NewBatcherCfg()) + + includeBatchTx := func(env *helpers.L2FaultProofEnv) { + // Instruct the batcher to submit the first channel frame to L1, and include the transaction. + env.Miner.ActL1StartBlock(12)(t) + env.Miner.ActL1IncludeTxByHash(env.Batcher.LastSubmitted.Hash())(t) + env.Miner.ActL1EndBlock(t) + + // Finalize the block with the first channel frame on L1. + env.Miner.ActL1SafeNext(t) + env.Miner.ActL1FinalizeNext(t) + + // Instruct the sequencer to derive the L2 chain from the data on L1 that the batcher just posted. + env.Sequencer.ActL1HeadSignal(t) + env.Sequencer.ActL2PipelineFull(t) + } + + const NumL2Blocks = 10 + + // Build NumL2Blocks empty blocks on L2 + for i := 0; i < NumL2Blocks; i++ { + env.Sequencer.ActL2StartBlock(t) + env.Sequencer.ActL2EndBlock(t) + } + + // Buffer the first half of L2 blocks in the batcher, and submit it. + for i := 0; i < NumL2Blocks/2; i++ { + env.Batcher.ActL2BatchBuffer(t) + } + env.Batcher.ActL2BatchSubmit(t) + + // Include the batcher transaction. + includeBatchTx(env) + + // Ensure that the safe head has not advanced - the channel is incomplete. + l2SafeHead := env.Engine.L2Chain().CurrentSafeBlock() + require.Equal(t, uint64(0), l2SafeHead.Number.Uint64()) + + // Buffer the second half of L2 blocks in the batcher. + for i := 0; i < NumL2Blocks/2; i++ { + env.Batcher.ActL2BatchBuffer(t) + } + env.Batcher.ActL2ChannelClose(t) + expectedSecondFrame := env.Batcher.ReadNextOutputFrame(t) + + // Submit a garbage frame, modified from the expected second frame. + env.Batcher.ActL2BatchSubmitGarbageRaw(t, expectedSecondFrame, testCfg.Custom) + // Include the garbage second frame tx + includeBatchTx(env) + + // Ensure that the safe head has not advanced - the channel is incomplete. + l2SafeHead = env.Engine.L2Chain().CurrentSafeBlock() + require.Equal(t, uint64(0), l2SafeHead.Number.Uint64()) + + // Submit the correct second frame. + env.Batcher.ActL2BatchSubmitRaw(t, expectedSecondFrame) + // Include the corract second frame tx. + includeBatchTx(env) + + // Ensure that the safe head has advanced - the channel is complete. + l2SafeHead = env.Engine.L2Chain().CurrentSafeBlock() + require.Equal(t, uint64(NumL2Blocks), l2SafeHead.Number.Uint64()) + + // Run the FPP on L2 block # NumL2Blocks. + env.RunFaultProofProgram(t, NumL2Blocks, testCfg.CheckResult, testCfg.InputParams...) +} + +func Test_ProgramAction_GarbageChannel(gt *testing.T) { + matrix := helpers.NewMatrix[actionsHelpers.GarbageKind]() + defer matrix.Run(gt) + + for _, garbageKind := range garbageKinds { + matrix.AddTestCase( + fmt.Sprintf("HonestClaim-%s", garbageKind.String()), + garbageKind, + helpers.LatestForkOnly, + runGarbageChannelTest, + helpers.ExpectNoError(), + ) + matrix.AddTestCase( + fmt.Sprintf("JunkClaim-%s", garbageKind.String()), + garbageKind, + helpers.LatestForkOnly, + runGarbageChannelTest, + helpers.ExpectError(claim.ErrClaimNotValid), + helpers.WithL2Claim(common.HexToHash("0xdeadbeef")), + ) + } +} diff --git a/op-e2e/actions/proofs/helpers/env.go b/op-e2e/actions/proofs/helpers/env.go new file mode 100644 index 0000000000000..ca670acb228d5 --- /dev/null +++ b/op-e2e/actions/proofs/helpers/env.go @@ -0,0 +1,257 @@ +package helpers + +import ( + "context" + "math/rand" + + altda "github.com/ethereum-optimism/optimism/op-alt-da" + batcherFlags "github.com/ethereum-optimism/optimism/op-batcher/flags" + "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/fakebeacon" + "github.com/ethereum-optimism/optimism/op-program/host" + "github.com/ethereum-optimism/optimism/op-program/host/config" + "github.com/ethereum-optimism/optimism/op-program/host/kvstore" + "github.com/ethereum-optimism/optimism/op-program/host/prefetcher" + hostTypes "github.com/ethereum-optimism/optimism/op-program/host/types" + "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/core/types" + "github.com/ethereum/go-ethereum/log" + "github.com/stretchr/testify/require" +) + +// L2FaultProofEnv is a test harness for a fault provable L2 chain. +type L2FaultProofEnv struct { + log log.Logger + Batcher *helpers.L2Batcher + Sequencer *helpers.L2Sequencer + Engine *helpers.L2Engine + engCl *sources.EngineClient + Sd *e2eutils.SetupData + Dp *e2eutils.DeployParams + Miner *helpers.L1Miner + Alice *helpers.CrossLayerUser + Bob *helpers.CrossLayerUser +} + +func NewL2FaultProofEnv[c any](t helpers.Testing, testCfg *TestCfg[c], tp *e2eutils.TestParams, batcherCfg *helpers.BatcherCfg) *L2FaultProofEnv { + log := testlog.Logger(t, log.LvlDebug) + dp := NewDeployParams(t, tp, func(dp *e2eutils.DeployParams) { + genesisBlock := hexutil.Uint64(0) + + // Enable cancun always + dp.DeployConfig.L1CancunTimeOffset = &genesisBlock + + // Enable L2 feature. + switch testCfg.Hardfork { + case Regolith: + dp.DeployConfig.L2GenesisRegolithTimeOffset = &genesisBlock + case Canyon: + dp.DeployConfig.L2GenesisCanyonTimeOffset = &genesisBlock + case Delta: + dp.DeployConfig.L2GenesisDeltaTimeOffset = &genesisBlock + case Ecotone: + dp.DeployConfig.L2GenesisEcotoneTimeOffset = &genesisBlock + case Fjord: + dp.DeployConfig.L2GenesisFjordTimeOffset = &genesisBlock + case Granite: + dp.DeployConfig.L2GenesisGraniteTimeOffset = &genesisBlock + } + }) + sd := e2eutils.Setup(t, dp, helpers.DefaultAlloc) + + jwtPath := e2eutils.WriteDefaultJWT(t) + cfg := &helpers.SequencerCfg{VerifierCfg: *helpers.DefaultVerifierCfg()} + + miner := helpers.NewL1Miner(t, log.New("role", "l1-miner"), sd.L1Cfg) + + l1Cl, err := sources.NewL1Client(miner.RPCClient(), log, nil, sources.L1ClientDefaultConfig(sd.RollupCfg, false, sources.RPCKindStandard)) + require.NoError(t, err) + engine := helpers.NewL2Engine(t, log.New("role", "sequencer-engine"), sd.L2Cfg, sd.RollupCfg.Genesis.L1, jwtPath, helpers.EngineWithP2P()) + l2EngineCl, err := sources.NewEngineClient(engine.RPCClient(), log, nil, sources.EngineClientDefaultConfig(sd.RollupCfg)) + require.NoError(t, err) + + sequencer := helpers.NewL2Sequencer(t, log.New("role", "sequencer"), l1Cl, miner.BlobStore(), altda.Disabled, l2EngineCl, sd.RollupCfg, 0, cfg.InteropBackend) + miner.ActL1SetFeeRecipient(common.Address{0xCA, 0xFE, 0xBA, 0xBE}) + sequencer.ActL2PipelineFull(t) + engCl := engine.EngineClient(t, sd.RollupCfg) + + // Set the batcher key to the secret key of the batcher + batcherCfg.BatcherKey = dp.Secrets.Batcher + batcher := helpers.NewL2Batcher(log, sd.RollupCfg, batcherCfg, sequencer.RollupClient(), miner.EthClient(), engine.EthClient(), engCl) + + addresses := e2eutils.CollectAddresses(sd, dp) + l1EthCl := miner.EthClient() + l2EthCl := engine.EthClient() + l1UserEnv := &helpers.BasicUserEnv[*helpers.L1Bindings]{ + EthCl: l1EthCl, + Signer: types.LatestSigner(sd.L1Cfg.Config), + AddressCorpora: addresses, + Bindings: helpers.NewL1Bindings(t, l1EthCl), + } + l2UserEnv := &helpers.BasicUserEnv[*helpers.L2Bindings]{ + EthCl: l2EthCl, + Signer: types.LatestSigner(sd.L2Cfg.Config), + AddressCorpora: addresses, + Bindings: helpers.NewL2Bindings(t, l2EthCl, engine.GethClient()), + } + alice := helpers.NewCrossLayerUser(log, dp.Secrets.Alice, rand.New(rand.NewSource(0xa57b))) + alice.L1.SetUserEnv(l1UserEnv) + alice.L2.SetUserEnv(l2UserEnv) + bob := helpers.NewCrossLayerUser(log, dp.Secrets.Bob, rand.New(rand.NewSource(0xbeef))) + bob.L1.SetUserEnv(l1UserEnv) + bob.L2.SetUserEnv(l2UserEnv) + + return &L2FaultProofEnv{ + log: log, + Batcher: batcher, + Sequencer: sequencer, + Engine: engine, + engCl: engCl, + Sd: sd, + Dp: dp, + Miner: miner, + Alice: alice, + Bob: bob, + } +} + +type FixtureInputParam func(f *FixtureInputs) + +type CheckResult func(helpers.Testing, error) + +func ExpectNoError() CheckResult { + return func(t helpers.Testing, err error) { + require.NoError(t, err, "fault proof program should have succeeded") + } +} + +func ExpectError(expectedErr error) CheckResult { + return func(t helpers.Testing, err error) { + require.ErrorIs(t, err, expectedErr, "fault proof program should have failed with expected error") + } +} + +func WithL2Claim(claim common.Hash) FixtureInputParam { + return func(f *FixtureInputs) { + f.L2Claim = claim + } +} + +func (env *L2FaultProofEnv) RunFaultProofProgram(t helpers.Testing, l2ClaimBlockNum uint64, checkResult CheckResult, fixtureInputParams ...FixtureInputParam) { + // Fetch the pre and post output roots for the fault proof. + preRoot, err := env.Sequencer.RollupClient().OutputAtBlock(t.Ctx(), l2ClaimBlockNum-1) + require.NoError(t, err) + claimRoot, err := env.Sequencer.RollupClient().OutputAtBlock(t.Ctx(), l2ClaimBlockNum) + require.NoError(t, err) + l1Head := env.Miner.L1Chain().CurrentBlock() + + fixtureInputs := &FixtureInputs{ + L2BlockNumber: l2ClaimBlockNum, + L2Claim: common.Hash(claimRoot.OutputRoot), + L2Head: preRoot.BlockRef.Hash, + L2OutputRoot: common.Hash(preRoot.OutputRoot), + L2ChainID: env.Sd.RollupCfg.L2ChainID.Uint64(), + L1Head: l1Head.Hash(), + } + for _, apply := range fixtureInputParams { + apply(fixtureInputs) + } + + // Run the fault proof program from the state transition from L2 block l2ClaimBlockNum - 1 -> l2ClaimBlockNum. + workDir := t.TempDir() + if IsKonaConfigured() { + fakeBeacon := fakebeacon.NewBeacon( + env.log, + env.Miner.BlobStore(), + env.Sd.L1Cfg.Timestamp, + 12, + ) + require.NoError(t, fakeBeacon.Start("127.0.0.1:0")) + defer fakeBeacon.Close() + + err = RunKonaNative(t, workDir, env, env.Miner.HTTPEndpoint(), fakeBeacon.BeaconAddr(), env.Engine.HTTPEndpoint(), *fixtureInputs) + checkResult(t, err) + } else { + programCfg := NewOpProgramCfg( + t, + env, + fixtureInputs, + ) + withInProcessPrefetcher := host.WithPrefetcher(func(ctx context.Context, logger log.Logger, kv kvstore.KV, cfg *config.Config) (host.Prefetcher, error) { + // Set up in-process L1 sources + l1Cl := env.Miner.L1Client(t, env.Sd.RollupCfg) + l1BlobFetcher := env.Miner.BlobSource() + + // Set up in-process L2 source + l2ClCfg := sources.L2ClientDefaultConfig(env.Sd.RollupCfg, true) + l2RPC := env.Engine.RPCClient() + l2Client, err := host.NewL2Client(l2RPC, env.log, nil, &host.L2ClientConfig{L2ClientConfig: l2ClCfg, L2Head: cfg.L2Head}) + require.NoError(t, err, "failed to create L2 client") + l2DebugCl := &host.L2Source{L2Client: l2Client, DebugClient: sources.NewDebugClient(l2RPC.CallContext)} + + return prefetcher.NewPrefetcher(logger, l1Cl, l1BlobFetcher, l2DebugCl, kv), nil + }) + err = host.FaultProofProgram(t.Ctx(), env.log, programCfg, withInProcessPrefetcher) + checkResult(t, err) + } + tryDumpTestFixture(t, err, t.Name(), env, *fixtureInputs, workDir) +} + +type TestParam func(p *e2eutils.TestParams) + +func NewTestParams(params ...TestParam) *e2eutils.TestParams { + dfault := helpers.DefaultRollupTestParams + for _, apply := range params { + apply(dfault) + } + return dfault +} + +type DeployParam func(p *e2eutils.DeployParams) + +func NewDeployParams(t helpers.Testing, tp *e2eutils.TestParams, params ...DeployParam) *e2eutils.DeployParams { + dfault := e2eutils.MakeDeployParams(t, tp) + for _, apply := range params { + apply(dfault) + } + return dfault +} + +type BatcherCfgParam func(c *helpers.BatcherCfg) + +func NewBatcherCfg(params ...BatcherCfgParam) *helpers.BatcherCfg { + dfault := &helpers.BatcherCfg{ + MinL1TxSize: 0, + MaxL1TxSize: 128_000, + DataAvailabilityType: batcherFlags.BlobsType, + } + for _, apply := range params { + apply(dfault) + } + return dfault +} + +type OpProgramCfgParam func(p *config.Config) + +func NewOpProgramCfg( + t helpers.Testing, + env *L2FaultProofEnv, + fi *FixtureInputs, + params ...OpProgramCfgParam, +) *config.Config { + dfault := config.NewConfig(env.Sd.RollupCfg, env.Sd.L2Cfg.Config, fi.L1Head, fi.L2Head, fi.L2OutputRoot, fi.L2Claim, fi.L2BlockNumber) + + if dumpFixtures { + dfault.DataDir = t.TempDir() + dfault.DataFormat = hostTypes.DataFormatPebble + } + + for _, apply := range params { + apply(dfault) + } + return dfault +} diff --git a/op-e2e/actions/proofs/helpers/fixture.go b/op-e2e/actions/proofs/helpers/fixture.go new file mode 100644 index 0000000000000..892848470897e --- /dev/null +++ b/op-e2e/actions/proofs/helpers/fixture.go @@ -0,0 +1,135 @@ +package helpers + +import ( + "encoding/json" + "errors" + "io/fs" + "os" + "os/exec" + "path/filepath" + "regexp" + "strings" + + "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" + "github.com/ethereum-optimism/optimism/op-program/client/claim" + "github.com/ethereum/go-ethereum/common" + "github.com/naoina/toml" + "github.com/stretchr/testify/require" +) + +var ( + dumpFixtures = false + fixtureDir string +) + +func init() { + fixtureDir = os.Getenv("OP_E2E_FPP_FIXTURE_DIR") + if fixtureDir != "" { + dumpFixtures = true + } +} + +type TestFixture struct { + Name string `toml:"name"` + ExpectedStatus uint8 `toml:"expected-status"` + Inputs FixtureInputs `toml:"inputs"` +} + +type FixtureInputs struct { + L2BlockNumber uint64 `toml:"l2-block-number"` + L2Claim common.Hash `toml:"l2-claim"` + L2Head common.Hash `toml:"l2-head"` + L2OutputRoot common.Hash `toml:"l2-output-root"` + L2ChainID uint64 `toml:"l2-chain-id"` + L1Head common.Hash `toml:"l1-head"` +} + +// Dumps a `fp-tests` test fixture to disk if the `OP_E2E_FPP_FIXTURE_DIR` environment variable is set. +// +// [fp-tests]: https://github.com/ethereum-optimism/fp-tests +func tryDumpTestFixture( + t helpers.Testing, + result error, + name string, + env *L2FaultProofEnv, + inputs FixtureInputs, + workDir string, +) { + if !dumpFixtures { + return + } + + name = convertToKebabCase(name) + rollupCfg := env.Sd.RollupCfg + l2Genesis := env.Sd.L2Cfg + + var expectedStatus uint8 + if result == nil { + expectedStatus = 0 + } else if errors.Is(result, claim.ErrClaimNotValid) { + expectedStatus = 1 + } else { + expectedStatus = 2 + } + + fixture := TestFixture{ + Name: name, + ExpectedStatus: expectedStatus, + Inputs: inputs, + } + + fixturePath := filepath.Join(fixtureDir, name) + + err := os.MkdirAll(filepath.Join(fixturePath), fs.ModePerm) + require.NoError(t, err, "failed to create fixture dir") + + fixtureFilePath := filepath.Join(fixturePath, "fixture.toml") + serFixture, err := toml.Marshal(fixture) + require.NoError(t, err, "failed to serialize fixture") + require.NoError(t, os.WriteFile(fixtureFilePath, serFixture, fs.ModePerm), "failed to write fixture") + + genesisPath := filepath.Join(fixturePath, "genesis.json") + serGenesis, err := l2Genesis.MarshalJSON() + require.NoError(t, err, "failed to serialize genesis") + require.NoError(t, os.WriteFile(genesisPath, serGenesis, fs.ModePerm), "failed to write genesis") + + rollupPath := filepath.Join(fixturePath, "rollup.json") + serRollup, err := json.Marshal(rollupCfg) + require.NoError(t, err, "failed to serialize rollup") + require.NoError(t, os.WriteFile(rollupPath, serRollup, fs.ModePerm), "failed to write rollup") + + // Copy the witness database into the fixture directory. + cmd := exec.Command("cp", "-r", workDir, filepath.Join(fixturePath, "witness-db")) + require.NoError(t, cmd.Run(), "Failed to copy witness DB") + + // Compress the genesis file. + cmd = exec.Command("zstd", genesisPath) + _ = cmd.Run() + require.NoError(t, os.Remove(genesisPath), "Failed to remove uncompressed genesis file") + + // Compress the witness database. + cmd = exec.Command( + "tar", + "--zstd", + "-cf", + filepath.Join(fixturePath, "witness-db.tar.zst"), + filepath.Join(fixturePath, "witness-db"), + ) + cmd.Dir = filepath.Join(fixturePath) + require.NoError(t, cmd.Run(), "Failed to compress witness DB") + require.NoError(t, os.RemoveAll(filepath.Join(fixturePath, "witness-db")), "Failed to remove uncompressed witness DB") +} + +// Convert to lower kebab case for strings containing `/` +func convertToKebabCase(input string) string { + if !strings.Contains(input, "/") { + return input + } + + // Replace non-alphanumeric characters with underscores + re := regexp.MustCompile(`[^a-zA-Z0-9]+`) + snake := re.ReplaceAllString(input, "-") + + // Convert to lower case + return strings.ToLower(snake) +} diff --git a/op-e2e/actions/proofs/helpers/kona.go b/op-e2e/actions/proofs/helpers/kona.go new file mode 100644 index 0000000000000..9d34a98dda01f --- /dev/null +++ b/op-e2e/actions/proofs/helpers/kona.go @@ -0,0 +1,78 @@ +package helpers + +import ( + "encoding/json" + "fmt" + "io/fs" + "math/big" + "os" + "os/exec" + "path/filepath" + + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils" + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/vm" + "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" + "github.com/ethereum-optimism/optimism/op-program/client/claim" + "github.com/stretchr/testify/require" +) + +var konaHostPath, konaClientPath string + +func init() { + konaHostPath = os.Getenv("KONA_HOST_PATH") + konaClientPath = os.Getenv("KONA_CLIENT_PATH") +} + +func IsKonaConfigured() bool { + return konaHostPath != "" && konaClientPath != "" +} + +func RunKonaNative( + t helpers.Testing, + workDir string, + env *L2FaultProofEnv, + l1Rpc string, + l1BeaconRpc string, + l2Rpc string, + fixtureInputs FixtureInputs, +) error { + // Write rollup config to tempdir. + rollupConfigPath := filepath.Join(workDir, "rollup.json") + ser, err := json.Marshal(env.Sd.RollupCfg) + require.NoError(t, err) + require.NoError(t, os.WriteFile(rollupConfigPath, ser, fs.ModePerm)) + + // Run the fault proof program from the state transition from L2 block L2Blocknumber - 1 -> L2BlockNumber. + vmCfg := vm.Config{ + L1: l1Rpc, + L1Beacon: l1BeaconRpc, + L2: l2Rpc, + RollupConfigPath: rollupConfigPath, + Server: konaHostPath, + } + inputs := utils.LocalGameInputs{ + L1Head: fixtureInputs.L1Head, + L2Head: fixtureInputs.L2Head, + L2OutputRoot: fixtureInputs.L2OutputRoot, + L2Claim: fixtureInputs.L2Claim, + L2BlockNumber: big.NewInt(int64(fixtureInputs.L2BlockNumber)), + } + hostCmd, err := vm.NewNativeKonaExecutor(konaClientPath).OracleCommand(vmCfg, workDir, inputs) + require.NoError(t, err) + + cmd := exec.Command(hostCmd[0], hostCmd[1:]...) + cmd.Dir = workDir + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stdout + + status := cmd.Run() + switch status := status.(type) { + case *exec.ExitError: + if status.ExitCode() == 1 { + return claim.ErrClaimNotValid + } + return fmt.Errorf("kona exited with status %d", status.ExitCode()) + default: + return status + } +} diff --git a/op-e2e/actions/proofs/helpers/matrix.go b/op-e2e/actions/proofs/helpers/matrix.go new file mode 100644 index 0000000000000..7f3e810e86b6c --- /dev/null +++ b/op-e2e/actions/proofs/helpers/matrix.go @@ -0,0 +1,97 @@ +package helpers + +import ( + "fmt" + "testing" +) + +type RunTest[cfg any] func(t *testing.T, testCfg *TestCfg[cfg]) + +type TestCfg[cfg any] struct { + Hardfork *Hardfork + CheckResult CheckResult + InputParams []FixtureInputParam + Custom cfg +} + +type TestCase[cfg any] struct { + Name string + Cfg cfg + ForkMatrix ForkMatrix + RunTest RunTest[cfg] + InputParams []FixtureInputParam + CheckResult CheckResult +} + +type TestMatrix[cfg any] struct { + CommonInputParams []FixtureInputParam + TestCases []TestCase[cfg] +} + +func (suite *TestMatrix[cfg]) Run(t *testing.T) { + for _, tc := range suite.TestCases { + for _, fork := range tc.ForkMatrix { + t.Run(fmt.Sprintf("%s-%s", tc.Name, fork.Name), func(t *testing.T) { + testCfg := &TestCfg[cfg]{ + Hardfork: fork, + CheckResult: tc.CheckResult, + InputParams: append(suite.CommonInputParams, tc.InputParams...), + Custom: tc.Cfg, + } + tc.RunTest(t, testCfg) + }) + } + } +} + +func NewMatrix[cfg any]() *TestMatrix[cfg] { + return &TestMatrix[cfg]{} +} + +func (ts *TestMatrix[cfg]) WithCommonInputParams(params ...FixtureInputParam) *TestMatrix[cfg] { + ts.CommonInputParams = params + return ts +} + +func (ts *TestMatrix[cfg]) AddTestCase( + name string, + testCfg cfg, + forkMatrix ForkMatrix, + runTest RunTest[cfg], + checkResult CheckResult, + inputParams ...FixtureInputParam, +) *TestMatrix[cfg] { + ts.TestCases = append(ts.TestCases, TestCase[cfg]{ + Name: name, + Cfg: testCfg, + ForkMatrix: forkMatrix, + RunTest: runTest, + InputParams: inputParams, + CheckResult: checkResult, + }) + return ts +} + +type Hardfork struct { + Name string + Precedence int +} + +type ForkMatrix = []*Hardfork + +// Hardfork definitions +var ( + Regolith = &Hardfork{Name: "Regolith", Precedence: 1} + Canyon = &Hardfork{Name: "Canyon", Precedence: 2} + Delta = &Hardfork{Name: "Delta", Precedence: 3} + Fjord = &Hardfork{Name: "Fjord", Precedence: 4} + Ecotone = &Hardfork{Name: "Ecotone", Precedence: 5} + Granite = &Hardfork{Name: "Granite", Precedence: 6} +) +var Hardforks = ForkMatrix{Regolith, Canyon, Delta, Fjord, Ecotone, Granite} + +var LatestForkOnly = ForkMatrix{Hardforks[len(Hardforks)-1]} + +func NewForkMatrix(forks ...*Hardfork) ForkMatrix { + return append(ForkMatrix{}, forks...) +} diff --git a/op-e2e/actions/proofs/l1_lookback_test.go b/op-e2e/actions/proofs/l1_lookback_test.go new file mode 100644 index 0000000000000..b40635ac55097 --- /dev/null +++ b/op-e2e/actions/proofs/l1_lookback_test.go @@ -0,0 +1,161 @@ +package proofs + +import ( + "testing" + + actionsHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" + "github.com/ethereum-optimism/optimism/op-e2e/actions/proofs/helpers" + "github.com/ethereum-optimism/optimism/op-program/client/claim" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/stretchr/testify/require" +) + +func runL1LookbackTest(gt *testing.T, testCfg *helpers.TestCfg[any]) { + t := actionsHelpers.NewDefaultTesting(gt) + tp := helpers.NewTestParams() + env := helpers.NewL2FaultProofEnv(t, testCfg, tp, helpers.NewBatcherCfg()) + + const numL2Blocks = 8 + for i := 0; i < numL2Blocks; i++ { + // Create an empty L2 block. + env.Sequencer.ActL2StartBlock(t) + env.Sequencer.ActL2EndBlock(t) + + // Buffer the L2 block in the batcher. + env.Batcher.ActBufferAll(t) + if i == numL2Blocks-1 { + env.Batcher.ActL2ChannelClose(t) + } + env.Batcher.ActL2BatchSubmit(t) + + // Include the frame on L1. + env.Miner.ActL1StartBlock(12)(t) + env.Miner.ActL1IncludeTxByHash(env.Batcher.LastSubmitted.Hash())(t) + env.Miner.ActL1EndBlock(t) + env.Miner.ActL1SafeNext(t) + } + + // Instruct the sequencer to derive the L2 chain from the data on L1 that the batcher just posted. + env.Sequencer.ActL1HeadSignal(t) + env.Sequencer.ActL2PipelineFull(t) + + // Ensure that the safe head has advanced to `NumL2Blocks`. + l2SafeHead := env.Engine.L2Chain().CurrentSafeBlock() + require.EqualValues(t, numL2Blocks, l2SafeHead.Number.Uint64()) + + // Run the FPP on the configured L2 block. + env.RunFaultProofProgram(t, numL2Blocks/2, testCfg.CheckResult, testCfg.InputParams...) +} + +func runL1LookbackTest_ReopenChannel(gt *testing.T, testCfg *helpers.TestCfg[any]) { + t := actionsHelpers.NewDefaultTesting(gt) + tp := helpers.NewTestParams() + env := helpers.NewL2FaultProofEnv(t, testCfg, tp, helpers.NewBatcherCfg()) + + // Create an L2 block with 1 transaction. + env.Sequencer.ActL2StartBlock(t) + env.Alice.L2.ActResetTxOpts(t) + env.Alice.L2.ActSetTxToAddr(&env.Dp.Addresses.Bob) + env.Alice.L2.ActMakeTx(t) + env.Engine.ActL2IncludeTx(env.Alice.Address())(t) + env.Sequencer.ActL2EndBlock(t) + l2BlockBeforeDerive := env.Engine.L2Chain().CurrentBlock() + + // Buffer the L2 block in the batcher. + env.Batcher.ActL2BatchBuffer(t) + env.Batcher.ActL2BatchSubmit(t) + + // Include the frame on L1. + env.Miner.ActL1StartBlock(12)(t) + env.Miner.ActL1IncludeTxByHash(env.Batcher.LastSubmitted.Hash())(t) + env.Miner.ActL1EndBlock(t) + env.Miner.ActL1SafeNext(t) + + // Re-submit the first L2 block frame w/ different transaction data. + err := env.Batcher.Buffer(t, func(block *types.Block) { + env.Bob.L2.ActResetTxOpts(t) + env.Bob.L2.ActSetTxToAddr(&env.Dp.Addresses.Mallory) + tx := env.Bob.L2.MakeTransaction(t) + block.Transactions()[1] = tx + }) + require.NoError(t, err) + env.Batcher.ActL2BatchSubmit(t) + + // Include the duplicate frame on L1. + env.Miner.ActL1StartBlock(12)(t) + env.Miner.ActL1IncludeTxByHash(env.Batcher.LastSubmitted.Hash())(t) + env.Miner.ActL1EndBlock(t) + env.Miner.ActL1SafeNext(t) + + const numL2Blocks = 8 + for i := 1; i < numL2Blocks; i++ { + // Create an empty L2 block. + env.Sequencer.ActL2StartBlock(t) + env.Sequencer.ActL2EndBlock(t) + + // Buffer the L2 block in the batcher. + env.Batcher.ActBufferAll(t) + if i == numL2Blocks-1 { + env.Batcher.ActL2ChannelClose(t) + } + env.Batcher.ActL2BatchSubmit(t) + + // Include the frame on L1. + env.Miner.ActL1StartBlock(12)(t) + env.Miner.ActL1IncludeTxByHash(env.Batcher.LastSubmitted.Hash())(t) + env.Miner.ActL1EndBlock(t) + env.Miner.ActL1SafeNext(t) + } + + // Instruct the sequencer to derive the L2 chain from the data on L1 that the batcher just posted. + env.Sequencer.ActL1HeadSignal(t) + env.Sequencer.ActL2PipelineFull(t) + + // Ensure that the correct block was derived. + l2BlockAfterDerive := env.Engine.L2Chain().GetBlockByNumber(1) + require.EqualValues(t, l2BlockAfterDerive.Hash(), l2BlockBeforeDerive.Hash()) + + // Ensure that the safe head has advanced to `NumL2Blocks`. + l2SafeHead := env.Engine.L2Chain().CurrentSafeBlock() + require.EqualValues(t, numL2Blocks, l2SafeHead.Number.Uint64()) + + // Run the FPP on the configured L2 block. + env.RunFaultProofProgram(t, numL2Blocks/2, testCfg.CheckResult, testCfg.InputParams...) +} + +func Test_ProgramAction_L1Lookback(gt *testing.T) { + matrix := helpers.NewMatrix[any]() + defer matrix.Run(gt) + + matrix.AddTestCase( + "HonestClaim", + nil, + helpers.LatestForkOnly, + runL1LookbackTest, + helpers.ExpectNoError(), + ) + matrix.AddTestCase( + "JunkClaim", + nil, + helpers.LatestForkOnly, + runL1LookbackTest, + helpers.ExpectError(claim.ErrClaimNotValid), + helpers.WithL2Claim(common.HexToHash("0xdeadbeef")), + ) + matrix.AddTestCase( + "HonestClaim-ReopenChannel", + nil, + helpers.LatestForkOnly, + runL1LookbackTest_ReopenChannel, + helpers.ExpectNoError(), + ) + matrix.AddTestCase( + "JunkClaim-ReopenChannel", + nil, + helpers.LatestForkOnly, + runL1LookbackTest_ReopenChannel, + helpers.ExpectError(claim.ErrClaimNotValid), + helpers.WithL2Claim(common.HexToHash("0xdeadbeef")), + ) +} diff --git a/op-e2e/actions/proofs/sequence_window_expiry_test.go b/op-e2e/actions/proofs/sequence_window_expiry_test.go new file mode 100644 index 0000000000000..3f5ca9562d4bf --- /dev/null +++ b/op-e2e/actions/proofs/sequence_window_expiry_test.go @@ -0,0 +1,165 @@ +package proofs + +import ( + "testing" + + actionsHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" + "github.com/ethereum-optimism/optimism/op-e2e/actions/proofs/helpers" + "github.com/ethereum-optimism/optimism/op-program/client/claim" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" +) + +// Run a test that proves a deposit-only block generated due to sequence window expiry. +func runSequenceWindowExpireTest(gt *testing.T, testCfg *helpers.TestCfg[any]) { + t := actionsHelpers.NewDefaultTesting(gt) + tp := helpers.NewTestParams() + env := helpers.NewL2FaultProofEnv(t, testCfg, tp, helpers.NewBatcherCfg()) + + // Mine an empty block for gas estimation purposes. + env.Miner.ActEmptyBlock(t) + + // Expire the sequence window by building `SequenceWindow + 1` empty blocks on L1. + for i := 0; i < int(tp.SequencerWindowSize)+1; i++ { + env.Alice.L1.ActResetTxOpts(t) + env.Alice.ActDeposit(t) + + env.Miner.ActL1StartBlock(12)(t) + env.Miner.ActL1IncludeTx(env.Alice.Address())(t) + env.Miner.ActL1EndBlock(t) + + env.Miner.ActL1SafeNext(t) + env.Miner.ActL1FinalizeNext(t) + } + + // Ensure the safe head is still 0. + l2SafeHead := env.Engine.L2Chain().CurrentSafeBlock() + require.EqualValues(t, 0, l2SafeHead.Number.Uint64()) + + // Ask the sequencer to derive the deposit-only L2 chain. + env.Sequencer.ActL1HeadSignal(t) + env.Sequencer.ActL2PipelineFull(t) + + // Ensure the safe head advanced forcefully. + l2SafeHead = env.Engine.L2Chain().CurrentSafeBlock() + require.Greater(t, l2SafeHead.Number.Uint64(), uint64(0)) + + // Run the FPP on one of the auto-derived blocks. + env.RunFaultProofProgram(t, l2SafeHead.Number.Uint64()/2, testCfg.CheckResult, testCfg.InputParams...) +} + +// Runs a that proves a block in a chain where the batcher opens a channel, the sequence window expires, and then the +// batcher attempts to close the channel afterwards. +func runSequenceWindowExpire_ChannelCloseAfterWindowExpiry_Test(gt *testing.T, testCfg *helpers.TestCfg[any]) { + t := actionsHelpers.NewDefaultTesting(gt) + tp := helpers.NewTestParams() + env := helpers.NewL2FaultProofEnv(t, testCfg, tp, helpers.NewBatcherCfg()) + + // Mine 2 empty blocks on L2. + for i := 0; i < 2; i++ { + env.Sequencer.ActL2StartBlock(t) + env.Alice.L2.ActResetTxOpts(t) + env.Alice.L2.ActSetTxToAddr(&env.Dp.Addresses.Bob) + env.Alice.L2.ActMakeTx(t) + env.Engine.ActL2IncludeTx(env.Alice.Address())(t) + env.Sequencer.ActL2EndBlock(t) + } + + // Open the channel on L1. + env.Batcher.ActL2BatchBuffer(t) + env.Batcher.ActL2BatchSubmit(t) + env.Miner.ActL1StartBlock(12)(t) + env.Miner.ActL1IncludeTxByHash(env.Batcher.LastSubmitted.Hash())(t) + env.Miner.ActL1EndBlock(t) + + // Finalize the block with the first channel frame on L1. + env.Miner.ActL1SafeNext(t) + env.Miner.ActL1FinalizeNext(t) + + // Instruct the sequencer to derive the L2 chain from the data on L1 that the batcher just posted. + env.Sequencer.ActL1HeadSignal(t) + env.Sequencer.ActL2PipelineFull(t) + + // Ensure the safe head is still 0. + l2SafeHead := env.Engine.L2Chain().CurrentSafeBlock() + require.EqualValues(t, 0, l2SafeHead.Number.Uint64()) + + // Cache the next frame data before expiring the sequence window, but don't submit it yet. + env.Batcher.ActL2BatchBuffer(t) + env.Batcher.ActL2ChannelClose(t) + finalFrame := env.Batcher.ReadNextOutputFrame(t) + + // Expire the sequence window by building `SequenceWindow + 1` empty blocks on L1. + for i := 0; i < int(tp.SequencerWindowSize)+1; i++ { + env.Alice.L1.ActResetTxOpts(t) + env.Alice.ActDeposit(t) + + env.Miner.ActL1StartBlock(12)(t) + env.Miner.ActL1IncludeTx(env.Alice.Address())(t) + env.Miner.ActL1EndBlock(t) + + env.Miner.ActL1SafeNext(t) + env.Miner.ActL1FinalizeNext(t) + } + + // Instruct the batcher to closethe channel on L1, after the sequence window + channel timeout has elapsed. + env.Batcher.ActL2BatchSubmitRaw(t, finalFrame) + env.Miner.ActL1StartBlock(12)(t) + env.Miner.ActL1IncludeTxByHash(env.Batcher.LastSubmitted.Hash())(t) + env.Miner.ActL1EndBlock(t) + + // Finalize the block with the second channel frame on L1. + env.Miner.ActL1SafeNext(t) + env.Miner.ActL1FinalizeNext(t) + + // Ensure the safe head is still 0. + l2SafeHead = env.Engine.L2Chain().CurrentSafeBlock() + require.EqualValues(t, 0, l2SafeHead.Number.Uint64()) + + // Ask the sequencer to derive the deposit-only L2 chain. + env.Sequencer.ActL1HeadSignal(t) + env.Sequencer.ActL2PipelineFull(t) + + // Ensure the safe head advanced forcefully. + l2SafeHead = env.Engine.L2Chain().CurrentSafeBlock() + require.Greater(t, l2SafeHead.Number.Uint64(), uint64(0)) + + // Run the FPP on one of the auto-derived blocks. + env.RunFaultProofProgram(t, l2SafeHead.Number.Uint64()/2, testCfg.CheckResult, testCfg.InputParams...) +} + +func Test_ProgramAction_SequenceWindowExpired(gt *testing.T) { + matrix := helpers.NewMatrix[any]() + defer matrix.Run(gt) + + matrix.AddTestCase( + "HonestClaim", + nil, + helpers.LatestForkOnly, + runSequenceWindowExpireTest, + helpers.ExpectNoError(), + ) + matrix.AddTestCase( + "JunkClaim", + nil, + helpers.LatestForkOnly, + runSequenceWindowExpireTest, + helpers.ExpectError(claim.ErrClaimNotValid), + helpers.WithL2Claim(common.HexToHash("0xdeadbeef")), + ) + matrix.AddTestCase( + "ChannelCloseAfterWindowExpiry-HonestClaim", + nil, + helpers.LatestForkOnly, + runSequenceWindowExpire_ChannelCloseAfterWindowExpiry_Test, + helpers.ExpectNoError(), + ) + matrix.AddTestCase( + "ChannelCloseAfterWindowExpiry-JunkClaim", + nil, + helpers.LatestForkOnly, + runSequenceWindowExpire_ChannelCloseAfterWindowExpiry_Test, + helpers.ExpectError(claim.ErrClaimNotValid), + helpers.WithL2Claim(common.HexToHash("0xdeadbeef")), + ) +} diff --git a/op-e2e/actions/proofs/simple_program_test.go b/op-e2e/actions/proofs/simple_program_test.go new file mode 100644 index 0000000000000..ab3218caf1e48 --- /dev/null +++ b/op-e2e/actions/proofs/simple_program_test.go @@ -0,0 +1,65 @@ +package proofs + +import ( + "testing" + + actionsHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" + "github.com/ethereum-optimism/optimism/op-e2e/actions/proofs/helpers" + "github.com/ethereum-optimism/optimism/op-program/client/claim" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" +) + +func runSimpleProgramTest(gt *testing.T, testCfg *helpers.TestCfg[any]) { + t := actionsHelpers.NewDefaultTesting(gt) + env := helpers.NewL2FaultProofEnv(t, testCfg, helpers.NewTestParams(), helpers.NewBatcherCfg()) + + // Build an empty block on L2 + env.Sequencer.ActL2StartBlock(t) + env.Sequencer.ActL2EndBlock(t) + + // Instruct the batcher to submit the block to L1, and include the transaction. + env.Batcher.ActSubmitAll(t) + env.Miner.ActL1StartBlock(12)(t) + env.Miner.ActL1IncludeTxByHash(env.Batcher.LastSubmitted.Hash())(t) + env.Miner.ActL1EndBlock(t) + + // Finalize the block with the batch on L1. + env.Miner.ActL1SafeNext(t) + env.Miner.ActL1FinalizeNext(t) + + // Instruct the sequencer to derive the L2 chain from the data on L1 that the batcher just posted. + env.Sequencer.ActL1HeadSignal(t) + env.Sequencer.ActL2PipelineFull(t) + + l1Head := env.Miner.L1Chain().CurrentBlock() + l2SafeHead := env.Engine.L2Chain().CurrentSafeBlock() + + // Ensure there is only 1 block on L1. + require.Equal(t, uint64(1), l1Head.Number.Uint64()) + // Ensure the block is marked as safe before we attempt to fault prove it. + require.Equal(t, uint64(1), l2SafeHead.Number.Uint64()) + + env.RunFaultProofProgram(t, l2SafeHead.Number.Uint64(), testCfg.CheckResult, testCfg.InputParams...) +} + +func Test_ProgramAction_SimpleEmptyChain(gt *testing.T) { + matrix := helpers.NewMatrix[any]() + defer matrix.Run(gt) + + matrix.AddTestCase( + "HonestClaim", + nil, + helpers.LatestForkOnly, + runSimpleProgramTest, + helpers.ExpectNoError(), + ) + matrix.AddTestCase( + "JunkClaim", + nil, + helpers.LatestForkOnly, + runSimpleProgramTest, + helpers.ExpectError(claim.ErrClaimNotValid), + helpers.WithL2Claim(common.HexToHash("0xdeadbeef")), + ) +} diff --git a/op-e2e/actions/l2_proposer_test.go b/op-e2e/actions/proposer/l2_proposer_test.go similarity index 88% rename from op-e2e/actions/l2_proposer_test.go rename to op-e2e/actions/proposer/l2_proposer_test.go index bed138cdb3a71..a75ece69b080d 100644 --- a/op-e2e/actions/l2_proposer_test.go +++ b/op-e2e/actions/proposer/l2_proposer_test.go @@ -1,10 +1,12 @@ -package actions +package proposer import ( "math/big" "testing" "time" + actionsHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" + upgradesHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/upgrades/helpers" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" @@ -44,24 +46,24 @@ func TestProposerBatchType(t *testing.T) { } func RunProposerTest(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { - t := NewDefaultTesting(gt) - dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) - applyDeltaTimeOffset(dp, deltaTimeOffset) - sd := e2eutils.Setup(t, dp, defaultAlloc) + t := actionsHelpers.NewDefaultTesting(gt) + dp := e2eutils.MakeDeployParams(t, actionsHelpers.DefaultRollupTestParams) + upgradesHelpers.ApplyDeltaTimeOffset(dp, deltaTimeOffset) + sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) log := testlog.Logger(t, log.LevelDebug) - miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) + miner, seqEngine, sequencer := actionsHelpers.SetupSequencerTest(t, sd, log) rollupSeqCl := sequencer.RollupClient() - batcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp), + batcher := actionsHelpers.NewL2Batcher(log, sd.RollupCfg, actionsHelpers.DefaultBatcherCfg(dp), rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) - var proposer *L2Proposer + var proposer *actionsHelpers.L2Proposer if e2eutils.UseFaultProofs() { optimismPortal2Contract, err := bindingspreview.NewOptimismPortal2(sd.DeploymentsL1.OptimismPortalProxy, miner.EthClient()) require.NoError(t, err) respectedGameType, err := optimismPortal2Contract.RespectedGameType(&bind.CallOpts{}) require.NoError(t, err) - proposer = NewL2Proposer(t, log, &ProposerCfg{ + proposer = actionsHelpers.NewL2Proposer(t, log, &actionsHelpers.ProposerCfg{ DisputeGameFactoryAddr: &sd.DeploymentsL1.DisputeGameFactoryProxy, ProposalInterval: 6 * time.Second, ProposalRetryInterval: 3 * time.Second, @@ -70,7 +72,7 @@ func RunProposerTest(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { AllowNonFinalized: true, }, miner.EthClient(), rollupSeqCl) } else { - proposer = NewL2Proposer(t, log, &ProposerCfg{ + proposer = actionsHelpers.NewL2Proposer(t, log, &actionsHelpers.ProposerCfg{ OutputOracleAddr: &sd.DeploymentsL1.L2OutputOracleProxy, ProposerKey: dp.Secrets.Proposer, ProposalRetryInterval: 3 * time.Second, diff --git a/op-e2e/actions/safedb/helpers/setups.go b/op-e2e/actions/safedb/helpers/setups.go new file mode 100644 index 0000000000000..fcc70f494a747 --- /dev/null +++ b/op-e2e/actions/safedb/helpers/setups.go @@ -0,0 +1,38 @@ +package helpers + +import ( + "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" + "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/testlog" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/log" + "github.com/stretchr/testify/require" +) + +func SetupSafeDBTest(t helpers.Testing, config *e2eutils.TestParams) (*e2eutils.SetupData, *helpers.L1Miner, *helpers.L2Sequencer, *helpers.L2Verifier, *helpers.L2Engine, *helpers.L2Batcher) { + dp := e2eutils.MakeDeployParams(t, config) + + sd := e2eutils.Setup(t, dp, helpers.DefaultAlloc) + logger := testlog.Logger(t, log.LevelDebug) + + return SetupSafeDBTestActors(t, dp, sd, logger) +} + +func SetupSafeDBTestActors(t helpers.Testing, dp *e2eutils.DeployParams, sd *e2eutils.SetupData, log log.Logger) (*e2eutils.SetupData, *helpers.L1Miner, *helpers.L2Sequencer, *helpers.L2Verifier, *helpers.L2Engine, *helpers.L2Batcher) { + dir := t.TempDir() + db, err := safedb.NewSafeDB(log, dir) + require.NoError(t, err) + t.Cleanup(func() { + _ = db.Close() + }) + miner, seqEngine, sequencer := helpers.SetupSequencerTest(t, sd, log) + miner.ActL1SetFeeRecipient(common.Address{'A'}) + sequencer.ActL2PipelineFull(t) + verifEngine, verifier := helpers.SetupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}, helpers.WithSafeHeadListener(db)) + rollupSeqCl := sequencer.RollupClient() + batcher := helpers.NewL2Batcher(log, sd.RollupCfg, helpers.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/safedb_test.go b/op-e2e/actions/safedb/safedb_test.go similarity index 68% rename from op-e2e/actions/safedb_test.go rename to op-e2e/actions/safedb/safedb_test.go index 9fd570fa79f5b..369825e46263c 100644 --- a/op-e2e/actions/safedb_test.go +++ b/op-e2e/actions/safedb/safedb_test.go @@ -1,23 +1,20 @@ -package actions +package safedb 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" + actionsHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" + "github.com/ethereum-optimism/optimism/op-e2e/actions/safedb/helpers" "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) + t := actionsHelpers.NewDefaultTesting(gt) + sd, miner, sequencer, verifier, verifierEng, batcher := helpers.SetupSafeDBTest(t, actionsHelpers.DefaultRollupTestParams) verifEngClient := verifierEng.EngineClient(t, sd.RollupCfg) sequencer.ActL2PipelineFull(t) @@ -36,7 +33,7 @@ func TestRecordSafeHeadUpdates(gt *testing.T) { // new L1 block with L2 batch miner.ActL1StartBlock(12)(t) miner.ActL1IncludeTx(sd.RollupCfg.Genesis.SystemConfig.BatcherAddr)(t) - batchTx := miner.l1Transactions[0] + batchTx := miner.L1Transactions[0] miner.ActL1EndBlock(t) // verifier picks up the L2 chain that was submitted @@ -46,7 +43,7 @@ func TestRecordSafeHeadUpdates(gt *testing.T) { require.NotEqual(t, sequencer.L2Safe(), sequencer.L2Unsafe(), "sequencer has not processed L1 yet") // Verify the safe head is recorded - l1Head := miner.l1Chain.CurrentBlock() + l1Head := miner.L1Chain().CurrentBlock() firstSafeHeadUpdateL1Block := l1Head.Number.Uint64() response, err := verifier.RollupClient().SafeHeadAtL1Block(context.Background(), firstSafeHeadUpdateL1Block) require.NoError(t, err) @@ -62,7 +59,7 @@ func TestRecordSafeHeadUpdates(gt *testing.T) { // 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, 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 @@ -83,7 +80,7 @@ func TestRecordSafeHeadUpdates(gt *testing.T) { // 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, 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 @@ -91,7 +88,7 @@ func TestRecordSafeHeadUpdates(gt *testing.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]) + 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) @@ -105,36 +102,10 @@ func TestRecordSafeHeadUpdates(gt *testing.T) { require.Equal(t, verifier.L2Safe(), ref, "verifier engine matches rollup client") // Verify the safe head is recorded again - l1Head = miner.l1Chain.CurrentBlock() + 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/l2_sequencer_test.go b/op-e2e/actions/sequencer/l2_sequencer_test.go similarity index 76% rename from op-e2e/actions/l2_sequencer_test.go rename to op-e2e/actions/sequencer/l2_sequencer_test.go index 6b8ec800408ef..5192c25d7afd0 100644 --- a/op-e2e/actions/l2_sequencer_test.go +++ b/op-e2e/actions/sequencer/l2_sequencer_test.go @@ -1,59 +1,23 @@ -package actions +package sequencer import ( "math/big" "testing" + "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/eth/ethconfig" - "github.com/ethereum/go-ethereum/node" - "github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" "github.com/stretchr/testify/require" - altda "github.com/ethereum-optimism/optimism/op-alt-da" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" - "github.com/ethereum-optimism/optimism/op-service/sources" "github.com/ethereum-optimism/optimism/op-service/testlog" ) -func EngineWithP2P() EngineOption { - return func(ethCfg *ethconfig.Config, nodeCfg *node.Config) error { - p2pKey, err := crypto.GenerateKey() - if err != nil { - return err - } - nodeCfg.P2P = p2p.Config{ - MaxPeers: 100, - NoDiscovery: true, - ListenAddr: "127.0.0.1:0", - PrivateKey: p2pKey, - } - return nil - } -} - -func setupSequencerTest(t Testing, sd *e2eutils.SetupData, log log.Logger) (*L1Miner, *L2Engine, *L2Sequencer) { - jwtPath := e2eutils.WriteDefaultJWT(t) - - miner := NewL1Miner(t, log.New("role", "l1-miner"), sd.L1Cfg) - - l1F, err := sources.NewL1Client(miner.RPCClient(), log, nil, sources.L1ClientDefaultConfig(sd.RollupCfg, false, sources.RPCKindStandard)) - require.NoError(t, err) - engine := NewL2Engine(t, log.New("role", "sequencer-engine"), sd.L2Cfg, sd.RollupCfg.Genesis.L1, jwtPath, EngineWithP2P()) - l2Cl, err := sources.NewEngineClient(engine.RPCClient(), log, nil, sources.EngineClientDefaultConfig(sd.RollupCfg)) - require.NoError(t, err) - - sequencer := NewL2Sequencer(t, log.New("role", "sequencer"), l1F, miner.BlobStore(), altda.Disabled, l2Cl, sd.RollupCfg, 0) - return miner, engine, sequencer -} - func TestL2Sequencer_SequencerDrift(gt *testing.T) { - t := NewDefaultTesting(gt) + t := helpers.NewDefaultTesting(gt) p := &e2eutils.TestParams{ MaxSequencerDrift: 20, // larger than L1 block time we simulate in this test (12) SequencerWindowSize: 24, @@ -61,9 +25,9 @@ func TestL2Sequencer_SequencerDrift(gt *testing.T) { L1BlockTime: 12, } dp := e2eutils.MakeDeployParams(t, p) - sd := e2eutils.Setup(t, dp, defaultAlloc) + sd := e2eutils.Setup(t, dp, helpers.DefaultAlloc) log := testlog.Logger(t, log.LevelDebug) - miner, engine, sequencer := setupSequencerTest(t, sd, log) + miner, engine, sequencer := helpers.SetupSequencerTest(t, sd, log) miner.ActL1SetFeeRecipient(common.Address{'A'}) sequencer.ActL2PipelineFull(t) @@ -77,7 +41,7 @@ func TestL2Sequencer_SequencerDrift(gt *testing.T) { 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)), + 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), @@ -95,7 +59,7 @@ func TestL2Sequencer_SequencerDrift(gt *testing.T) { miner.ActL1StartBlock(12)(t) miner.ActL1EndBlock(t) sequencer.ActL1HeadSignal(t) - origin := miner.l1Chain.CurrentBlock() + origin := miner.L1Chain().CurrentBlock() // L2 makes blocks to catch up for sequencer.SyncStatus().UnsafeL2.Time+sd.RollupCfg.BlockTime < origin.Time { @@ -120,18 +84,18 @@ func TestL2Sequencer_SequencerDrift(gt *testing.T) { // We passed the sequencer drift: we can still keep the old origin, but can't include any txs sequencer.ActL2KeepL1Origin(t) sequencer.ActL2StartBlock(t) - require.True(t, engine.engineApi.ForcedEmpty(), "engine should not be allowed to include anything after sequencer drift is surpassed") + require.True(t, engine.EngineApi.ForcedEmpty(), "engine should not be allowed to include anything after sequencer drift is surpassed") } // TestL2Sequencer_SequencerOnlyReorg regression-tests a Goerli halt where the sequencer // would build an unsafe L2 block with a L1 origin that then gets reorged out, // while the verifier-codepath only ever sees the valid post-reorg L1 chain. func TestL2Sequencer_SequencerOnlyReorg(gt *testing.T) { - t := NewDefaultTesting(gt) - dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) - sd := e2eutils.Setup(t, dp, defaultAlloc) + t := helpers.NewDefaultTesting(gt) + dp := e2eutils.MakeDeployParams(t, helpers.DefaultRollupTestParams) + sd := e2eutils.Setup(t, dp, helpers.DefaultAlloc) log := testlog.Logger(t, log.LevelDebug) - miner, _, sequencer := setupSequencerTest(t, sd, log) + miner, _, sequencer := helpers.SetupSequencerTest(t, sd, log) // Sequencer at first only recognizes the genesis as safe. // The rest of the L1 chain will be incorporated as L1 origins into unsafe L2 blocks. diff --git a/op-e2e/actions/sync_test.go b/op-e2e/actions/sync/sync_test.go similarity index 79% rename from op-e2e/actions/sync_test.go rename to op-e2e/actions/sync/sync_test.go index 78297a5a81359..523b68517afb6 100644 --- a/op-e2e/actions/sync_test.go +++ b/op-e2e/actions/sync/sync_test.go @@ -1,4 +1,4 @@ -package actions +package sync import ( "errors" @@ -8,6 +8,8 @@ import ( "testing" "time" + actionsHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" + upgradesHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/upgrades/helpers" "github.com/stretchr/testify/require" "github.com/ethereum/go-ethereum" @@ -32,8 +34,8 @@ import ( "github.com/ethereum-optimism/optimism/op-service/testutils" ) -func newSpanChannelOut(t StatefulTesting, e e2eutils.SetupData) derive.ChannelOut { - channelOut, err := derive.NewSpanChannelOut(e.RollupCfg.Genesis.L2Time, e.RollupCfg.L2ChainID, 128_000, derive.Zlib, rollup.NewChainSpec(e.RollupCfg)) +func newSpanChannelOut(t actionsHelpers.StatefulTesting, e e2eutils.SetupData) derive.ChannelOut { + channelOut, err := derive.NewSpanChannelOut(128_000, derive.Zlib, rollup.NewChainSpec(e.RollupCfg)) require.NoError(t, err) return channelOut } @@ -64,12 +66,12 @@ func TestSyncBatchType(t *testing.T) { } func DerivationWithFlakyL1RPC(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { - t := NewDefaultTesting(gt) - dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) - applyDeltaTimeOffset(dp, deltaTimeOffset) - sd := e2eutils.Setup(t, dp, defaultAlloc) + t := actionsHelpers.NewDefaultTesting(gt) + dp := e2eutils.MakeDeployParams(t, actionsHelpers.DefaultRollupTestParams) + upgradesHelpers.ApplyDeltaTimeOffset(dp, deltaTimeOffset) + sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) 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) + _, _, miner, sequencer, _, verifier, _, batcher := actionsHelpers.SetupReorgTestActors(t, dp, sd, log) rng := rand.New(rand.NewSource(1234)) sequencer.ActL2PipelineFull(t) @@ -83,7 +85,7 @@ func DerivationWithFlakyL1RPC(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { sequencer.ActBuildToL1Head(t) batcher.ActSubmitAll(t) miner.ActL1StartBlock(12)(t) - miner.ActL1IncludeTx(batcher.batcherAddr)(t) + miner.ActL1IncludeTx(batcher.BatcherAddr)(t) miner.ActL1EndBlock(t) } // Make verifier aware of head @@ -104,12 +106,12 @@ func DerivationWithFlakyL1RPC(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { } func FinalizeWhileSyncing(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { - t := NewDefaultTesting(gt) - dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) - applyDeltaTimeOffset(dp, deltaTimeOffset) - sd := e2eutils.Setup(t, dp, defaultAlloc) + t := actionsHelpers.NewDefaultTesting(gt) + dp := e2eutils.MakeDeployParams(t, actionsHelpers.DefaultRollupTestParams) + upgradesHelpers.ApplyDeltaTimeOffset(dp, deltaTimeOffset) + sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) 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) + _, _, miner, sequencer, _, verifier, _, batcher := actionsHelpers.SetupReorgTestActors(t, dp, sd, log) sequencer.ActL2PipelineFull(t) verifier.ActL2PipelineFull(t) @@ -126,10 +128,10 @@ func FinalizeWhileSyncing(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { sequencer.ActBuildToL1Head(t) batcher.ActSubmitAll(t) miner.ActL1StartBlock(12)(t) - miner.ActL1IncludeTx(batcher.batcherAddr)(t) + miner.ActL1IncludeTx(batcher.BatcherAddr)(t) miner.ActL1EndBlock(t) } - l1Head := miner.l1Chain.CurrentHeader() + l1Head := miner.L1Chain().CurrentHeader() // finalize all of L1 miner.ActL1Safe(t, l1Head.Number.Uint64()) miner.ActL1Finalize(t, l1Head.Number.Uint64()) @@ -150,12 +152,12 @@ func FinalizeWhileSyncing(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { // TestUnsafeSync tests that a verifier properly imports unsafe blocks via gossip. func TestUnsafeSync(gt *testing.T) { - t := NewDefaultTesting(gt) - dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) - sd := e2eutils.Setup(t, dp, defaultAlloc) + t := actionsHelpers.NewDefaultTesting(gt) + dp := e2eutils.MakeDeployParams(t, actionsHelpers.DefaultRollupTestParams) + sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) log := testlog.Logger(t, log.LevelInfo) - sd, _, _, sequencer, seqEng, verifier, _, _ := setupReorgTestActors(t, dp, sd, log) + sd, _, _, sequencer, seqEng, verifier, _, _ := actionsHelpers.SetupReorgTestActors(t, dp, sd, log) seqEngCl, err := sources.NewEngineClient(seqEng.RPCClient(), log, nil, sources.EngineClientDefaultConfig(sd.RollupCfg)) require.NoError(t, err) @@ -178,15 +180,15 @@ func TestUnsafeSync(gt *testing.T) { } func TestBackupUnsafe(gt *testing.T) { - t := NewDefaultTesting(gt) - dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) + t := actionsHelpers.NewDefaultTesting(gt) + dp := e2eutils.MakeDeployParams(t, actionsHelpers.DefaultRollupTestParams) minTs := hexutil.Uint64(0) // Activate Delta hardfork - applyDeltaTimeOffset(dp, &minTs) + upgradesHelpers.ApplyDeltaTimeOffset(dp, &minTs) dp.DeployConfig.L2BlockTime = 2 - sd := e2eutils.Setup(t, dp, defaultAlloc) + sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) log := testlog.Logger(t, log.LvlInfo) - _, dp, miner, sequencer, seqEng, verifier, _, batcher := setupReorgTestActors(t, dp, sd, log) + _, dp, miner, sequencer, seqEng, verifier, _, batcher := actionsHelpers.SetupReorgTestActors(t, dp, sd, log) l2Cl := seqEng.EthClient() seqEngCl, err := sources.NewEngineClient(seqEng.RPCClient(), log, nil, sources.EngineClientDefaultConfig(sd.RollupCfg)) require.NoError(t, err) @@ -238,7 +240,7 @@ func TestBackupUnsafe(gt *testing.T) { 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)), + 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), @@ -256,7 +258,7 @@ func TestBackupUnsafe(gt *testing.T) { } // Submit span batch(A1, B2, invalid B3, B4, B5) - batcher.l2ChannelOut = channelOut + batcher.L2ChannelOut = channelOut batcher.ActL2ChannelClose(t) batcher.ActL2BatchSubmit(t) @@ -339,15 +341,15 @@ func TestBackupUnsafe(gt *testing.T) { } func TestBackupUnsafeReorgForkChoiceInputError(gt *testing.T) { - t := NewDefaultTesting(gt) - dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) + t := actionsHelpers.NewDefaultTesting(gt) + dp := e2eutils.MakeDeployParams(t, actionsHelpers.DefaultRollupTestParams) minTs := hexutil.Uint64(0) // Activate Delta hardfork - applyDeltaTimeOffset(dp, &minTs) + upgradesHelpers.ApplyDeltaTimeOffset(dp, &minTs) dp.DeployConfig.L2BlockTime = 2 - sd := e2eutils.Setup(t, dp, defaultAlloc) + sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) log := testlog.Logger(t, log.LvlInfo) - _, dp, miner, sequencer, seqEng, verifier, _, batcher := setupReorgTestActors(t, dp, sd, log) + _, dp, miner, sequencer, seqEng, verifier, _, batcher := actionsHelpers.SetupReorgTestActors(t, dp, sd, log) l2Cl := seqEng.EthClient() seqEngCl, err := sources.NewEngineClient(seqEng.RPCClient(), log, nil, sources.EngineClientDefaultConfig(sd.RollupCfg)) require.NoError(t, err) @@ -399,7 +401,7 @@ func TestBackupUnsafeReorgForkChoiceInputError(gt *testing.T) { 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)), + 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), @@ -417,7 +419,7 @@ func TestBackupUnsafeReorgForkChoiceInputError(gt *testing.T) { } // Submit span batch(A1, B2, invalid B3, B4, B5) - batcher.l2ChannelOut = channelOut + batcher.L2ChannelOut = channelOut batcher.ActL2ChannelClose(t) batcher.ActL2BatchSubmit(t) @@ -472,15 +474,15 @@ func TestBackupUnsafeReorgForkChoiceInputError(gt *testing.T) { } func TestBackupUnsafeReorgForkChoiceNotInputError(gt *testing.T) { - t := NewDefaultTesting(gt) - dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) + t := actionsHelpers.NewDefaultTesting(gt) + dp := e2eutils.MakeDeployParams(t, actionsHelpers.DefaultRollupTestParams) minTs := hexutil.Uint64(0) // Activate Delta hardfork - applyDeltaTimeOffset(dp, &minTs) + upgradesHelpers.ApplyDeltaTimeOffset(dp, &minTs) dp.DeployConfig.L2BlockTime = 2 - sd := e2eutils.Setup(t, dp, defaultAlloc) + sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) log := testlog.Logger(t, log.LvlInfo) - _, dp, miner, sequencer, seqEng, verifier, _, batcher := setupReorgTestActors(t, dp, sd, log) + _, dp, miner, sequencer, seqEng, verifier, _, batcher := actionsHelpers.SetupReorgTestActors(t, dp, sd, log) l2Cl := seqEng.EthClient() seqEngCl, err := sources.NewEngineClient(seqEng.RPCClient(), log, nil, sources.EngineClientDefaultConfig(sd.RollupCfg)) require.NoError(t, err) @@ -532,7 +534,7 @@ func TestBackupUnsafeReorgForkChoiceNotInputError(gt *testing.T) { 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)), + 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), @@ -550,7 +552,7 @@ func TestBackupUnsafeReorgForkChoiceNotInputError(gt *testing.T) { } // Submit span batch(A1, B2, invalid B3, B4, B5) - batcher.l2ChannelOut = channelOut + batcher.L2ChannelOut = channelOut batcher.ActL2ChannelClose(t) batcher.ActL2BatchSubmit(t) @@ -587,7 +589,7 @@ func TestBackupUnsafeReorgForkChoiceNotInputError(gt *testing.T) { serverErrCnt := 2 // mock forkChoiceUpdate failure while restoring previous unsafe chain using backupUnsafe. - seqEng.failL2RPC = func(call []rpc.BatchElem) error { + seqEng.FailL2RPC = func(call []rpc.BatchElem) error { for _, e := range call { // There may be other calls, like payload-processing-cancellation // based on previous invalid block, and processing of block attributes. @@ -625,7 +627,7 @@ func TestBackupUnsafeReorgForkChoiceNotInputError(gt *testing.T) { // builds l2 blocks within the specified range `from` - `to` // and performs an EL sync between the sequencer and the verifier, // then checks the validity of the payloads within a specified block range. -func PerformELSyncAndCheckPayloads(t Testing, miner *L1Miner, seqEng *L2Engine, sequencer *L2Sequencer, verEng *L2Engine, verifier *L2Verifier, seqEngCl *sources.EngineClient, from, to uint64) { +func PerformELSyncAndCheckPayloads(t actionsHelpers.Testing, miner *actionsHelpers.L1Miner, seqEng *actionsHelpers.L2Engine, sequencer *actionsHelpers.L2Sequencer, verEng *actionsHelpers.L2Engine, verifier *actionsHelpers.L2Verifier, seqEngCl *sources.EngineClient, from, to uint64) { miner.ActEmptyBlock(t) sequencer.ActL2PipelineFull(t) @@ -658,7 +660,7 @@ func PerformELSyncAndCheckPayloads(t Testing, miner *L1Miner, seqEng *L2Engine, // 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(), from) + block, err := verifier.Eng.L2BlockRefByNumber(t.Ctx(), from) if err != nil { return false } @@ -670,14 +672,14 @@ func PerformELSyncAndCheckPayloads(t Testing, miner *L1Miner, seqEng *L2Engine, } // verifies that a specific block number on the L2 engine has the expected label. -func VerifyBlock(t Testing, engine L2API, number uint64, label eth.BlockLabel) { +func VerifyBlock(t actionsHelpers.Testing, engine actionsHelpers.L2API, number uint64, label eth.BlockLabel) { id, err := engine.L2BlockRefByLabel(t.Ctx(), label) require.NoError(t, err) require.Equal(t, number, id.Number) } // submits batch at a specified block number -func BatchSubmitBlock(t Testing, miner *L1Miner, sequencer *L2Sequencer, verifier *L2Verifier, batcher *L2Batcher, dp *e2eutils.DeployParams, number uint64) { +func BatchSubmitBlock(t actionsHelpers.Testing, miner *actionsHelpers.L1Miner, sequencer *actionsHelpers.L2Sequencer, verifier *actionsHelpers.L2Verifier, batcher *actionsHelpers.L2Batcher, dp *e2eutils.DeployParams, number uint64) { sequencer.ActL2StartBlock(t) sequencer.ActL2EndBlock(t) batcher.ActSubmitAll(t) @@ -691,14 +693,14 @@ func BatchSubmitBlock(t Testing, miner *L1Miner, sequencer *L2Sequencer, verifie // 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) + t := actionsHelpers.NewDefaultTesting(gt) + dp := e2eutils.MakeDeployParams(t, actionsHelpers.DefaultRollupTestParams) + sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) log := testlog.Logger(t, log.LevelInfo) - miner, seqEng, sequencer := setupSequencerTest(t, sd, log) + miner, seqEng, sequencer := actionsHelpers.SetupSequencerTest(t, sd, log) // Enable engine P2P sync - verEng, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{SyncMode: sync.ELSync}) + verEng, verifier := actionsHelpers.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) @@ -706,11 +708,11 @@ func TestELSync(gt *testing.T) { PerformELSyncAndCheckPayloads(t, miner, seqEng, sequencer, verEng, verifier, seqEngCl, 0, 10) } -func PrepareELSyncedNode(t Testing, miner *L1Miner, sequencer *L2Sequencer, seqEng *L2Engine, verifier *L2Verifier, verEng *L2Engine, seqEngCl *sources.EngineClient, batcher *L2Batcher, dp *e2eutils.DeployParams) { +func PrepareELSyncedNode(t actionsHelpers.Testing, miner *actionsHelpers.L1Miner, sequencer *actionsHelpers.L2Sequencer, seqEng *actionsHelpers.L2Engine, verifier *actionsHelpers.L2Verifier, verEng *actionsHelpers.L2Engine, seqEngCl *sources.EngineClient, batcher *actionsHelpers.L2Batcher, dp *e2eutils.DeployParams) { PerformELSyncAndCheckPayloads(t, miner, seqEng, sequencer, verEng, verifier, seqEngCl, 0, 10) // Despite downloading the blocks, it has not finished finalizing - _, err := verifier.eng.L2BlockRefByLabel(t.Ctx(), "safe") + _, err := verifier.Eng.L2BlockRefByLabel(t.Ctx(), "safe") require.ErrorIs(t, err, ethereum.NotFound) // Insert a block on the verifier to end snap sync @@ -721,15 +723,15 @@ func PrepareELSyncedNode(t Testing, miner *L1Miner, sequencer *L2Sequencer, seqE verifier.ActL2InsertUnsafePayload(seqHead)(t) // Check that safe + finalized are there - VerifyBlock(t, verifier.eng, 11, eth.Safe) - VerifyBlock(t, verifier.eng, 11, eth.Finalized) + VerifyBlock(t, verifier.Eng, 11, eth.Safe) + VerifyBlock(t, verifier.Eng, 11, eth.Finalized) // Batch submit everything BatchSubmitBlock(t, miner, sequencer, verifier, batcher, dp, 12) // Verify that the batch submitted blocks are there now - VerifyBlock(t, sequencer.eng, 12, eth.Safe) - VerifyBlock(t, verifier.eng, 12, eth.Safe) + VerifyBlock(t, sequencer.Eng, 12, eth.Safe) + VerifyBlock(t, verifier.Eng, 12, eth.Safe) } // TestELSyncTransitionstoCL tests that a verifier which starts with EL sync can switch back to a proper CL sync. @@ -744,17 +746,17 @@ func PrepareELSyncedNode(t Testing, miner *L1Miner, sequencer *L2Sequencer, seqE // 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) + t := actionsHelpers.NewDefaultTesting(gt) + dp := e2eutils.MakeDeployParams(t, actionsHelpers.DefaultRollupTestParams) + sd := e2eutils.Setup(t, dp, actionsHelpers.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)) + miner, seqEng, sequencer := actionsHelpers.SetupSequencerTest(t, sd, logger) + batcher := actionsHelpers.NewL2Batcher(logger, sd.RollupCfg, actionsHelpers.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}) + verEng, verifier := actionsHelpers.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) @@ -790,28 +792,28 @@ func TestELSyncTransitionstoCL(gt *testing.T) { // 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. - VerifyBlock(t, verifier.eng, 22, eth.Unsafe) + VerifyBlock(t, verifier.Eng, 22, eth.Unsafe) // Create 1 more block & batch submit everything BatchSubmitBlock(t, miner, sequencer, verifier, batcher, dp, 12) // Verify that the batch submitted blocks are there now - VerifyBlock(t, sequencer.eng, 23, eth.Safe) - VerifyBlock(t, verifier.eng, 23, eth.Safe) + VerifyBlock(t, sequencer.Eng, 23, eth.Safe) + VerifyBlock(t, verifier.Eng, 23, eth.Safe) } func TestELSyncTransitionsToCLSyncAfterNodeRestart(gt *testing.T) { - t := NewDefaultTesting(gt) - dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) - sd := e2eutils.Setup(t, dp, defaultAlloc) + t := actionsHelpers.NewDefaultTesting(gt) + dp := e2eutils.MakeDeployParams(t, actionsHelpers.DefaultRollupTestParams) + sd := e2eutils.Setup(t, dp, actionsHelpers.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)) + miner, seqEng, sequencer := actionsHelpers.SetupSequencerTest(t, sd, logger) + batcher := actionsHelpers.NewL2Batcher(logger, sd.RollupCfg, actionsHelpers.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}) + verEng, verifier := actionsHelpers.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) @@ -819,7 +821,7 @@ func TestELSyncTransitionsToCLSyncAfterNodeRestart(gt *testing.T) { PrepareELSyncedNode(t, miner, sequencer, seqEng, verifier, verEng, seqEngCl, batcher, dp) // Create a new verifier which is essentially a new op-node with the sync mode of ELSync and default geth engine kind. - verifier = NewL2Verifier(t, captureLog, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), altda.Disabled, verifier.eng, sd.RollupCfg, &sync.Config{SyncMode: sync.ELSync}, defaultVerifierCfg().safeHeadListener) + verifier = actionsHelpers.NewL2Verifier(t, captureLog, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), altda.Disabled, verifier.Eng, sd.RollupCfg, &sync.Config{SyncMode: sync.ELSync}, actionsHelpers.DefaultVerifierCfg().SafeHeadListener, nil) // Build another 10 L1 blocks on the sequencer for i := 0; i < 10; i++ { @@ -843,17 +845,17 @@ func TestELSyncTransitionsToCLSyncAfterNodeRestart(gt *testing.T) { } func TestForcedELSyncCLAfterNodeRestart(gt *testing.T) { - t := NewDefaultTesting(gt) - dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) - sd := e2eutils.Setup(t, dp, defaultAlloc) + t := actionsHelpers.NewDefaultTesting(gt) + dp := e2eutils.MakeDeployParams(t, actionsHelpers.DefaultRollupTestParams) + sd := e2eutils.Setup(t, dp, actionsHelpers.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)) + miner, seqEng, sequencer := actionsHelpers.SetupSequencerTest(t, sd, logger) + batcher := actionsHelpers.NewL2Batcher(logger, sd.RollupCfg, actionsHelpers.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}) + verEng, verifier := actionsHelpers.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) @@ -861,7 +863,7 @@ func TestForcedELSyncCLAfterNodeRestart(gt *testing.T) { PrepareELSyncedNode(t, miner, sequencer, seqEng, verifier, verEng, seqEngCl, batcher, dp) // Create a new verifier which is essentially a new op-node with the sync mode of ELSync and erigon engine kind. - verifier2 := NewL2Verifier(t, captureLog, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), altda.Disabled, verifier.eng, sd.RollupCfg, &sync.Config{SyncMode: sync.ELSync, SupportsPostFinalizationELSync: true}, defaultVerifierCfg().safeHeadListener) + verifier2 := actionsHelpers.NewL2Verifier(t, captureLog, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), altda.Disabled, verifier.Eng, sd.RollupCfg, &sync.Config{SyncMode: sync.ELSync, SupportsPostFinalizationELSync: true}, actionsHelpers.DefaultVerifierCfg().SafeHeadListener, nil) // Build another 10 L1 blocks on the sequencer for i := 0; i < 10; i++ { @@ -889,15 +891,15 @@ func TestForcedELSyncCLAfterNodeRestart(gt *testing.T) { } func TestInvalidPayloadInSpanBatch(gt *testing.T) { - t := NewDefaultTesting(gt) - dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) + t := actionsHelpers.NewDefaultTesting(gt) + dp := e2eutils.MakeDeployParams(t, actionsHelpers.DefaultRollupTestParams) minTs := hexutil.Uint64(0) // Activate Delta hardfork - applyDeltaTimeOffset(dp, &minTs) + upgradesHelpers.ApplyDeltaTimeOffset(dp, &minTs) dp.DeployConfig.L2BlockTime = 2 - sd := e2eutils.Setup(t, dp, defaultAlloc) + sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) log := testlog.Logger(t, log.LevelInfo) - _, _, miner, sequencer, seqEng, verifier, _, batcher := setupReorgTestActors(t, dp, sd, log) + _, _, miner, sequencer, seqEng, verifier, _, batcher := actionsHelpers.SetupReorgTestActors(t, dp, sd, log) l2Cl := seqEng.EthClient() rng := rand.New(rand.NewSource(1234)) signer := types.LatestSigner(sd.L2Cfg.Config) @@ -927,7 +929,7 @@ func TestInvalidPayloadInSpanBatch(gt *testing.T) { } // Submit span batch(A1, ..., A7, invalid A8, A9, ..., A12) - batcher.l2ChannelOut = channelOut + batcher.L2ChannelOut = channelOut batcher.ActL2ChannelClose(t) batcher.ActL2BatchSubmit(t) @@ -956,7 +958,7 @@ func TestInvalidPayloadInSpanBatch(gt *testing.T) { data := make([]byte, rand.Intn(100)) gas, err := core.IntrinsicGas(data, nil, false, true, true, false) require.NoError(t, err) - baseFee := seqEng.l2Chain.CurrentBlock().BaseFee + baseFee := seqEng.L2Chain().CurrentBlock().BaseFee tx := types.MustSignNewTx(dp.Secrets.Alice, signer, &types.DynamicFeeTx{ ChainID: sd.L2Cfg.Config.ChainID, Nonce: aliceNonce, @@ -975,7 +977,7 @@ func TestInvalidPayloadInSpanBatch(gt *testing.T) { require.NoError(t, err) } // Submit span batch(B1, A2, ... A12) - batcher.l2ChannelOut = channelOut + batcher.L2ChannelOut = channelOut batcher.ActL2ChannelClose(t) batcher.ActL2BatchSubmit(t) @@ -994,15 +996,15 @@ func TestInvalidPayloadInSpanBatch(gt *testing.T) { } func TestSpanBatchAtomicity_Consolidation(gt *testing.T) { - t := NewDefaultTesting(gt) - dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) + t := actionsHelpers.NewDefaultTesting(gt) + dp := e2eutils.MakeDeployParams(t, actionsHelpers.DefaultRollupTestParams) minTs := hexutil.Uint64(0) // Activate Delta hardfork - applyDeltaTimeOffset(dp, &minTs) + upgradesHelpers.ApplyDeltaTimeOffset(dp, &minTs) dp.DeployConfig.L2BlockTime = 2 - sd := e2eutils.Setup(t, dp, defaultAlloc) + sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) log := testlog.Logger(t, log.LevelInfo) - _, _, miner, sequencer, seqEng, verifier, _, batcher := setupReorgTestActors(t, dp, sd, log) + _, _, miner, sequencer, seqEng, verifier, _, batcher := actionsHelpers.SetupReorgTestActors(t, dp, sd, log) seqEngCl, err := sources.NewEngineClient(seqEng.RPCClient(), log, nil, sources.EngineClientDefaultConfig(sd.RollupCfg)) require.NoError(t, err) @@ -1036,15 +1038,22 @@ func TestSpanBatchAtomicity_Consolidation(gt *testing.T) { // Start verifier safe sync verifier.ActL1HeadSignal(t) - verifier.l2PipelineIdle = false - for !verifier.l2PipelineIdle { + verifier.L2PipelineIdle = false + for !verifier.L2PipelineIdle { // wait for next pending block - verifier.ActL2EventsUntil(t, event.Any( - event.Is[engine2.PendingSafeUpdateEvent], event.Is[derive.DeriverIdleEvent]), 1000, false) + verifier.ActL2EventsUntil(t, func(ev event.Event) bool { + if event.Is[engine2.SafeDerivedEvent](ev) { // safe updates should only happen once the pending-safe reaches the target. + t.Fatal("unexpected next safe update") + } + return event.Any(event.Is[engine2.PendingSafeUpdateEvent], event.Is[derive.DeriverIdleEvent])(ev) + }, 1000, false) if verifier.L2PendingSafe().Number < targetHeadNumber { // If the span batch is not fully processed, the safe head must not advance. require.Equal(t, verifier.L2Safe().Number, uint64(0)) } else { + // Make sure we do the post-processing of what safety updates might happen + // after the pending-safe event, before the next pending-safe event. + verifier.ActL2EventsUntil(t, event.Is[engine2.PendingSafeUpdateEvent], 100, true) // Once the span batch is fully processed, the safe head must advance to the end of span batch. require.Equal(t, verifier.L2Safe().Number, targetHeadNumber) require.Equal(t, verifier.L2Safe(), verifier.L2PendingSafe()) @@ -1055,15 +1064,15 @@ func TestSpanBatchAtomicity_Consolidation(gt *testing.T) { } func TestSpanBatchAtomicity_ForceAdvance(gt *testing.T) { - t := NewDefaultTesting(gt) - dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) + t := actionsHelpers.NewDefaultTesting(gt) + dp := e2eutils.MakeDeployParams(t, actionsHelpers.DefaultRollupTestParams) minTs := hexutil.Uint64(0) // Activate Delta hardfork - applyDeltaTimeOffset(dp, &minTs) + upgradesHelpers.ApplyDeltaTimeOffset(dp, &minTs) dp.DeployConfig.L2BlockTime = 2 - sd := e2eutils.Setup(t, dp, defaultAlloc) + sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) log := testlog.Logger(t, log.LevelInfo) - _, _, miner, sequencer, _, verifier, _, batcher := setupReorgTestActors(t, dp, sd, log) + _, _, miner, sequencer, _, verifier, _, batcher := actionsHelpers.SetupReorgTestActors(t, dp, sd, log) targetHeadNumber := uint64(6) // L1 block time / L2 block time @@ -1085,15 +1094,22 @@ func TestSpanBatchAtomicity_ForceAdvance(gt *testing.T) { // Start verifier safe sync verifier.ActL1HeadSignal(t) - verifier.l2PipelineIdle = false - for !verifier.l2PipelineIdle { + verifier.L2PipelineIdle = false + for !verifier.L2PipelineIdle { // wait for next pending block - verifier.ActL2EventsUntil(t, event.Any( - event.Is[engine2.PendingSafeUpdateEvent], event.Is[derive.DeriverIdleEvent]), 1000, false) + verifier.ActL2EventsUntil(t, func(ev event.Event) bool { + if event.Is[engine2.SafeDerivedEvent](ev) { // safe updates should only happen once the pending-safe reaches the target. + t.Fatal("unexpected next safe update") + } + return event.Any(event.Is[engine2.PendingSafeUpdateEvent], event.Is[derive.DeriverIdleEvent])(ev) + }, 1000, false) if verifier.L2PendingSafe().Number < targetHeadNumber { // If the span batch is not fully processed, the safe head must not advance. require.Equal(t, verifier.L2Safe().Number, uint64(0)) } else { + // Make sure we do the post-processing of what safety updates might happen + // after the pending-safe event, before the next pending-safe event. + verifier.ActL2EventsUntil(t, event.Is[engine2.PendingSafeUpdateEvent], 100, true) // Once the span batch is fully processed, the safe head must advance to the end of span batch. require.Equal(t, verifier.L2Safe().Number, targetHeadNumber) require.Equal(t, verifier.L2Safe(), verifier.L2PendingSafe()) diff --git a/op-e2e/actions/dencun_fork_test.go b/op-e2e/actions/upgrades/dencun_fork_test.go similarity index 71% rename from op-e2e/actions/dencun_fork_test.go rename to op-e2e/actions/upgrades/dencun_fork_test.go index 9b411e28f1e71..a9e3eb2cc2562 100644 --- a/op-e2e/actions/dencun_fork_test.go +++ b/op-e2e/actions/upgrades/dencun_fork_test.go @@ -1,9 +1,10 @@ -package actions +package upgrades import ( "context" "testing" + "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" "github.com/stretchr/testify/require" "github.com/ethereum/go-ethereum/common" @@ -17,15 +18,15 @@ import ( ) func TestDencunL1ForkAfterGenesis(gt *testing.T) { - t := NewDefaultTesting(gt) - dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) + t := helpers.NewDefaultTesting(gt) + dp := e2eutils.MakeDeployParams(t, helpers.DefaultRollupTestParams) offset := hexutil.Uint64(24) dp.DeployConfig.L1CancunTimeOffset = &offset - sd := e2eutils.Setup(t, dp, defaultAlloc) + sd := e2eutils.Setup(t, dp, helpers.DefaultAlloc) log := testlog.Logger(t, log.LevelDebug) - _, _, miner, sequencer, _, verifier, _, batcher := setupReorgTestActors(t, dp, sd, log) + _, _, miner, sequencer, _, verifier, _, batcher := helpers.SetupReorgTestActors(t, dp, sd, log) - l1Head := miner.l1Chain.CurrentBlock() + l1Head := miner.L1Chain().CurrentBlock() require.False(t, sd.L1Cfg.Config.IsCancun(l1Head.Number, l1Head.Time), "Cancun not active yet") require.Nil(t, l1Head.ExcessBlobGas, "Cancun blob gas not in header") @@ -39,7 +40,7 @@ func TestDencunL1ForkAfterGenesis(gt *testing.T) { miner.ActEmptyBlock(t) // Cancun activates here miner.ActEmptyBlock(t) // verify Cancun is active - l1Head = miner.l1Chain.CurrentBlock() + l1Head = miner.L1Chain().CurrentBlock() require.True(t, sd.L1Cfg.Config.IsCancun(l1Head.Number, l1Head.Time), "Cancun active") require.NotNil(t, l1Head.ExcessBlobGas, "Cancun blob gas in header") @@ -48,7 +49,7 @@ func TestDencunL1ForkAfterGenesis(gt *testing.T) { sequencer.ActBuildToL1Head(t) miner.ActL1StartBlock(12)(t) batcher.ActSubmitAll(t) - miner.ActL1IncludeTx(batcher.batcherAddr)(t) + miner.ActL1IncludeTx(batcher.BatcherAddr)(t) miner.ActL1EndBlock(t) // sync verifier @@ -60,14 +61,14 @@ func TestDencunL1ForkAfterGenesis(gt *testing.T) { } func TestDencunL1ForkAtGenesis(gt *testing.T) { - t := NewDefaultTesting(gt) - dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) + t := helpers.NewDefaultTesting(gt) + dp := e2eutils.MakeDeployParams(t, helpers.DefaultRollupTestParams) require.Zero(t, *dp.DeployConfig.L1CancunTimeOffset) - sd := e2eutils.Setup(t, dp, defaultAlloc) + sd := e2eutils.Setup(t, dp, helpers.DefaultAlloc) log := testlog.Logger(t, log.LevelDebug) - _, _, miner, sequencer, _, verifier, _, batcher := setupReorgTestActors(t, dp, sd, log) + _, _, miner, sequencer, _, verifier, _, batcher := helpers.SetupReorgTestActors(t, dp, sd, log) - l1Head := miner.l1Chain.CurrentBlock() + l1Head := miner.L1Chain().CurrentBlock() require.True(t, sd.L1Cfg.Config.IsCancun(l1Head.Number, l1Head.Time), "Cancun active at genesis") require.NotNil(t, l1Head.ExcessBlobGas, "Cancun blob gas in header") @@ -81,7 +82,7 @@ func TestDencunL1ForkAtGenesis(gt *testing.T) { miner.ActEmptyBlock(t) // verify Cancun is still active - l1Head = miner.l1Chain.CurrentBlock() + l1Head = miner.L1Chain().CurrentBlock() require.True(t, sd.L1Cfg.Config.IsCancun(l1Head.Number, l1Head.Time), "Cancun active") require.NotNil(t, l1Head.ExcessBlobGas, "Cancun blob gas in header") @@ -90,7 +91,7 @@ func TestDencunL1ForkAtGenesis(gt *testing.T) { sequencer.ActBuildToL1Head(t) miner.ActL1StartBlock(12)(t) batcher.ActSubmitAll(t) - miner.ActL1IncludeTx(batcher.batcherAddr)(t) + miner.ActL1IncludeTx(batcher.BatcherAddr)(t) miner.ActL1EndBlock(t) // sync verifier @@ -117,8 +118,8 @@ func verifyEcotoneBlock(gt *testing.T, header *types.Header) { } func TestDencunL2ForkAfterGenesis(gt *testing.T) { - t := NewDefaultTesting(gt) - dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) + t := helpers.NewDefaultTesting(gt) + dp := e2eutils.MakeDeployParams(t, helpers.DefaultRollupTestParams) require.Zero(t, *dp.DeployConfig.L1CancunTimeOffset) // This test wil fork on the second block offset := hexutil.Uint64(dp.DeployConfig.L2BlockTime * 2) @@ -127,56 +128,56 @@ func TestDencunL2ForkAfterGenesis(gt *testing.T) { dp.DeployConfig.L2GenesisGraniteTimeOffset = nil // New forks have to be added here, after changing the default deploy config! - sd := e2eutils.Setup(t, dp, defaultAlloc) + sd := e2eutils.Setup(t, dp, helpers.DefaultAlloc) log := testlog.Logger(t, log.LevelDebug) - _, _, _, sequencer, engine, verifier, _, _ := setupReorgTestActors(t, dp, sd, log) + _, _, _, sequencer, engine, verifier, _, _ := helpers.SetupReorgTestActors(t, dp, sd, log) // start op-nodes sequencer.ActL2PipelineFull(t) verifier.ActL2PipelineFull(t) // Genesis block is pre-ecotone - verifyPreEcotoneBlock(gt, engine.l2Chain.CurrentBlock()) + verifyPreEcotoneBlock(gt, engine.L2Chain().CurrentBlock()) // Block before fork block sequencer.ActL2StartBlock(t) sequencer.ActL2EndBlock(t) - verifyPreEcotoneBlock(gt, engine.l2Chain.CurrentBlock()) + verifyPreEcotoneBlock(gt, engine.L2Chain().CurrentBlock()) // Fork block is ecotone sequencer.ActL2StartBlock(t) sequencer.ActL2EndBlock(t) - verifyEcotoneBlock(gt, engine.l2Chain.CurrentBlock()) + verifyEcotoneBlock(gt, engine.L2Chain().CurrentBlock()) // Blocks post fork have Ecotone properties sequencer.ActL2StartBlock(t) sequencer.ActL2EndBlock(t) - verifyEcotoneBlock(gt, engine.l2Chain.CurrentBlock()) + verifyEcotoneBlock(gt, engine.L2Chain().CurrentBlock()) } func TestDencunL2ForkAtGenesis(gt *testing.T) { - t := NewDefaultTesting(gt) - dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) + t := helpers.NewDefaultTesting(gt) + dp := e2eutils.MakeDeployParams(t, helpers.DefaultRollupTestParams) require.Zero(t, *dp.DeployConfig.L2GenesisEcotoneTimeOffset) - sd := e2eutils.Setup(t, dp, defaultAlloc) + sd := e2eutils.Setup(t, dp, helpers.DefaultAlloc) log := testlog.Logger(t, log.LevelDebug) - _, _, _, sequencer, engine, verifier, _, _ := setupReorgTestActors(t, dp, sd, log) + _, _, _, sequencer, engine, verifier, _, _ := helpers.SetupReorgTestActors(t, dp, sd, log) // start op-nodes sequencer.ActL2PipelineFull(t) verifier.ActL2PipelineFull(t) // Genesis block has ecotone properties - verifyEcotoneBlock(gt, engine.l2Chain.CurrentBlock()) + verifyEcotoneBlock(gt, engine.L2Chain().CurrentBlock()) // Blocks post fork have Ecotone properties sequencer.ActL2StartBlock(t) sequencer.ActL2EndBlock(t) - verifyEcotoneBlock(gt, engine.l2Chain.CurrentBlock()) + verifyEcotoneBlock(gt, engine.L2Chain().CurrentBlock()) } -func aliceSimpleBlobTx(t Testing, dp *e2eutils.DeployParams) *types.Transaction { +func aliceSimpleBlobTx(t helpers.Testing, dp *e2eutils.DeployParams) *types.Transaction { txData := transactions.CreateEmptyBlobTx(true, dp.DeployConfig.L2ChainID) // Manual signer creation, so we can sign a blob tx on the chain, // even though we have disabled cancun signer support in Ecotone. @@ -186,17 +187,17 @@ func aliceSimpleBlobTx(t Testing, dp *e2eutils.DeployParams) *types.Transaction return tx } -func newEngine(t Testing, sd *e2eutils.SetupData, log log.Logger) *L2Engine { +func newEngine(t helpers.Testing, sd *e2eutils.SetupData, log log.Logger) *helpers.L2Engine { jwtPath := e2eutils.WriteDefaultJWT(t) - return NewL2Engine(t, log, sd.L2Cfg, sd.RollupCfg.Genesis.L1, jwtPath) + return helpers.NewL2Engine(t, log, sd.L2Cfg, sd.RollupCfg.Genesis.L1, jwtPath) } // TestDencunBlobTxRPC tries to send a Blob tx to the L2 engine via RPC, it should not be accepted. func TestDencunBlobTxRPC(gt *testing.T) { - t := NewDefaultTesting(gt) - dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) + t := helpers.NewDefaultTesting(gt) + dp := e2eutils.MakeDeployParams(t, helpers.DefaultRollupTestParams) - sd := e2eutils.Setup(t, dp, defaultAlloc) + sd := e2eutils.Setup(t, dp, helpers.DefaultAlloc) log := testlog.Logger(t, log.LevelDebug) engine := newEngine(t, sd, log) cl := engine.EthClient() @@ -207,31 +208,31 @@ func TestDencunBlobTxRPC(gt *testing.T) { // TestDencunBlobTxInTxPool tries to insert a blob tx directly into the tx pool, it should not be accepted. func TestDencunBlobTxInTxPool(gt *testing.T) { - t := NewDefaultTesting(gt) - dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) + t := helpers.NewDefaultTesting(gt) + dp := e2eutils.MakeDeployParams(t, helpers.DefaultRollupTestParams) - sd := e2eutils.Setup(t, dp, defaultAlloc) + sd := e2eutils.Setup(t, dp, helpers.DefaultAlloc) 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) + errs := engine.Eth.TxPool().Add([]*types.Transaction{tx}, true, true) require.ErrorContains(t, errs[0], "transaction type not supported") } // TestDencunBlobTxInclusion tries to send a Blob tx to the L2 engine, it should not be accepted. func TestDencunBlobTxInclusion(gt *testing.T) { - t := NewDefaultTesting(gt) - dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) + t := helpers.NewDefaultTesting(gt) + dp := e2eutils.MakeDeployParams(t, helpers.DefaultRollupTestParams) - sd := e2eutils.Setup(t, dp, defaultAlloc) + sd := e2eutils.Setup(t, dp, helpers.DefaultAlloc) log := testlog.Logger(t, log.LevelDebug) - _, engine, sequencer := setupSequencerTest(t, sd, log) + _, engine, sequencer := helpers.SetupSequencerTest(t, sd, log) sequencer.ActL2PipelineFull(t) tx := aliceSimpleBlobTx(t, dp) sequencer.ActL2StartBlock(t) - err := engine.engineApi.IncludeTx(tx, dp.Addresses.Alice) + err := engine.EngineApi.IncludeTx(tx, dp.Addresses.Alice) require.ErrorContains(t, err, "invalid L2 block (tx 1): failed to apply transaction to L2 block (tx 1): transaction type not supported") } diff --git a/op-e2e/actions/ecotone_fork_test.go b/op-e2e/actions/upgrades/ecotone_fork_test.go similarity index 93% rename from op-e2e/actions/ecotone_fork_test.go rename to op-e2e/actions/upgrades/ecotone_fork_test.go index 260a7960089ad..c4135266e1625 100644 --- a/op-e2e/actions/ecotone_fork_test.go +++ b/op-e2e/actions/upgrades/ecotone_fork_test.go @@ -1,10 +1,11 @@ -package actions +package upgrades import ( "context" "math/big" "testing" + "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" "github.com/stretchr/testify/require" "github.com/ethereum/go-ethereum/common" @@ -30,7 +31,7 @@ var ( // 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 { +func verifyCodeHashMatches(t helpers.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) @@ -40,8 +41,8 @@ func verifyCodeHashMatches(t Testing, client *ethclient.Client, address common.A } func TestEcotoneNetworkUpgradeTransactions(gt *testing.T) { - t := NewDefaultTesting(gt) - dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) + t := helpers.NewDefaultTesting(gt) + dp := e2eutils.MakeDeployParams(t, helpers.DefaultRollupTestParams) ecotoneOffset := hexutil.Uint64(4) log := testlog.Logger(t, log.LevelDebug) @@ -54,8 +55,8 @@ func TestEcotoneNetworkUpgradeTransactions(gt *testing.T) { // New forks have to be added here... require.NoError(t, dp.DeployConfig.Check(log), "must have valid config") - sd := e2eutils.Setup(t, dp, defaultAlloc) - _, _, miner, sequencer, engine, verifier, _, _ := setupReorgTestActors(t, dp, sd, log) + sd := e2eutils.Setup(t, dp, helpers.DefaultAlloc) + _, _, miner, sequencer, engine, verifier, _, _ := helpers.SetupReorgTestActors(t, dp, sd, log) ethCl := engine.EthClient() // build a single block to move away from the genesis with 0-values in L1Block contract @@ -238,8 +239,8 @@ func TestEcotoneNetworkUpgradeTransactions(gt *testing.T) { // TestEcotoneBeforeL1 tests that the L2 Ecotone fork can activate before L1 Dencun does func TestEcotoneBeforeL1(gt *testing.T) { - t := NewDefaultTesting(gt) - dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) + t := helpers.NewDefaultTesting(gt) + dp := e2eutils.MakeDeployParams(t, helpers.DefaultRollupTestParams) offset := hexutil.Uint64(0) farOffset := hexutil.Uint64(10000) dp.DeployConfig.L2GenesisRegolithTimeOffset = &offset @@ -248,19 +249,19 @@ func TestEcotoneBeforeL1(gt *testing.T) { dp.DeployConfig.L2GenesisDeltaTimeOffset = &offset dp.DeployConfig.L2GenesisEcotoneTimeOffset = &offset - sd := e2eutils.Setup(t, dp, defaultAlloc) + sd := e2eutils.Setup(t, dp, helpers.DefaultAlloc) log := testlog.Logger(t, log.LevelDebug) - _, _, _, sequencer, engine, verifier, _, _ := setupReorgTestActors(t, dp, sd, log) + _, _, _, sequencer, engine, verifier, _, _ := helpers.SetupReorgTestActors(t, dp, sd, log) // start op-nodes sequencer.ActL2PipelineFull(t) verifier.ActL2PipelineFull(t) // Genesis block has ecotone properties - verifyEcotoneBlock(gt, engine.l2Chain.CurrentBlock()) + verifyEcotoneBlock(gt, engine.L2Chain().CurrentBlock()) // Blocks post fork have Ecotone properties sequencer.ActL2StartBlock(t) sequencer.ActL2EndBlock(t) - verifyEcotoneBlock(gt, engine.l2Chain.CurrentBlock()) + verifyEcotoneBlock(gt, engine.L2Chain().CurrentBlock()) } diff --git a/op-e2e/actions/fjord_fork_test.go b/op-e2e/actions/upgrades/fjord_fork_test.go similarity index 94% rename from op-e2e/actions/fjord_fork_test.go rename to op-e2e/actions/upgrades/fjord_fork_test.go index 517ec5cd2618a..9444fcfcb7ae6 100644 --- a/op-e2e/actions/fjord_fork_test.go +++ b/op-e2e/actions/upgrades/fjord_fork_test.go @@ -1,4 +1,4 @@ -package actions +package upgrades import ( "context" @@ -6,6 +6,7 @@ import ( "math/big" "testing" + "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" @@ -29,8 +30,8 @@ var ( ) func TestFjordNetworkUpgradeTransactions(gt *testing.T) { - t := NewDefaultTesting(gt) - dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) + t := helpers.NewDefaultTesting(gt) + dp := e2eutils.MakeDeployParams(t, helpers.DefaultRollupTestParams) genesisBlock := hexutil.Uint64(0) fjordOffset := hexutil.Uint64(2) @@ -46,8 +47,8 @@ func TestFjordNetworkUpgradeTransactions(gt *testing.T) { dp.DeployConfig.L2GenesisFjordTimeOffset = &fjordOffset require.NoError(t, dp.DeployConfig.Check(log), "must have valid config") - sd := e2eutils.Setup(t, dp, defaultAlloc) - _, _, _, sequencer, engine, verifier, _, _ := setupReorgTestActors(t, dp, sd, log) + sd := e2eutils.Setup(t, dp, helpers.DefaultAlloc) + _, _, _, sequencer, engine, verifier, _, _ := helpers.SetupReorgTestActors(t, dp, sd, log) ethCl := engine.EthClient() // start op-nodes diff --git a/op-e2e/actions/upgrades/helpers/config.go b/op-e2e/actions/upgrades/helpers/config.go new file mode 100644 index 0000000000000..a936d86250a05 --- /dev/null +++ b/op-e2e/actions/upgrades/helpers/config.go @@ -0,0 +1,27 @@ +package helpers + +import ( + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" + "github.com/ethereum/go-ethereum/common/hexutil" +) + +// ApplyDeltaTimeOffset adjusts fork configuration to not conflict with the delta overrides +func ApplyDeltaTimeOffset(dp *e2eutils.DeployParams, deltaTimeOffset *hexutil.Uint64) { + dp.DeployConfig.L2GenesisDeltaTimeOffset = deltaTimeOffset + // configure Ecotone to not be before Delta accidentally + if dp.DeployConfig.L2GenesisEcotoneTimeOffset != nil { + if deltaTimeOffset == nil { + dp.DeployConfig.L2GenesisEcotoneTimeOffset = nil + } else if *dp.DeployConfig.L2GenesisEcotoneTimeOffset < *deltaTimeOffset { + dp.DeployConfig.L2GenesisEcotoneTimeOffset = deltaTimeOffset + } + } + // configure Fjord to not be before Delta accidentally + if dp.DeployConfig.L2GenesisFjordTimeOffset != nil { + if deltaTimeOffset == nil { + dp.DeployConfig.L2GenesisFjordTimeOffset = nil + } else if *dp.DeployConfig.L2GenesisFjordTimeOffset < *deltaTimeOffset { + dp.DeployConfig.L2GenesisFjordTimeOffset = deltaTimeOffset + } + } +} diff --git a/op-e2e/actions/span_batch_test.go b/op-e2e/actions/upgrades/span_batch_test.go similarity index 82% rename from op-e2e/actions/span_batch_test.go rename to op-e2e/actions/upgrades/span_batch_test.go index 23f5963fa97ae..fc1707b158a05 100644 --- a/op-e2e/actions/span_batch_test.go +++ b/op-e2e/actions/upgrades/span_batch_test.go @@ -1,4 +1,4 @@ -package actions +package upgrades import ( "context" @@ -10,6 +10,8 @@ import ( "math/rand" "testing" + actionsHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" + upgradesHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/upgrades/helpers" "github.com/stretchr/testify/require" "github.com/ethereum/go-ethereum" @@ -31,7 +33,7 @@ import ( // TestDropSpanBatchBeforeHardfork tests behavior of op-node before Delta hardfork. // op-node must drop SpanBatch before Delta hardfork. func TestDropSpanBatchBeforeHardfork(gt *testing.T) { - t := NewDefaultTesting(gt) + t := actionsHelpers.NewDefaultTesting(gt) p := &e2eutils.TestParams{ MaxSequencerDrift: 20, // larger than L1 block time we simulate in this test (12) SequencerWindowSize: 24, @@ -40,15 +42,15 @@ func TestDropSpanBatchBeforeHardfork(gt *testing.T) { } dp := e2eutils.MakeDeployParams(t, p) // do not activate Delta hardfork for verifier - applyDeltaTimeOffset(dp, nil) - sd := e2eutils.Setup(t, dp, defaultAlloc) + upgradesHelpers.ApplyDeltaTimeOffset(dp, nil) + sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) log := testlog.Logger(t, log.LevelError) - miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) - verifEngine, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) + miner, seqEngine, sequencer := actionsHelpers.SetupSequencerTest(t, sd, log) + verifEngine, verifier := actionsHelpers.SetupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) rollupSeqCl := sequencer.RollupClient() // Force batcher to submit SpanBatches to L1. - batcher := NewL2Batcher(log, sd.RollupCfg, &BatcherCfg{ + batcher := actionsHelpers.NewL2Batcher(log, sd.RollupCfg, &actionsHelpers.BatcherCfg{ MinL1TxSize: 0, MaxL1TxSize: 128_000, BatcherKey: dp.Secrets.Batcher, @@ -65,7 +67,7 @@ func TestDropSpanBatchBeforeHardfork(gt *testing.T) { 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)), + 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), @@ -89,8 +91,8 @@ func TestDropSpanBatchBeforeHardfork(gt *testing.T) { miner.ActL1StartBlock(12)(t) miner.ActL1IncludeTx(dp.Addresses.Batcher)(t) miner.ActL1EndBlock(t) - bl := miner.l1Chain.CurrentBlock() - log.Info("bl", "txs", len(miner.l1Chain.GetBlockByHash(bl.Hash()).Transactions())) + bl := miner.L1Chain().CurrentBlock() + log.Info("bl", "txs", len(miner.L1Chain().GetBlockByHash(bl.Hash()).Transactions())) // Now make enough L1 blocks that the verifier will have to derive a L2 block // It will also eagerly derive the block from the batcher @@ -120,7 +122,7 @@ func TestDropSpanBatchBeforeHardfork(gt *testing.T) { // TestHardforkMiddleOfSpanBatch tests behavior of op-node Delta hardfork. // If Delta activation time is in the middle of time range of a SpanBatch, op-node must drop the batch. func TestHardforkMiddleOfSpanBatch(gt *testing.T) { - t := NewDefaultTesting(gt) + t := actionsHelpers.NewDefaultTesting(gt) p := &e2eutils.TestParams{ MaxSequencerDrift: 20, // larger than L1 block time we simulate in this test (12) SequencerWindowSize: 24, @@ -131,21 +133,21 @@ func TestHardforkMiddleOfSpanBatch(gt *testing.T) { // Activate HF in the middle of the first epoch deltaOffset := hexutil.Uint64(6) - applyDeltaTimeOffset(dp, &deltaOffset) + upgradesHelpers.ApplyDeltaTimeOffset(dp, &deltaOffset) // Applies to HF that goes into Delta. Otherwise we end up with more upgrade txs and things during this case. dp.DeployConfig.L2GenesisEcotoneTimeOffset = nil dp.DeployConfig.L2GenesisFjordTimeOffset = nil dp.DeployConfig.L2GenesisGraniteTimeOffset = nil - sd := e2eutils.Setup(t, dp, defaultAlloc) + sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) log := testlog.Logger(t, log.LevelError) - miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) - verifEngine, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) + miner, seqEngine, sequencer := actionsHelpers.SetupSequencerTest(t, sd, log) + verifEngine, verifier := actionsHelpers.SetupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) minerCl := miner.EthClient() rollupSeqCl := sequencer.RollupClient() // Force batcher to submit SpanBatches to L1. - batcher := NewL2Batcher(log, sd.RollupCfg, &BatcherCfg{ + batcher := actionsHelpers.NewL2Batcher(log, sd.RollupCfg, &actionsHelpers.BatcherCfg{ MinL1TxSize: 0, MaxL1TxSize: 128_000, BatcherKey: dp.Secrets.Batcher, @@ -162,7 +164,7 @@ func TestHardforkMiddleOfSpanBatch(gt *testing.T) { 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)), + 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), @@ -202,8 +204,8 @@ func TestHardforkMiddleOfSpanBatch(gt *testing.T) { miner.ActL1StartBlock(12)(t) miner.ActL1IncludeTx(dp.Addresses.Batcher)(t) miner.ActL1EndBlock(t) - bl := miner.l1Chain.CurrentBlock() - log.Info("bl", "txs", len(miner.l1Chain.GetBlockByHash(bl.Hash()).Transactions())) + bl := miner.L1Chain().CurrentBlock() + log.Info("bl", "txs", len(miner.L1Chain().GetBlockByHash(bl.Hash()).Transactions())) // Now make enough L1 blocks that the verifier will have to derive a L2 block // It will also eagerly derive the block from the batcher @@ -233,7 +235,7 @@ func TestHardforkMiddleOfSpanBatch(gt *testing.T) { // TestAcceptSingularBatchAfterHardfork tests behavior of op-node after Delta hardfork. // op-node must accept SingularBatch after Delta hardfork. func TestAcceptSingularBatchAfterHardfork(gt *testing.T) { - t := NewDefaultTesting(gt) + t := actionsHelpers.NewDefaultTesting(gt) p := &e2eutils.TestParams{ MaxSequencerDrift: 20, // larger than L1 block time we simulate in this test (12) SequencerWindowSize: 24, @@ -244,15 +246,15 @@ func TestAcceptSingularBatchAfterHardfork(gt *testing.T) { dp := e2eutils.MakeDeployParams(t, p) // activate Delta hardfork for verifier. - applyDeltaTimeOffset(dp, &minTs) - sd := e2eutils.Setup(t, dp, defaultAlloc) + upgradesHelpers.ApplyDeltaTimeOffset(dp, &minTs) + sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) log := testlog.Logger(t, log.LevelError) - miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) - verifEngine, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) + miner, seqEngine, sequencer := actionsHelpers.SetupSequencerTest(t, sd, log) + verifEngine, verifier := actionsHelpers.SetupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) rollupSeqCl := sequencer.RollupClient() // Force batcher to submit SingularBatches to L1. - batcher := NewL2Batcher(log, sd.RollupCfg, &BatcherCfg{ + batcher := actionsHelpers.NewL2Batcher(log, sd.RollupCfg, &actionsHelpers.BatcherCfg{ MinL1TxSize: 0, MaxL1TxSize: 128_000, BatcherKey: dp.Secrets.Batcher, @@ -269,7 +271,7 @@ func TestAcceptSingularBatchAfterHardfork(gt *testing.T) { 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)), + 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), @@ -293,8 +295,8 @@ func TestAcceptSingularBatchAfterHardfork(gt *testing.T) { miner.ActL1StartBlock(12)(t) miner.ActL1IncludeTx(dp.Addresses.Batcher)(t) miner.ActL1EndBlock(t) - bl := miner.l1Chain.CurrentBlock() - log.Info("bl", "txs", len(miner.l1Chain.GetBlockByHash(bl.Hash()).Transactions())) + bl := miner.L1Chain().CurrentBlock() + log.Info("bl", "txs", len(miner.L1Chain().GetBlockByHash(bl.Hash()).Transactions())) // Now make enough L1 blocks that the verifier will have to derive a L2 block // It will also eagerly derive the block from the batcher @@ -319,7 +321,7 @@ func TestAcceptSingularBatchAfterHardfork(gt *testing.T) { // TestMixOfBatchesAfterHardfork tests behavior of op-node after Delta hardfork. // op-node must accept SingularBatch and SpanBatch in sequence. func TestMixOfBatchesAfterHardfork(gt *testing.T) { - t := NewDefaultTesting(gt) + t := actionsHelpers.NewDefaultTesting(gt) p := &e2eutils.TestParams{ MaxSequencerDrift: 20, // larger than L1 block time we simulate in this test (12) SequencerWindowSize: 24, @@ -330,11 +332,11 @@ func TestMixOfBatchesAfterHardfork(gt *testing.T) { dp := e2eutils.MakeDeployParams(t, p) // Activate Delta hardfork for verifier. - applyDeltaTimeOffset(dp, &minTs) - sd := e2eutils.Setup(t, dp, defaultAlloc) + upgradesHelpers.ApplyDeltaTimeOffset(dp, &minTs) + sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) log := testlog.Logger(t, log.LevelError) - miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) - verifEngine, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) + miner, seqEngine, sequencer := actionsHelpers.SetupSequencerTest(t, sd, log) + verifEngine, verifier := actionsHelpers.SetupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) rollupSeqCl := sequencer.RollupClient() seqEngCl := seqEngine.EthClient() @@ -352,7 +354,7 @@ func TestMixOfBatchesAfterHardfork(gt *testing.T) { 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)), + 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), @@ -368,7 +370,7 @@ func TestMixOfBatchesAfterHardfork(gt *testing.T) { sequencer.ActBuildToL1Head(t) // Select batcher mode - batcherCfg := BatcherCfg{ + batcherCfg := actionsHelpers.BatcherCfg{ MinL1TxSize: 0, MaxL1TxSize: 128_000, BatcherKey: dp.Secrets.Batcher, @@ -376,7 +378,7 @@ func TestMixOfBatchesAfterHardfork(gt *testing.T) { 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)) + batcher := actionsHelpers.NewL2Batcher(log, sd.RollupCfg, &batcherCfg, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) // Submit all new blocks batcher.ActSubmitAll(t) @@ -410,7 +412,7 @@ func TestMixOfBatchesAfterHardfork(gt *testing.T) { // TestSpanBatchEmptyChain tests derivation of empty chain using SpanBatch. func TestSpanBatchEmptyChain(gt *testing.T) { - t := NewDefaultTesting(gt) + t := actionsHelpers.NewDefaultTesting(gt) p := &e2eutils.TestParams{ MaxSequencerDrift: 20, SequencerWindowSize: 24, @@ -420,14 +422,14 @@ func TestSpanBatchEmptyChain(gt *testing.T) { dp := e2eutils.MakeDeployParams(t, p) minTs := hexutil.Uint64(0) // Activate Delta hardfork - applyDeltaTimeOffset(dp, &minTs) - sd := e2eutils.Setup(t, dp, defaultAlloc) + upgradesHelpers.ApplyDeltaTimeOffset(dp, &minTs) + sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) log := testlog.Logger(t, log.LevelError) - miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) - _, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) + miner, seqEngine, sequencer := actionsHelpers.SetupSequencerTest(t, sd, log) + _, verifier := actionsHelpers.SetupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) rollupSeqCl := sequencer.RollupClient() - batcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp), + batcher := actionsHelpers.NewL2Batcher(log, sd.RollupCfg, actionsHelpers.DefaultBatcherCfg(dp), rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) sequencer.ActL2PipelineFull(t) @@ -473,7 +475,7 @@ func TestSpanBatchEmptyChain(gt *testing.T) { // TestSpanBatchLowThroughputChain tests derivation of low-throughput chain using SpanBatch. func TestSpanBatchLowThroughputChain(gt *testing.T) { - t := NewDefaultTesting(gt) + t := actionsHelpers.NewDefaultTesting(gt) p := &e2eutils.TestParams{ MaxSequencerDrift: 20, SequencerWindowSize: 24, @@ -483,14 +485,14 @@ func TestSpanBatchLowThroughputChain(gt *testing.T) { dp := e2eutils.MakeDeployParams(t, p) minTs := hexutil.Uint64(0) // Activate Delta hardfork - applyDeltaTimeOffset(dp, &minTs) - sd := e2eutils.Setup(t, dp, defaultAlloc) + upgradesHelpers.ApplyDeltaTimeOffset(dp, &minTs) + sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) log := testlog.Logger(t, log.LevelError) - miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) - _, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) + miner, seqEngine, sequencer := actionsHelpers.SetupSequencerTest(t, sd, log) + _, verifier := actionsHelpers.SetupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) rollupSeqCl := sequencer.RollupClient() - batcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp), + batcher := actionsHelpers.NewL2Batcher(log, sd.RollupCfg, actionsHelpers.DefaultBatcherCfg(dp), rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) cl := seqEngine.EthClient() @@ -521,7 +523,7 @@ func TestSpanBatchLowThroughputChain(gt *testing.T) { totalTxCount := 0 // Make 600 L2 blocks (L1BlockTime / L2BlockTime * 50) including 1~3 txs for i := 0; i < 50; i++ { - for sequencer.engine.UnsafeL2Head().L1Origin.Number < sequencer.syncStatus.L1Head().Number { + for sequencer.L2Unsafe().L1Origin.Number < sequencer.SyncStatus().HeadL1.Number { sequencer.ActL2StartBlock(t) // fill the block with random number of L2 txs for j := 0; j < rand.Intn(3); j++ { @@ -532,7 +534,7 @@ func TestSpanBatchLowThroughputChain(gt *testing.T) { require.NoError(t, err) gas, err := core.IntrinsicGas(data, nil, false, true, true, false) require.NoError(t, err) - baseFee := seqEngine.l2Chain.CurrentBlock().BaseFee + baseFee := seqEngine.L2Chain().CurrentBlock().BaseFee nonce, err := cl.PendingNonceAt(t.Ctx(), addrs[userIdx]) require.NoError(t, err) tx := types.MustSignNewTx(privKeys[userIdx], signer, &types.DynamicFeeTx{ @@ -585,7 +587,7 @@ func TestSpanBatchLowThroughputChain(gt *testing.T) { } func TestBatchEquivalence(gt *testing.T) { - t := NewDefaultTesting(gt) + t := actionsHelpers.NewDefaultTesting(gt) log := testlog.Logger(t, log.LevelError) p := &e2eutils.TestParams{ @@ -597,8 +599,8 @@ func TestBatchEquivalence(gt *testing.T) { // Delta activated deploy config dp := e2eutils.MakeDeployParams(t, p) minTs := hexutil.Uint64(0) - applyDeltaTimeOffset(dp, &minTs) - sdDeltaActivated := e2eutils.Setup(t, dp, defaultAlloc) + upgradesHelpers.ApplyDeltaTimeOffset(dp, &minTs) + sdDeltaActivated := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) // Delta deactivated deploy config rcfg := *sdDeltaActivated.RollupCfg @@ -611,18 +613,18 @@ func TestBatchEquivalence(gt *testing.T) { } // Setup sequencer - miner, seqEngine, sequencer := setupSequencerTest(t, sdDeltaActivated, log) + miner, seqEngine, sequencer := actionsHelpers.SetupSequencerTest(t, sdDeltaActivated, log) rollupSeqCl := sequencer.RollupClient() seqEngCl := seqEngine.EthClient() // Setup Delta activated spanVerifier - _, spanVerifier := setupVerifier(t, sdDeltaActivated, log, miner.L1Client(t, sdDeltaActivated.RollupCfg), miner.BlobStore(), &sync.Config{}) + _, spanVerifier := actionsHelpers.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), miner.BlobStore(), &sync.Config{}) + _, singularVerifier := actionsHelpers.SetupVerifier(t, sdDeltaDeactivated, log, miner.L1Client(t, sdDeltaDeactivated.RollupCfg), miner.BlobStore(), &sync.Config{}) // Setup SpanBatcher - spanBatcher := NewL2Batcher(log, sdDeltaActivated.RollupCfg, &BatcherCfg{ + spanBatcher := actionsHelpers.NewL2Batcher(log, sdDeltaActivated.RollupCfg, &actionsHelpers.BatcherCfg{ MinL1TxSize: 0, MaxL1TxSize: 128_000, BatcherKey: dp.Secrets.Batcher, @@ -631,7 +633,7 @@ func TestBatchEquivalence(gt *testing.T) { }, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sdDeltaActivated.RollupCfg)) // Setup SingularBatcher - singularBatcher := NewL2Batcher(log, sdDeltaDeactivated.RollupCfg, &BatcherCfg{ + singularBatcher := actionsHelpers.NewL2Batcher(log, sdDeltaDeactivated.RollupCfg, &actionsHelpers.BatcherCfg{ MinL1TxSize: 0, MaxL1TxSize: 128_000, BatcherKey: dp.Secrets.Batcher, @@ -660,7 +662,7 @@ func TestBatchEquivalence(gt *testing.T) { sequencer.ActL2PipelineFull(t) totalTxCount := 0 // Build random blocks - for sequencer.engine.UnsafeL2Head().L1Origin.Number < sequencer.syncStatus.L1Head().Number { + for sequencer.L2Unsafe().L1Origin.Number < sequencer.SyncStatus().HeadL1.Number { sequencer.ActL2StartBlock(t) // fill the block with random number of L2 txs for j := 0; j < rand.Intn(3); j++ { @@ -671,7 +673,7 @@ func TestBatchEquivalence(gt *testing.T) { require.NoError(t, err) gas, err := core.IntrinsicGas(data, nil, false, true, true, false) require.NoError(t, err) - baseFee := seqEngine.l2Chain.CurrentBlock().BaseFee + baseFee := seqEngine.L2Chain().CurrentBlock().BaseFee nonce, err := seqEngCl.PendingNonceAt(t.Ctx(), addrs[userIdx]) require.NoError(t, err) tx := types.MustSignNewTx(privKeys[userIdx], signer, &types.DynamicFeeTx{ diff --git a/op-e2e/devnet/devnet_test.go b/op-e2e/devnet/devnet_test.go index 2a9b4be8aa5d9..8bf7bd7665dab 100644 --- a/op-e2e/devnet/devnet_test.go +++ b/op-e2e/devnet/devnet_test.go @@ -6,11 +6,11 @@ import ( "testing" "time" - e2e "github.com/ethereum-optimism/optimism/op-e2e" - "github.com/ethereum-optimism/optimism/op-service/testlog" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/ethereum-optimism/optimism/op-e2e/system/bridge" + "github.com/ethereum-optimism/optimism/op-service/testlog" ) func TestDevnet(t *testing.T) { @@ -29,7 +29,7 @@ func TestDevnet(t *testing.T) { }) t.Run("Withdrawal", func(t *testing.T) { t.Parallel() - e2e.RunWithdrawalsTest(t, sys) + bridge.RunWithdrawalsTest(t, sys) }) } diff --git a/op-e2e/devnet/setup.go b/op-e2e/devnet/setup.go index 8724fcfc4e1f9..557caed0388b2 100644 --- a/op-e2e/devnet/setup.go +++ b/op-e2e/devnet/setup.go @@ -6,8 +6,9 @@ import ( "os" "path/filepath" + "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" + "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" - e2e "github.com/ethereum-optimism/optimism/op-e2e" "github.com/ethereum-optimism/optimism/op-e2e/config" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" op_service "github.com/ethereum-optimism/optimism/op-service" @@ -29,7 +30,7 @@ type System struct { L1 *ethclient.Client L2 *ethclient.Client Rollup *sources.RollupClient - Cfg e2e.SystemConfig + Cfg e2esys.SystemConfig } func NewSystem(ctx context.Context, lgr log.Logger) (sys *System, err error) { @@ -69,7 +70,7 @@ func NewSystem(ctx context.Context, lgr log.Logger) (sys *System, err error) { } // Incomplete SystemConfig suffices for withdrawal test (only consumer right now) - sys.Cfg = e2e.SystemConfig{ + sys.Cfg = e2esys.SystemConfig{ DeployConfig: deployConfig, L1Deployments: config.L1Deployments.Copy(), Secrets: secrets, @@ -79,9 +80,9 @@ func NewSystem(ctx context.Context, lgr log.Logger) (sys *System, err error) { func (s System) NodeClient(role string) *ethclient.Client { switch role { - case e2e.RoleL1: + case e2esys.RoleL1: return s.L1 - case e2e.RoleSeq, e2e.RoleVerif: + case e2esys.RoleSeq, e2esys.RoleVerif: // we have only one L2 node return s.L2 default: @@ -94,7 +95,7 @@ func (s System) RollupClient(string) *sources.RollupClient { return s.Rollup } -func (s System) Config() e2e.SystemConfig { +func (s System) Config() e2esys.SystemConfig { return s.Cfg } diff --git a/op-e2e/helper.go b/op-e2e/e2e.go similarity index 83% rename from op-e2e/helper.go rename to op-e2e/e2e.go index 441bc3d9275c1..ebcf5750e3818 100644 --- a/op-e2e/helper.go +++ b/op-e2e/e2e.go @@ -2,13 +2,33 @@ package op_e2e import ( "crypto/md5" + "fmt" "os" + "runtime" "strconv" "strings" + "testing" + "github.com/ethereum-optimism/optimism/op-e2e/config" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" ) +func RunMain(m *testing.M) { + if config.ExternalL2Shim != "" { + fmt.Println("Running tests with external L2 process adapter at ", config.ExternalL2Shim) + // As these are integration tests which launch many other processes, the + // default parallelism makes the tests flaky. This change aims to + // reduce the flakiness of these tests. + maxProcs := runtime.NumCPU() / 4 + if maxProcs == 0 { + maxProcs = 1 + } + runtime.GOMAXPROCS(maxProcs) + } + + os.Exit(m.Run()) +} + var enableParallelTesting bool = os.Getenv("OP_E2E_DISABLE_PARALLEL") != "true" func InitParallel(t e2eutils.TestingBase, args ...func(t e2eutils.TestingBase)) { diff --git a/op-e2e/e2eutils/blobs.go b/op-e2e/e2eutils/blobs.go index 730aae1d94c5e..791130470eda5 100644 --- a/op-e2e/e2eutils/blobs.go +++ b/op-e2e/e2eutils/blobs.go @@ -5,7 +5,7 @@ import ( "fmt" "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto/kzg4844" "github.com/ethereum-optimism/optimism/op-node/rollup/derive" "github.com/ethereum-optimism/optimism/op-service/eth" @@ -13,31 +13,31 @@ import ( // 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 + // block timestamp -> blob versioned hash -> blob + blobs map[uint64]map[eth.IndexedBlobHash]*eth.Blob } func NewBlobStore() *BlobsStore { - return &BlobsStore{blobs: make(map[common.Hash]map[common.Hash]*eth.Blob)} + return &BlobsStore{blobs: make(map[uint64]map[eth.IndexedBlobHash]*eth.Blob)} } -func (store *BlobsStore) StoreBlob(blockHash common.Hash, versionedHash common.Hash, blob *eth.Blob) { - m, ok := store.blobs[blockHash] +func (store *BlobsStore) StoreBlob(blockTime uint64, indexedHash eth.IndexedBlobHash, blob *eth.Blob) { + m, ok := store.blobs[blockTime] if !ok { - m = make(map[common.Hash]*eth.Blob) - store.blobs[blockHash] = m + m = make(map[eth.IndexedBlobHash]*eth.Blob) + store.blobs[blockTime] = m } - m[versionedHash] = blob + m[indexedHash] = 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] + m, ok := store.blobs[ref.Time] if !ok { return nil, fmt.Errorf("no blobs known with given time: %w", ethereum.NotFound) } for _, h := range hashes { - b, ok := m[h.Hash] + b, ok := m[h] if !ok { return nil, fmt.Errorf("blob %d %s is not in store: %w", h.Index, h.Hash, ethereum.NotFound) } @@ -46,4 +46,66 @@ func (store *BlobsStore) GetBlobs(ctx context.Context, ref eth.L1BlockRef, hashe return out, nil } +func (store *BlobsStore) GetBlobSidecars(ctx context.Context, ref eth.L1BlockRef, hashes []eth.IndexedBlobHash) ([]*eth.BlobSidecar, error) { + out := make([]*eth.BlobSidecar, 0, len(hashes)) + m, ok := store.blobs[ref.Time] + if !ok { + return nil, fmt.Errorf("no blobs known with given time: %w", ethereum.NotFound) + } + for _, h := range hashes { + b, ok := m[h] + if !ok { + return nil, fmt.Errorf("blob %d %s is not in store: %w", h.Index, h.Hash, ethereum.NotFound) + } + if b == nil { + return nil, fmt.Errorf("blob %d %s is nil, cannot copy: %w", h.Index, h.Hash, ethereum.NotFound) + } + + commitment, err := kzg4844.BlobToCommitment(b.KZGBlob()) + if err != nil { + return nil, fmt.Errorf("failed to convert blob to commitment: %w", err) + } + proof, err := kzg4844.ComputeBlobProof(b.KZGBlob(), commitment) + if err != nil { + return nil, fmt.Errorf("failed to compute blob proof: %w", err) + } + out = append(out, ð.BlobSidecar{ + Index: eth.Uint64String(h.Index), + Blob: *b, + KZGCommitment: eth.Bytes48(commitment), + KZGProof: eth.Bytes48(proof), + }) + } + return out, nil +} + +func (store *BlobsStore) GetAllSidecars(ctx context.Context, l1Timestamp uint64) ([]*eth.BlobSidecar, error) { + m, ok := store.blobs[l1Timestamp] + if !ok { + return nil, fmt.Errorf("no blobs known with given time: %w", ethereum.NotFound) + } + out := make([]*eth.BlobSidecar, len(m)) + for h, b := range m { + if b == nil { + return nil, fmt.Errorf("blob %d %s is nil, cannot copy: %w", h.Index, h.Hash, ethereum.NotFound) + } + + commitment, err := kzg4844.BlobToCommitment(b.KZGBlob()) + if err != nil { + return nil, fmt.Errorf("failed to convert blob to commitment: %w", err) + } + proof, err := kzg4844.ComputeBlobProof(b.KZGBlob(), commitment) + if err != nil { + return nil, fmt.Errorf("failed to compute blob proof: %w", err) + } + out[h.Index] = ð.BlobSidecar{ + Index: eth.Uint64String(h.Index), + Blob: *b, + KZGCommitment: eth.Bytes48(commitment), + KZGProof: eth.Bytes48(proof), + } + } + 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 e79bb56b3304b..87a51d96a5f0f 100644 --- a/op-e2e/e2eutils/challenger/helper.go +++ b/op-e2e/e2eutils/challenger/helper.go @@ -11,6 +11,8 @@ import ( "testing" "time" + "github.com/ethereum-optimism/optimism/op-service/crypto" + "github.com/ethereum/go-ethereum/ethclient" "github.com/stretchr/testify/require" @@ -72,7 +74,7 @@ func WithGameAddress(addr common.Address) Option { func WithPrivKey(key *ecdsa.PrivateKey) Option { return func(c *config.Config) { - c.TxMgrConfig.PrivateKey = e2eutils.EncodePrivKeyToString(key) + c.TxMgrConfig.PrivateKey = crypto.EncodePrivKeyToString(key) } } @@ -106,7 +108,12 @@ func applyCannonConfig(c *config.Config, t *testing.T, rollupCfg *rollup.Config, root := FindMonorepoRoot(t) c.Cannon.VmBin = root + "cannon/bin/cannon" c.Cannon.Server = root + "op-program/bin/op-program" - c.CannonAbsolutePreState = root + "op-program/bin/prestate.json" + if e2eutils.UseMTCannon() { + t.Log("Using MT-Cannon absolute prestate") + c.CannonAbsolutePreState = root + "op-program/bin/prestate-mt.bin.gz" + } else { + c.CannonAbsolutePreState = root + "op-program/bin/prestate.json" + } c.Cannon.SnapshotFreq = 10_000_000 genesisBytes, err := json.Marshal(l2Genesis) diff --git a/op-e2e/e2eutils/disputegame/claim_helper.go b/op-e2e/e2eutils/disputegame/claim_helper.go index 4eb9c420cc03b..a3abf2b79e79f 100644 --- a/op-e2e/e2eutils/disputegame/claim_helper.go +++ b/op-e2e/e2eutils/disputegame/claim_helper.go @@ -6,6 +6,7 @@ import ( "slices" "time" + "github.com/ethereum-optimism/optimism/cannon/mipsevm" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" "github.com/ethereum/go-ethereum/common" @@ -98,6 +99,10 @@ 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) RequireInvalidStatusCode() { + c.require.Equal(byte(mipsevm.VMStatusInvalid), c.claim[0], "should have had invalid status code") +} + 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) diff --git a/op-e2e/e2eutils/disputegame/output_cannon_helper.go b/op-e2e/e2eutils/disputegame/output_cannon_helper.go index fdb8fd6b3195b..a4e017f9c9806 100644 --- a/op-e2e/e2eutils/disputegame/output_cannon_helper.go +++ b/op-e2e/e2eutils/disputegame/output_cannon_helper.go @@ -316,7 +316,7 @@ func (g *OutputCannonGameHelper) createCannonTraceProvider(ctx context.Context, 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 + return cannon.NewTraceProviderForTest(logger, metrics.NoopMetrics.VmMetrics(types.TraceTypeCannon.String()), cfg, localInputs, subdir, g.MaxDepth(ctx)-splitDepth-1), nil }) claims, err := g.Game.GetAllClaims(ctx, rpcblock.Latest) diff --git a/op-e2e/e2eutils/fakebeacon/blobs.go b/op-e2e/e2eutils/fakebeacon/blobs.go index 6be65bbb3521e..a96042bc7add4 100644 --- a/op-e2e/e2eutils/fakebeacon/blobs.go +++ b/op-e2e/e2eutils/fakebeacon/blobs.go @@ -1,23 +1,24 @@ package fakebeacon import ( + "context" "encoding/binary" "encoding/json" "errors" "fmt" - "io/fs" "net" "net/http" - "os" - "path/filepath" "strconv" "strings" "sync" "time" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/beacon/engine" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/crypto/kzg4844" "github.com/ethereum/go-ethereum/log" ) @@ -27,8 +28,8 @@ import ( type FakeBeacon struct { log log.Logger - // directory to store blob contents in after the blobs are persisted in a block - blobsDir string + // in-memory blob store + blobStore *e2eutils.BlobsStore blobsLock sync.Mutex beaconSrv *http.Server @@ -38,10 +39,10 @@ type FakeBeacon struct { blockTime uint64 } -func NewBeacon(log log.Logger, blobsDir string, genesisTime uint64, blockTime uint64) *FakeBeacon { +func NewBeacon(log log.Logger, blobStore *e2eutils.BlobsStore, genesisTime uint64, blockTime uint64) *FakeBeacon { return &FakeBeacon{ log: log, - blobsDir: blobsDir, + blobStore: blobStore, genesisTime: genesisTime, blockTime: blockTime, } @@ -158,20 +159,23 @@ func (f *FakeBeacon) Start(addr string) error { } func (f *FakeBeacon) StoreBlobsBundle(slot uint64, bundle *engine.BlobsBundleV1) error { - data, err := json.Marshal(bundle) - if err != nil { - return fmt.Errorf("failed to encode blobs bundle of slot %d: %w", slot, err) - } - f.blobsLock.Lock() defer f.blobsLock.Unlock() - bundlePath := fmt.Sprintf("blobs_bundle_%d.json", slot) - if err := os.MkdirAll(f.blobsDir, 0755); err != nil { - return fmt.Errorf("failed to create dir for blob storage: %w", err) - } - err = os.WriteFile(filepath.Join(f.blobsDir, bundlePath), data, 0755) - if err != nil { - return fmt.Errorf("failed to write blobs bundle of slot %d: %w", slot, err) + + // Solve for the slot timestamp. + // slot = (timestamp - genesis) / slot_time + // timestamp = slot * slot_time + genesis + slotTimestamp := slot*f.blockTime + f.genesisTime + + for i, b := range bundle.Blobs { + f.blobStore.StoreBlob( + slotTimestamp, + eth.IndexedBlobHash{ + Index: uint64(i), + Hash: eth.KZGToVersionedHash(kzg4844.Commitment(bundle.Commitments[i])), + }, + (*eth.Blob)(b[:]), + ) } return nil } @@ -179,19 +183,30 @@ func (f *FakeBeacon) StoreBlobsBundle(slot uint64, bundle *engine.BlobsBundleV1) func (f *FakeBeacon) LoadBlobsBundle(slot uint64) (*engine.BlobsBundleV1, error) { f.blobsLock.Lock() defer f.blobsLock.Unlock() - bundlePath := fmt.Sprintf("blobs_bundle_%d.json", slot) - data, err := os.ReadFile(filepath.Join(f.blobsDir, bundlePath)) + + // Solve for the slot timestamp. + // slot = (timestamp - genesis) / slot_time + // timestamp = slot * slot_time + genesis + slotTimestamp := slot*f.blockTime + f.genesisTime + + // Load blobs from the store + blobs, err := f.blobStore.GetAllSidecars(context.Background(), slotTimestamp) if err != nil { - if errors.Is(err, fs.ErrNotExist) { - return nil, fmt.Errorf("no blobs bundle found for slot %d (%q): %w", slot, bundlePath, ethereum.NotFound) - } else { - return nil, fmt.Errorf("failed to read blobs bundle of slot %d (%q): %w", slot, bundlePath, err) - } + return nil, fmt.Errorf("failed to load blobs from store: %w", err) } - var out engine.BlobsBundleV1 - if err := json.Unmarshal(data, &out); err != nil { - return nil, fmt.Errorf("failed to decode blobs bundle of slot %d (%q): %w", slot, bundlePath, err) + + // Convert blobs to the bundle + out := engine.BlobsBundleV1{ + Commitments: make([]hexutil.Bytes, len(blobs)), + Proofs: make([]hexutil.Bytes, len(blobs)), + Blobs: make([]hexutil.Bytes, len(blobs)), + } + for _, b := range blobs { + out.Commitments[b.Index] = hexutil.Bytes(b.KZGCommitment[:]) + out.Proofs[b.Index] = hexutil.Bytes(b.KZGProof[:]) + out.Blobs[b.Index] = hexutil.Bytes(b.Blob[:]) } + return &out, nil } diff --git a/op-e2e/tracer.go b/op-e2e/e2eutils/opnode/tracer.go similarity index 98% rename from op-e2e/tracer.go rename to op-e2e/e2eutils/opnode/tracer.go index 217c1762082ac..33a23b775ce5f 100644 --- a/op-e2e/tracer.go +++ b/op-e2e/e2eutils/opnode/tracer.go @@ -1,4 +1,4 @@ -package op_e2e +package opnode import ( "context" diff --git a/op-e2e/e2eutils/secrets.go b/op-e2e/e2eutils/secrets.go index 7c934cc65f5a5..cd4c91e1e09e5 100644 --- a/op-e2e/e2eutils/secrets.go +++ b/op-e2e/e2eutils/secrets.go @@ -8,7 +8,6 @@ import ( hdwallet "github.com/ethereum-optimism/go-ethereum-hdwallet" "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/crypto" ) @@ -134,18 +133,6 @@ type Secrets struct { Wallet *hdwallet.Wallet } -// EncodePrivKey encodes the given private key in 32 bytes -func EncodePrivKey(priv *ecdsa.PrivateKey) hexutil.Bytes { - privkey := make([]byte, 32) - blob := priv.D.Bytes() - copy(privkey[32-len(blob):], blob) - return privkey -} - -func EncodePrivKeyToString(priv *ecdsa.PrivateKey) string { - return hexutil.Encode(EncodePrivKey(priv)) -} - // Addresses computes the ethereum address of each account, // which can then be kept around for fast precomputed address access. func (s *Secrets) Addresses() *Addresses { diff --git a/op-e2e/e2eutils/setup.go b/op-e2e/e2eutils/setup.go index e226b3da80959..52dd6ec2d3aef 100644 --- a/op-e2e/e2eutils/setup.go +++ b/op-e2e/e2eutils/setup.go @@ -134,7 +134,7 @@ func Setup(t require.TestingT, deployParams *DeployParams, alloc *AllocParams) * allocsMode = genesis.L2AllocsEcotone } l2Allocs := config.L2Allocs(allocsMode) - l2Genesis, err := genesis.BuildL2Genesis(deployConf, l2Allocs, l1Block) + l2Genesis, err := genesis.BuildL2Genesis(deployConf, l2Allocs, l1Block.Header()) require.NoError(t, err, "failed to create l2 genesis") if alloc.PrefundTestUsers { for _, addr := range deployParams.Addresses.All() { @@ -249,3 +249,8 @@ func UseAltDA() bool { return (os.Getenv("OP_E2E_USE_ALTDA") == "true" || os.Getenv("DEVNET_ALTDA") == "true") } + +func UseMTCannon() bool { + return (os.Getenv("OP_E2E_USE_MT_CANNON") == "true" || + os.Getenv("USE_MT_CANNON") == "true") +} diff --git a/op-e2e/e2eutils/setuputils/utils.go b/op-e2e/e2eutils/setuputils/utils.go new file mode 100644 index 0000000000000..12f6bca83f424 --- /dev/null +++ b/op-e2e/e2eutils/setuputils/utils.go @@ -0,0 +1,32 @@ +package setuputils + +import ( + "crypto/ecdsa" + "time" + + "github.com/ethereum-optimism/optimism/op-service/crypto" + + "github.com/ethereum/go-ethereum/common/hexutil" + + "github.com/ethereum-optimism/optimism/op-service/endpoint" + "github.com/ethereum-optimism/optimism/op-service/txmgr" +) + +func hexPriv(in *ecdsa.PrivateKey) string { + b := crypto.EncodePrivKey(in) + return hexutil.Encode(b) +} + +func NewTxMgrConfig(l1Addr endpoint.RPC, privKey *ecdsa.PrivateKey) txmgr.CLIConfig { + return txmgr.CLIConfig{ + L1RPCURL: l1Addr.RPC(), + PrivateKey: hexPriv(privKey), + NumConfirmations: 1, + SafeAbortNonceTooLowCount: 3, + FeeLimitMultiplier: 5, + ResubmissionTimeout: 3 * time.Second, + ReceiptQueryInterval: 50 * time.Millisecond, + NetworkTimeout: 2 * time.Second, + TxNotInMempoolTimeout: 2 * time.Minute, + } +} diff --git a/op-e2e/e2eutils/transactions/count.go b/op-e2e/e2eutils/transactions/count.go new file mode 100644 index 0000000000000..0f4d41fe04786 --- /dev/null +++ b/op-e2e/e2eutils/transactions/count.go @@ -0,0 +1,21 @@ +package transactions + +import ( + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" +) + +func TransactionsBySender(block *types.Block, sender common.Address) (int64, error) { + txCount := int64(0) + for _, tx := range block.Transactions() { + signer := types.NewCancunSigner(tx.ChainId()) + txSender, err := types.Sender(signer, tx) + if err != nil { + return 0, err + } + if txSender == sender { + txCount++ + } + } + return txCount, nil +} diff --git a/op-e2e/external_geth/main.go b/op-e2e/external_geth/main.go index c97061d868ff3..c8921b9b3ece0 100644 --- a/op-e2e/external_geth/main.go +++ b/op-e2e/external_geth/main.go @@ -73,7 +73,8 @@ func run(configPath string) error { fmt.Printf("================== op-geth shim awaiting termination ==========================\n") sigs := make(chan os.Signal, 1) - signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) + defer signal.Stop(sigs) + signal.Notify(sigs, os.Interrupt, syscall.SIGTERM) select { case <-sigs: diff --git a/op-e2e/external_geth/main_test.go b/op-e2e/external_geth/main_test.go index 8cea0ec81fdb1..b971057e0cc29 100644 --- a/op-e2e/external_geth/main_test.go +++ b/op-e2e/external_geth/main_test.go @@ -9,9 +9,10 @@ import ( "testing" "time" + "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" + "github.com/stretchr/testify/require" - e2e "github.com/ethereum-optimism/optimism/op-e2e" "github.com/ethereum-optimism/optimism/op-e2e/config" "github.com/ethereum-optimism/optimism/op-service/endpoint" ) @@ -37,7 +38,7 @@ func TestShim(t *testing.T) { config.EthNodeVerbosity = config.LegacyLevelDebug - ec := (&e2e.ExternalRunner{ + ec := (&e2esys.ExternalRunner{ Name: "TestShim", BinPath: shimPath, }).Run(t) diff --git a/op-e2e/faultproofs/cannon_benchmark_test.go b/op-e2e/faultproofs/cannon_benchmark_test.go index a4e1674810873..7171d1211764e 100644 --- a/op-e2e/faultproofs/cannon_benchmark_test.go +++ b/op-e2e/faultproofs/cannon_benchmark_test.go @@ -11,6 +11,9 @@ import ( "testing" "time" + op_e2e "github.com/ethereum-optimism/optimism/op-e2e" + "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" @@ -23,7 +26,6 @@ import ( "github.com/ethereum-optimism/optimism/cannon/mipsevm" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils" - op_e2e "github.com/ethereum-optimism/optimism/op-e2e" "github.com/ethereum-optimism/optimism/op-e2e/bindings" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" "github.com/ethereum-optimism/optimism/op-service/predeploys" @@ -35,7 +37,7 @@ func TestBenchmarkCannon_FPP(t *testing.T) { op_e2e.InitParallel(t, op_e2e.UsesCannon) ctx := context.Background() - cfg := op_e2e.DefaultSystemConfig(t) + cfg := e2esys.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 @@ -93,7 +95,7 @@ func TestBenchmarkCannon_FPP(t *testing.T) { L2BlockNumber: l2ClaimBlockNumber, } debugfile := path.Join(t.TempDir(), "debug.json") - runCannon(t, ctx, sys, inputs, "sequencer", "--debug-info", debugfile) + runCannon(t, ctx, sys, inputs, "--debug-info", debugfile) data, err := os.ReadFile(debugfile) require.NoError(t, err) var debuginfo mipsevm.DebugInfo @@ -102,7 +104,7 @@ func TestBenchmarkCannon_FPP(t *testing.T) { // TODO(client-pod#906): Use maximum witness size for assertions against pages allocated by the VM } -func createBigContracts(ctx context.Context, t *testing.T, cfg op_e2e.SystemConfig, client *ethclient.Client, key *ecdsa.PrivateKey, numContracts int) []common.Address { +func createBigContracts(ctx context.Context, t *testing.T, cfg e2esys.SystemConfig, client *ethclient.Client, key *ecdsa.PrivateKey, numContracts int) []common.Address { /* contract Big { bytes constant foo = hex"<24.4 KB of random data>"; @@ -162,7 +164,7 @@ func createBigContracts(ctx context.Context, t *testing.T, cfg op_e2e.SystemConf return addrs } -func callBigContracts(ctx context.Context, t *testing.T, cfg op_e2e.SystemConfig, client *ethclient.Client, key *ecdsa.PrivateKey, addrs []common.Address) *types.Receipt { +func callBigContracts(ctx context.Context, t *testing.T, cfg e2esys.SystemConfig, client *ethclient.Client, key *ecdsa.PrivateKey, addrs []common.Address) *types.Receipt { multicall3, err := bindings.NewMultiCall3(predeploys.MultiCall3Addr, client) require.NoError(t, err) diff --git a/op-e2e/faultproofs/challenge_preimage_test.go b/op-e2e/faultproofs/challenge_preimage_test.go index 226f85c825c15..3bed79ad068ec 100644 --- a/op-e2e/faultproofs/challenge_preimage_test.go +++ b/op-e2e/faultproofs/challenge_preimage_test.go @@ -5,6 +5,7 @@ import ( "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" diff --git a/op-e2e/faultproofs/multi_test.go b/op-e2e/faultproofs/multi_test.go index 8073c3e7596b2..83b475d60e0d5 100644 --- a/op-e2e/faultproofs/multi_test.go +++ b/op-e2e/faultproofs/multi_test.go @@ -5,6 +5,7 @@ import ( "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/go-ethereum/common" diff --git a/op-e2e/faultproofs/output_alphabet_test.go b/op-e2e/faultproofs/output_alphabet_test.go index 3e46c732edb3a..9255214ff39b7 100644 --- a/op-e2e/faultproofs/output_alphabet_test.go +++ b/op-e2e/faultproofs/output_alphabet_test.go @@ -6,8 +6,9 @@ import ( "testing" "time" - "github.com/ethereum-optimism/optimism/op-challenger/game/types" op_e2e "github.com/ethereum-optimism/optimism/op-e2e" + + "github.com/ethereum-optimism/optimism/op-challenger/game/types" "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" diff --git a/op-e2e/faultproofs/output_cannon_test.go b/op-e2e/faultproofs/output_cannon_test.go index 797ed2bcd43c0..d0abbac7338c9 100644 --- a/op-e2e/faultproofs/output_cannon_test.go +++ b/op-e2e/faultproofs/output_cannon_test.go @@ -5,10 +5,11 @@ import ( "fmt" "testing" + op_e2e "github.com/ethereum-optimism/optimism/op-e2e" + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" gameTypes "github.com/ethereum-optimism/optimism/op-challenger/game/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" @@ -910,3 +911,45 @@ func TestOutputCannonHonestSafeTraceExtension_InvalidRoot(t *testing.T) { game.LogGameData(ctx) require.EqualValues(t, gameTypes.GameStatusChallengerWon, game.Status(ctx)) } + +func TestAgreeFirstBlockWithOriginOf1(t *testing.T) { + op_e2e.InitParallel(t, op_e2e.UsesCannon) + + ctx := context.Background() + sys, _ := StartFaultDisputeSystem(t) + t.Cleanup(sys.Close) + + rollupClient := sys.RollupClient("sequencer") + blockNum := uint64(0) + limit := uint64(100) + for ; blockNum <= limit; blockNum++ { + require.NoError(t, wait.ForBlock(ctx, sys.NodeClient("sequencer"), blockNum)) + output, err := rollupClient.OutputAtBlock(ctx, blockNum) + require.NoError(t, err) + if output.BlockRef.L1Origin.Number == 1 { + break + } + } + require.Less(t, blockNum, limit) + + // Create a dispute game with a dishonest claim @ L2 block #4 + disputeGameFactory := disputegame.NewFactoryHelper(t, ctx, sys) + // Make the agreed block the first one with L1 origin of block 1 so the claim is blockNum+1 + game := disputeGameFactory.StartOutputCannonGame(ctx, "sequencer", blockNum+1, common.Hash{0xCA, 0xFE}) + require.NotNil(t, game) + outputRootClaim := game.DisputeLastBlock(ctx) + game.LogGameData(ctx) + + honestChallenger := game.StartChallenger(ctx, "HonestActor", 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) + + // Should claim output root is invalid, but actually panics. + outputRootClaim.RequireInvalidStatusCode() + // 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. + require.NoError(t, honestChallenger.Close()) +} diff --git a/op-e2e/faultproofs/precompile_test.go b/op-e2e/faultproofs/precompile_test.go index ba60d45802e9a..aebe6a8fd1a99 100644 --- a/op-e2e/faultproofs/precompile_test.go +++ b/op-e2e/faultproofs/precompile_test.go @@ -2,13 +2,16 @@ package faultproofs import ( "context" - "encoding/json" - "fmt" "math" "math/big" "path/filepath" "testing" + op_e2e "github.com/ethereum-optimism/optimism/op-e2e" + "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" + "github.com/ethereum-optimism/optimism/op-e2e/system/helpers" + + "github.com/ethereum-optimism/optimism/cannon/mipsevm/versions" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" @@ -16,16 +19,13 @@ import ( "github.com/ethereum/go-ethereum/params" "github.com/stretchr/testify/require" - "github.com/ethereum-optimism/optimism/cannon/mipsevm/singlethreaded" "github.com/ethereum-optimism/optimism/op-challenger/config" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/vm" "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/disputegame" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" - "github.com/ethereum-optimism/optimism/op-service/ioutil" "github.com/ethereum-optimism/optimism/op-service/testlog" ) @@ -78,7 +78,7 @@ func TestPrecompiles(t *testing.T) { op_e2e.InitParallel(t, op_e2e.UsesCannon) ctx := context.Background() genesisTime := hexutil.Uint64(0) - cfg := op_e2e.EcotoneSystemConfig(t, &genesisTime) + cfg := e2esys.EcotoneSystemConfig(t, &genesisTime) // 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 @@ -104,7 +104,7 @@ func TestPrecompiles(t *testing.T) { l2Head := agreedL2Output.BlockRef.Hash l2OutputRoot := agreedL2Output.OutputRoot - receipt := op_e2e.SendL2Tx(t, cfg, l2Seq, aliceKey, func(opts *op_e2e.TxOpts) { + receipt := helpers.SendL2Tx(t, cfg, l2Seq, aliceKey, func(opts *helpers.TxOpts) { opts.Gas = 1_000_000 opts.ToAddr = &test.address opts.Nonce = 0 @@ -130,7 +130,7 @@ func TestPrecompiles(t *testing.T) { L2OutputRoot: common.Hash(l2OutputRoot), L2BlockNumber: l2ClaimBlockNumber, } - runCannon(t, ctx, sys, inputs, "sequencer") + runCannon(t, ctx, sys, inputs) }) t.Run("DisputePrecompile-"+test.name, func(t *testing.T) { @@ -143,7 +143,7 @@ func TestPrecompiles(t *testing.T) { l2Seq := sys.NodeClient("sequencer") aliceKey := sys.Cfg.Secrets.Alice - receipt := op_e2e.SendL2Tx(t, sys.Cfg, l2Seq, aliceKey, func(opts *op_e2e.TxOpts) { + receipt := helpers.SendL2Tx(t, sys.Cfg, l2Seq, aliceKey, func(opts *helpers.TxOpts) { opts.Gas = 1_000_000 opts.ToAddr = &test.address opts.Nonce = 0 @@ -177,7 +177,7 @@ func TestGranitePrecompiles(t *testing.T) { op_e2e.InitParallel(t, op_e2e.UsesCannon) ctx := context.Background() genesisTime := hexutil.Uint64(0) - cfg := op_e2e.GraniteSystemConfig(t, &genesisTime) + cfg := e2esys.GraniteSystemConfig(t, &genesisTime) // 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 @@ -242,10 +242,10 @@ func TestGranitePrecompiles(t *testing.T) { L2OutputRoot: common.Hash(l2OutputRoot), L2BlockNumber: l2ClaimBlockNumber, } - runCannon(t, ctx, sys, inputs, "sequencer") + runCannon(t, ctx, sys, inputs) } -func runCannon(t *testing.T, ctx context.Context, sys *op_e2e.System, inputs utils.LocalGameInputs, l2Node string, extraVmArgs ...string) { +func runCannon(t *testing.T, ctx context.Context, sys *e2esys.System, inputs utils.LocalGameInputs, extraVmArgs ...string) { l1Endpoint := sys.NodeEndpoint("l1").RPC() l1Beacon := sys.L1BeaconEndpoint().RestHTTP() rollupEndpoint := sys.RollupEndpoint("sequencer").RPC() @@ -257,29 +257,15 @@ func runCannon(t *testing.T, ctx context.Context, sys *op_e2e.System, inputs uti cannonOpts(&cfg) logger := testlog.Logger(t, log.LevelInfo).New("role", "cannon") - executor := vm.NewExecutor(logger, metrics.NoopMetrics, cfg.Cannon, vm.NewOpProgramServerExecutor(), cfg.CannonAbsolutePreState, inputs) + executor := vm.NewExecutor(logger, metrics.NoopMetrics.VmMetrics("cannon"), cfg.Cannon, vm.NewOpProgramServerExecutor(), cfg.CannonAbsolutePreState, inputs) t.Log("Running cannon") err := executor.DoGenerateProof(ctx, proofsDir, math.MaxUint, math.MaxUint, extraVmArgs...) require.NoError(t, err, "failed to generate proof") - state, err := parseState(filepath.Join(proofsDir, "final.json.gz")) + state, err := versions.LoadStateFromFile(vm.FinalStatePath(proofsDir, cfg.Cannon.BinarySnapshots)) require.NoError(t, err, "failed to parse state") - require.True(t, state.Exited, "cannon did not exit") - require.Zero(t, state.ExitCode, "cannon failed with exit code %d", state.ExitCode) - t.Logf("Completed in %d steps", state.Step) -} - -func parseState(path string) (*singlethreaded.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 singlethreaded.State - err = json.NewDecoder(file).Decode(&state) - if err != nil { - return nil, fmt.Errorf("invalid mipsevm state (%v): %w", path, err) - } - return &state, nil + require.True(t, state.GetExited(), "cannon did not exit") + require.Zero(t, state.GetExitCode(), "cannon failed with exit code %d", state.GetExitCode()) + t.Logf("Completed in %d steps", state.GetStep()) } diff --git a/op-e2e/faultproofs/preimages_test.go b/op-e2e/faultproofs/preimages_test.go index 03acf824daf36..8536fe578a5f5 100644 --- a/op-e2e/faultproofs/preimages_test.go +++ b/op-e2e/faultproofs/preimages_test.go @@ -6,6 +6,7 @@ import ( "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" diff --git a/op-e2e/faultproofs/util.go b/op-e2e/faultproofs/util.go index c3457b299d5ab..5beebafd88a6a 100644 --- a/op-e2e/faultproofs/util.go +++ b/op-e2e/faultproofs/util.go @@ -4,8 +4,10 @@ import ( "crypto/ecdsa" "testing" + "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" + "github.com/ethereum-optimism/optimism/op-e2e/system/helpers" + 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" @@ -13,16 +15,16 @@ import ( "github.com/stretchr/testify/require" ) -type faultDisputeConfigOpts func(cfg *op_e2e.SystemConfig) +type faultDisputeConfigOpts func(cfg *e2esys.SystemConfig) func WithBatcherStopped() faultDisputeConfigOpts { - return func(cfg *op_e2e.SystemConfig) { + return func(cfg *e2esys.SystemConfig) { cfg.DisableBatcher = true } } func WithBlobBatches() faultDisputeConfigOpts { - return func(cfg *op_e2e.SystemConfig) { + return func(cfg *e2esys.SystemConfig) { cfg.DataAvailabilityType = batcherFlags.BlobsType genesisActivation := hexutil.Uint64(0) @@ -33,7 +35,7 @@ func WithBlobBatches() faultDisputeConfigOpts { } func WithEcotone() faultDisputeConfigOpts { - return func(cfg *op_e2e.SystemConfig) { + return func(cfg *e2esys.SystemConfig) { genesisActivation := hexutil.Uint64(0) cfg.DeployConfig.L1CancunTimeOffset = &genesisActivation cfg.DeployConfig.L2GenesisDeltaTimeOffset = &genesisActivation @@ -42,13 +44,13 @@ func WithEcotone() faultDisputeConfigOpts { } func WithSequencerWindowSize(size uint64) faultDisputeConfigOpts { - return func(cfg *op_e2e.SystemConfig) { + return func(cfg *e2esys.SystemConfig) { cfg.DeployConfig.SequencerWindowSize = size } } -func StartFaultDisputeSystem(t *testing.T, opts ...faultDisputeConfigOpts) (*op_e2e.System, *ethclient.Client) { - cfg := op_e2e.DefaultSystemConfig(t) +func StartFaultDisputeSystem(t *testing.T, opts ...faultDisputeConfigOpts) (*e2esys.System, *ethclient.Client) { + cfg := e2esys.DefaultSystemConfig(t) delete(cfg.Nodes, "verifier") cfg.Nodes["sequencer"].SafeDBPath = t.TempDir() cfg.DeployConfig.SequencerWindowSize = 4 @@ -64,8 +66,8 @@ func StartFaultDisputeSystem(t *testing.T, opts ...faultDisputeConfigOpts) (*op_ return sys, sys.NodeClient("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.NodeClient(l2Node), privateKey, func(opts *op_e2e.TxOpts) { +func SendKZGPointEvaluationTx(t *testing.T, sys *e2esys.System, l2Node string, privateKey *ecdsa.PrivateKey) *types.Receipt { + return helpers.SendL2Tx(t, sys.Cfg, sys.NodeClient(l2Node), privateKey, func(opts *helpers.TxOpts) { precompile := common.BytesToAddress([]byte{0x0a}) opts.Gas = 100_000 opts.ToAddr = &precompile diff --git a/op-e2e/interop/contracts/emit.go b/op-e2e/interop/contracts/emit.go new file mode 100644 index 0000000000000..ceae2412659bc --- /dev/null +++ b/op-e2e/interop/contracts/emit.go @@ -0,0 +1,368 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package emit + +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 + _ = abi.ConvertType +) + +// EmitMetaData contains all meta data concerning the Emit contract. +var EmitMetaData = &bind.MetaData{ + ABI: "[{\"type\":\"function\",\"name\":\"emitData\",\"inputs\":[{\"name\":\"_data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"DataEmitted\",\"inputs\":[{\"name\":\"_data\",\"type\":\"bytes\",\"indexed\":true,\"internalType\":\"bytes\"}],\"anonymous\":false}]", + Bin: "0x6080604052348015600e575f80fd5b5060ff8061001b5f395ff3fe6080604052348015600e575f80fd5b50600436106026575f3560e01c8063d836083e14602a575b5f80fd5b60396035366004607c565b603b565b005b8181604051604992919060e3565b604051908190038120907fe00bbfe6f6f8f1bbed2da38e3f5a139c6f9da594ab248a3cf8b44fc73627772c905f90a25050565b5f8060208385031215608c575f80fd5b823567ffffffffffffffff8082111560a2575f80fd5b818501915085601f83011260b4575f80fd5b81358181111560c1575f80fd5b86602082850101111560d1575f80fd5b60209290920196919550909350505050565b818382375f910190815291905056fea164736f6c6343000819000a", +} + +// EmitABI is the input ABI used to generate the binding from. +// Deprecated: Use EmitMetaData.ABI instead. +var EmitABI = EmitMetaData.ABI + +// EmitBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use EmitMetaData.Bin instead. +var EmitBin = EmitMetaData.Bin + +// DeployEmit deploys a new Ethereum contract, binding an instance of Emit to it. +func DeployEmit(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *Emit, error) { + parsed, err := EmitMetaData.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(EmitBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &Emit{EmitCaller: EmitCaller{contract: contract}, EmitTransactor: EmitTransactor{contract: contract}, EmitFilterer: EmitFilterer{contract: contract}}, nil +} + +// Emit is an auto generated Go binding around an Ethereum contract. +type Emit struct { + EmitCaller // Read-only binding to the contract + EmitTransactor // Write-only binding to the contract + EmitFilterer // Log filterer for contract events +} + +// EmitCaller is an auto generated read-only Go binding around an Ethereum contract. +type EmitCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// EmitTransactor is an auto generated write-only Go binding around an Ethereum contract. +type EmitTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// EmitFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type EmitFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// EmitSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type EmitSession struct { + Contract *Emit // 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 +} + +// EmitCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type EmitCallerSession struct { + Contract *EmitCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// EmitTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type EmitTransactorSession struct { + Contract *EmitTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// EmitRaw is an auto generated low-level Go binding around an Ethereum contract. +type EmitRaw struct { + Contract *Emit // Generic contract binding to access the raw methods on +} + +// EmitCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type EmitCallerRaw struct { + Contract *EmitCaller // Generic read-only contract binding to access the raw methods on +} + +// EmitTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type EmitTransactorRaw struct { + Contract *EmitTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewEmit creates a new instance of Emit, bound to a specific deployed contract. +func NewEmit(address common.Address, backend bind.ContractBackend) (*Emit, error) { + contract, err := bindEmit(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Emit{EmitCaller: EmitCaller{contract: contract}, EmitTransactor: EmitTransactor{contract: contract}, EmitFilterer: EmitFilterer{contract: contract}}, nil +} + +// NewEmitCaller creates a new read-only instance of Emit, bound to a specific deployed contract. +func NewEmitCaller(address common.Address, caller bind.ContractCaller) (*EmitCaller, error) { + contract, err := bindEmit(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &EmitCaller{contract: contract}, nil +} + +// NewEmitTransactor creates a new write-only instance of Emit, bound to a specific deployed contract. +func NewEmitTransactor(address common.Address, transactor bind.ContractTransactor) (*EmitTransactor, error) { + contract, err := bindEmit(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &EmitTransactor{contract: contract}, nil +} + +// NewEmitFilterer creates a new log filterer instance of Emit, bound to a specific deployed contract. +func NewEmitFilterer(address common.Address, filterer bind.ContractFilterer) (*EmitFilterer, error) { + contract, err := bindEmit(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &EmitFilterer{contract: contract}, nil +} + +// bindEmit binds a generic wrapper to an already deployed contract. +func bindEmit(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := EmitMetaData.GetAbi() + 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 (_Emit *EmitRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Emit.Contract.EmitCaller.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 (_Emit *EmitRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Emit.Contract.EmitTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Emit *EmitRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Emit.Contract.EmitTransactor.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 (_Emit *EmitCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Emit.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 (_Emit *EmitTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Emit.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Emit *EmitTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Emit.Contract.contract.Transact(opts, method, params...) +} + +// EmitData is a paid mutator transaction binding the contract method 0xd836083e. +// +// Solidity: function emitData(bytes _data) returns() +func (_Emit *EmitTransactor) EmitData(opts *bind.TransactOpts, _data []byte) (*types.Transaction, error) { + return _Emit.contract.Transact(opts, "emitData", _data) +} + +// EmitData is a paid mutator transaction binding the contract method 0xd836083e. +// +// Solidity: function emitData(bytes _data) returns() +func (_Emit *EmitSession) EmitData(_data []byte) (*types.Transaction, error) { + return _Emit.Contract.EmitData(&_Emit.TransactOpts, _data) +} + +// EmitData is a paid mutator transaction binding the contract method 0xd836083e. +// +// Solidity: function emitData(bytes _data) returns() +func (_Emit *EmitTransactorSession) EmitData(_data []byte) (*types.Transaction, error) { + return _Emit.Contract.EmitData(&_Emit.TransactOpts, _data) +} + +// EmitDataEmittedIterator is returned from FilterDataEmitted and is used to iterate over the raw logs and unpacked data for DataEmitted events raised by the Emit contract. +type EmitDataEmittedIterator struct { + Event *EmitDataEmitted // 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 *EmitDataEmittedIterator) 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(EmitDataEmitted) + 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(EmitDataEmitted) + 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 *EmitDataEmittedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *EmitDataEmittedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// EmitDataEmitted represents a DataEmitted event raised by the Emit contract. +type EmitDataEmitted struct { + Data common.Hash + Raw types.Log // Blockchain specific contextual infos +} + +// FilterDataEmitted is a free log retrieval operation binding the contract event 0xe00bbfe6f6f8f1bbed2da38e3f5a139c6f9da594ab248a3cf8b44fc73627772c. +// +// Solidity: event DataEmitted(bytes indexed _data) +func (_Emit *EmitFilterer) FilterDataEmitted(opts *bind.FilterOpts, _data [][]byte) (*EmitDataEmittedIterator, error) { + + var _dataRule []interface{} + for _, _dataItem := range _data { + _dataRule = append(_dataRule, _dataItem) + } + + logs, sub, err := _Emit.contract.FilterLogs(opts, "DataEmitted", _dataRule) + if err != nil { + return nil, err + } + return &EmitDataEmittedIterator{contract: _Emit.contract, event: "DataEmitted", logs: logs, sub: sub}, nil +} + +// WatchDataEmitted is a free log subscription operation binding the contract event 0xe00bbfe6f6f8f1bbed2da38e3f5a139c6f9da594ab248a3cf8b44fc73627772c. +// +// Solidity: event DataEmitted(bytes indexed _data) +func (_Emit *EmitFilterer) WatchDataEmitted(opts *bind.WatchOpts, sink chan<- *EmitDataEmitted, _data [][]byte) (event.Subscription, error) { + + var _dataRule []interface{} + for _, _dataItem := range _data { + _dataRule = append(_dataRule, _dataItem) + } + + logs, sub, err := _Emit.contract.WatchLogs(opts, "DataEmitted", _dataRule) + 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(EmitDataEmitted) + if err := _Emit.contract.UnpackLog(event, "DataEmitted", 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 +} + +// ParseDataEmitted is a log parse operation binding the contract event 0xe00bbfe6f6f8f1bbed2da38e3f5a139c6f9da594ab248a3cf8b44fc73627772c. +// +// Solidity: event DataEmitted(bytes indexed _data) +func (_Emit *EmitFilterer) ParseDataEmitted(log types.Log) (*EmitDataEmitted, error) { + event := new(EmitDataEmitted) + if err := _Emit.contract.UnpackLog(event, "DataEmitted", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/op-e2e/interop/contracts/foundry.toml b/op-e2e/interop/contracts/foundry.toml new file mode 100644 index 0000000000000..587dba436380c --- /dev/null +++ b/op-e2e/interop/contracts/foundry.toml @@ -0,0 +1,31 @@ +################################################################ +# PROFILE: DEFAULT (Local) # +################################################################ + +[profile.default] + +# Compilation settings +src = 'src' +out = 'build' +script = 'scripts' +optimizer = true +optimizer_runs = 999999 +remappings = [] +extra_output = ['devdoc', 'userdoc', 'metadata', 'storageLayout'] +bytecode_hash = 'none' +build_info_path = 'artifacts/build-info' +ast = true +evm_version = "cancun" +# 5159 error code is selfdestruct error code +ignored_error_codes = ["transient-storage", "code-size", "init-code-size", 5159] + +# We set the gas limit to max int64 to avoid running out of gas during testing, since the default +# gas limit is 1B and some of our tests require more gas than that, such as `test_callWithMinGas_noLeakageLow_succeeds`. +# We use this gas limit since it was the default gas limit prior to https://github.com/foundry-rs/foundry/pull/8274. +# Due to toml-rs limitations, if you increase the gas limit above this value it must be a string. +gas_limit = 9223372036854775807 + +# Test / Script Runner Settings +ffi = false +fs_permissions = [] +libs = ["node_modules", "lib"] diff --git a/op-e2e/interop/contracts/generate.sh b/op-e2e/interop/contracts/generate.sh new file mode 100755 index 0000000000000..bba960153ec62 --- /dev/null +++ b/op-e2e/interop/contracts/generate.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +set -euo + +forge build + +cd build/emit.sol +cat EmitEvent.json | jq -r '.bytecode.object' > EmitEvent.bin +cat EmitEvent.json | jq '.abi' > EmitEvent.abi +cd ../.. + +abigen --abi ./build/emit.sol/EmitEvent.abi --bin ./build/emit.sol/EmitEvent.bin --pkg emit --out ./emit.go diff --git a/op-e2e/interop/contracts/src/emit.sol b/op-e2e/interop/contracts/src/emit.sol new file mode 100644 index 0000000000000..5464bb7bbe6e6 --- /dev/null +++ b/op-e2e/interop/contracts/src/emit.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.15; + +contract EmitEvent { + // Define an event that logs the emitted data + event DataEmitted(bytes indexed _data); + + // Function that takes calldata and emits the data as an event + function emitData(bytes calldata _data) external { + emit DataEmitted(_data); + } +} diff --git a/op-e2e/interop/contracts/test-artifacts/emit.sol/EmitEvent.abi b/op-e2e/interop/contracts/test-artifacts/emit.sol/EmitEvent.abi new file mode 100644 index 0000000000000..79170e79f968e --- /dev/null +++ b/op-e2e/interop/contracts/test-artifacts/emit.sol/EmitEvent.abi @@ -0,0 +1,28 @@ +[ + { + "type": "function", + "name": "emitData", + "inputs": [ + { + "name": "data", + "type": "bytes", + "internalType": "bytes" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "event", + "name": "DataEmitted", + "inputs": [ + { + "name": "data", + "type": "bytes", + "indexed": true, + "internalType": "bytes" + } + ], + "anonymous": false + } +] diff --git a/op-e2e/interop/contracts/test-artifacts/emit.sol/EmitEvent.bin b/op-e2e/interop/contracts/test-artifacts/emit.sol/EmitEvent.bin new file mode 100644 index 0000000000000..f4c15ab05dca7 --- /dev/null +++ b/op-e2e/interop/contracts/test-artifacts/emit.sol/EmitEvent.bin @@ -0,0 +1 @@ +0x6080604052348015600e575f80fd5b5060ff8061001b5f395ff3fe6080604052348015600e575f80fd5b50600436106026575f3560e01c8063d836083e14602a575b5f80fd5b60396035366004607c565b603b565b005b8181604051604992919060e3565b604051908190038120907fe00bbfe6f6f8f1bbed2da38e3f5a139c6f9da594ab248a3cf8b44fc73627772c905f90a25050565b5f8060208385031215608c575f80fd5b823567ffffffffffffffff8082111560a2575f80fd5b818501915085601f83011260b4575f80fd5b81358181111560c1575f80fd5b86602082850101111560d1575f80fd5b60209290920196919550909350505050565b818382375f910190815291905056fea164736f6c6343000819000a diff --git a/op-e2e/interop/contracts/test-artifacts/emit.sol/EmitEvent.json b/op-e2e/interop/contracts/test-artifacts/emit.sol/EmitEvent.json new file mode 100644 index 0000000000000..422f62ea73242 --- /dev/null +++ b/op-e2e/interop/contracts/test-artifacts/emit.sol/EmitEvent.json @@ -0,0 +1 @@ +{"abi":[{"type":"function","name":"emitData","inputs":[{"name":"data","type":"bytes","internalType":"bytes"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"event","name":"DataEmitted","inputs":[{"name":"data","type":"bytes","indexed":true,"internalType":"bytes"}],"anonymous":false}],"bytecode":{"object":"0x6080604052348015600e575f80fd5b5060ff8061001b5f395ff3fe6080604052348015600e575f80fd5b50600436106026575f3560e01c8063d836083e14602a575b5f80fd5b60396035366004607c565b603b565b005b8181604051604992919060e3565b604051908190038120907fe00bbfe6f6f8f1bbed2da38e3f5a139c6f9da594ab248a3cf8b44fc73627772c905f90a25050565b5f8060208385031215608c575f80fd5b823567ffffffffffffffff8082111560a2575f80fd5b818501915085601f83011260b4575f80fd5b81358181111560c1575f80fd5b86602082850101111560d1575f80fd5b60209290920196919550909350505050565b818382375f910190815291905056fea164736f6c6343000819000a","sourceMap":"58:275:0:-:0;;;;;;;;;;;;;;;;;;;","linkReferences":{}},"deployedBytecode":{"object":"0x6080604052348015600e575f80fd5b50600436106026575f3560e01c8063d836083e14602a575b5f80fd5b60396035366004607c565b603b565b005b8181604051604992919060e3565b604051908190038120907fe00bbfe6f6f8f1bbed2da38e3f5a139c6f9da594ab248a3cf8b44fc73627772c905f90a25050565b5f8060208385031215608c575f80fd5b823567ffffffffffffffff8082111560a2575f80fd5b818501915085601f83011260b4575f80fd5b81358181111560c1575f80fd5b86602082850101111560d1575f80fd5b60209290920196919550909350505050565b818382375f910190815291905056fea164736f6c6343000819000a","sourceMap":"58:275:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;244:87;;;;;;:::i;:::-;;:::i;:::-;;;319:4;;307:17;;;;;;;:::i;:::-;;;;;;;;;;;;;;;244:87;;:::o;14:591:1:-;84:6;92;145:2;133:9;124:7;120:23;116:32;113:52;;;161:1;158;151:12;113:52;201:9;188:23;230:18;271:2;263:6;260:14;257:34;;;287:1;284;277:12;257:34;325:6;314:9;310:22;300:32;;370:7;363:4;359:2;355:13;351:27;341:55;;392:1;389;382:12;341:55;432:2;419:16;458:2;450:6;447:14;444:34;;;474:1;471;464:12;444:34;519:7;514:2;505:6;501:2;497:15;493:24;490:37;487:57;;;540:1;537;530:12;487:57;571:2;563:11;;;;;593:6;;-1:-1:-1;14:591:1;;-1:-1:-1;;;;14:591:1:o;610:271::-;793:6;785;780:3;767:33;749:3;819:16;;844:13;;;819:16;610:271;-1:-1:-1;610:271:1:o","linkReferences":{}},"methodIdentifiers":{"emitData(bytes)":"d836083e"},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"DataEmitted\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"emitData\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/emit.sol\":\"EmitEvent\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[]},\"sources\":{\"src/emit.sol\":{\"keccak256\":\"0xdee458d231a8b41e5ba097be7258a6da27501fafb2a6f865705953458aecafbf\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://912d125138604114be66c8d044a39ef83861e6dc2d5fe3be32a1a4e014ea2763\",\"dweb:/ipfs/QmUx5NRsTXzujjwU1SXMSNp5Wjys3v5PDLuhdpoAyCy7nx\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.25+commit.b61c2a91"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"bytes","name":"data","type":"bytes","indexed":true}],"type":"event","name":"DataEmitted","anonymous":false},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"}],"stateMutability":"nonpayable","type":"function","name":"emitData"}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"remappings":[],"optimizer":{"enabled":true,"runs":999999},"metadata":{"bytecodeHash":"none"},"compilationTarget":{"src/emit.sol":"EmitEvent"},"evmVersion":"cancun","libraries":{}},"sources":{"src/emit.sol":{"keccak256":"0xdee458d231a8b41e5ba097be7258a6da27501fafb2a6f865705953458aecafbf","urls":["bzz-raw://912d125138604114be66c8d044a39ef83861e6dc2d5fe3be32a1a4e014ea2763","dweb:/ipfs/QmUx5NRsTXzujjwU1SXMSNp5Wjys3v5PDLuhdpoAyCy7nx"],"license":"MIT"}},"version":1},"storageLayout":{"storage":[],"types":{}},"userdoc":{"version":1,"kind":"user"},"devdoc":{"version":1,"kind":"dev"},"ast":{"absolutePath":"src/emit.sol","id":17,"exportedSymbols":{"EmitEvent":[16]},"nodeType":"SourceUnit","src":"32:302:0","nodes":[{"id":1,"nodeType":"PragmaDirective","src":"32:24:0","nodes":[],"literals":["solidity","^","0.8",".15"]},{"id":16,"nodeType":"ContractDefinition","src":"58:275:0","nodes":[{"id":5,"nodeType":"EventDefinition","src":"133:38:0","nodes":[],"anonymous":false,"eventSelector":"e00bbfe6f6f8f1bbed2da38e3f5a139c6f9da594ab248a3cf8b44fc73627772c","name":"DataEmitted","nameLocation":"139:11:0","parameters":{"id":4,"nodeType":"ParameterList","parameters":[{"constant":false,"id":3,"indexed":true,"mutability":"mutable","name":"data","nameLocation":"165:4:0","nodeType":"VariableDeclaration","scope":5,"src":"151:18:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":2,"name":"bytes","nodeType":"ElementaryTypeName","src":"151:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"150:20:0"}},{"id":15,"nodeType":"FunctionDefinition","src":"244:87:0","nodes":[],"body":{"id":14,"nodeType":"Block","src":"292:39:0","nodes":[],"statements":[{"eventCall":{"arguments":[{"id":11,"name":"data","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":7,"src":"319:4:0","typeDescriptions":{"typeIdentifier":"t_bytes_calldata_ptr","typeString":"bytes calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_calldata_ptr","typeString":"bytes calldata"}],"id":10,"name":"DataEmitted","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":5,"src":"307:11:0","typeDescriptions":{"typeIdentifier":"t_function_event_nonpayable$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory)"}},"id":12,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"nameLocations":[],"names":[],"nodeType":"FunctionCall","src":"307:17:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":13,"nodeType":"EmitStatement","src":"302:22:0"}]},"functionSelector":"d836083e","implemented":true,"kind":"function","modifiers":[],"name":"emitData","nameLocation":"253:8:0","parameters":{"id":8,"nodeType":"ParameterList","parameters":[{"constant":false,"id":7,"mutability":"mutable","name":"data","nameLocation":"277:4:0","nodeType":"VariableDeclaration","scope":15,"src":"262:19:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_bytes_calldata_ptr","typeString":"bytes"},"typeName":{"id":6,"name":"bytes","nodeType":"ElementaryTypeName","src":"262:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"261:21:0"},"returnParameters":{"id":9,"nodeType":"ParameterList","parameters":[],"src":"292:0:0"},"scope":16,"stateMutability":"nonpayable","virtual":false,"visibility":"external"}],"abstract":false,"baseContracts":[],"canonicalName":"EmitEvent","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"linearizedBaseContracts":[16],"name":"EmitEvent","nameLocation":"67:9:0","scope":17,"usedErrors":[],"usedEvents":[5]}],"license":"MIT"},"id":0} \ No newline at end of file diff --git a/op-e2e/interop/interop_recipe_test.go b/op-e2e/interop/interop_recipe_test.go new file mode 100644 index 0000000000000..05a2e056c39b7 --- /dev/null +++ b/op-e2e/interop/interop_recipe_test.go @@ -0,0 +1,44 @@ +package interop + +import ( + "encoding/json" + "os" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/ethereum/go-ethereum/log" + + "github.com/ethereum-optimism/optimism/op-chain-ops/devkeys" + "github.com/ethereum-optimism/optimism/op-chain-ops/foundry" + "github.com/ethereum-optimism/optimism/op-chain-ops/interopgen" + "github.com/ethereum-optimism/optimism/op-service/testlog" +) + +func TestInteropDevRecipe(t *testing.T) { + rec := interopgen.InteropDevRecipe{ + L1ChainID: 900100, + L2ChainIDs: []uint64{900200, 900201}, + GenesisTimestamp: uint64(1234567), + } + hd, err := devkeys.NewMnemonicDevKeys(devkeys.TestMnemonic) + require.NoError(t, err) + worldCfg, err := rec.Build(hd) + require.NoError(t, err) + + logger := testlog.Logger(t, log.LevelDebug) + require.NoError(t, worldCfg.Check(logger)) + + fa := foundry.OpenArtifactsDir("../../packages/contracts-bedrock/forge-artifacts") + srcFS := foundry.NewSourceMapFS(os.DirFS("../../packages/contracts-bedrock")) + + worldDeployment, worldOutput, err := interopgen.Deploy(logger, fa, srcFS, worldCfg) + require.NoError(t, err) + enc := json.NewEncoder(os.Stdout) + enc.SetIndent(" ", " ") + require.NoError(t, enc.Encode(worldDeployment)) + logger.Info("L1 output", "accounts", len(worldOutput.L1.Genesis.Alloc)) + for id, l2Output := range worldOutput.L2s { + logger.Info("L2 output", "chain", &id, "accounts", len(l2Output.Genesis.Alloc)) + } +} diff --git a/op-e2e/interop/interop_test.go b/op-e2e/interop/interop_test.go new file mode 100644 index 0000000000000..65265c22e7c24 --- /dev/null +++ b/op-e2e/interop/interop_test.go @@ -0,0 +1,100 @@ +package interop + +import ( + "context" + "fmt" + "math/big" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "github.com/ethereum-optimism/optimism/op-chain-ops/interopgen" + "github.com/ethereum-optimism/optimism/op-e2e/system/helpers" +) + +// TestInteropTrivial tests a simple interop scenario +// Chains A and B exist, but no messages are sent between them +// and in fact no event-logs are emitted by either chain at all. +// A transaction is sent from Alice to Bob on Chain A. +// The balance of Bob on Chain A is checked before and after the tx. +// The balance of Bob on Chain B is checked after the tx. +func TestInteropTrivial(t *testing.T) { + recipe := interopgen.InteropDevRecipe{ + L1ChainID: 900100, + L2ChainIDs: []uint64{900200, 900201}, + GenesisTimestamp: uint64(time.Now().Unix() + 3), // start chain 3 seconds from now + } + worldResources := worldResourcePaths{ + foundryArtifacts: "../../packages/contracts-bedrock/forge-artifacts", + sourceMap: "../../packages/contracts-bedrock", + } + + // create a super system from the recipe + // and get the L2 IDs for use in the test + s2 := NewSuperSystem(t, &recipe, worldResources) + ids := s2.L2IDs() + + // chainA is the first L2 chain + chainA := ids[0] + // chainB is the second L2 chain + chainB := ids[1] + + // create two users on all L2 chains + s2.AddUser("Alice") + s2.AddUser("Bob") + + bobAddr := s2.Address(chainA, "Bob") + + // check the balance of Bob + clientA := s2.L2GethClient(chainA) + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) + defer cancel() + bobBalance, err := clientA.BalanceAt(ctx, bobAddr, nil) + require.NoError(t, err) + expectedBalance, _ := big.NewInt(0).SetString("10000000000000000000000000", 10) + require.Equal(t, expectedBalance, bobBalance) + + // send a tx from Alice to Bob + s2.SendL2Tx( + chainA, + "Alice", + func(l2Opts *helpers.TxOpts) { + l2Opts.ToAddr = &bobAddr + l2Opts.Value = big.NewInt(1000000) + l2Opts.GasFeeCap = big.NewInt(1_000_000_000) + l2Opts.GasTipCap = big.NewInt(1_000_000_000) + }, + ) + + // check the balance of Bob after the tx + ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second) + defer cancel() + bobBalance, err = clientA.BalanceAt(ctx, bobAddr, nil) + require.NoError(t, err) + expectedBalance, _ = big.NewInt(0).SetString("10000000000000000001000000", 10) + require.Equal(t, expectedBalance, bobBalance) + + // check that the balance of Bob on ChainB hasn't changed + bobAddrB := s2.Address(chainB, "Bob") + clientB := s2.L2GethClient(chainB) + ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second) + defer cancel() + bobBalance, err = clientB.BalanceAt(ctx, bobAddrB, nil) + require.NoError(t, err) + expectedBalance, _ = big.NewInt(0).SetString("10000000000000000000000000", 10) + require.Equal(t, expectedBalance, bobBalance) + + s2.DeployEmitterContract(chainA, "Alice") + rec := s2.EmitData(chainA, "Alice", "0x1234567890abcdef") + + fmt.Println("Result of emitting event:", rec) + + s2.DeployEmitterContract(chainB, "Alice") + rec = s2.EmitData(chainB, "Alice", "0x1234567890abcdef") + + fmt.Println("Result of emitting event:", rec) + + time.Sleep(10 * time.Second) + +} diff --git a/op-e2e/interop/supersystem.go b/op-e2e/interop/supersystem.go new file mode 100644 index 0000000000000..ffa91bef97f30 --- /dev/null +++ b/op-e2e/interop/supersystem.go @@ -0,0 +1,678 @@ +package interop + +import ( + "context" + "crypto/ecdsa" + "math/big" + "os" + "path" + "path/filepath" + "testing" + "time" + + emit "github.com/ethereum-optimism/optimism/op-e2e/interop/contracts" + "github.com/ethereum-optimism/optimism/op-e2e/system/helpers" + + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" + "github.com/stretchr/testify/require" + + "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/crypto" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/rpc" + + bss "github.com/ethereum-optimism/optimism/op-batcher/batcher" + batcherFlags "github.com/ethereum-optimism/optimism/op-batcher/flags" + "github.com/ethereum-optimism/optimism/op-chain-ops/devkeys" + "github.com/ethereum-optimism/optimism/op-chain-ops/foundry" + "github.com/ethereum-optimism/optimism/op-chain-ops/interopgen" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/fakebeacon" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/opnode" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/services" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/setuputils" + "github.com/ethereum-optimism/optimism/op-node/node" + "github.com/ethereum-optimism/optimism/op-node/p2p" + "github.com/ethereum-optimism/optimism/op-node/rollup/derive" + "github.com/ethereum-optimism/optimism/op-node/rollup/driver" + "github.com/ethereum-optimism/optimism/op-node/rollup/sync" + l2os "github.com/ethereum-optimism/optimism/op-proposer/proposer" + "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/endpoint" + oplog "github.com/ethereum-optimism/optimism/op-service/log" + "github.com/ethereum-optimism/optimism/op-service/metrics" + "github.com/ethereum-optimism/optimism/op-service/oppprof" + oprpc "github.com/ethereum-optimism/optimism/op-service/rpc" + "github.com/ethereum-optimism/optimism/op-service/sources" + "github.com/ethereum-optimism/optimism/op-service/testlog" + supervisorConfig "github.com/ethereum-optimism/optimism/op-supervisor/config" + "github.com/ethereum-optimism/optimism/op-supervisor/supervisor" +) + +// SuperSystem is an interface for the system (collection of connected resources) +// it provides a way to get the resources for a network by network ID +// and provides a way to get the list of network IDs +// this is useful for testing multiple network backends, +// for example, interopE2ESystem is the default implementation, but a shim to +// kurtosis or another testing framework could be implemented +type SuperSystem interface { + // get the supervisor + Supervisor() *supervisor.SupervisorService + // get the supervisor client + SupervisorClient() *sources.SupervisorClient + // get the batcher for a network + Batcher(network string) *bss.BatcherService + // get the proposer for a network + Proposer(network string) *l2os.ProposerService + // get the opnode for a network + OpNode(network string) *opnode.Opnode + // get the geth instance for a network + L2Geth(network string) *geth.GethInstance + // get the L2 geth client for a network + L2GethClient(network string) *ethclient.Client + // get the secret for a network and role + L2OperatorKey(network string, role devkeys.ChainOperatorRole) ecdsa.PrivateKey + // get the list of network IDs + L2IDs() []string + // register a username to an account on all L2s + AddUser(username string) + // get the user key for a user on an L2 + UserKey(id, username string) ecdsa.PrivateKey + // send a transaction on an L2 on the given network, from the given user + SendL2Tx(network string, username string, applyTxOpts helpers.TxOptsFn) *types.Receipt + // get the address for a user on an L2 + Address(network string, username string) common.Address + // Deploy the Emitter Contract, which emits Event Logs + DeployEmitterContract(network string, username string) common.Address + // Use the Emitter Contract to emit an Event Log + EmitData(network string, username string, data string) *types.Receipt + // Access a contract on a network by name + Contract(network string, contractName string) interface{} +} + +// NewSuperSystem creates a new SuperSystem from a recipe. It creates an interopE2ESystem. +func NewSuperSystem(t *testing.T, recipe *interopgen.InteropDevRecipe, w worldResourcePaths) SuperSystem { + s2 := &interopE2ESystem{recipe: recipe} + s2.prepare(t, w) + return s2 +} + +// interopE2ESystem implements the SuperSystem interface +// it prepares network resources and provides access to them +// the functionality is broken down into smaller functions so that +// the system can be prepared iteratively if desired +type interopE2ESystem struct { + t *testing.T + recipe *interopgen.InteropDevRecipe + logger log.Logger + hdWallet *devkeys.MnemonicDevKeys + worldDeployment *interopgen.WorldDeployment + worldOutput *interopgen.WorldOutput + beacon *fakebeacon.FakeBeacon + l1 *geth.GethInstance + l2s map[string]l2Set + l2GethClients map[string]*ethclient.Client + supervisor *supervisor.SupervisorService + superClient *sources.SupervisorClient +} + +// l2Set is a set of resources for an L2 chain +type l2Set struct { + chainID *big.Int + opNode *opnode.Opnode + l2Geth *geth.GethInstance + proposer *l2os.ProposerService + batcher *bss.BatcherService + operatorKeys map[devkeys.ChainOperatorRole]ecdsa.PrivateKey + userKeys map[string]ecdsa.PrivateKey + contracts map[string]interface{} +} + +// prepareHDWallet creates a new HD wallet to derive keys from +func (s *interopE2ESystem) prepareHDWallet() *devkeys.MnemonicDevKeys { + hdWallet, err := devkeys.NewMnemonicDevKeys(devkeys.TestMnemonic) + require.NoError(s.t, err) + return hdWallet +} + +type worldResourcePaths struct { + foundryArtifacts string + sourceMap string +} + +// prepareWorld creates the world configuration from the recipe and deploys it +func (s *interopE2ESystem) prepareWorld(w worldResourcePaths) (*interopgen.WorldDeployment, *interopgen.WorldOutput) { + // Build the world configuration from the recipe and the HD wallet + worldCfg, err := s.recipe.Build(s.hdWallet) + require.NoError(s.t, err) + + // create a logger for the world configuration + logger := s.logger.New("role", "world") + require.NoError(s.t, worldCfg.Check(logger)) + + // create the foundry artifacts and source map + foundryArtifacts := foundry.OpenArtifactsDir(w.foundryArtifacts) + sourceMap := foundry.NewSourceMapFS(os.DirFS(w.sourceMap)) + + // deploy the world, using the logger, foundry artifacts, source map, and world configuration + worldDeployment, worldOutput, err := interopgen.Deploy(logger, foundryArtifacts, sourceMap, worldCfg) + require.NoError(s.t, err) + + return worldDeployment, worldOutput +} + +// prepareL1 creates the L1 chain resources +func (s *interopE2ESystem) prepareL1() (*fakebeacon.FakeBeacon, *geth.GethInstance) { + // Create a fake Beacon node to hold on to blobs created by the L1 miner, and to serve them to L2 + genesisTimestampL1 := s.worldOutput.L1.Genesis.Timestamp + blockTimeL1 := uint64(6) + blobPath := s.t.TempDir() + bcn := fakebeacon.NewBeacon(s.logger.New("role", "l1_cl"), + e2eutils.NewBlobStore(), genesisTimestampL1, blockTimeL1) + s.t.Cleanup(func() { + _ = bcn.Close() + }) + require.NoError(s.t, bcn.Start("127.0.0.1:0")) + beaconApiAddr := bcn.BeaconAddr() + require.NotEmpty(s.t, beaconApiAddr, "beacon API listener must be up") + + l1FinalizedDistance := uint64(3) + l1Clock := clock.SystemClock + // Start the L1 chain + l1Geth, err := geth.InitL1( + blockTimeL1, + l1FinalizedDistance, + s.worldOutput.L1.Genesis, + l1Clock, + filepath.Join(blobPath, "l1_el"), + bcn) + + require.NoError(s.t, err) + require.NoError(s.t, l1Geth.Node.Start()) + s.t.Cleanup(func() { + _ = l1Geth.Close() + }) + return bcn, l1Geth +} + +// newOperatorKeysForL2 creates the operator keys for an L2 chain +// it uses an L2Output to determine the chain ID and configuration, +// and then makes a key for each operator role [SequencerP2PRole, ProposerRole, BatcherRole] +func (s *interopE2ESystem) newOperatorKeysForL2(l2Out *interopgen.L2Output) map[devkeys.ChainOperatorRole]ecdsa.PrivateKey { + // Create operatorKeys for the L2 chain actors + operatorKeys := map[devkeys.ChainOperatorRole]ecdsa.PrivateKey{} + // create the sequencer P2P secret + seqP2PSecret, err := s.hdWallet.Secret(devkeys.ChainOperatorKey{ + ChainID: l2Out.Genesis.Config.ChainID, + Role: devkeys.SequencerP2PRole, + }) + require.NoError(s.t, err) + operatorKeys[devkeys.SequencerP2PRole] = *seqP2PSecret + // create the proposer secret + proposerSecret, err := s.hdWallet.Secret(devkeys.ChainOperatorKey{ + ChainID: l2Out.Genesis.Config.ChainID, + Role: devkeys.ProposerRole, + }) + require.NoError(s.t, err) + operatorKeys[devkeys.ProposerRole] = *proposerSecret + // create the batcher secret + batcherSecret, err := s.hdWallet.Secret(devkeys.ChainOperatorKey{ + ChainID: l2Out.Genesis.Config.ChainID, + Role: devkeys.BatcherRole, + }) + require.NoError(s.t, err) + operatorKeys[devkeys.BatcherRole] = *batcherSecret + return operatorKeys +} + +// newGethForL2 creates a new Geth instance for an L2 chain +func (s *interopE2ESystem) newGethForL2(id string, l2Out *interopgen.L2Output) *geth.GethInstance { + jwtPath := writeDefaultJWT(s.t) + name := "l2-" + id + l2Geth, err := geth.InitL2(name, l2Out.Genesis, jwtPath) + require.NoError(s.t, err) + require.NoError(s.t, l2Geth.Node.Start()) + s.t.Cleanup(func() { + _ = l2Geth.Close() + }) + return l2Geth +} + +// newNodeForL2 creates a new Opnode for an L2 chain +func (s *interopE2ESystem) newNodeForL2( + id string, + l2Out *interopgen.L2Output, + operatorKeys map[devkeys.ChainOperatorRole]ecdsa.PrivateKey, + l2Geth *geth.GethInstance, +) *opnode.Opnode { + logger := s.logger.New("role", "op-node-"+id) + p2pKey := operatorKeys[devkeys.SequencerP2PRole] + nodeCfg := &node.Config{ + L1: &node.PreparedL1Endpoint{ + Client: client.NewBaseRPCClient(endpoint.DialRPC( + endpoint.PreferAnyRPC, + s.l1.UserRPC(), + mustDial(s.t, logger))), + TrustRPC: false, + RPCProviderKind: sources.RPCKindDebugGeth, + }, + L2: &node.L2EndpointConfig{ + L2EngineAddr: l2Geth.AuthRPC().RPC(), + L2EngineJWTSecret: testingJWTSecret, + }, + Beacon: &node.L1BeaconEndpointConfig{ + BeaconAddr: s.beacon.BeaconAddr(), + }, + Driver: driver.Config{ + SequencerEnabled: true, + }, + Rollup: *l2Out.RollupCfg, + P2PSigner: &p2p.PreparedSigner{ + Signer: p2p.NewLocalSigner(&p2pKey)}, + RPC: node.RPCConfig{ + ListenAddr: "127.0.0.1", + ListenPort: 0, + EnableAdmin: true, + }, + Supervisor: &node.SupervisorEndpointConfig{ + SupervisorAddr: s.supervisor.RPC(), + }, + P2P: nil, // disabled P2P setup for now + L1EpochPollInterval: time.Second * 2, + RuntimeConfigReloadInterval: 0, + Tracer: nil, + Sync: sync.Config{ + SyncMode: sync.CLSync, + SkipSyncStartCheck: false, + SupportsPostFinalizationELSync: false, + }, + ConfigPersistence: node.DisabledConfigPersistence{}, + } + opNode, err := opnode.NewOpnode(logger.New("service", "op-node"), + nodeCfg, func(err error) { + s.t.Error(err) + }) + require.NoError(s.t, err) + s.t.Cleanup(func() { + ctx, cancel := context.WithCancel(context.Background()) + cancel() // force-quit + _ = opNode.Stop(ctx) + }) + return opNode +} + +// newProposerForL2 creates a new Proposer for an L2 chain +// it is currently unused, as the generated world does not have a DisputeGameFactoryProxy +// TODO(#11888): name this function "newProposerForL2" and use it in the prepareL2s function when the DisputeGameFactoryProxy is available +func (s *interopE2ESystem) _( + id string, + operatorKeys map[devkeys.ChainOperatorRole]ecdsa.PrivateKey, + opNode *opnode.Opnode, +) *l2os.ProposerService { + proposerSecret := operatorKeys[devkeys.ProposerRole] + logger := s.logger.New("role", "proposer"+id) + proposerCLIConfig := &l2os.CLIConfig{ + L1EthRpc: s.l1.UserRPC().RPC(), + RollupRpc: opNode.UserRPC().RPC(), + DGFAddress: s.worldDeployment.L2s[id].DisputeGameFactoryProxy.Hex(), + ProposalInterval: 6 * time.Second, + DisputeGameType: 254, // Fast game type + PollInterval: 500 * time.Millisecond, + TxMgrConfig: setuputils.NewTxMgrConfig(s.l1.UserRPC(), &proposerSecret), + AllowNonFinalized: false, + LogConfig: oplog.CLIConfig{ + Level: log.LvlInfo, + Format: oplog.FormatText, + }, + } + proposer, err := l2os.ProposerServiceFromCLIConfig( + context.Background(), + "0.0.1", + proposerCLIConfig, + logger.New("service", "proposer")) + require.NoError(s.t, err, "must start proposer") + require.NoError(s.t, proposer.Start(context.Background())) + s.t.Cleanup(func() { + ctx, cancel := context.WithCancel(context.Background()) + cancel() // force-quit + _ = proposer.Stop(ctx) + }) + return proposer +} + +// newBatcherForL2 creates a new Batcher for an L2 chain +func (s *interopE2ESystem) newBatcherForL2( + id string, + operatorKeys map[devkeys.ChainOperatorRole]ecdsa.PrivateKey, + l2Geth *geth.GethInstance, + opNode *opnode.Opnode, +) *bss.BatcherService { + batcherSecret := operatorKeys[devkeys.BatcherRole] + logger := s.logger.New("role", "batcher"+id) + batcherCLIConfig := &bss.CLIConfig{ + L1EthRpc: s.l1.UserRPC().RPC(), + L2EthRpc: l2Geth.UserRPC().RPC(), + RollupRpc: opNode.UserRPC().RPC(), + MaxPendingTransactions: 1, + MaxChannelDuration: 1, + MaxL1TxSize: 120_000, + TestUseMaxTxSizeForBlobs: false, + TargetNumFrames: 1, + ApproxComprRatio: 0.4, + SubSafetyMargin: 4, + PollInterval: 50 * time.Millisecond, + TxMgrConfig: setuputils.NewTxMgrConfig(s.l1.UserRPC(), &batcherSecret), + LogConfig: oplog.CLIConfig{ + Level: log.LevelInfo, + Format: oplog.FormatText, + }, + Stopped: false, + BatchType: derive.SpanBatchType, + MaxBlocksPerSpanBatch: 10, + DataAvailabilityType: batcherFlags.CalldataType, + CompressionAlgo: derive.Brotli, + } + batcher, err := bss.BatcherServiceFromCLIConfig( + context.Background(), "0.0.1", batcherCLIConfig, + logger.New("service", "batcher")) + require.NoError(s.t, err) + require.NoError(s.t, batcher.Start(context.Background())) + s.t.Cleanup(func() { + ctx, cancel := context.WithCancel(context.Background()) + cancel() // force-quit + _ = batcher.Stop(ctx) + }) + return batcher +} + +// newL2 creates a new L2, starting with the L2Output from the world configuration +// and iterating through the resources needed for the L2. +// it returns a l2Set with the resources for the L2 +func (s *interopE2ESystem) newL2(id string, l2Out *interopgen.L2Output) l2Set { + operatorKeys := s.newOperatorKeysForL2(l2Out) + l2Geth := s.newGethForL2(id, l2Out) + opNode := s.newNodeForL2(id, l2Out, operatorKeys, l2Geth) + // TODO(#11886): proposer does not work with the generated world as there is no DisputeGameFactoryProxy + //proposer := s.newProposerForL2(id, operatorKeys, opNode) + batcher := s.newBatcherForL2(id, operatorKeys, l2Geth, opNode) + + return l2Set{ + chainID: l2Out.Genesis.Config.ChainID, + opNode: opNode, + l2Geth: l2Geth, + proposer: nil, + batcher: batcher, + operatorKeys: operatorKeys, + userKeys: make(map[string]ecdsa.PrivateKey), + contracts: make(map[string]interface{}), + } +} + +// prepareSupervisor creates a new supervisor for the system +func (s *interopE2ESystem) prepareSupervisor() *supervisor.SupervisorService { + // Be verbose with op-supervisor, it's in early test phase + logger := testlog.Logger(s.t, log.LevelDebug).New("role", "supervisor") + cfg := supervisorConfig.Config{ + MetricsConfig: metrics.CLIConfig{ + Enabled: false, + }, + PprofConfig: oppprof.CLIConfig{ + ListenEnabled: false, + }, + LogConfig: oplog.CLIConfig{ + Level: log.LevelDebug, + Format: oplog.FormatText, + }, + RPC: oprpc.CLIConfig{ + ListenAddr: "127.0.0.1", + ListenPort: 0, + EnableAdmin: true, + }, + L2RPCs: []string{}, + Datadir: path.Join(s.t.TempDir(), "supervisor"), + } + for id := range s.l2s { + cfg.L2RPCs = append(cfg.L2RPCs, s.l2s[id].l2Geth.UserRPC().RPC()) + } + // Create the supervisor with the configuration + super, err := supervisor.SupervisorFromConfig(context.Background(), &cfg, logger) + require.NoError(s.t, err) + // Start the supervisor + err = super.Start(context.Background()) + require.NoError(s.t, err) + s.t.Cleanup(func() { + ctx, cancel := context.WithCancel(context.Background()) + cancel() // force-quit + _ = super.Stop(ctx) + }) + return super +} + +// SupervisorClient returns the supervisor client for the system, creating it if it doesn't exist +func (s *interopE2ESystem) SupervisorClient() *sources.SupervisorClient { + if s.superClient != nil { + return s.superClient + } + cl, err := client.NewRPC(context.Background(), s.logger, s.supervisor.RPC()) + require.NoError(s.t, err, "failed to dial supervisor RPC") + superClient := sources.NewSupervisorClient(cl) + s.superClient = superClient + return superClient +} + +// prepare sets up the system for testing +// components are built iteratively, so that they can be reused or modified +// their creation can't be safely skipped or reordered at this time +func (s *interopE2ESystem) prepare(t *testing.T, w worldResourcePaths) { + s.t = t + s.logger = testlog.Logger(s.t, log.LevelInfo) + s.hdWallet = s.prepareHDWallet() + s.worldDeployment, s.worldOutput = s.prepareWorld(w) + + // the supervisor and client are created first so that the L2s can use the supervisor + s.supervisor = s.prepareSupervisor() + + s.beacon, s.l1 = s.prepareL1() + s.l2s = s.prepareL2s() + + // add the L2 RPCs to the supervisor now that the L2s are created + ctx := context.Background() + for _, l2 := range s.l2s { + err := s.SupervisorClient().AddL2RPC(ctx, l2.l2Geth.UserRPC().RPC()) + require.NoError(s.t, err, "failed to add L2 RPC to supervisor", "error", err) + } +} + +// AddUser adds a user to the system by creating a user key for each L2. +// each user key is stored in the L2's userKeys map. +// because all user maps start empty, a users index should be the same for all L2s, +// but if in the future these maps can diverge, the indexes for username would also diverge +// NOTE: The first 20 accounts are implicitly funded by the Recipe's World Deployment +// see: op-chain-ops/interopgen/recipe.go +// TODO(#11887): make the funded account quantity specified in the recipe so SuperSystems can know which accounts are funded +func (s *interopE2ESystem) AddUser(username string) { + for id, l2 := range s.l2s { + bigID, _ := big.NewInt(0).SetString(id, 10) + userSecret, _ := s.hdWallet.Secret( + devkeys.ChainUserKey{ + ChainID: bigID, + Index: uint64(len(l2.userKeys)), + }, + ) + l2.userKeys[username] = *userSecret + } +} + +// UserKey returns the user key for a user on an L2 +func (s *interopE2ESystem) UserKey(id, username string) ecdsa.PrivateKey { + return s.l2s[id].userKeys[username] +} + +// Address returns the address for a user on an L2 +func (s *interopE2ESystem) Address(id, username string) common.Address { + secret := s.UserKey(id, username) + require.NotNil(s.t, secret, "no secret found for user %s", username) + return crypto.PubkeyToAddress(secret.PublicKey) +} + +// prepareL2s creates the L2s for the system, returning a map of L2s +func (s *interopE2ESystem) prepareL2s() map[string]l2Set { + l2s := make(map[string]l2Set) + for id, l2Out := range s.worldOutput.L2s { + l2s[id] = s.newL2(id, l2Out) + } + return l2s +} + +func (s *interopE2ESystem) L2GethClient(id string) *ethclient.Client { + // guard: check if the client already exists and return it in that case + nodeClient, ok := s.l2GethClients[id] + if ok { + return nodeClient + } + // create a new client for the L2 from the L2's geth instance + var ethClient services.EthInstance = s.L2Geth(id) + rpcEndpoint := ethClient.UserRPC() + rpcCl := endpoint.DialRPC( + endpoint.PreferAnyRPC, + rpcEndpoint, + func(v string) *rpc.Client { + logger := testlog.Logger(s.t, log.LevelInfo).New("node", id) + cl, err := dial.DialRPCClientWithTimeout(context.Background(), 30*time.Second, logger, v) + require.NoError(s.t, err, "failed to dial eth node instance %s", id) + return cl + }) + nodeClient = ethclient.NewClient(rpcCl) + // register the client so it can be reused + s.addL2GethClient(id, nodeClient) + return nodeClient +} + +func (sys *interopE2ESystem) addL2GethClient(name string, client *ethclient.Client) { + if sys.l2GethClients == nil { + sys.l2GethClients = make(map[string]*ethclient.Client) + } + sys.l2GethClients[name] = client +} + +// getter functions for L1 entities +func (s *interopE2ESystem) Supervisor() *supervisor.SupervisorService { + return s.supervisor +} + +// gettter functions for the individual L2s +func (s *interopE2ESystem) Batcher(id string) *bss.BatcherService { + return s.l2s[id].batcher +} +func (s *interopE2ESystem) Proposer(id string) *l2os.ProposerService { + return s.l2s[id].proposer +} +func (s *interopE2ESystem) OpNode(id string) *opnode.Opnode { + return s.l2s[id].opNode +} +func (s *interopE2ESystem) L2Geth(id string) *geth.GethInstance { + return s.l2s[id].l2Geth +} +func (s *interopE2ESystem) L2OperatorKey(id string, role devkeys.ChainOperatorRole) ecdsa.PrivateKey { + return s.l2s[id].operatorKeys[role] +} + +// L2IDs returns the list of L2 IDs, which are the keys of the L2s map +func (s *interopE2ESystem) L2IDs() []string { + ids := make([]string, 0, len(s.l2s)) + for id := range s.l2s { + ids = append(ids, id) + } + return ids +} + +// SendL2Tx sends an L2 transaction to the L2 with the given ID. +// it acts as a wrapper around op-e2e.SendL2TxWithID +// and uses the L2's chain ID, username key, and geth client. +func (s *interopE2ESystem) SendL2Tx( + id string, + sender string, + applyTxOpts helpers.TxOptsFn, +) *types.Receipt { + senderSecret := s.UserKey(id, sender) + require.NotNil(s.t, senderSecret, "no secret found for sender %s", sender) + nonce, err := s.L2GethClient(id).PendingNonceAt(context.Background(), crypto.PubkeyToAddress(senderSecret.PublicKey)) + require.NoError(s.t, err, "failed to get nonce") + newApply := func(opts *helpers.TxOpts) { + applyTxOpts(opts) + opts.Nonce = nonce + } + return helpers.SendL2TxWithID( + s.t, + s.l2s[id].chainID, + s.L2GethClient(id), + &senderSecret, + newApply) +} + +func (s *interopE2ESystem) DeployEmitterContract( + id string, + sender string, +) common.Address { + secret := s.UserKey(id, sender) + auth, err := bind.NewKeyedTransactorWithChainID(&secret, s.l2s[id].chainID) + require.NoError(s.t, err) + auth.GasLimit = uint64(3000000) + auth.GasPrice = big.NewInt(20000000000) + address, _, _, err := emit.DeployEmit(auth, s.L2GethClient(id)) + require.NoError(s.t, err) + contract, err := emit.NewEmit(address, s.L2GethClient(id)) + require.NoError(s.t, err) + s.l2s[id].contracts["emitter"] = contract + return address +} + +func (s *interopE2ESystem) EmitData( + id string, + sender string, + data string, +) *types.Receipt { + secret := s.UserKey(id, sender) + auth, err := bind.NewKeyedTransactorWithChainID(&secret, s.l2s[id].chainID) + + require.NoError(s.t, err) + + auth.GasLimit = uint64(3000000) + auth.GasPrice = big.NewInt(20000000000) + + contract := s.Contract(id, "emitter").(*emit.Emit) + tx, err := contract.EmitTransactor.EmitData(auth, []byte(data)) + require.NoError(s.t, err) + receipt, err := bind.WaitMined(context.Background(), s.L2GethClient(id), tx) + require.NoError(s.t, err) + return receipt +} + +func (s *interopE2ESystem) Contract(id string, name string) interface{} { + return s.l2s[id].contracts[name] +} + +func mustDial(t *testing.T, logger log.Logger) func(v string) *rpc.Client { + return func(v string) *rpc.Client { + cl, err := dial.DialRPCClientWithTimeout(context.Background(), 30*time.Second, logger, v) + require.NoError(t, err, "failed to dial") + return cl + } +} + +var testingJWTSecret = [32]byte{123} + +func writeDefaultJWT(t testing.TB) string { + // Sadly the geth node config cannot load JWT secret from memory, it has to be a file + jwtPath := path.Join(t.TempDir(), "jwt_secret") + if err := os.WriteFile(jwtPath, []byte(hexutil.Encode(testingJWTSecret[:])), 0o600); err != nil { + t.Fatalf("failed to prepare jwt file for geth: %v", err) + } + return jwtPath +} diff --git a/op-e2e/fastlz_test.go b/op-e2e/opgeth/fastlz_test.go similarity index 99% rename from op-e2e/fastlz_test.go rename to op-e2e/opgeth/fastlz_test.go index 2323764e4678d..5b03ca38eca3c 100644 --- a/op-e2e/fastlz_test.go +++ b/op-e2e/opgeth/fastlz_test.go @@ -1,7 +1,7 @@ //go:build cgo_test // +build cgo_test -package op_e2e +package opgeth import ( "context" @@ -13,6 +13,7 @@ import ( "github.com/ethereum-optimism/optimism/op-e2e/bindings" "github.com/ethereum-optimism/optimism/op-e2e/fastlz" + "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -79,7 +80,7 @@ func FuzzFjordCostFunction(f *testing.F) { f.Add(seed) } - cfg := DefaultSystemConfig(f) + cfg := e2esys.DefaultSystemConfig(f) s := hexutil.Uint64(0) cfg.DeployConfig.L2GenesisCanyonTimeOffset = &s cfg.DeployConfig.L2GenesisDeltaTimeOffset = &s diff --git a/op-e2e/op_geth.go b/op-e2e/opgeth/op_geth.go similarity index 96% rename from op-e2e/op_geth.go rename to op-e2e/opgeth/op_geth.go index e13f42d8e8851..1e15eecbd08ae 100644 --- a/op-e2e/op_geth.go +++ b/op-e2e/opgeth/op_geth.go @@ -1,4 +1,4 @@ -package op_e2e +package opgeth import ( "context" @@ -7,6 +7,8 @@ import ( "reflect" "testing" + "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" + "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" "github.com/ethereum-optimism/optimism/op-e2e/config" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" @@ -51,7 +53,7 @@ type OpGeth struct { lgr log.Logger } -func NewOpGeth(t testing.TB, ctx context.Context, cfg *SystemConfig) (*OpGeth, error) { +func NewOpGeth(t testing.TB, ctx context.Context, cfg *e2esys.SystemConfig) (*OpGeth, error) { logger := testlog.Logger(t, log.LevelCrit) l1Genesis, err := genesis.BuildL1DeveloperGenesis(cfg.DeployConfig, config.L1Allocs, config.L1Deployments) @@ -68,7 +70,7 @@ func NewOpGeth(t testing.TB, ctx context.Context, cfg *SystemConfig) (*OpGeth, e allocsMode = genesis.L2AllocsEcotone } l2Allocs := config.L2Allocs(allocsMode) - l2Genesis, err := genesis.BuildL2Genesis(cfg.DeployConfig, l2Allocs, l1Block) + l2Genesis, err := genesis.BuildL2Genesis(cfg.DeployConfig, l2Allocs, l1Block.Header()) require.NoError(t, err) l2GenesisBlock := l2Genesis.ToBlock() @@ -92,7 +94,7 @@ func NewOpGeth(t testing.TB, ctx context.Context, cfg *SystemConfig) (*OpGeth, e require.NoError(t, gethNode.Node.Start()) node = gethNode } else { - externalNode := (&ExternalRunner{ + externalNode := (&e2esys.ExternalRunner{ Name: "l2", BinPath: cfg.ExternalL2Shim, Genesis: l2Genesis, @@ -106,7 +108,7 @@ func NewOpGeth(t testing.TB, ctx context.Context, cfg *SystemConfig) (*OpGeth, e require.NoError(t, err) // Finally create the engine client - rollupCfg, err := cfg.DeployConfig.RollupConfig(l1Block, l2GenesisBlock.Hash(), l2GenesisBlock.NumberU64()) + rollupCfg, err := cfg.DeployConfig.RollupConfig(l1Block.Header(), l2GenesisBlock.Hash(), l2GenesisBlock.NumberU64()) require.NoError(t, err) rollupCfg.Genesis = rollupGenesis l2Engine, err := sources.NewEngineClient( diff --git a/op-e2e/op_geth_test.go b/op-e2e/opgeth/op_geth_test.go similarity index 94% rename from op-e2e/op_geth_test.go rename to op-e2e/opgeth/op_geth_test.go index f34dfb81633b9..0f27e7b7f0473 100644 --- a/op-e2e/op_geth_test.go +++ b/op-e2e/opgeth/op_geth_test.go @@ -1,4 +1,4 @@ -package op_e2e +package opgeth import ( "context" @@ -7,6 +7,10 @@ import ( "testing" "time" + op_e2e "github.com/ethereum-optimism/optimism/op-e2e" + + "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" + "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" @@ -32,8 +36,8 @@ var ( // TestMissingGasLimit tests that op-geth cannot build a block without gas limit while optimism is active in the chain config. func TestMissingGasLimit(t *testing.T) { - InitParallel(t) - cfg := DefaultSystemConfig(t) + op_e2e.InitParallel(t) + cfg := e2esys.DefaultSystemConfig(t) ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) defer cancel() opGeth, err := NewOpGeth(t, ctx, &cfg) @@ -55,8 +59,8 @@ func TestMissingGasLimit(t *testing.T) { // TestTxGasSameAsBlockGasLimit tests that op-geth rejects transactions that attempt to use the full block gas limit. // The L1 Info deposit always takes gas so the effective gas limit is lower than the full block gas limit. func TestTxGasSameAsBlockGasLimit(t *testing.T) { - InitParallel(t) - cfg := DefaultSystemConfig(t) + op_e2e.InitParallel(t) + cfg := e2esys.DefaultSystemConfig(t) sys, err := cfg.Start(t) require.Nil(t, err, "Error starting up system") @@ -75,8 +79,8 @@ func TestTxGasSameAsBlockGasLimit(t *testing.T) { // TestInvalidDepositInFCU runs an invalid deposit through a FCU/GetPayload/NewPayload/FCU set of calls. // This tests that deposits must always allow the block to be built even if they are invalid. func TestInvalidDepositInFCU(t *testing.T) { - InitParallel(t) - cfg := DefaultSystemConfig(t) + op_e2e.InitParallel(t) + cfg := e2esys.DefaultSystemConfig(t) ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) defer cancel() opGeth, err := NewOpGeth(t, ctx, &cfg) @@ -115,8 +119,8 @@ func TestInvalidDepositInFCU(t *testing.T) { // and asserts that the pending block is set to match the latest block at every stage, // for stability and tx-privacy. func TestGethOnlyPendingBlockIsLatest(t *testing.T) { - InitParallel(t) - cfg := DefaultSystemConfig(t) + op_e2e.InitParallel(t) + cfg := e2esys.DefaultSystemConfig(t) cfg.DeployConfig.FundDevAccounts = true ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) defer cancel() @@ -125,7 +129,7 @@ func TestGethOnlyPendingBlockIsLatest(t *testing.T) { defer opGeth.Close() checkPending := func(stage string, number uint64) { - // TODO(CLI-4044): pending-block ID change + // TODO: pending-block ID change pendingBlock, err := opGeth.L2Client.BlockByNumber(ctx, big.NewInt(-1)) require.NoError(t, err, "failed to fetch pending block at stage "+stage) require.Equal(t, number, pendingBlock.NumberU64(), "pending block must have expected number") @@ -241,10 +245,10 @@ func TestPreregolith(t *testing.T) { for _, test := range tests { test := test t.Run("GasUsed_"+test.name, func(t *testing.T) { - InitParallel(t) + op_e2e.InitParallel(t) // Setup an L2 EE and create a client connection to the engine. // We also need to setup a L1 Genesis to create the rollup genesis. - cfg := RegolithSystemConfig(t, test.regolithTime) + cfg := e2esys.RegolithSystemConfig(t, test.regolithTime) ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) defer cancel() @@ -289,10 +293,10 @@ func TestPreregolith(t *testing.T) { }) t.Run("DepositNonce_"+test.name, func(t *testing.T) { - InitParallel(t) + op_e2e.InitParallel(t) // Setup an L2 EE and create a client connection to the engine. // We also need to setup a L1 Genesis to create the rollup genesis. - cfg := RegolithSystemConfig(t, test.regolithTime) + cfg := e2esys.RegolithSystemConfig(t, test.regolithTime) ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) defer cancel() @@ -347,8 +351,8 @@ func TestPreregolith(t *testing.T) { }) t.Run("UnusedGasConsumed_"+test.name, func(t *testing.T) { - InitParallel(t) - cfg := RegolithSystemConfig(t, test.regolithTime) + op_e2e.InitParallel(t) + cfg := e2esys.RegolithSystemConfig(t, test.regolithTime) ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) defer cancel() @@ -388,8 +392,8 @@ func TestPreregolith(t *testing.T) { }) t.Run("AllowSystemTx_"+test.name, func(t *testing.T) { - InitParallel(t) - cfg := RegolithSystemConfig(t, test.regolithTime) + op_e2e.InitParallel(t) + cfg := e2esys.RegolithSystemConfig(t, test.regolithTime) ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) defer cancel() @@ -424,10 +428,10 @@ func TestRegolith(t *testing.T) { for _, test := range tests { test := test t.Run("GasUsedIsAccurate_"+test.name, func(t *testing.T) { - InitParallel(t) + op_e2e.InitParallel(t) // Setup an L2 EE and create a client connection to the engine. // We also need to setup a L1 Genesis to create the rollup genesis. - cfg := RegolithSystemConfig(t, &test.regolithTime) + cfg := e2esys.RegolithSystemConfig(t, &test.regolithTime) ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) defer cancel() @@ -475,10 +479,10 @@ func TestRegolith(t *testing.T) { }) t.Run("DepositNonceCorrect_"+test.name, func(t *testing.T) { - InitParallel(t) + op_e2e.InitParallel(t) // Setup an L2 EE and create a client connection to the engine. // We also need to setup a L1 Genesis to create the rollup genesis. - cfg := RegolithSystemConfig(t, &test.regolithTime) + cfg := e2esys.RegolithSystemConfig(t, &test.regolithTime) ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) defer cancel() @@ -536,8 +540,8 @@ func TestRegolith(t *testing.T) { }) t.Run("ReturnUnusedGasToPool_"+test.name, func(t *testing.T) { - InitParallel(t) - cfg := RegolithSystemConfig(t, &test.regolithTime) + op_e2e.InitParallel(t) + cfg := e2esys.RegolithSystemConfig(t, &test.regolithTime) ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) defer cancel() @@ -578,8 +582,8 @@ func TestRegolith(t *testing.T) { }) t.Run("RejectSystemTx_"+test.name, func(t *testing.T) { - InitParallel(t) - cfg := RegolithSystemConfig(t, &test.regolithTime) + op_e2e.InitParallel(t) + cfg := e2esys.RegolithSystemConfig(t, &test.regolithTime) ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) defer cancel() @@ -600,7 +604,7 @@ func TestRegolith(t *testing.T) { }) t.Run("IncludeGasRefunds_"+test.name, func(t *testing.T) { - InitParallel(t) + op_e2e.InitParallel(t) // Simple constructor that is prefixed to the actual contract code // Results in the contract code being returned as the code for the new contract deployPrefixSize := byte(16) @@ -638,7 +642,7 @@ func TestRegolith(t *testing.T) { deployData := append(deployPrefix, sstoreContract...) - cfg := RegolithSystemConfig(t, &test.regolithTime) + cfg := e2esys.RegolithSystemConfig(t, &test.regolithTime) ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) defer cancel() @@ -735,8 +739,8 @@ func TestPreCanyon(t *testing.T) { test := test t.Run(fmt.Sprintf("ReturnsNilWithdrawals_%s", test.name), func(t *testing.T) { - InitParallel(t) - cfg := CanyonSystemConfig(t, test.canyonTime) + op_e2e.InitParallel(t) + cfg := e2esys.CanyonSystemConfig(t, test.canyonTime) ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) defer cancel() @@ -755,8 +759,8 @@ func TestPreCanyon(t *testing.T) { }) t.Run(fmt.Sprintf("RejectPushZeroTx_%s", test.name), func(t *testing.T) { - InitParallel(t) - cfg := CanyonSystemConfig(t, test.canyonTime) + op_e2e.InitParallel(t) + cfg := e2esys.CanyonSystemConfig(t, test.canyonTime) ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) defer cancel() @@ -801,8 +805,8 @@ func TestCanyon(t *testing.T) { for _, test := range tests { test := test t.Run(fmt.Sprintf("ReturnsEmptyWithdrawals_%s", test.name), func(t *testing.T) { - InitParallel(t) - cfg := CanyonSystemConfig(t, &test.canyonTime) + op_e2e.InitParallel(t) + cfg := e2esys.CanyonSystemConfig(t, &test.canyonTime) ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) defer cancel() @@ -823,8 +827,8 @@ func TestCanyon(t *testing.T) { }) t.Run(fmt.Sprintf("AcceptsPushZeroTxn_%s", test.name), func(t *testing.T) { - InitParallel(t) - cfg := CanyonSystemConfig(t, &test.canyonTime) + op_e2e.InitParallel(t) + cfg := e2esys.CanyonSystemConfig(t, &test.canyonTime) ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) defer cancel() @@ -869,8 +873,8 @@ func TestPreEcotone(t *testing.T) { test := test t.Run(fmt.Sprintf("NilParentBeaconRoot_%s", test.name), func(t *testing.T) { - InitParallel(t) - cfg := EcotoneSystemConfig(t, test.ecotoneTime) + op_e2e.InitParallel(t) + cfg := e2esys.EcotoneSystemConfig(t, test.ecotoneTime) ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) defer cancel() @@ -889,8 +893,8 @@ func TestPreEcotone(t *testing.T) { }) t.Run(fmt.Sprintf("RejectTstoreTxn_%s", test.name), func(t *testing.T) { - InitParallel(t) - cfg := EcotoneSystemConfig(t, test.ecotoneTime) + op_e2e.InitParallel(t) + cfg := e2esys.EcotoneSystemConfig(t, test.ecotoneTime) ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) defer cancel() @@ -937,8 +941,8 @@ func TestEcotone(t *testing.T) { for _, test := range tests { test := test t.Run(fmt.Sprintf("HashParentBeaconBlockRoot_%s", test.name), func(t *testing.T) { - InitParallel(t) - cfg := EcotoneSystemConfig(t, &test.ecotoneTime) + op_e2e.InitParallel(t) + cfg := e2esys.EcotoneSystemConfig(t, &test.ecotoneTime) ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) defer cancel() @@ -961,8 +965,8 @@ func TestEcotone(t *testing.T) { }) t.Run(fmt.Sprintf("TstoreTxn_%s", test.name), func(t *testing.T) { - InitParallel(t) - cfg := EcotoneSystemConfig(t, &test.ecotoneTime) + op_e2e.InitParallel(t) + cfg := e2esys.EcotoneSystemConfig(t, &test.ecotoneTime) ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) defer cancel() @@ -1013,8 +1017,8 @@ func TestPreFjord(t *testing.T) { test := test t.Run(fmt.Sprintf("RIP7212_%s", test.name), func(t *testing.T) { - InitParallel(t) - cfg := FjordSystemConfig(t, test.fjordTime) + op_e2e.InitParallel(t) + cfg := e2esys.FjordSystemConfig(t, test.fjordTime) ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) defer cancel() @@ -1061,8 +1065,8 @@ func TestFjord(t *testing.T) { for _, test := range tests { test := test t.Run(fmt.Sprintf("RIP7212_%s", test.name), func(t *testing.T) { - InitParallel(t) - cfg := FjordSystemConfig(t, &test.fjordTime) + op_e2e.InitParallel(t) + cfg := e2esys.FjordSystemConfig(t, &test.fjordTime) ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) defer cancel() diff --git a/op-e2e/system/altda/altda_test.go b/op-e2e/system/altda/altda_test.go new file mode 100644 index 0000000000000..9a9546328c028 --- /dev/null +++ b/op-e2e/system/altda/altda_test.go @@ -0,0 +1,11 @@ +package altda + +import ( + "testing" + + op_e2e "github.com/ethereum-optimism/optimism/op-e2e" +) + +func TestMain(m *testing.M) { + op_e2e.RunMain(m) +} diff --git a/op-e2e/system/altda/concurrent_test.go b/op-e2e/system/altda/concurrent_test.go new file mode 100644 index 0000000000000..4d6835b1fc551 --- /dev/null +++ b/op-e2e/system/altda/concurrent_test.go @@ -0,0 +1,77 @@ +package altda + +import ( + "context" + "math/big" + "testing" + "time" + + op_e2e "github.com/ethereum-optimism/optimism/op-e2e" + + "github.com/ethereum-optimism/optimism/op-batcher/flags" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/transactions" + "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" + "github.com/ethereum-optimism/optimism/op-node/rollup/derive" + "github.com/stretchr/testify/require" +) + +func TestBatcherConcurrentAltDARequests(t *testing.T) { + op_e2e.InitParallel(t) + + numL1TxsExpected := int64(10) + + cfg := e2esys.DefaultSystemConfig(t) + cfg.DeployConfig.UseAltDA = true + cfg.BatcherMaxPendingTransactions = 0 // no limit on parallel txs + // ensures that batcher txs are as small as possible + cfg.BatcherMaxL1TxSizeBytes = derive.FrameV0OverHeadSize + 1 /*version bytes*/ + 1 + cfg.BatcherBatchType = 0 + cfg.DataAvailabilityType = flags.CalldataType + cfg.BatcherMaxConcurrentDARequest = uint64(numL1TxsExpected) + + // disable batcher because we start it manually below + cfg.DisableBatcher = true + sys, err := cfg.Start(t) + require.NoError(t, err, "Error starting up system") + defer sys.Close() + + // make every request take 5 seconds, such that only concurrent requests will be able to make progress fast enough + sys.FakeAltDAServer.SetPutRequestLatency(5 * time.Second) + + l1Client := sys.NodeClient("l1") + l2Seq := sys.NodeClient("sequencer") + + // we wait for numL1TxsExpected L2 blocks to have been produced, just to make sure the sequencer is working properly + _, err = geth.WaitForBlock(big.NewInt(numL1TxsExpected), l2Seq, time.Duration(cfg.DeployConfig.L2BlockTime*uint64(numL1TxsExpected))*time.Second) + require.NoError(t, err, "Waiting for L2 blocks") + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + startingL1BlockNum, err := l1Client.BlockNumber(ctx) + require.NoError(t, err) + + // start batch submission + driver := sys.BatchSubmitter.TestDriver() + err = driver.StartBatchSubmitting() + require.NoError(t, err) + + totalBatcherTxsCount := int64(0) + // wait for up to 5 L1 blocks, expecting 10 L2 batcher txs in them. + // usually only 3 is required, but it's possible additional L1 blocks will be created + // before the batcher starts, so we wait additional blocks. + for i := int64(0); i < 5; i++ { + block, err := geth.WaitForBlock(big.NewInt(int64(startingL1BlockNum)+i), l1Client, time.Duration(cfg.DeployConfig.L1BlockTime*2)*time.Second) + require.NoError(t, err, "Waiting for l1 blocks") + // there are possibly other services (proposer/challenger) in the background sending txs + // so we only count the batcher txs + batcherTxCount, err := transactions.TransactionsBySender(block, cfg.DeployConfig.BatchSenderAddress) + require.NoError(t, err) + totalBatcherTxsCount += int64(batcherTxCount) + + if totalBatcherTxsCount >= numL1TxsExpected { + return + } + } + + t.Fatal("Expected at least 10 transactions from the batcher") +} diff --git a/op-e2e/bridge_test.go b/op-e2e/system/bridge/bridge_test.go similarity index 94% rename from op-e2e/bridge_test.go rename to op-e2e/system/bridge/bridge_test.go index 2846e3218688a..655cf612c9ad4 100644 --- a/op-e2e/bridge_test.go +++ b/op-e2e/system/bridge/bridge_test.go @@ -1,4 +1,4 @@ -package op_e2e +package bridge import ( "context" @@ -6,6 +6,10 @@ import ( "math/big" "testing" + op_e2e "github.com/ethereum-optimism/optimism/op-e2e" + + "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" + "github.com/ethereum-optimism/optimism/op-e2e/bindings" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/receipts" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/transactions" @@ -20,12 +24,16 @@ import ( "github.com/stretchr/testify/require" ) +func TestMain(m *testing.M) { + op_e2e.RunMain(m) +} + // TestERC20BridgeDeposits tests the the L1StandardBridge bridge ERC20 // functionality. func TestERC20BridgeDeposits(t *testing.T) { - InitParallel(t) + op_e2e.InitParallel(t) - cfg := DefaultSystemConfig(t) + cfg := e2esys.DefaultSystemConfig(t) sys, err := cfg.Start(t) require.Nil(t, err, "Error starting up system") diff --git a/op-e2e/deposit_test.go b/op-e2e/system/bridge/deposit_test.go similarity index 88% rename from op-e2e/deposit_test.go rename to op-e2e/system/bridge/deposit_test.go index c36d8aa445841..d01e9b3f3be9c 100644 --- a/op-e2e/deposit_test.go +++ b/op-e2e/system/bridge/deposit_test.go @@ -1,4 +1,4 @@ -package op_e2e +package bridge import ( "context" @@ -6,6 +6,11 @@ import ( "testing" "time" + op_e2e "github.com/ethereum-optimism/optimism/op-e2e" + + "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" + "github.com/ethereum-optimism/optimism/op-e2e/system/helpers" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -16,8 +21,8 @@ import ( ) func TestMintOnRevertedDeposit(t *testing.T) { - InitParallel(t) - cfg := DefaultSystemConfig(t) + op_e2e.InitParallel(t) + cfg := e2esys.DefaultSystemConfig(t) delete(cfg.Nodes, "verifier") sys, err := cfg.Start(t) require.NoError(t, err, "Error starting up system") @@ -44,7 +49,7 @@ func TestMintOnRevertedDeposit(t *testing.T) { toAddr := common.Address{0xff, 0xff} mintAmount := big.NewInt(9_000_000) opts.Value = mintAmount - SendDepositTx(t, cfg, l1Client, l2Verif, opts, func(l2Opts *DepositTxOpts) { + helpers.SendDepositTx(t, cfg, l1Client, l2Verif, opts, func(l2Opts *helpers.DepositTxOpts) { l2Opts.ToAddr = toAddr // trigger a revert by transferring more than we have available l2Opts.Value = new(big.Int).Mul(common.Big2, startBalance) @@ -75,8 +80,8 @@ func TestMintOnRevertedDeposit(t *testing.T) { } func TestDepositTxCreateContract(t *testing.T) { - InitParallel(t) - cfg := DefaultSystemConfig(t) + op_e2e.InitParallel(t) + cfg := e2esys.DefaultSystemConfig(t) delete(cfg.Nodes, "verifier") sys, err := cfg.Start(t) @@ -125,7 +130,7 @@ func TestDepositTxCreateContract(t *testing.T) { deployData := append(deployPrefix, sstoreContract...) - l2Receipt := SendDepositTx(t, cfg, l1Client, l2Client, opts, func(l2Opts *DepositTxOpts) { + l2Receipt := helpers.SendDepositTx(t, cfg, l1Client, l2Client, opts, func(l2Opts *helpers.DepositTxOpts) { l2Opts.Data = deployData l2Opts.Value = common.Big0 l2Opts.IsCreation = true diff --git a/op-e2e/system/bridge/rpc_test.go b/op-e2e/system/bridge/rpc_test.go new file mode 100644 index 0000000000000..74a243ac2a93f --- /dev/null +++ b/op-e2e/system/bridge/rpc_test.go @@ -0,0 +1,55 @@ +package bridge + +import ( + "context" + "math/big" + "testing" + "time" + + op_e2e "github.com/ethereum-optimism/optimism/op-e2e" + + "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/stretchr/testify/require" +) + +// TestL2SequencerRPCDepositTx checks that the L2 sequencer will not accept DepositTx type transactions. +// The acceptance of these transactions would allow for arbitrary minting of ETH in L2. +func TestL2SequencerRPCDepositTx(t *testing.T) { + op_e2e.InitParallel(t) + + // Create our system configuration for L1/L2 and start it + cfg := e2esys.DefaultSystemConfig(t) + sys, err := cfg.Start(t) + require.Nil(t, err, "Error starting up system") + + // Obtain our sequencer, verifier, and transactor keypair. + l2Seq := sys.NodeClient("sequencer") + l2Verif := sys.NodeClient("verifier") + txSigningKey := sys.Cfg.Secrets.Alice + require.Nil(t, err) + + // Create a deposit tx to send over RPC. + tx := types.NewTx(&types.DepositTx{ + SourceHash: common.Hash{}, + From: crypto.PubkeyToAddress(txSigningKey.PublicKey), + To: &common.Address{0xff, 0xff}, + Mint: big.NewInt(1000), + Value: big.NewInt(1000), + Gas: 0, + IsSystemTransaction: false, + Data: nil, + }) + + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + err = l2Seq.SendTransaction(ctx, tx) + cancel() + require.Error(t, err, "a DepositTx was accepted by L2 sequencer over RPC when it should not have been.") + + ctx, cancel = context.WithTimeout(context.Background(), 5*time.Second) + err = l2Verif.SendTransaction(ctx, tx) + cancel() + require.Error(t, err, "a DepositTx was accepted by L2 verifier over RPC when it should not have been.") +} diff --git a/op-e2e/system_tob_test.go b/op-e2e/system/bridge/validity_test.go similarity index 81% rename from op-e2e/system_tob_test.go rename to op-e2e/system/bridge/validity_test.go index 99668d995acff..d799190159516 100644 --- a/op-e2e/system_tob_test.go +++ b/op-e2e/system/bridge/validity_test.go @@ -1,26 +1,28 @@ -package op_e2e +package bridge import ( "bytes" "context" "crypto/ecdsa" "fmt" - "math" "math/big" "math/rand" "testing" "time" + op_e2e "github.com/ethereum-optimism/optimism/op-e2e" + + "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" + "github.com/ethereum-optimism/optimism/op-e2e/system/helpers" + "github.com/ethereum-optimism/optimism/op-chain-ops/crossdomain" legacybindings "github.com/ethereum-optimism/optimism/op-e2e/bindings" "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/bindings" bindingspreview "github.com/ethereum-optimism/optimism/op-node/bindings/preview" - "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum-optimism/optimism/op-service/testutils/fuzzerutils" "github.com/ethereum/go-ethereum/accounts" @@ -36,127 +38,6 @@ import ( "github.com/stretchr/testify/require" ) -// TestGasPriceOracleFeeUpdates checks that the gas price oracle cannot be locked by mis-configuring parameters. -func TestGasPriceOracleFeeUpdates(t *testing.T) { - ctx, ctxCancel := context.WithCancel(context.Background()) - defer ctxCancel() - - InitParallel(t) - maxScalars := eth.EcotoneScalars{ - BaseFeeScalar: math.MaxUint32, - BlobBaseFeeScalar: math.MaxUint32, - } - var cancel context.CancelFunc - - // Create our system configuration for L1/L2 and start it - cfg := DefaultSystemConfig(t) - sys, err := cfg.Start(t) - require.NoError(t, err, "Error starting up system") - - // Obtain our sequencer, verifier, and transactor keypair. - l1Client := sys.NodeClient("l1") - l2Seq := sys.NodeClient("sequencer") - // l2Verif := sys.NodeClient("verifier") - ethPrivKey := cfg.Secrets.SysCfgOwner - - // Bind to the SystemConfig & GasPriceOracle contracts - sysconfig, err := legacybindings.NewSystemConfig(cfg.L1Deployments.SystemConfigProxy, l1Client) - require.NoError(t, err) - gpoContract, err := legacybindings.NewGasPriceOracleCaller(predeploys.GasPriceOracleAddr, l2Seq) - require.NoError(t, err) - - // Obtain our signer. - opts, err := bind.NewKeyedTransactorWithChainID(ethPrivKey, cfg.L1ChainIDBig()) - require.NoError(t, err) - - // Define our L1 transaction timeout duration. - 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(ctx, txTimeoutDuration) - tx, err := sysconfig.SetGasConfigEcotone(opts, maxScalars.BaseFeeScalar, maxScalars.BlobBaseFeeScalar) - cancel() - require.NoError(t, err, "SetGasConfigEcotone update tx") - - receipt, err := wait.ForReceiptOK(ctx, l1Client, tx.Hash()) - require.NoError(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") - - baseFeeScalar, err := gpoContract.BaseFeeScalar(&bind.CallOpts{}) - require.NoError(t, err, "reading base fee scalar") - require.Equal(t, baseFeeScalar, maxScalars.BaseFeeScalar) - - blobBaseFeeScalar, err := gpoContract.BlobBaseFeeScalar(&bind.CallOpts{}) - require.NoError(t, err, "reading blob base fee scalar") - require.Equal(t, blobBaseFeeScalar, maxScalars.BlobBaseFeeScalar) - - // Now modify the scalar value & ensure that the gas params can be modified - normalScalars := eth.EcotoneScalars{ - BaseFeeScalar: 1e6, - BlobBaseFeeScalar: 1e6, - } - - opts.Context, cancel = context.WithTimeout(context.Background(), txTimeoutDuration) - tx, err = sysconfig.SetGasConfigEcotone(opts, normalScalars.BaseFeeScalar, normalScalars.BlobBaseFeeScalar) - cancel() - require.NoError(t, err, "SetGasConfigEcotone update tx") - - receipt, err = wait.ForReceiptOK(ctx, l1Client, tx.Hash()) - require.NoError(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") - - baseFeeScalar, err = gpoContract.BaseFeeScalar(&bind.CallOpts{}) - require.NoError(t, err, "reading base fee scalar") - require.Equal(t, baseFeeScalar, normalScalars.BaseFeeScalar) - - blobBaseFeeScalar, err = gpoContract.BlobBaseFeeScalar(&bind.CallOpts{}) - require.NoError(t, err, "reading blob base fee scalar") - require.Equal(t, blobBaseFeeScalar, normalScalars.BlobBaseFeeScalar) -} - -// TestL2SequencerRPCDepositTx checks that the L2 sequencer will not accept DepositTx type transactions. -// The acceptance of these transactions would allow for arbitrary minting of ETH in L2. -func TestL2SequencerRPCDepositTx(t *testing.T) { - InitParallel(t) - - // Create our system configuration for L1/L2 and start it - cfg := DefaultSystemConfig(t) - sys, err := cfg.Start(t) - require.Nil(t, err, "Error starting up system") - - // Obtain our sequencer, verifier, and transactor keypair. - l2Seq := sys.NodeClient("sequencer") - l2Verif := sys.NodeClient("verifier") - txSigningKey := sys.Cfg.Secrets.Alice - require.Nil(t, err) - - // Create a deposit tx to send over RPC. - tx := types.NewTx(&types.DepositTx{ - SourceHash: common.Hash{}, - From: crypto.PubkeyToAddress(txSigningKey.PublicKey), - To: &common.Address{0xff, 0xff}, - Mint: big.NewInt(1000), - Value: big.NewInt(1000), - Gas: 0, - IsSystemTransaction: false, - Data: nil, - }) - - ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) - err = l2Seq.SendTransaction(ctx, tx) - cancel() - require.Error(t, err, "a DepositTx was accepted by L2 sequencer over RPC when it should not have been.") - - ctx, cancel = context.WithTimeout(context.Background(), 5*time.Second) - err = l2Verif.SendTransaction(ctx, tx) - cancel() - require.Error(t, err, "a DepositTx was accepted by L2 verifier over RPC when it should not have been.") -} - // TestAccount defines an account generated by startConfigWithTestAccounts type TestAccount struct { HDPath string @@ -169,7 +50,7 @@ type TestAccount struct { // startConfigWithTestAccounts takes a SystemConfig, generates additional accounts, adds them to the config, so they // are funded on startup, starts the system, and imports the keys into the keystore, and obtains transaction opts for // each account. -func startConfigWithTestAccounts(t *testing.T, cfg *SystemConfig, accountsToGenerate int) (*System, []*TestAccount, error) { +func startConfigWithTestAccounts(t *testing.T, cfg *e2esys.SystemConfig, accountsToGenerate int) (*e2esys.System, []*TestAccount, error) { // Create our test accounts and add them to the pre-mine cfg. testAccounts := make([]*TestAccount, 0) var err error @@ -223,7 +104,7 @@ func startConfigWithTestAccounts(t *testing.T, cfg *SystemConfig, accountsToGene // TestMixedDepositValidity makes a number of deposit transactions, some which will succeed in transferring value, // while others do not. It ensures that the expected nonces/balances match after several interactions. func TestMixedDepositValidity(t *testing.T) { - InitParallel(t) + op_e2e.InitParallel(t) // Define how many deposit txs we'll make. Each deposit mints a fixed amount and transfers up to 1/3 of the user's // balance. As such, this number cannot be too high or else the test will always fail due to lack of balance in L1. const depositTxCount = 15 @@ -232,7 +113,7 @@ func TestMixedDepositValidity(t *testing.T) { const accountUsedToDeposit = 5 // Create our system configuration, funding all accounts we created for L1/L2, and start it - cfg := DefaultSystemConfig(t) + cfg := e2esys.DefaultSystemConfig(t) sys, testAccounts, err := startConfigWithTestAccounts(t, &cfg, accountUsedToDeposit) require.Nil(t, err, "Error starting up system") @@ -315,7 +196,7 @@ func TestMixedDepositValidity(t *testing.T) { } else { transferValue = new(big.Int).Mul(common.Big2, transactor.ExpectedL2Balance) // trigger a revert by trying to transfer our current balance * 2 } - SendDepositTx(t, cfg, l1Client, l2Verif, transactor.Account.L1Opts, func(l2Opts *DepositTxOpts) { + helpers.SendDepositTx(t, cfg, l1Client, l2Verif, transactor.Account.L1Opts, func(l2Opts *helpers.DepositTxOpts) { l2Opts.GasLimit = 100_000 l2Opts.IsCreation = false l2Opts.Data = nil @@ -386,7 +267,7 @@ func TestMixedDepositValidity(t *testing.T) { // TestMixedWithdrawalValidity makes a number of withdrawal transactions and ensures ones with modified parameters are // rejected while unmodified ones are accepted. This runs test cases in different systems. func TestMixedWithdrawalValidity(t *testing.T) { - InitParallel(t) + op_e2e.InitParallel(t) // There are 7 different fields we try modifying to cause a failure, plus one "good" test result we test. for i := 0; i <= 8; i++ { @@ -395,10 +276,10 @@ func TestMixedWithdrawalValidity(t *testing.T) { ctx, bgCancel := context.WithCancel(context.Background()) defer bgCancel() - InitParallel(t) + op_e2e.InitParallel(t) // Create our system configuration, funding all accounts we created for L1/L2, and start it - cfg := DefaultSystemConfig(t) + cfg := e2esys.DefaultSystemConfig(t) cfg.Nodes["sequencer"].SafeDBPath = t.TempDir() cfg.DeployConfig.L2BlockTime = 2 require.LessOrEqual(t, cfg.DeployConfig.FinalizationPeriodSeconds, uint64(6)) @@ -529,7 +410,7 @@ func TestMixedWithdrawalValidity(t *testing.T) { require.Nil(t, err) // Calculate gas fees for the withdrawal in L2 to later adjust our balance. - withdrawalL2GasFee := calcGasFees(receipt.GasUsed, tx.GasTipCap(), tx.GasFeeCap(), header.BaseFee) + withdrawalL2GasFee := helpers.CalcGasFees(receipt.GasUsed, tx.GasTipCap(), tx.GasFeeCap(), header.BaseFee) // Adjust our expected L2 balance (should've decreased by withdraw amount + fees) transactor.ExpectedL2Balance = new(big.Int).Sub(transactor.ExpectedL2Balance, withdrawAmount) @@ -557,7 +438,7 @@ func TestMixedWithdrawalValidity(t *testing.T) { blockCl := ethclient.NewClient(rpcClient) // Now create the withdrawal - params, err := ProveWithdrawalParameters(context.Background(), proofCl, receiptCl, blockCl, tx.Hash(), header, l2OutputOracle, disputeGameFactory, optimismPortal2) + params, err := helpers.ProveWithdrawalParameters(context.Background(), proofCl, receiptCl, blockCl, tx.Hash(), header, l2OutputOracle, disputeGameFactory, optimismPortal2) require.Nil(t, err) // Obtain our withdrawal parameters @@ -662,7 +543,7 @@ func TestMixedWithdrawalValidity(t *testing.T) { // Ensure that withdrawal - gas fees are added to the L1 balance // Fun fact, the fee is greater than the withdrawal amount - withdrawalL1GasFee := calcGasFees(receipt.GasUsed, tx.GasTipCap(), tx.GasFeeCap(), header.BaseFee) + withdrawalL1GasFee := helpers.CalcGasFees(receipt.GasUsed, tx.GasTipCap(), tx.GasFeeCap(), header.BaseFee) transactor.ExpectedL1Balance = new(big.Int).Add(transactor.ExpectedL2Balance, withdrawAmount) transactor.ExpectedL1Balance = new(big.Int).Sub(transactor.ExpectedL2Balance, withdrawalL1GasFee) transactor.ExpectedL1Nonce++ diff --git a/op-e2e/withdrawal.go b/op-e2e/system/bridge/withdrawal.go similarity index 88% rename from op-e2e/withdrawal.go rename to op-e2e/system/bridge/withdrawal.go index a5f44434a8eed..29864db02dbfc 100644 --- a/op-e2e/withdrawal.go +++ b/op-e2e/system/bridge/withdrawal.go @@ -1,4 +1,4 @@ -package op_e2e +package bridge import ( "context" @@ -7,6 +7,9 @@ import ( "testing" "time" + "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" + "github.com/ethereum-optimism/optimism/op-e2e/system/helpers" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" @@ -22,7 +25,7 @@ import ( type CommonSystem interface { NodeClient(role string) *ethclient.Client RollupClient(role string) *sources.RollupClient - Config() SystemConfig + Config() e2esys.SystemConfig TestAccount(int) *ecdsa.PrivateKey } @@ -33,9 +36,9 @@ func RunWithdrawalsTest(t *testing.T, sys CommonSystem) { t.Logf("WithdrawalsTest: running with FP == %t", e2eutils.UseFaultProofs()) cfg := sys.Config() - l1Client := sys.NodeClient(RoleL1) - l2Seq := sys.NodeClient(RoleSeq) - l2Verif := sys.NodeClient(RoleVerif) + l1Client := sys.NodeClient(e2esys.RoleL1) + l2Seq := sys.NodeClient(e2esys.RoleSeq) + l2Verif := sys.NodeClient(e2esys.RoleVerif) // Transactor Account ethPrivKey := sys.TestAccount(0) @@ -55,7 +58,7 @@ func RunWithdrawalsTest(t *testing.T, sys CommonSystem) { mintAmount := big.NewInt(1_000_000_000_000) opts.Value = mintAmount t.Logf("WithdrawalsTest: depositing %v with L2 start balance %v...", mintAmount, startBalanceBeforeDeposit) - SendDepositTx(t, cfg, l1Client, l2Verif, opts, func(l2Opts *DepositTxOpts) { + helpers.SendDepositTx(t, cfg, l1Client, l2Verif, opts, func(l2Opts *helpers.DepositTxOpts) { l2Opts.Value = common.Big0 }) t.Log("WithdrawalsTest: waiting for balance change...") @@ -78,7 +81,7 @@ func RunWithdrawalsTest(t *testing.T, sys CommonSystem) { withdrawAmount := big.NewInt(500_000_000_000) t.Logf("WithdrawalsTest: sending L2 withdrawal for %v...", withdrawAmount) - tx, receipt := SendWithdrawal(t, cfg, l2Seq, ethPrivKey, func(opts *WithdrawalTxOpts) { + tx, receipt := helpers.SendWithdrawal(t, cfg, l2Seq, ethPrivKey, func(opts *helpers.WithdrawalTxOpts) { opts.Value = withdrawAmount opts.VerifyOnClients(l2Verif) }) @@ -97,7 +100,7 @@ func RunWithdrawalsTest(t *testing.T, sys CommonSystem) { // Take fee into account diff = new(big.Int).Sub(startBalanceBeforeWithdrawal, endBalanceAfterWithdrawal) - fees := calcGasFees(receipt.GasUsed, tx.GasTipCap(), tx.GasFeeCap(), header.BaseFee) + fees := helpers.CalcGasFees(receipt.GasUsed, tx.GasTipCap(), tx.GasFeeCap(), header.BaseFee) fees = fees.Add(fees, receipt.L1Fee) diff = diff.Sub(diff, fees) require.Equal(t, withdrawAmount, diff) @@ -109,7 +112,7 @@ func RunWithdrawalsTest(t *testing.T, sys CommonSystem) { require.NoError(t, err) t.Log("WithdrawalsTest: ProveAndFinalizeWithdrawal...") - proveReceipt, finalizeReceipt, resolveClaimReceipt, resolveReceipt := ProveAndFinalizeWithdrawal(t, cfg, sys, RoleVerif, ethPrivKey, receipt) + proveReceipt, finalizeReceipt, resolveClaimReceipt, resolveReceipt := helpers.ProveAndFinalizeWithdrawal(t, cfg, sys, e2esys.RoleVerif, ethPrivKey, receipt) // Verify balance after withdrawal ctx, cancel = context.WithTimeout(context.Background(), 30*time.Second) diff --git a/op-e2e/system/bridge/withdrawal_test.go b/op-e2e/system/bridge/withdrawal_test.go new file mode 100644 index 0000000000000..9f37240cbdbef --- /dev/null +++ b/op-e2e/system/bridge/withdrawal_test.go @@ -0,0 +1,26 @@ +package bridge + +import ( + "testing" + + op_e2e "github.com/ethereum-optimism/optimism/op-e2e" + + "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" + "github.com/stretchr/testify/require" +) + +// TestWithdrawals checks that a deposit and then withdrawal execution succeeds. It verifies the +// balance changes on L1 and L2 and has to include gas fees in the balance checks. +// It does not check that the withdrawal can be executed prior to the end of the finality period. +func TestWithdrawals(t *testing.T) { + op_e2e.InitParallel(t) + + cfg := e2esys.DefaultSystemConfig(t) + cfg.DeployConfig.FinalizationPeriodSeconds = 2 // 2s finalization period + cfg.L1FinalizedDistance = 2 // Finalize quick, don't make the proposer wait too long + + sys, err := cfg.Start(t) + require.NoError(t, err, "Error starting up system") + + RunWithdrawalsTest(t, sys) +} diff --git a/op-e2e/system/conductor/conductor_test.go b/op-e2e/system/conductor/conductor_test.go new file mode 100644 index 0000000000000..ec4175807f8cc --- /dev/null +++ b/op-e2e/system/conductor/conductor_test.go @@ -0,0 +1,11 @@ +package conductor + +import ( + "testing" + + op_e2e "github.com/ethereum-optimism/optimism/op-e2e" +) + +func TestMain(m *testing.M) { + op_e2e.RunMain(m) +} diff --git a/op-e2e/sequencer_failover_setup.go b/op-e2e/system/conductor/sequencer_failover_setup.go similarity index 91% rename from op-e2e/sequencer_failover_setup.go rename to op-e2e/system/conductor/sequencer_failover_setup.go index db4e05bff4336..ea515ecc1e64d 100644 --- a/op-e2e/sequencer_failover_setup.go +++ b/op-e2e/system/conductor/sequencer_failover_setup.go @@ -1,4 +1,4 @@ -package op_e2e +package conductor import ( "context" @@ -9,6 +9,11 @@ import ( "testing" "time" + op_e2e "github.com/ethereum-optimism/optimism/op-e2e" + + "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rpc" "github.com/stretchr/testify/require" @@ -18,6 +23,7 @@ import ( con "github.com/ethereum-optimism/optimism/op-conductor/conductor" "github.com/ethereum-optimism/optimism/op-conductor/consensus" conrpc "github.com/ethereum-optimism/optimism/op-conductor/rpc" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/setuputils" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" rollupNode "github.com/ethereum-optimism/optimism/op-node/node" "github.com/ethereum-optimism/optimism/op-node/rollup" @@ -59,11 +65,11 @@ func (c *conductor) RPCEndpoint() string { return fmt.Sprintf("http://%s:%d", localhost, c.rpcPort) } -func setupSequencerFailoverTest(t *testing.T) (*System, map[string]*conductor, func()) { - InitParallel(t) +func setupSequencerFailoverTest(t *testing.T) (*e2esys.System, map[string]*conductor, func()) { + op_e2e.InitParallel(t) ctx := context.Background() - sys, conductors, err := retry.Do2(ctx, maxSetupRetries, retryStrategy, func() (*System, map[string]*conductor, error) { + sys, conductors, err := retry.Do2(ctx, maxSetupRetries, retryStrategy, func() (*e2esys.System, map[string]*conductor, error) { return setupHAInfra(t, ctx) }) require.NoError(t, err, "Expected to successfully setup sequencers and conductors after retry") @@ -137,10 +143,10 @@ func setupSequencerFailoverTest(t *testing.T) (*System, map[string]*conductor, f } } -func setupHAInfra(t *testing.T, ctx context.Context) (*System, map[string]*conductor, error) { +func setupHAInfra(t *testing.T, ctx context.Context) (*e2esys.System, map[string]*conductor, error) { startTime := time.Now() - var sys *System + var sys *e2esys.System var conductors map[string]*conductor var err error @@ -208,14 +214,17 @@ func setupConductor( ) (*conductor, error) { consensusPort := findAvailablePort(t) cfg := con.Config{ - ConsensusAddr: localhost, - ConsensusPort: consensusPort, - RaftServerID: serverID, - RaftStorageDir: dir, - RaftBootstrap: bootstrap, - NodeRPC: nodeRPC, - ExecutionRPC: engineRPC, - Paused: true, + ConsensusAddr: localhost, + ConsensusPort: consensusPort, + RaftServerID: serverID, + RaftStorageDir: dir, + RaftBootstrap: bootstrap, + RaftSnapshotInterval: 120 * time.Second, + RaftSnapshotThreshold: 8192, + RaftTrailingLogs: 10240, + NodeRPC: nodeRPC, + ExecutionRPC: engineRPC, + Paused: true, HealthCheck: con.HealthCheckConfig{ Interval: 1, // per test setup, l2 block time is 1s. MinPeerCount: 2, // per test setup, each sequencer has 2 peers @@ -263,7 +272,7 @@ func setupConductor( }, nil } -func setupBatcher(t *testing.T, sys *System, conductors map[string]*conductor) { +func setupBatcher(t *testing.T, sys *e2esys.System, conductors map[string]*conductor) { // 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. @@ -288,7 +297,7 @@ func setupBatcher(t *testing.T, sys *System, conductors map[string]*conductor) { ApproxComprRatio: 0.4, SubSafetyMargin: 4, PollInterval: 1 * time.Second, - TxMgrConfig: newTxMgrConfig(sys.EthInstances["l1"].UserRPC().RPC(), sys.Cfg.Secrets.Batcher), + TxMgrConfig: setuputils.NewTxMgrConfig(sys.EthInstances["l1"].UserRPC(), sys.Cfg.Secrets.Batcher), LogConfig: oplog.CLIConfig{ Level: log.LevelDebug, Format: oplog.FormatText, @@ -307,8 +316,8 @@ func setupBatcher(t *testing.T, sys *System, conductors map[string]*conductor) { sys.BatchSubmitter = batcher } -func sequencerFailoverSystemConfig(t *testing.T, ports map[string]int) SystemConfig { - cfg := EcotoneSystemConfig(t, &genesisTime) +func sequencerFailoverSystemConfig(t *testing.T, ports map[string]int) e2esys.SystemConfig { + cfg := e2esys.EcotoneSystemConfig(t, new(hexutil.Uint64)) delete(cfg.Nodes, "sequencer") cfg.Nodes[Sequencer1Name] = sequencerCfg(ports[Sequencer1Name]) cfg.Nodes[Sequencer2Name] = sequencerCfg(ports[Sequencer2Name]) @@ -368,7 +377,7 @@ func waitForLeadership(t *testing.T, c *conductor) error { return wait.For(ctx, 1*time.Second, condition) } -func waitForLeadershipChange(t *testing.T, prev *conductor, prevID string, conductors map[string]*conductor, sys *System) string { +func waitForLeadershipChange(t *testing.T, prev *conductor, prevID string, conductors map[string]*conductor, sys *e2esys.System) string { ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() @@ -482,7 +491,7 @@ func findFollower(t *testing.T, conductors map[string]*conductor) (string, *cond return "", nil } -func ensureOnlyOneLeader(t *testing.T, sys *System, conductors map[string]*conductor) { +func ensureOnlyOneLeader(t *testing.T, sys *e2esys.System, conductors map[string]*conductor) { ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() diff --git a/op-e2e/sequencer_failover_test.go b/op-e2e/system/conductor/sequencer_failover_test.go similarity index 99% rename from op-e2e/sequencer_failover_test.go rename to op-e2e/system/conductor/sequencer_failover_test.go index c153832b9f768..1b49b989654f4 100644 --- a/op-e2e/sequencer_failover_test.go +++ b/op-e2e/system/conductor/sequencer_failover_test.go @@ -1,4 +1,4 @@ -package op_e2e +package conductor import ( "context" diff --git a/op-e2e/system_adminrpc_test.go b/op-e2e/system/conductor/system_adminrpc_test.go similarity index 90% rename from op-e2e/system_adminrpc_test.go rename to op-e2e/system/conductor/system_adminrpc_test.go index aabae9d6047b3..5501ece79fff9 100644 --- a/op-e2e/system_adminrpc_test.go +++ b/op-e2e/system/conductor/system_adminrpc_test.go @@ -1,4 +1,4 @@ -package op_e2e +package conductor import ( "context" @@ -6,6 +6,11 @@ import ( "testing" "time" + op_e2e "github.com/ethereum-optimism/optimism/op-e2e" + + "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/rpc" "github.com/stretchr/testify/require" @@ -18,9 +23,9 @@ import ( ) func TestStopStartSequencer(t *testing.T) { - InitParallel(t) + op_e2e.InitParallel(t) - cfg := DefaultSystemConfig(t) + cfg := e2esys.DefaultSystemConfig(t) sys, err := cfg.Start(t) require.Nil(t, err, "Error starting up system") @@ -74,13 +79,21 @@ func TestStopStartSequencer(t *testing.T) { ) } +func latestBlock(t *testing.T, client *ethclient.Client) uint64 { + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + blockAfter, err := client.BlockNumber(ctx) + require.Nil(t, err, "Error getting latest block") + return blockAfter +} + func TestPersistSequencerStateWhenChanged(t *testing.T) { - InitParallel(t) + op_e2e.InitParallel(t) ctx := context.Background() dir := t.TempDir() stateFile := dir + "/state.json" - cfg := DefaultSystemConfig(t) + cfg := e2esys.DefaultSystemConfig(t) // We don't need a verifier - just the sequencer is enough delete(cfg.Nodes, "verifier") cfg.Nodes["sequencer"].ConfigPersistence = node.NewConfigPersistence(stateFile) @@ -104,7 +117,7 @@ func TestPersistSequencerStateWhenChanged(t *testing.T) { } func TestLoadSequencerStateOnStarted_Stopped(t *testing.T) { - InitParallel(t) + op_e2e.InitParallel(t) ctx := context.Background() dir := t.TempDir() stateFile := dir + "/state.json" @@ -113,7 +126,7 @@ func TestLoadSequencerStateOnStarted_Stopped(t *testing.T) { configReader := node.NewConfigPersistence(stateFile) require.NoError(t, configReader.SequencerStopped()) - cfg := DefaultSystemConfig(t) + cfg := e2esys.DefaultSystemConfig(t) // We don't need a verifier - just the sequencer is enough delete(cfg.Nodes, "verifier") seqCfg := cfg.Nodes["sequencer"] @@ -136,7 +149,7 @@ func TestLoadSequencerStateOnStarted_Stopped(t *testing.T) { } func TestLoadSequencerStateOnStarted_Started(t *testing.T) { - InitParallel(t) + op_e2e.InitParallel(t) ctx := context.Background() dir := t.TempDir() stateFile := dir + "/state.json" @@ -145,7 +158,7 @@ func TestLoadSequencerStateOnStarted_Started(t *testing.T) { configReader := node.NewConfigPersistence(stateFile) require.NoError(t, configReader.SequencerStarted()) - cfg := DefaultSystemConfig(t) + cfg := e2esys.DefaultSystemConfig(t) // We don't need a verifier - just the sequencer is enough delete(cfg.Nodes, "verifier") seqCfg := cfg.Nodes["sequencer"] @@ -169,10 +182,10 @@ func TestLoadSequencerStateOnStarted_Started(t *testing.T) { } func TestPostUnsafePayload(t *testing.T) { - InitParallel(t) + op_e2e.InitParallel(t) ctx := context.Background() - cfg := DefaultSystemConfig(t) + cfg := e2esys.DefaultSystemConfig(t) cfg.Nodes["verifier"].RPC.EnableAdmin = true cfg.DisableBatcher = true diff --git a/op-e2e/artifactsfs_test.go b/op-e2e/system/contracts/artifactsfs_test.go similarity index 87% rename from op-e2e/artifactsfs_test.go rename to op-e2e/system/contracts/artifactsfs_test.go index 98d23be8e1128..a52680a0b2d1d 100644 --- a/op-e2e/artifactsfs_test.go +++ b/op-e2e/system/contracts/artifactsfs_test.go @@ -1,9 +1,11 @@ -package op_e2e +package contracts import ( "errors" "testing" + op_e2e "github.com/ethereum-optimism/optimism/op-e2e" + "github.com/stretchr/testify/require" "github.com/ethereum/go-ethereum/log" @@ -13,9 +15,9 @@ import ( ) func TestArtifacts(t *testing.T) { - InitParallel(t) + op_e2e.InitParallel(t) logger := testlog.Logger(t, log.LevelWarn) // lower this log level to get verbose test dump of all artifacts - af := foundry.OpenArtifactsDir("../packages/contracts-bedrock/forge-artifacts") + af := foundry.OpenArtifactsDir("../../../packages/contracts-bedrock/forge-artifacts") artifacts, err := af.ListArtifacts() require.NoError(t, err) require.NotEmpty(t, artifacts) diff --git a/op-e2e/system/contracts/contracts_test.go b/op-e2e/system/contracts/contracts_test.go new file mode 100644 index 0000000000000..da4a081a90ca3 --- /dev/null +++ b/op-e2e/system/contracts/contracts_test.go @@ -0,0 +1,11 @@ +package contracts + +import ( + "testing" + + op_e2e "github.com/ethereum-optimism/optimism/op-e2e" +) + +func TestMain(m *testing.M) { + op_e2e.RunMain(m) +} diff --git a/op-e2e/brotli_batcher_test.go b/op-e2e/system/da/brotli_batcher_test.go similarity index 87% rename from op-e2e/brotli_batcher_test.go rename to op-e2e/system/da/brotli_batcher_test.go index ee4a223bf3ea5..b44bd5af16237 100644 --- a/op-e2e/brotli_batcher_test.go +++ b/op-e2e/system/da/brotli_batcher_test.go @@ -1,4 +1,4 @@ -package op_e2e +package da import ( "context" @@ -7,6 +7,11 @@ import ( "testing" "time" + op_e2e "github.com/ethereum-optimism/optimism/op-e2e" + + "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" + "github.com/ethereum-optimism/optimism/op-e2e/system/helpers" + "github.com/stretchr/testify/require" batcherFlags "github.com/ethereum-optimism/optimism/op-batcher/flags" @@ -19,7 +24,7 @@ import ( "github.com/ethereum/go-ethereum/log" ) -func setupAliceAccount(t *testing.T, cfg SystemConfig, sys *System, ethPrivKey *ecdsa.PrivateKey) { +func setupAliceAccount(t *testing.T, cfg e2esys.SystemConfig, sys *e2esys.System, ethPrivKey *ecdsa.PrivateKey) { l1Client := sys.NodeClient("l1") l2Verif := sys.NodeClient("verifier") @@ -37,7 +42,7 @@ func setupAliceAccount(t *testing.T, cfg SystemConfig, sys *System, ethPrivKey * require.NoError(t, err) mintAmount := big.NewInt(1_000_000_000_000) opts.Value = mintAmount - SendDepositTx(t, cfg, l1Client, l2Verif, opts, func(l2Opts *DepositTxOpts) {}) + helpers.SendDepositTx(t, cfg, l1Client, l2Verif, opts, func(l2Opts *helpers.DepositTxOpts) {}) // Confirm balance ctx, cancel = context.WithTimeout(context.Background(), 15*time.Second) @@ -50,9 +55,9 @@ func setupAliceAccount(t *testing.T, cfg SystemConfig, sys *System, ethPrivKey * } func TestBrotliBatcherFjord(t *testing.T) { - InitParallel(t) + op_e2e.InitParallel(t) - cfg := DefaultSystemConfig(t) + cfg := e2esys.DefaultSystemConfig(t) cfg.DataAvailabilityType = batcherFlags.BlobsType genesisActivation := hexutil.Uint64(0) @@ -62,7 +67,7 @@ func TestBrotliBatcherFjord(t *testing.T) { cfg.DeployConfig.L2GenesisFjordTimeOffset = &genesisActivation // set up batcher to use brotli - sys, err := cfg.Start(t, SystemConfigOption{"compressionAlgo", "brotli", nil}) + sys, err := cfg.Start(t, e2esys.SystemConfigOption{Key: "compressionAlgo", Role: "brotli", Action: nil}) require.Nil(t, err, "Error starting up system") log := testlog.Logger(t, log.LevelInfo) @@ -76,7 +81,7 @@ func TestBrotliBatcherFjord(t *testing.T) { setupAliceAccount(t, cfg, sys, ethPrivKey) // Submit TX to L2 sequencer node - receipt := SendL2Tx(t, cfg, l2Seq, ethPrivKey, func(opts *TxOpts) { + receipt := helpers.SendL2Tx(t, cfg, l2Seq, ethPrivKey, func(opts *helpers.TxOpts) { opts.Value = big.NewInt(1_000_000_000) opts.Nonce = 1 // Already have deposit opts.ToAddr = &common.Address{0xff, 0xff} diff --git a/op-e2e/system/da/da_test.go b/op-e2e/system/da/da_test.go new file mode 100644 index 0000000000000..ae5606e8df532 --- /dev/null +++ b/op-e2e/system/da/da_test.go @@ -0,0 +1,11 @@ +package da + +import ( + "testing" + + op_e2e "github.com/ethereum-optimism/optimism/op-e2e" +) + +func TestMain(m *testing.M) { + op_e2e.RunMain(m) +} diff --git a/op-e2e/system/da/dencun_test.go b/op-e2e/system/da/dencun_test.go new file mode 100644 index 0000000000000..4bdaee540c008 --- /dev/null +++ b/op-e2e/system/da/dencun_test.go @@ -0,0 +1,53 @@ +package da + +import ( + "context" + "testing" + "time" + + op_e2e "github.com/ethereum-optimism/optimism/op-e2e" + + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/transactions" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" + "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/types" + "github.com/stretchr/testify/require" +) + +// TestSystemE2EDencunAtGenesis tests if L2 finalizes when blobs are present on L1 +func TestSystemE2EDencunAtGenesisWithBlobs(t *testing.T) { + op_e2e.InitParallel(t) + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + cfg := e2esys.DefaultSystemConfig(t) + cfg.DeployConfig.L1CancunTimeOffset = new(hexutil.Uint64) + + sys, err := cfg.Start(t) + require.Nil(t, err, "Error starting up system") + + // send a blob-containing txn on l1 + ethPrivKey := sys.Cfg.Secrets.Alice + txData := transactions.CreateEmptyBlobTx(true, sys.Cfg.L1ChainIDBig().Uint64()) + tx := types.MustSignNewTx(ethPrivKey, types.LatestSignerForChainID(cfg.L1ChainIDBig()), txData) + // send blob-containing txn + sendCtx, sendCancel := context.WithTimeout(context.Background(), 15*time.Second) + defer sendCancel() + + l1Client := sys.NodeClient("l1") + err = l1Client.SendTransaction(sendCtx, tx) + require.NoError(t, err, "Sending L1 empty blob tx") + // Wait for transaction on L1 + 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.NodeClient("sequencer") + finalizedBlock, err := geth.WaitForL1OriginOnL2(sys.RollupConfig, blockContainsBlob.BlockNumber.Uint64(), l2Client, 30*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) + require.Nil(t, err, "Waiting for L1 origin of blob tx on L2") + finalizationTimeout := 30 * time.Duration(cfg.DeployConfig.L1BlockTime) * time.Second + _, err = geth.WaitForBlockToBeSafe(finalizedBlock.Header().Number, l2Client, finalizationTimeout) + require.Nil(t, err, "Waiting for safety of L2 block") +} diff --git a/op-e2e/eip4844_test.go b/op-e2e/system/da/eip4844_test.go similarity index 95% rename from op-e2e/eip4844_test.go rename to op-e2e/system/da/eip4844_test.go index 7069fba72afc3..332da11f9d6f4 100644 --- a/op-e2e/eip4844_test.go +++ b/op-e2e/system/da/eip4844_test.go @@ -1,4 +1,4 @@ -package op_e2e +package da import ( "context" @@ -7,6 +7,11 @@ import ( "testing" "time" + op_e2e "github.com/ethereum-optimism/optimism/op-e2e" + + "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" + "github.com/ethereum-optimism/optimism/op-e2e/system/helpers" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -38,9 +43,9 @@ func TestSystem4844E2E(t *testing.T) { } func testSystem4844E2E(t *testing.T, multiBlob bool, daType batcherFlags.DataAvailabilityType) { - InitParallel(t) + op_e2e.InitParallel(t) - cfg := EcotoneSystemConfig(t, &genesisTime) + cfg := e2esys.EcotoneSystemConfig(t, new(hexutil.Uint64)) cfg.DataAvailabilityType = daType cfg.BatcherBatchType = derive.SpanBatchType cfg.DeployConfig.L1GenesisBlockBaseFeePerGas = (*hexutil.Big)(big.NewInt(7000)) @@ -62,9 +67,9 @@ func testSystem4844E2E(t *testing.T, multiBlob bool, daType batcherFlags.DataAva // is started, as is required by the function. var jamChan chan error jamCtx, jamCancel := context.WithTimeout(context.Background(), 20*time.Second) - action := SystemConfigOption{ - key: "beforeBatcherStart", - action: func(cfg *SystemConfig, s *System) { + action := e2esys.SystemConfigOption{ + Key: "beforeBatcherStart", + Action: func(cfg *e2esys.SystemConfig, s *e2esys.System) { driver := s.BatchSubmitter.TestDriver() err := driver.JamTxPool(jamCtx) require.NoError(t, err) @@ -108,7 +113,7 @@ func testSystem4844E2E(t *testing.T, multiBlob bool, daType batcherFlags.DataAva require.NoError(t, err) mintAmount := big.NewInt(1_000_000_000_000) opts.Value = mintAmount - SendDepositTx(t, cfg, l1Client, l2Verif, opts, func(l2Opts *DepositTxOpts) {}) + helpers.SendDepositTx(t, cfg, l1Client, l2Verif, opts, func(l2Opts *helpers.DepositTxOpts) {}) // Confirm balance ctx2, cancel2 := context.WithTimeout(context.Background(), 20*time.Second) @@ -120,7 +125,7 @@ func testSystem4844E2E(t *testing.T, multiBlob bool, daType batcherFlags.DataAva require.Equal(t, mintAmount, diff, "Did not get expected balance change") // Submit TX to L2 sequencer node - receipt := SendL2Tx(t, cfg, l2Seq, ethPrivKey, func(opts *TxOpts) { + receipt := helpers.SendL2Tx(t, cfg, l2Seq, ethPrivKey, func(opts *helpers.TxOpts) { opts.Value = big.NewInt(1_000_000_000) opts.Nonce = 1 // Already have deposit opts.ToAddr = &common.Address{0xff, 0xff} @@ -237,9 +242,9 @@ func toIndexedBlobHashes(hs ...common.Hash) []eth.IndexedBlobHash { // We then send a couple of expensive Deposit transactions, which drives up the // gas price. The L1 blob gas limit is set to a low value to speed up this process. func TestBatcherAutoDA(t *testing.T) { - InitParallel(t) + op_e2e.InitParallel(t) - cfg := EcotoneSystemConfig(t, &genesisTime) + cfg := e2esys.EcotoneSystemConfig(t, new(hexutil.Uint64)) cfg.DataAvailabilityType = batcherFlags.AutoType // We set the genesis fee values and block gas limit such that calldata txs are initially cheaper, // but then drive up the base fee over the coming L1 blocks such that blobs become cheaper again. diff --git a/op-e2e/l1_beacon_client_test.go b/op-e2e/system/da/l1_beacon_client_test.go similarity index 79% rename from op-e2e/l1_beacon_client_test.go rename to op-e2e/system/da/l1_beacon_client_test.go index 93094d4884e76..68698a5e3187a 100644 --- a/op-e2e/l1_beacon_client_test.go +++ b/op-e2e/system/da/l1_beacon_client_test.go @@ -1,9 +1,12 @@ -package op_e2e +package da import ( "context" "testing" + op_e2e "github.com/ethereum-optimism/optimism/op-e2e" + + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/fakebeacon" "github.com/ethereum-optimism/optimism/op-service/client" "github.com/ethereum-optimism/optimism/op-service/eth" @@ -15,11 +18,12 @@ import ( ) func TestGetVersion(t *testing.T) { - InitParallel(t) + op_e2e.InitParallel(t) l := testlog.Logger(t, log.LevelInfo) - beaconApi := fakebeacon.NewBeacon(l, t.TempDir(), uint64(0), uint64(0)) + blobStore := e2eutils.NewBlobStore() + beaconApi := fakebeacon.NewBeacon(l, blobStore, uint64(0), uint64(0)) t.Cleanup(func() { _ = beaconApi.Close() }) @@ -34,11 +38,12 @@ func TestGetVersion(t *testing.T) { } func Test404NotFound(t *testing.T) { - InitParallel(t) + op_e2e.InitParallel(t) l := testlog.Logger(t, log.LevelInfo) - beaconApi := fakebeacon.NewBeacon(l, t.TempDir(), uint64(0), uint64(12)) + blobStore := e2eutils.NewBlobStore() + beaconApi := fakebeacon.NewBeacon(l, blobStore, uint64(0), uint64(12)) t.Cleanup(func() { _ = beaconApi.Close() }) diff --git a/op-e2e/system/da/multi_test.go b/op-e2e/system/da/multi_test.go new file mode 100644 index 0000000000000..8272930da765b --- /dev/null +++ b/op-e2e/system/da/multi_test.go @@ -0,0 +1,64 @@ +package da + +import ( + "context" + "math/big" + "testing" + "time" + + op_e2e "github.com/ethereum-optimism/optimism/op-e2e" + + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/transactions" + "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" + "github.com/ethereum-optimism/optimism/op-node/rollup/derive" + "github.com/stretchr/testify/require" +) + +func TestBatcherMultiTx(t *testing.T) { + op_e2e.InitParallel(t) + + cfg := e2esys.DefaultSystemConfig(t) + cfg.BatcherMaxPendingTransactions = 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.NoError(t, err, "Error starting up system") + + l1Client := sys.NodeClient("l1") + l2Seq := sys.NodeClient("sequencer") + + _, err = geth.WaitForBlock(big.NewInt(10), l2Seq, time.Duration(cfg.DeployConfig.L2BlockTime*15)*time.Second) + require.NoError(t, err, "Waiting for L2 blocks") + + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + l1Number, err := l1Client.BlockNumber(ctx) + require.NoError(t, err) + + // start batch submission + driver := sys.BatchSubmitter.TestDriver() + err = driver.StartBatchSubmitting() + require.NoError(t, err) + + totalBatcherTxsCount := int64(0) + // wait for up to 5 L1 blocks, usually only 3 is required, but it's + // possible additional L1 blocks will be created before the batcher starts, + // so we wait additional blocks. + for i := int64(0); i < 5; i++ { + block, err := geth.WaitForBlock(big.NewInt(int64(l1Number)+i), l1Client, time.Duration(cfg.DeployConfig.L1BlockTime*2)*time.Second) + require.NoError(t, err, "Waiting for l1 blocks") + // there are possibly other services (proposer/challenger) in the background sending txs + // so we only count the batcher txs + batcherTxCount, err := transactions.TransactionsBySender(block, cfg.DeployConfig.BatchSenderAddress) + require.NoError(t, err) + totalBatcherTxsCount += int64(batcherTxCount) + + if totalBatcherTxsCount >= 10 { + return + } + } + + t.Fatal("Expected at least 10 transactions from the batcher") +} diff --git a/op-e2e/system/da/startstop_test.go b/op-e2e/system/da/startstop_test.go new file mode 100644 index 0000000000000..c15c1c0394389 --- /dev/null +++ b/op-e2e/system/da/startstop_test.go @@ -0,0 +1,131 @@ +package da + +import ( + "context" + "math/big" + "testing" + "time" + + op_e2e "github.com/ethereum-optimism/optimism/op-e2e" + + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" + "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" + "github.com/ethereum-optimism/optimism/op-e2e/system/helpers" + "github.com/ethereum-optimism/optimism/op-node/rollup/derive" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/stretchr/testify/require" +) + +// TestSystemBatchType run each system e2e test case in singular batch mode and span batch mode. +// If the test case tests batch submission and advancing safe head, it should be tested in both singular and span batch mode. +func TestSystemBatchType(t *testing.T) { + tests := []struct { + name string + f func(*testing.T, func(*e2esys.SystemConfig)) + }{ + {"StopStartBatcher", StopStartBatcher}, + } + for _, test := range tests { + test := test + t.Run(test.name+"_SingularBatch", func(t *testing.T) { + test.f(t, func(sc *e2esys.SystemConfig) { + sc.BatcherBatchType = derive.SingularBatchType + }) + }) + t.Run(test.name+"_SpanBatch", func(t *testing.T) { + test.f(t, func(sc *e2esys.SystemConfig) { + sc.BatcherBatchType = derive.SpanBatchType + }) + }) + t.Run(test.name+"_SpanBatchMaxBlocks", func(t *testing.T) { + test.f(t, func(sc *e2esys.SystemConfig) { + sc.BatcherBatchType = derive.SpanBatchType + sc.BatcherMaxBlocksPerSpanBatch = 2 + }) + }) + } +} + +func StopStartBatcher(t *testing.T, cfgMod func(*e2esys.SystemConfig)) { + op_e2e.InitParallel(t) + + cfg := e2esys.DefaultSystemConfig(t) + cfgMod(&cfg) + sys, err := cfg.Start(t) + require.NoError(t, err, "Error starting up system") + + rollupClient := sys.RollupClient("verifier") + + l2Seq := sys.NodeClient("sequencer") + l2Verif := sys.NodeClient("verifier") + + // retrieve the initial sync status + seqStatus, err := rollupClient.SyncStatus(context.Background()) + require.NoError(t, err) + + nonce := uint64(0) + sendTx := func() *types.Receipt { + // Submit TX to L2 sequencer node + receipt := helpers.SendL2Tx(t, cfg, l2Seq, cfg.Secrets.Alice, func(opts *helpers.TxOpts) { + opts.ToAddr = &common.Address{0xff, 0xff} + opts.Value = big.NewInt(1_000_000_000) + opts.Nonce = nonce + }) + nonce++ + return receipt + } + // send a transaction + receipt := sendTx() + + // 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.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.NoError(t, err) + require.Greater(t, newSeqStatus.SafeL2.Number, seqStatus.SafeL2.Number, "Safe chain did not advance") + + driver := sys.BatchSubmitter.TestDriver() + // stop the batch submission + err = driver.StopBatchSubmitting(context.Background()) + 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.NoError(t, err) + + // send another tx + sendTx() + time.Sleep(safeBlockInclusionDuration) + + // ensure that the safe chain does not advance while the batcher is stopped + newSeqStatus, err = rollupClient.SyncStatus(context.Background()) + 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 = driver.StartBatchSubmitting() + require.NoError(t, err) + time.Sleep(safeBlockInclusionDuration) + + // send a third tx + receipt = sendTx() + + // 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.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.NoError(t, err) + require.Greater(t, newSeqStatus.SafeL2.Number, seqStatus.SafeL2.Number, "Safe chain did not advance after batcher was restarted") +} diff --git a/op-e2e/external.go b/op-e2e/system/e2esys/external.go similarity index 99% rename from op-e2e/external.go rename to op-e2e/system/e2esys/external.go index 7b83aef4ff661..cfdc4fcb88cc7 100644 --- a/op-e2e/external.go +++ b/op-e2e/system/e2esys/external.go @@ -1,4 +1,4 @@ -package op_e2e +package e2esys import ( "encoding/json" diff --git a/op-e2e/setup.go b/op-e2e/system/e2esys/setup.go similarity index 87% rename from op-e2e/setup.go rename to op-e2e/system/e2esys/setup.go index c0168b7d207d8..bc4364de9ad4b 100644 --- a/op-e2e/setup.go +++ b/op-e2e/system/e2esys/setup.go @@ -1,4 +1,4 @@ -package op_e2e +package e2esys import ( "context" @@ -33,12 +33,14 @@ import ( "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/eth/ethconfig" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rpc" + altda "github.com/ethereum-optimism/optimism/op-alt-da" bss "github.com/ethereum-optimism/optimism/op-batcher/batcher" batcherFlags "github.com/ethereum-optimism/optimism/op-batcher/flags" "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" @@ -49,6 +51,7 @@ import ( "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/opnode" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/services" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/setuputils" "github.com/ethereum-optimism/optimism/op-node/chaincfg" rollupNode "github.com/ethereum-optimism/optimism/op-node/node" "github.com/ethereum-optimism/optimism/op-node/p2p" @@ -67,7 +70,6 @@ import ( "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum-optimism/optimism/op-service/sources" "github.com/ethereum-optimism/optimism/op-service/testlog" - "github.com/ethereum-optimism/optimism/op-service/txmgr" ) const ( @@ -81,20 +83,6 @@ var ( genesisTime = hexutil.Uint64(0) ) -func newTxMgrConfig(l1Addr string, privKey *ecdsa.PrivateKey) txmgr.CLIConfig { - return txmgr.CLIConfig{ - L1RPCURL: l1Addr, - PrivateKey: hexPriv(privKey), - NumConfirmations: 1, - SafeAbortNonceTooLowCount: 3, - FeeLimitMultiplier: 5, - ResubmissionTimeout: 3 * time.Second, - ReceiptQueryInterval: 50 * time.Millisecond, - NetworkTimeout: 2 * time.Second, - TxNotInMempoolTimeout: 2 * time.Minute, - } -} - func DefaultSystemConfig(t testing.TB) SystemConfig { config.ExternalL2TestParms.SkipIfNecessary(t) @@ -164,18 +152,19 @@ func DefaultSystemConfig(t testing.TB) SystemConfig { }, }, Loggers: map[string]log.Logger{ - RoleVerif: testlog.Logger(t, log.LevelInfo).New("role", RoleVerif), - RoleSeq: testlog.Logger(t, log.LevelInfo).New("role", RoleSeq), - "batcher": testlog.Logger(t, log.LevelInfo).New("role", "batcher"), - "proposer": testlog.Logger(t, log.LevelInfo).New("role", "proposer"), + RoleVerif: testlog.Logger(t, log.LevelInfo).New("role", RoleVerif), + RoleSeq: testlog.Logger(t, log.LevelInfo).New("role", RoleSeq), + "batcher": testlog.Logger(t, log.LevelInfo).New("role", "batcher"), + "proposer": testlog.Logger(t, log.LevelInfo).New("role", "proposer"), + "da-server": testlog.Logger(t, log.LevelInfo).New("role", "da-server"), }, - GethOptions: map[string][]geth.GethOption{}, - P2PTopology: nil, // no P2P connectivity by default - NonFinalizedProposals: false, - ExternalL2Shim: config.ExternalL2Shim, - DataAvailabilityType: batcherFlags.CalldataType, - MaxPendingTransactions: 1, - BatcherTargetNumFrames: 1, + GethOptions: map[string][]geth.GethOption{}, + P2PTopology: nil, // no P2P connectivity by default + NonFinalizedProposals: false, + ExternalL2Shim: config.ExternalL2Shim, + DataAvailabilityType: batcherFlags.CalldataType, + BatcherMaxPendingTransactions: 1, + BatcherTargetNumFrames: 1, } } @@ -278,6 +267,9 @@ type SystemConfig struct { // Explicitly disable batcher, for tests that rely on unsafe L2 payloads DisableBatcher bool + // Explicitly disable setting `RollupSequencerHTTP` to forward txs from sentry nodes + DisableTxForwarder bool + // Configure data-availability type that is used by the batcher. DataAvailabilityType batcherFlags.DataAvailabilityType @@ -298,12 +290,16 @@ type SystemConfig struct { // If >0, limits the number of blocks per span batch BatcherMaxBlocksPerSpanBatch int + // BatcherMaxPendingTransactions determines how many transactions the batcher will try to send + // concurrently. 0 means unlimited. + BatcherMaxPendingTransactions uint64 + + // BatcherMaxConcurrentDARequest determines how many DAserver requests the batcher is allowed to + // make concurrently. 0 means unlimited. + BatcherMaxConcurrentDARequest uint64 + // 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 System struct { @@ -319,6 +315,7 @@ type System struct { L2OutputSubmitter *l2os.ProposerService BatchSubmitter *bss.BatcherService Mocknet mocknet.Mocknet + FakeAltDAServer *altda.FakeDAServer L1BeaconAPIAddr endpoint.RestHTTP @@ -415,7 +412,7 @@ func (sys *System) Close() { } for name, node := range sys.RollupNodes { - if err := node.Stop(postCtx); err != nil && !errors.Is(err, rollupNode.ErrAlreadyClosed) { + if err := node.Stop(postCtx); err != nil && !errors.Is(err, rollupNode.ErrAlreadyClosed) && !errors.Is(err, postCtx.Err()) { combinedErr = errors.Join(combinedErr, fmt.Errorf("stop rollup node %v: %w", name, err)) } } @@ -438,25 +435,25 @@ func (sys *System) Close() { require.NoError(sys.t, combinedErr, "Failed to stop system") } -type systemConfigHook func(sCfg *SystemConfig, s *System) +type SystemConfigHook func(sCfg *SystemConfig, s *System) type SystemConfigOption struct { - key string - role string - action systemConfigHook + Key string + Role string + Action SystemConfigHook } type SystemConfigOptions struct { - opts map[string]systemConfigHook + opts map[string]SystemConfigHook } func NewSystemConfigOptions(_opts []SystemConfigOption) (SystemConfigOptions, error) { - opts := make(map[string]systemConfigHook) + opts := make(map[string]SystemConfigHook) for _, opt := range _opts { - if _, ok := opts[opt.key+":"+opt.role]; ok { - return SystemConfigOptions{}, fmt.Errorf("duplicate option for key %s and role %s", opt.key, opt.role) + if _, ok := opts[opt.Key+":"+opt.Role]; ok { + return SystemConfigOptions{}, fmt.Errorf("duplicate option for key %s and role %s", opt.Key, opt.Role) } - opts[opt.key+":"+opt.role] = opt.action + opts[opt.Key+":"+opt.Role] = opt.Action } return SystemConfigOptions{ @@ -464,7 +461,7 @@ func NewSystemConfigOptions(_opts []SystemConfigOption) (SystemConfigOptions, er }, nil } -func (s *SystemConfigOptions) Get(key, role string) (systemConfigHook, bool) { +func (s *SystemConfigOptions) Get(key, role string) (SystemConfigHook, bool) { v, ok := s.opts[key+":"+role] return v, ok } @@ -522,7 +519,7 @@ func (cfg SystemConfig) Start(t *testing.T, _opts ...SystemConfigOption) (*Syste t.Log("Generating L2 genesis", "l2_allocs_mode", string(allocsMode)) l2Allocs := config.L2Allocs(allocsMode) - l2Genesis, err := genesis.BuildL2Genesis(cfg.DeployConfig, l2Allocs, l1Block) + l2Genesis, err := genesis.BuildL2Genesis(cfg.DeployConfig, l2Allocs, l1Block.Header()) if err != nil { return nil, err } @@ -543,6 +540,16 @@ func (cfg SystemConfig) Start(t *testing.T, _opts ...SystemConfigOption) (*Syste } } + var rollupAltDAConfig *rollup.AltDAConfig + if cfg.DeployConfig.UseAltDA { + rollupAltDAConfig = &rollup.AltDAConfig{ + DAChallengeAddress: cfg.L1Deployments.DataAvailabilityChallengeProxy, + DAChallengeWindow: cfg.DeployConfig.DAChallengeWindow, + DAResolveWindow: cfg.DeployConfig.DAResolveWindow, + CommitmentType: altda.GenericCommitmentString, + } + } + makeRollupConfig := func() rollup.Config { return rollup.Config{ Genesis: rollup.Genesis{ @@ -574,6 +581,7 @@ func (cfg SystemConfig) Start(t *testing.T, _opts ...SystemConfigOption) (*Syste GraniteTime: cfg.DeployConfig.GraniteTime(uint64(cfg.DeployConfig.L1GenesisBlockTimestamp)), InteropTime: cfg.DeployConfig.InteropTime(uint64(cfg.DeployConfig.L1GenesisBlockTimestamp)), ProtocolVersionsAddress: cfg.L1Deployments.ProtocolVersionsProxy, + AltDAConfig: rollupAltDAConfig, } } defaultConfig := makeRollupConfig() @@ -584,7 +592,7 @@ func (cfg SystemConfig) Start(t *testing.T, _opts ...SystemConfigOption) (*Syste // 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.LevelInfo).New("role", "l1_cl"), - path.Join(cfg.BlobsPath, "l1_cl"), l1Genesis.Timestamp, cfg.DeployConfig.L1BlockTime) + e2eutils.NewBlobStore(), l1Genesis.Timestamp, cfg.DeployConfig.L1BlockTime) t.Cleanup(func() { _ = bcn.Close() }) @@ -606,25 +614,44 @@ func (cfg SystemConfig) Start(t *testing.T, _opts ...SystemConfigOption) (*Syste return nil, err } + // Ordered such that the Sequencer is initialized first. Setup this way so that + // the `RollupSequencerHTTP` GethOption can be supplied to any sentry nodes. + l2Nodes := []string{RoleSeq} for name := range cfg.Nodes { - if name == RoleL1 { - return nil, fmt.Errorf("node name %s is reserved for L1 node", RoleL1) + if name == RoleSeq { + continue } + l2Nodes = append(l2Nodes, name) + } + + for _, name := range l2Nodes { var ethClient services.EthInstance if cfg.ExternalL2Shim == "" { + if name != RoleSeq && !cfg.DisableTxForwarder { + cfg.GethOptions[name] = append(cfg.GethOptions[name], func(ethCfg *ethconfig.Config, nodeCfg *node.Config) error { + ethCfg.RollupSequencerHTTP = sys.EthInstances[RoleSeq].UserRPC().RPC() + return nil + }) + } + l2Geth, err := geth.InitL2(name, l2Genesis, cfg.JWTFilePath, cfg.GethOptions[name]...) if err != nil { return nil, err } - err = l2Geth.Node.Start() - if err != nil { + if err := l2Geth.Node.Start(); err != nil { return nil, err } + ethClient = l2Geth } else { if len(cfg.GethOptions[name]) > 0 { t.Skip("External L2 nodes do not support configuration through GethOptions") } + + if name != RoleSeq && !cfg.DisableTxForwarder { + cfg.Loggers[name].Warn("External L2 nodes do not support `RollupSequencerHTTP` configuration. No tx forwarding support.") + } + ethClient = (&ExternalRunner{ Name: name, BinPath: cfg.ExternalL2Shim, @@ -632,6 +659,7 @@ func (cfg SystemConfig) Start(t *testing.T, _opts ...SystemConfigOption) (*Syste JWTPath: cfg.JWTFilePath, }).Run(t) } + sys.EthInstances[name] = ethClient } @@ -639,8 +667,8 @@ func (cfg SystemConfig) Start(t *testing.T, _opts ...SystemConfigOption) (*Syste // TODO: refactor testing to allow use of in-process rpc connections instead // of only websockets (which are required for external eth client tests). for name, nodeCfg := range cfg.Nodes { - configureL1(nodeCfg, sys.EthInstances[RoleL1], sys.L1BeaconEndpoint()) - configureL2(nodeCfg, sys.EthInstances[name], cfg.JWTSecret) + ConfigureL1(nodeCfg, sys.EthInstances[RoleL1], sys.L1BeaconEndpoint()) + ConfigureL2(nodeCfg, sys.EthInstances[name], cfg.JWTSecret) } l1Client := sys.NodeClient(RoleL1) @@ -658,7 +686,7 @@ func (cfg SystemConfig) Start(t *testing.T, _opts ...SystemConfigOption) (*Syste if p, ok := p2pNodes[name]; ok { return p, nil } - h, err := sys.newMockNetPeer() + h, err := sys.NewMockNetPeer() if err != nil { return nil, fmt.Errorf("failed to init p2p host for node %s", name) } @@ -771,7 +799,7 @@ func (cfg SystemConfig) Start(t *testing.T, _opts ...SystemConfigOption) (*Syste ProposalInterval: 6 * time.Second, DisputeGameType: 254, // Fast game type PollInterval: 500 * time.Millisecond, - TxMgrConfig: newTxMgrConfig(sys.EthInstances[RoleL1].UserRPC().RPC(), cfg.Secrets.Proposer), + TxMgrConfig: setuputils.NewTxMgrConfig(sys.EthInstances[RoleL1].UserRPC(), cfg.Secrets.Proposer), AllowNonFinalized: cfg.NonFinalizedProposals, LogConfig: oplog.CLIConfig{ Level: log.LvlInfo, @@ -784,7 +812,7 @@ func (cfg SystemConfig) Start(t *testing.T, _opts ...SystemConfigOption) (*Syste RollupRpc: sys.RollupNodes[RoleSeq].UserRPC().RPC(), L2OOAddress: config.L1Deployments.L2OutputOracleProxy.Hex(), PollInterval: 500 * time.Millisecond, - TxMgrConfig: newTxMgrConfig(sys.EthInstances[RoleL1].UserRPC().RPC(), cfg.Secrets.Proposer), + TxMgrConfig: setuputils.NewTxMgrConfig(sys.EthInstances[RoleL1].UserRPC(), cfg.Secrets.Proposer), AllowNonFinalized: cfg.NonFinalizedProposals, LogConfig: oplog.CLIConfig{ Level: log.LvlInfo, @@ -819,11 +847,27 @@ func (cfg SystemConfig) Start(t *testing.T, _opts ...SystemConfigOption) (*Syste compressionAlgo = derive.Brotli10 } + var batcherAltDACLIConfig altda.CLIConfig + if cfg.DeployConfig.UseAltDA { + fakeAltDAServer := altda.NewFakeDAServer("127.0.0.1", 0, sys.Cfg.Loggers["da-server"]) + if err := fakeAltDAServer.Start(); err != nil { + return nil, fmt.Errorf("failed to start fake altDA server: %w", err) + } + sys.FakeAltDAServer = fakeAltDAServer + + batcherAltDACLIConfig = altda.CLIConfig{ + Enabled: cfg.DeployConfig.UseAltDA, + DAServerURL: fakeAltDAServer.HttpEndpoint(), + VerifyOnRead: true, + GenericDA: true, + MaxConcurrentRequests: cfg.BatcherMaxConcurrentDARequest, + } + } batcherCLIConfig := &bss.CLIConfig{ L1EthRpc: sys.EthInstances[RoleL1].UserRPC().RPC(), L2EthRpc: sys.EthInstances[RoleSeq].UserRPC().RPC(), RollupRpc: sys.RollupNodes[RoleSeq].UserRPC().RPC(), - MaxPendingTransactions: cfg.MaxPendingTransactions, + MaxPendingTransactions: cfg.BatcherMaxPendingTransactions, MaxChannelDuration: 1, MaxL1TxSize: batcherMaxL1TxSizeBytes, TestUseMaxTxSizeForBlobs: cfg.BatcherUseMaxTxSizeForBlobs, @@ -831,7 +875,7 @@ func (cfg SystemConfig) Start(t *testing.T, _opts ...SystemConfigOption) (*Syste ApproxComprRatio: 0.4, SubSafetyMargin: 4, PollInterval: 50 * time.Millisecond, - TxMgrConfig: newTxMgrConfig(sys.EthInstances[RoleL1].UserRPC().RPC(), cfg.Secrets.Batcher), + TxMgrConfig: setuputils.NewTxMgrConfig(sys.EthInstances[RoleL1].UserRPC(), cfg.Secrets.Batcher), LogConfig: oplog.CLIConfig{ Level: log.LevelInfo, Format: oplog.FormatText, @@ -841,6 +885,7 @@ func (cfg SystemConfig) Start(t *testing.T, _opts ...SystemConfigOption) (*Syste MaxBlocksPerSpanBatch: cfg.BatcherMaxBlocksPerSpanBatch, DataAvailabilityType: sys.Cfg.DataAvailabilityType, CompressionAlgo: compressionAlgo, + AltDA: batcherAltDACLIConfig, } // Batch Submitter batcher, err := bss.BatcherServiceFromCLIConfig(context.Background(), "0.0.1", batcherCLIConfig, sys.Cfg.Loggers["batcher"]) @@ -862,7 +907,7 @@ func (cfg SystemConfig) Start(t *testing.T, _opts ...SystemConfigOption) (*Syste var blackholeIP6 = net.ParseIP("100::") // mocknet doesn't allow us to add a peerstore without fully creating the peer ourselves -func (sys *System) newMockNetPeer() (host.Host, error) { +func (sys *System) NewMockNetPeer() (host.Host, error) { sk, _, err := ic.GenerateECDSAKeyPair(rand.Reader) if err != nil { return nil, err @@ -919,7 +964,7 @@ func (sys *System) TestAccount(idx int) *ecdsa.PrivateKey { } } -func configureL1(rollupNodeCfg *rollupNode.Config, l1Node services.EthInstance, beaconEndpoint endpoint.RestHTTP) { +func ConfigureL1(rollupNodeCfg *rollupNode.Config, l1Node services.EthInstance, beaconEndpoint endpoint.RestHTTP) { rollupNodeCfg.L1 = &rollupNode.L1EndpointConfig{ L1NodeAddr: endpoint.SelectRPC(EnvRPCPreference(), l1Node.UserRPC()), L1TrustRPC: false, @@ -934,7 +979,7 @@ func configureL1(rollupNodeCfg *rollupNode.Config, l1Node services.EthInstance, } } -func configureL2(rollupNodeCfg *rollupNode.Config, l2Node services.EthInstance, jwtSecret [32]byte) { +func ConfigureL2(rollupNodeCfg *rollupNode.Config, l2Node services.EthInstance, jwtSecret [32]byte) { rollupNodeCfg.L2 = &rollupNode.L2EndpointConfig{ L2EngineAddr: endpoint.SelectRPC(EnvRPCPreference(), l2Node.AuthRPC()), L2EngineJWTSecret: jwtSecret, @@ -949,11 +994,6 @@ func (cfg SystemConfig) L2ChainIDBig() *big.Int { return new(big.Int).SetUint64(cfg.DeployConfig.L2ChainID) } -func hexPriv(in *ecdsa.PrivateKey) string { - b := e2eutils.EncodePrivKey(in) - return hexutil.Encode(b) -} - func (sys *System) RollupClient(name string) *sources.RollupClient { rollupClient, ok := sys.rollupClients[name] if ok { diff --git a/op-e2e/system/fees/fees_test.go b/op-e2e/system/fees/fees_test.go new file mode 100644 index 0000000000000..61590313cbc4f --- /dev/null +++ b/op-e2e/system/fees/fees_test.go @@ -0,0 +1,266 @@ +package fees + +import ( + "context" + "math/big" + "testing" + "time" + + op_e2e "github.com/ethereum-optimism/optimism/op-e2e" + + "github.com/ethereum-optimism/optimism/op-e2e/bindings" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" + "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" + "github.com/ethereum-optimism/optimism/op-e2e/system/helpers" + "github.com/ethereum-optimism/optimism/op-service/predeploys" + "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/crypto" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/rpc" + "github.com/stretchr/testify/require" +) + +func TestMain(m *testing.M) { + op_e2e.RunMain(m) +} + +type stateGetterAdapter struct { + ctx context.Context + t *testing.T + client *ethclient.Client + blockNum *big.Int +} + +func (sga *stateGetterAdapter) GetState(addr common.Address, key common.Hash) common.Hash { + sga.t.Helper() + val, err := sga.client.StorageAt(sga.ctx, addr, key, sga.blockNum) + require.NoError(sga.t, err) + var res common.Hash + copy(res[:], val) + return res +} + +// TestFees checks that L1/L2 fees are handled. +func TestFees(t *testing.T) { + t.Run("pre-regolith", func(t *testing.T) { + op_e2e.InitParallel(t) + cfg := e2esys.RegolithSystemConfig(t, nil) + cfg.DeployConfig.L1GenesisBlockBaseFeePerGas = (*hexutil.Big)(big.NewInt(7)) + + testFees(t, cfg) + }) + t.Run("regolith", func(t *testing.T) { + op_e2e.InitParallel(t) + cfg := e2esys.RegolithSystemConfig(t, new(hexutil.Uint64)) + cfg.DeployConfig.L1GenesisBlockBaseFeePerGas = (*hexutil.Big)(big.NewInt(7)) + + testFees(t, cfg) + }) + t.Run("ecotone", func(t *testing.T) { + op_e2e.InitParallel(t) + cfg := e2esys.EcotoneSystemConfig(t, new(hexutil.Uint64)) + cfg.DeployConfig.L1GenesisBlockBaseFeePerGas = (*hexutil.Big)(big.NewInt(7)) + + testFees(t, cfg) + }) + t.Run("fjord", func(t *testing.T) { + op_e2e.InitParallel(t) + cfg := e2esys.DefaultSystemConfig(t) + cfg.DeployConfig.L1GenesisBlockBaseFeePerGas = (*hexutil.Big)(big.NewInt(7)) + + cfg.DeployConfig.L2GenesisRegolithTimeOffset = new(hexutil.Uint64) + cfg.DeployConfig.L2GenesisCanyonTimeOffset = new(hexutil.Uint64) + cfg.DeployConfig.L2GenesisDeltaTimeOffset = new(hexutil.Uint64) + cfg.DeployConfig.L2GenesisEcotoneTimeOffset = new(hexutil.Uint64) + cfg.DeployConfig.L2GenesisFjordTimeOffset = new(hexutil.Uint64) + testFees(t, cfg) + }) +} + +func testFees(t *testing.T, cfg e2esys.SystemConfig) { + sys, err := cfg.Start(t) + require.Nil(t, err, "Error starting up system") + + l2Seq := sys.NodeClient("sequencer") + l2Verif := sys.NodeClient("verifier") + l1 := sys.NodeClient("l1") + + // Wait for first block after genesis. The genesis block has zero L1Block values and will throw off the GPO checks + _, err = geth.WaitForBlock(big.NewInt(1), l2Verif, time.Minute) + require.NoError(t, err) + + config := sys.L2Genesis().Config + + sga := &stateGetterAdapter{ + ctx: context.Background(), + t: t, + client: l2Seq, + } + + l1CostFn := types.NewL1CostFunc(config, sga) + + // Transactor Account + ethPrivKey := cfg.Secrets.Alice + fromAddr := crypto.PubkeyToAddress(ethPrivKey.PublicKey) + + require.NotEqual(t, cfg.DeployConfig.L2OutputOracleProposer, fromAddr) + require.NotEqual(t, cfg.DeployConfig.BatchSenderAddress, fromAddr) + + // Find gaspriceoracle contract + gpoContract, err := bindings.NewGasPriceOracle(predeploys.GasPriceOracleAddr, l2Seq) + require.Nil(t, err) + + if !sys.RollupConfig.IsEcotone(sys.L2GenesisCfg.Timestamp) { + overhead, err := gpoContract.Overhead(&bind.CallOpts{}) + require.Nil(t, err, "reading gpo overhead") + require.Equal(t, overhead.Uint64(), cfg.DeployConfig.GasPriceOracleOverhead, "wrong gpo overhead") + + scalar, err := gpoContract.Scalar(&bind.CallOpts{}) + require.Nil(t, err, "reading gpo scalar") + feeScalar := cfg.DeployConfig.FeeScalar() + require.Equal(t, scalar, new(big.Int).SetBytes(feeScalar[:]), "wrong gpo scalar") + } else { + _, err := gpoContract.Overhead(&bind.CallOpts{}) + require.ErrorContains(t, err, "deprecated") + _, err = gpoContract.Scalar(&bind.CallOpts{}) + require.ErrorContains(t, err, "deprecated") + } + + decimals, err := gpoContract.Decimals(&bind.CallOpts{}) + require.Nil(t, err, "reading gpo decimals") + + require.Equal(t, decimals.Uint64(), uint64(6), "wrong gpo decimals") + + // BaseFee Recipient + baseFeeRecipientStartBalance, err := l2Seq.BalanceAt(context.Background(), predeploys.BaseFeeVaultAddr, big.NewInt(rpc.EarliestBlockNumber.Int64())) + require.Nil(t, err) + + // L1Fee Recipient + l1FeeRecipientStartBalance, err := l2Seq.BalanceAt(context.Background(), predeploys.L1FeeVaultAddr, big.NewInt(rpc.EarliestBlockNumber.Int64())) + require.Nil(t, err) + + sequencerFeeVaultStartBalance, err := l2Seq.BalanceAt(context.Background(), predeploys.SequencerFeeVaultAddr, big.NewInt(rpc.EarliestBlockNumber.Int64())) + require.Nil(t, err) + + genesisBlock, err := l2Seq.BlockByNumber(context.Background(), big.NewInt(rpc.EarliestBlockNumber.Int64())) + require.NoError(t, err) + + coinbaseStartBalance, err := l2Seq.BalanceAt(context.Background(), genesisBlock.Coinbase(), big.NewInt(rpc.EarliestBlockNumber.Int64())) + require.NoError(t, err) + + // Simple transfer from signer to random account + startBalance, err := l2Seq.BalanceAt(context.Background(), fromAddr, big.NewInt(rpc.EarliestBlockNumber.Int64())) + require.Nil(t, err) + require.Greater(t, startBalance.Uint64(), big.NewInt(params.Ether).Uint64()) + + transferAmount := big.NewInt(params.Ether) + gasTip := big.NewInt(10) + receipt := helpers.SendL2Tx(t, cfg, l2Seq, ethPrivKey, func(opts *helpers.TxOpts) { + opts.ToAddr = &common.Address{0xff, 0xff} + opts.Value = transferAmount + opts.GasTipCap = gasTip + opts.Gas = 21000 + opts.GasFeeCap = big.NewInt(200) + opts.VerifyOnClients(l2Verif) + }) + + require.Equal(t, receipt.Status, types.ReceiptStatusSuccessful) + + header, err := l2Seq.HeaderByNumber(context.Background(), receipt.BlockNumber) + require.Nil(t, err) + + coinbaseEndBalance, err := l2Seq.BalanceAt(context.Background(), header.Coinbase, header.Number) + require.Nil(t, err) + + endBalance, err := l2Seq.BalanceAt(context.Background(), fromAddr, header.Number) + require.Nil(t, err) + + baseFeeRecipientEndBalance, err := l2Seq.BalanceAt(context.Background(), predeploys.BaseFeeVaultAddr, header.Number) + require.Nil(t, err) + + l1Header, err := l1.HeaderByNumber(context.Background(), nil) + require.Nil(t, err) + + l1FeeRecipientEndBalance, err := l2Seq.BalanceAt(context.Background(), predeploys.L1FeeVaultAddr, header.Number) + require.Nil(t, err) + + sequencerFeeVaultEndBalance, err := l2Seq.BalanceAt(context.Background(), predeploys.SequencerFeeVaultAddr, header.Number) + require.Nil(t, err) + + // Diff fee recipient + coinbase balances + baseFeeRecipientDiff := new(big.Int).Sub(baseFeeRecipientEndBalance, baseFeeRecipientStartBalance) + l1FeeRecipientDiff := new(big.Int).Sub(l1FeeRecipientEndBalance, l1FeeRecipientStartBalance) + sequencerFeeVaultDiff := new(big.Int).Sub(sequencerFeeVaultEndBalance, sequencerFeeVaultStartBalance) + coinbaseDiff := new(big.Int).Sub(coinbaseEndBalance, coinbaseStartBalance) + + // Tally L2 Fee + l2Fee := gasTip.Mul(gasTip, new(big.Int).SetUint64(receipt.GasUsed)) + require.Equal(t, sequencerFeeVaultDiff, coinbaseDiff, "coinbase is always sequencer fee vault") + require.Equal(t, l2Fee, coinbaseDiff, "l2 fee mismatch") + require.Equal(t, l2Fee, sequencerFeeVaultDiff) + + // Tally BaseFee + baseFee := new(big.Int).Mul(header.BaseFee, new(big.Int).SetUint64(receipt.GasUsed)) + require.Equal(t, baseFee, baseFeeRecipientDiff, "base fee mismatch") + + // Tally L1 Fee + tx, _, err := l2Seq.TransactionByHash(context.Background(), receipt.TxHash) + require.NoError(t, err, "Should be able to get transaction") + bytes, err := tx.MarshalBinary() + require.Nil(t, err) + + l1Fee := l1CostFn(tx.RollupCostData(), header.Time) + require.Equalf(t, l1Fee, l1FeeRecipientDiff, "L1 fee mismatch: start balance %v, end balance %v", l1FeeRecipientStartBalance, l1FeeRecipientEndBalance) + + gpoEcotone, err := gpoContract.IsEcotone(nil) + require.NoError(t, err) + require.Equal(t, sys.RollupConfig.IsEcotone(header.Time), gpoEcotone, "GPO and chain must have same ecotone view") + + gpoFjord, err := gpoContract.IsFjord(nil) + require.NoError(t, err) + require.Equal(t, sys.RollupConfig.IsFjord(header.Time), gpoFjord, "GPO and chain must have same fjord view") + + gpoL1Fee, err := gpoContract.GetL1Fee(&bind.CallOpts{}, bytes) + require.Nil(t, err) + + adjustedGPOFee := gpoL1Fee + if sys.RollupConfig.IsFjord(header.Time) { + // The fastlz size of the transaction is 102 bytes + require.Equal(t, uint64(102), tx.RollupCostData().FastLzSize) + // Which results in both the fjord cost function and GPO using the minimum value for the fastlz regression: + // Geth Linear Regression: -42.5856 + 102 * 0.8365 = 42.7374 + // GPO Linear Regression: -42.5856 + 170 * 0.8365 = 99.6194 + // The additional 68 (170 vs. 102) is due to the GPO adding 68 bytes to account for the signature. + require.Greater(t, types.MinTransactionSize.Uint64(), uint64(99)) + // Because of this, we don't need to do any adjustment as the GPO and cost func are both bounded to the minimum value. + // However, if the fastlz regression output is ever larger than the minimum, this will require an adjustment. + } else if sys.RollupConfig.IsRegolith(header.Time) { + // if post-regolith, adjust the GPO fee by removing the overhead it adds because of signature data + artificialGPOOverhead := big.NewInt(68 * 16) // it adds 68 bytes to cover signature and RLP data + l1BaseFee := big.NewInt(7) // we assume the L1 basefee is the minimum, 7 + // in our case we already include that, so we subtract it, to do a 1:1 comparison + adjustedGPOFee = new(big.Int).Sub(gpoL1Fee, new(big.Int).Mul(artificialGPOOverhead, l1BaseFee)) + } + require.Equal(t, l1Fee, adjustedGPOFee, "GPO reports L1 fee mismatch") + + require.Equal(t, receipt.L1Fee, l1Fee, "l1 fee in receipt is correct") + if !sys.RollupConfig.IsEcotone(header.Time) { // FeeScalar receipt attribute is removed as of Ecotone + require.Equal(t, + new(big.Float).Mul( + new(big.Float).SetInt(l1Header.BaseFee), + new(big.Float).Mul(new(big.Float).SetInt(receipt.L1GasUsed), receipt.FeeScalar), + ), + new(big.Float).SetInt(receipt.L1Fee), "fee field in receipt matches gas used times scalar times base fee") + } + + // Calculate total fee + baseFeeRecipientDiff.Add(baseFeeRecipientDiff, coinbaseDiff) + totalFee := new(big.Int).Add(baseFeeRecipientDiff, l1FeeRecipientDiff) + balanceDiff := new(big.Int).Sub(startBalance, endBalance) + balanceDiff.Sub(balanceDiff, transferAmount) + require.Equal(t, balanceDiff, totalFee, "balances should add up") +} diff --git a/op-e2e/system/fees/gaspriceoracle_test.go b/op-e2e/system/fees/gaspriceoracle_test.go new file mode 100644 index 0000000000000..58a679fa86f09 --- /dev/null +++ b/op-e2e/system/fees/gaspriceoracle_test.go @@ -0,0 +1,102 @@ +package fees + +import ( + "context" + "math" + "testing" + "time" + + op_e2e "github.com/ethereum-optimism/optimism/op-e2e" + + legacybindings "github.com/ethereum-optimism/optimism/op-e2e/bindings" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" + "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" + "github.com/ethereum-optimism/optimism/op-service/eth" + "github.com/ethereum-optimism/optimism/op-service/predeploys" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/stretchr/testify/require" +) + +// TestGasPriceOracleFeeUpdates checks that the gas price oracle cannot be locked by mis-configuring parameters. +func TestGasPriceOracleFeeUpdates(t *testing.T) { + op_e2e.InitParallel(t) + + ctx, ctxCancel := context.WithCancel(context.Background()) + defer ctxCancel() + + maxScalars := eth.EcotoneScalars{ + BaseFeeScalar: math.MaxUint32, + BlobBaseFeeScalar: math.MaxUint32, + } + var cancel context.CancelFunc + + // Create our system configuration for L1/L2 and start it + cfg := e2esys.DefaultSystemConfig(t) + sys, err := cfg.Start(t) + require.NoError(t, err, "Error starting up system") + + // Obtain our sequencer, verifier, and transactor keypair. + l1Client := sys.NodeClient("l1") + l2Seq := sys.NodeClient("sequencer") + // l2Verif := sys.NodeClient("verifier") + ethPrivKey := cfg.Secrets.SysCfgOwner + + // Bind to the SystemConfig & GasPriceOracle contracts + sysconfig, err := legacybindings.NewSystemConfig(cfg.L1Deployments.SystemConfigProxy, l1Client) + require.NoError(t, err) + gpoContract, err := legacybindings.NewGasPriceOracleCaller(predeploys.GasPriceOracleAddr, l2Seq) + require.NoError(t, err) + + // Obtain our signer. + opts, err := bind.NewKeyedTransactorWithChainID(ethPrivKey, cfg.L1ChainIDBig()) + require.NoError(t, err) + + // Define our L1 transaction timeout duration. + 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(ctx, txTimeoutDuration) + tx, err := sysconfig.SetGasConfigEcotone(opts, maxScalars.BaseFeeScalar, maxScalars.BlobBaseFeeScalar) + cancel() + require.NoError(t, err, "SetGasConfigEcotone update tx") + + receipt, err := wait.ForReceiptOK(ctx, l1Client, tx.Hash()) + require.NoError(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") + + baseFeeScalar, err := gpoContract.BaseFeeScalar(&bind.CallOpts{}) + require.NoError(t, err, "reading base fee scalar") + require.Equal(t, baseFeeScalar, maxScalars.BaseFeeScalar) + + blobBaseFeeScalar, err := gpoContract.BlobBaseFeeScalar(&bind.CallOpts{}) + require.NoError(t, err, "reading blob base fee scalar") + require.Equal(t, blobBaseFeeScalar, maxScalars.BlobBaseFeeScalar) + + // Now modify the scalar value & ensure that the gas params can be modified + normalScalars := eth.EcotoneScalars{ + BaseFeeScalar: 1e6, + BlobBaseFeeScalar: 1e6, + } + + opts.Context, cancel = context.WithTimeout(context.Background(), txTimeoutDuration) + tx, err = sysconfig.SetGasConfigEcotone(opts, normalScalars.BaseFeeScalar, normalScalars.BlobBaseFeeScalar) + cancel() + require.NoError(t, err, "SetGasConfigEcotone update tx") + + receipt, err = wait.ForReceiptOK(ctx, l1Client, tx.Hash()) + require.NoError(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") + + baseFeeScalar, err = gpoContract.BaseFeeScalar(&bind.CallOpts{}) + require.NoError(t, err, "reading base fee scalar") + require.Equal(t, baseFeeScalar, normalScalars.BaseFeeScalar) + + blobBaseFeeScalar, err = gpoContract.BlobBaseFeeScalar(&bind.CallOpts{}) + require.NoError(t, err, "reading blob base fee scalar") + require.Equal(t, blobBaseFeeScalar, normalScalars.BlobBaseFeeScalar) +} diff --git a/op-e2e/system/fees/l1info_test.go b/op-e2e/system/fees/l1info_test.go new file mode 100644 index 0000000000000..2fdd3f70747a0 --- /dev/null +++ b/op-e2e/system/fees/l1info_test.go @@ -0,0 +1,205 @@ +package fees + +import ( + "context" + "fmt" + "math/big" + "testing" + "time" + + op_e2e "github.com/ethereum-optimism/optimism/op-e2e" + + "github.com/ethereum-optimism/optimism/op-e2e/bindings" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" + "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" + "github.com/ethereum-optimism/optimism/op-node/rollup/derive" + "github.com/ethereum-optimism/optimism/op-service/eth" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/consensus/misc/eip4844" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/stretchr/testify/require" +) + +func L1InfoFromState(ctx context.Context, contract *bindings.L1Block, l2Number *big.Int, ecotone bool) (*derive.L1BlockInfo, error) { + var err error + out := &derive.L1BlockInfo{} + opts := bind.CallOpts{ + BlockNumber: l2Number, + Context: ctx, + } + + out.Number, err = contract.Number(&opts) + if err != nil { + return nil, fmt.Errorf("failed to get number: %w", err) + } + + out.Time, err = contract.Timestamp(&opts) + if err != nil { + return nil, fmt.Errorf("failed to get timestamp: %w", err) + } + + out.BaseFee, err = contract.Basefee(&opts) + if err != nil { + return nil, fmt.Errorf("failed to get base fee: %w", err) + } + + blockHashBytes, err := contract.Hash(&opts) + if err != nil { + return nil, fmt.Errorf("failed to get block hash: %w", err) + } + out.BlockHash = common.BytesToHash(blockHashBytes[:]) + + out.SequenceNumber, err = contract.SequenceNumber(&opts) + if err != nil { + return nil, fmt.Errorf("failed to get sequence number: %w", err) + } + + if !ecotone { + overhead, err := contract.L1FeeOverhead(&opts) + if err != nil { + return nil, fmt.Errorf("failed to get l1 fee overhead: %w", err) + } + out.L1FeeOverhead = eth.Bytes32(common.BigToHash(overhead)) + + scalar, err := contract.L1FeeScalar(&opts) + if err != nil { + return nil, fmt.Errorf("failed to get l1 fee scalar: %w", err) + } + out.L1FeeScalar = eth.Bytes32(common.BigToHash(scalar)) + } + + batcherHash, err := contract.BatcherHash(&opts) + if err != nil { + return nil, fmt.Errorf("failed to get batch sender: %w", err) + } + out.BatcherAddr = common.BytesToAddress(batcherHash[:]) + + if ecotone { + blobBaseFeeScalar, err := contract.BlobBaseFeeScalar(&opts) + if err != nil { + return nil, fmt.Errorf("failed to get blob basefee scalar: %w", err) + } + out.BlobBaseFeeScalar = blobBaseFeeScalar + + baseFeeScalar, err := contract.BaseFeeScalar(&opts) + if err != nil { + return nil, fmt.Errorf("failed to get basefee scalar: %w", err) + } + out.BaseFeeScalar = baseFeeScalar + + blobBaseFee, err := contract.BlobBaseFee(&opts) + if err != nil { + return nil, fmt.Errorf("failed to get blob basefee: %w", err) + } + out.BlobBaseFee = blobBaseFee + } + + return out, nil +} + +func TestL1InfoContract(t *testing.T) { + op_e2e.InitParallel(t) + + cfg := e2esys.DefaultSystemConfig(t) + + sys, err := cfg.Start(t) + require.Nil(t, err, "Error starting up system") + + l1Client := sys.NodeClient("l1") + l2Seq := sys.NodeClient("sequencer") + l2Verif := sys.NodeClient("verifier") + + endVerifBlockNumber := big.NewInt(4) + endSeqBlockNumber := big.NewInt(6) + endVerifBlock, err := geth.WaitForBlock(endVerifBlockNumber, l2Verif, time.Minute) + require.Nil(t, err) + endSeqBlock, err := geth.WaitForBlock(endSeqBlockNumber, l2Seq, time.Minute) + require.Nil(t, err) + + seqL1Info, err := bindings.NewL1Block(cfg.L1InfoPredeployAddress, l2Seq) + require.Nil(t, err) + + verifL1Info, err := bindings.NewL1Block(cfg.L1InfoPredeployAddress, l2Verif) + require.Nil(t, err) + + ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) + defer cancel() + + fillInfoLists := func(start *types.Block, contract *bindings.L1Block, client *ethclient.Client) ([]*derive.L1BlockInfo, []*derive.L1BlockInfo) { + var txList, stateList []*derive.L1BlockInfo + for b := start; ; { + var infoFromTx *derive.L1BlockInfo + infoFromTx, err := derive.L1BlockInfoFromBytes(sys.RollupConfig, b.Time(), b.Transactions()[0].Data()) + require.NoError(t, err) + txList = append(txList, infoFromTx) + + ecotone := sys.RollupConfig.IsEcotone(b.Time()) && !sys.RollupConfig.IsEcotoneActivationBlock(b.Time()) + infoFromState, err := L1InfoFromState(ctx, contract, b.Number(), ecotone) + require.Nil(t, err) + stateList = append(stateList, infoFromState) + + // Genesis L2 block contains no L1 Deposit TX + if b.NumberU64() == 1 { + return txList, stateList + } + b, err = client.BlockByHash(ctx, b.ParentHash()) + require.Nil(t, err) + } + } + + l1InfosFromSequencerTransactions, l1InfosFromSequencerState := fillInfoLists(endSeqBlock, seqL1Info, l2Seq) + l1InfosFromVerifierTransactions, l1InfosFromVerifierState := fillInfoLists(endVerifBlock, verifL1Info, l2Verif) + + l1blocks := make(map[common.Hash]*derive.L1BlockInfo) + maxL1Hash := l1InfosFromSequencerTransactions[0].BlockHash + for h := maxL1Hash; ; { + b, err := l1Client.BlockByHash(ctx, h) + require.Nil(t, err) + + l1blocks[h] = &derive.L1BlockInfo{ + Number: b.NumberU64(), + Time: b.Time(), + BaseFee: b.BaseFee(), + BlockHash: h, + SequenceNumber: 0, // ignored, will be overwritten + BatcherAddr: sys.RollupConfig.Genesis.SystemConfig.BatcherAddr, + } + if sys.RollupConfig.IsEcotone(b.Time()) && !sys.RollupConfig.IsEcotoneActivationBlock(b.Time()) { + scalars, err := sys.RollupConfig.Genesis.SystemConfig.EcotoneScalars() + require.NoError(t, err) + l1blocks[h].BlobBaseFeeScalar = scalars.BlobBaseFeeScalar + l1blocks[h].BaseFeeScalar = scalars.BaseFeeScalar + if excess := b.ExcessBlobGas(); excess != nil { + l1blocks[h].BlobBaseFee = eip4844.CalcBlobFee(*excess) + } else { + l1blocks[h].BlobBaseFee = big.NewInt(1) + } + } else { + l1blocks[h].L1FeeOverhead = sys.RollupConfig.Genesis.SystemConfig.Overhead + l1blocks[h].L1FeeScalar = sys.RollupConfig.Genesis.SystemConfig.Scalar + } + + h = b.ParentHash() + if b.NumberU64() == 0 { + break + } + } + + checkInfoList := func(name string, list []*derive.L1BlockInfo) { + for _, info := range list { + if expected, ok := l1blocks[info.BlockHash]; ok { + expected.SequenceNumber = info.SequenceNumber // the seq nr is not part of the L1 info we know in advance, so we ignore it. + require.Equal(t, expected, info) + } else { + t.Fatalf("Did not find block hash for L1 Info: %v in test %s", info, name) + } + } + } + + checkInfoList("On sequencer with tx", l1InfosFromSequencerTransactions) + checkInfoList("On sequencer with state", l1InfosFromSequencerState) + checkInfoList("On verifier with tx", l1InfosFromVerifierTransactions) + checkInfoList("On verifier with state", l1InfosFromVerifierState) +} diff --git a/op-e2e/check_scripts_test.go b/op-e2e/system/fjord/check_scripts_test.go similarity index 92% rename from op-e2e/check_scripts_test.go rename to op-e2e/system/fjord/check_scripts_test.go index 151d11fa0197a..b6115dbd7e0b8 100644 --- a/op-e2e/check_scripts_test.go +++ b/op-e2e/system/fjord/check_scripts_test.go @@ -1,9 +1,13 @@ -package op_e2e +package fjord import ( "context" "testing" + op_e2e "github.com/ethereum-optimism/optimism/op-e2e" + + "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/log" @@ -16,7 +20,7 @@ import ( // TestCheckFjordScript ensures the op-chain-ops/cmd/check-fjord script runs successfully // against a test chain with the fjord hardfork activated/unactivated func TestCheckFjordScript(t *testing.T) { - InitParallel(t) + op_e2e.InitParallel(t) genesisActivation := hexutil.Uint64(0) tests := []struct { name string @@ -37,11 +41,11 @@ func TestCheckFjordScript(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - InitParallel(t) + op_e2e.InitParallel(t) log := testlog.Logger(t, log.LevelInfo) - cfg := DefaultSystemConfig(t) + cfg := e2esys.DefaultSystemConfig(t) cfg.DeployConfig.L1CancunTimeOffset = &genesisActivation cfg.DeployConfig.L2GenesisRegolithTimeOffset = &genesisActivation cfg.DeployConfig.L2GenesisCanyonTimeOffset = &genesisActivation diff --git a/op-e2e/system/fjord/fjord_test.go b/op-e2e/system/fjord/fjord_test.go new file mode 100644 index 0000000000000..09e2ca47ddd58 --- /dev/null +++ b/op-e2e/system/fjord/fjord_test.go @@ -0,0 +1,11 @@ +package fjord + +import ( + "testing" + + op_e2e "github.com/ethereum-optimism/optimism/op-e2e" +) + +func TestMain(m *testing.M) { + op_e2e.RunMain(m) +} diff --git a/op-e2e/custom_gas_token_test.go b/op-e2e/system/gastoken/gastoken_test.go similarity index 96% rename from op-e2e/custom_gas_token_test.go rename to op-e2e/system/gastoken/gastoken_test.go index 454e73439aec2..445f672743cfd 100644 --- a/op-e2e/custom_gas_token_test.go +++ b/op-e2e/system/gastoken/gastoken_test.go @@ -1,4 +1,4 @@ -package op_e2e +package gastoken import ( "context" @@ -7,6 +7,11 @@ import ( "testing" "time" + op_e2e "github.com/ethereum-optimism/optimism/op-e2e" + + "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" + "github.com/ethereum-optimism/optimism/op-e2e/system/helpers" + "github.com/ethereum-optimism/optimism/op-e2e/bindings" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/receipts" @@ -22,10 +27,14 @@ import ( "github.com/stretchr/testify/require" ) +func TestMain(m *testing.M) { + op_e2e.RunMain(m) +} + func TestCustomGasToken(t *testing.T) { - InitParallel(t, SkipOnFaultProofs) // Custom Gas Token feature is not yet compatible with fault proofs + op_e2e.InitParallel(t, op_e2e.SkipOnFaultProofs) // Custom Gas Token feature is not yet compatible with fault proofs - cfg := DefaultSystemConfig(t) + cfg := e2esys.DefaultSystemConfig(t) offset := hexutil.Uint64(0) cfg.DeployConfig.L2GenesisRegolithTimeOffset = &offset cfg.DeployConfig.L1CancunTimeOffset = &offset @@ -143,7 +152,7 @@ func TestCustomGasToken(t *testing.T) { require.NoError(t, err) withdrawAmount := big.NewInt(5) - tx, receipt := SendWithdrawal(t, cfg, l2Seq, cfg.Secrets.Alice, func(opts *WithdrawalTxOpts) { + tx, receipt := helpers.SendWithdrawal(t, cfg, l2Seq, cfg.Secrets.Alice, func(opts *helpers.WithdrawalTxOpts) { opts.Value = withdrawAmount opts.VerifyOnClients(l2Verif) }) @@ -157,7 +166,7 @@ func TestCustomGasToken(t *testing.T) { // Take fee into account diff := new(big.Int).Sub(startBalanceBeforeWithdrawal, endBalanceAfterWithdrawal) - fees := calcGasFees(receipt.GasUsed, tx.GasTipCap(), tx.GasFeeCap(), header.BaseFee) + fees := helpers.CalcGasFees(receipt.GasUsed, tx.GasTipCap(), tx.GasFeeCap(), header.BaseFee) fees = fees.Add(fees, receipt.L1Fee) diff = diff.Sub(diff, fees) require.Equal(t, withdrawAmount, diff) @@ -169,7 +178,7 @@ func TestCustomGasToken(t *testing.T) { startETHBalanceBeforeFinalize, err := l1Client.BalanceAt(context.Background(), fromAddr, nil) require.NoError(t, err) - proveReceipt, finalizeReceipt, resolveClaimReceipt, resolveReceipt := ProveAndFinalizeWithdrawal(t, cfg, sys, "verifier", ethPrivKey, receipt) + proveReceipt, finalizeReceipt, resolveClaimReceipt, resolveReceipt := helpers.ProveAndFinalizeWithdrawal(t, cfg, sys, "verifier", ethPrivKey, receipt) // Verify L1 ETH balance change proveFee := new(big.Int).Mul(new(big.Int).SetUint64(proveReceipt.GasUsed), proveReceipt.EffectiveGasPrice) @@ -318,7 +327,7 @@ func TestCustomGasToken(t *testing.T) { withdrawnAmount := it.Event.Value // Finalize the withdrawal - proveReceipt, finalizeReceipt, resolveClaimReceipt, resolveReceipt := ProveAndFinalizeWithdrawal(t, cfg, sys, "verifier", cfg.Secrets.Alice, receipt) + proveReceipt, finalizeReceipt, resolveClaimReceipt, resolveReceipt := helpers.ProveAndFinalizeWithdrawal(t, cfg, sys, "verifier", cfg.Secrets.Alice, receipt) require.Equal(t, types.ReceiptStatusSuccessful, proveReceipt.Status) require.Equal(t, types.ReceiptStatusSuccessful, finalizeReceipt.Status) if e2eutils.UseFaultProofs() { @@ -462,7 +471,7 @@ func callViaSafe(opts *bind.TransactOpts, client *ethclient.Client, safeAddress // setCustomGasToeken enables the Custom Gas Token feature on a chain where it wasn't enabled at genesis. // It reads existing parameters from the SystemConfig contract, inserts the supplied cgtAddress and reinitializes that contract. // To do this it uses the ProxyAdmin and StorageSetter from the supplied cfg. -func setCustomGasToken(t *testing.T, cfg SystemConfig, sys *System, cgtAddress common.Address) { +func setCustomGasToken(t *testing.T, cfg e2esys.SystemConfig, sys *e2esys.System, cgtAddress common.Address) { l1Client := sys.NodeClient("l1") deployerOpts, err := bind.NewKeyedTransactorWithChainID(cfg.Secrets.Deployer, cfg.L1ChainIDBig()) require.NoError(t, err) diff --git a/op-e2e/tx_helper.go b/op-e2e/system/helpers/tx_helper.go similarity index 87% rename from op-e2e/tx_helper.go rename to op-e2e/system/helpers/tx_helper.go index 2a398728689cd..f5cb11aa8a1d2 100644 --- a/op-e2e/tx_helper.go +++ b/op-e2e/system/helpers/tx_helper.go @@ -1,4 +1,4 @@ -package op_e2e +package helpers import ( "context" @@ -7,6 +7,8 @@ import ( "testing" "time" + "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" "github.com/ethereum-optimism/optimism/op-e2e/bindings" @@ -24,7 +26,7 @@ import ( // The L2 transaction options can be configured by modifying the DepositTxOps value supplied to applyL2Opts // Will verify that the transaction is included with the expected status on L1 and L2 // Returns the receipt of the L2 transaction -func SendDepositTx(t *testing.T, cfg SystemConfig, l1Client *ethclient.Client, l2Client *ethclient.Client, l1Opts *bind.TransactOpts, applyL2Opts DepositTxOptsFn) *types.Receipt { +func SendDepositTx(t *testing.T, cfg e2esys.SystemConfig, l1Client *ethclient.Client, l2Client *ethclient.Client, l1Opts *bind.TransactOpts, applyL2Opts DepositTxOptsFn) *types.Receipt { l2Opts := defaultDepositTxOpts(l1Opts) applyL2Opts(l2Opts) @@ -84,11 +86,11 @@ func defaultDepositTxOpts(opts *bind.TransactOpts) *DepositTxOpts { // The supplied privKey is used to specify the account to send from and the transaction is sent to the supplied l2Client // Transaction options and expected status can be configured in the applyTxOpts function by modifying the supplied TxOpts // Will verify that the transaction is included with the expected status on l2Client and any clients added to TxOpts.VerifyClients -func SendL2Tx(t *testing.T, cfg SystemConfig, l2Client *ethclient.Client, privKey *ecdsa.PrivateKey, applyTxOpts TxOptsFn) *types.Receipt { +func SendL2TxWithID(t *testing.T, chainID *big.Int, l2Client *ethclient.Client, privKey *ecdsa.PrivateKey, applyTxOpts TxOptsFn) *types.Receipt { opts := defaultTxOpts() applyTxOpts(opts) - tx := types.MustSignNewTx(privKey, types.LatestSignerForChainID(cfg.L2ChainIDBig()), &types.DynamicFeeTx{ - ChainID: cfg.L2ChainIDBig(), + tx := types.MustSignNewTx(privKey, types.LatestSignerForChainID(chainID), &types.DynamicFeeTx{ + ChainID: chainID, Nonce: opts.Nonce, // Already have deposit To: opts.ToAddr, Value: opts.Value, @@ -115,6 +117,10 @@ func SendL2Tx(t *testing.T, cfg SystemConfig, l2Client *ethclient.Client, privKe return receipt } +func SendL2Tx(t *testing.T, cfg e2esys.SystemConfig, l2Client *ethclient.Client, privKey *ecdsa.PrivateKey, applyTxOpts TxOptsFn) *types.Receipt { + return SendL2TxWithID(t, cfg.L2ChainIDBig(), l2Client, privKey, applyTxOpts) +} + type TxOptsFn func(opts *TxOpts) type TxOpts struct { @@ -148,9 +154,9 @@ func defaultTxOpts() *TxOpts { } } -// calcGasFees determines the actual cost of the transaction given a specific base fee +// CalcGasFees determines the actual cost of the transaction given a specific base fee // This does not include the L1 data fee charged from L2 transactions. -func calcGasFees(gasUsed uint64, gasTipCap *big.Int, gasFeeCap *big.Int, baseFee *big.Int) *big.Int { +func CalcGasFees(gasUsed uint64, gasTipCap *big.Int, gasFeeCap *big.Int, baseFee *big.Int) *big.Int { x := new(big.Int).Add(gasTipCap, baseFee) // If tip + basefee > gas fee cap, clamp it to the gas fee cap if x.Cmp(gasFeeCap) > 0 { diff --git a/op-e2e/withdrawal_helper.go b/op-e2e/system/helpers/withdrawal_helper.go similarity index 91% rename from op-e2e/withdrawal_helper.go rename to op-e2e/system/helpers/withdrawal_helper.go index e2d1c5a03fa9b..b7d11a63060c6 100644 --- a/op-e2e/withdrawal_helper.go +++ b/op-e2e/system/helpers/withdrawal_helper.go @@ -1,4 +1,4 @@ -package op_e2e +package helpers import ( "context" @@ -8,6 +8,8 @@ import ( "testing" "time" + "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" + "github.com/ethereum-optimism/optimism/op-chain-ops/crossdomain" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts/metrics" @@ -37,7 +39,7 @@ type ClientProvider interface { NodeClient(name string) *ethclient.Client } -func SendWithdrawal(t *testing.T, cfg SystemConfig, l2Client *ethclient.Client, privKey *ecdsa.PrivateKey, applyOpts WithdrawalTxOptsFn) (*types.Transaction, *types.Receipt) { +func SendWithdrawal(t *testing.T, cfg e2esys.SystemConfig, l2Client *ethclient.Client, privKey *ecdsa.PrivateKey, applyOpts WithdrawalTxOptsFn) (*types.Transaction, *types.Receipt) { opts := defaultWithdrawalTxOpts() applyOpts(opts) @@ -94,18 +96,18 @@ func defaultWithdrawalTxOpts() *WithdrawalTxOpts { } } -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) { +func ProveAndFinalizeWithdrawal(t *testing.T, cfg e2esys.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, 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) { +func ProveWithdrawal(t *testing.T, cfg e2esys.SystemConfig, clients ClientProvider, l2NodeName string, ethPrivKey *ecdsa.PrivateKey, l2WithdrawalReceipt *types.Receipt) (withdrawals.ProvenWithdrawalParameters, *types.Receipt) { // Get l2BlockNumber for proof generation ctx, cancel := context.WithTimeout(context.Background(), 40*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) defer cancel() - l1Client := clients.NodeClient(RoleL1) + l1Client := clients.NodeClient(e2esys.RoleL1) var blockNumber uint64 var err error if e2eutils.UseFaultProofs() { @@ -176,7 +178,7 @@ func ProveWithdrawalParameters(ctx context.Context, proofCl withdrawals.ProofCli } } -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) { +func FinalizeWithdrawal(t *testing.T, cfg e2esys.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() diff --git a/op-e2e/system/p2p/gossip_test.go b/op-e2e/system/p2p/gossip_test.go new file mode 100644 index 0000000000000..6958bdffcf4f3 --- /dev/null +++ b/op-e2e/system/p2p/gossip_test.go @@ -0,0 +1,203 @@ +package p2p + +import ( + "context" + "math/big" + "slices" + "testing" + "time" + + op_e2e "github.com/ethereum-optimism/optimism/op-e2e" + + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/opnode" + "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" + "github.com/ethereum-optimism/optimism/op-e2e/system/helpers" + rollupNode "github.com/ethereum-optimism/optimism/op-node/node" + "github.com/ethereum-optimism/optimism/op-node/p2p" + "github.com/ethereum-optimism/optimism/op-node/rollup/driver" + "github.com/ethereum-optimism/optimism/op-service/eth" + "github.com/ethereum-optimism/optimism/op-service/retry" + "github.com/ethereum-optimism/optimism/op-service/testlog" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/log" + "github.com/libp2p/go-libp2p/core/peer" + "github.com/stretchr/testify/require" +) + +// TestSystemMockP2P sets up a L1 Geth node, a rollup node, and a L2 geth node and then confirms that +// the nodes can sync L2 blocks before they are confirmed on L1. +func TestSystemMockP2P(t *testing.T) { + op_e2e.InitParallel(t) + + cfg := e2esys.DefaultSystemConfig(t) + // Disable batcher, so we don't sync from L1 & set a large sequence window so we only have unsafe blocks + cfg.DisableBatcher = true + cfg.DeployConfig.SequencerWindowSize = 100_000 + cfg.DeployConfig.MaxSequencerDrift = 100_000 + // disable at the start, so we don't miss any gossiped blocks. + cfg.Nodes["sequencer"].Driver.SequencerStopped = true + + // connect the nodes + cfg.P2PTopology = map[string][]string{ + "verifier": {"sequencer"}, + } + + var published, received []common.Hash + seqTracer, verifTracer := new(opnode.FnTracer), new(opnode.FnTracer) + seqTracer.OnPublishL2PayloadFn = func(ctx context.Context, payload *eth.ExecutionPayloadEnvelope) { + published = append(published, payload.ExecutionPayload.BlockHash) + } + verifTracer.OnUnsafeL2PayloadFn = func(ctx context.Context, from peer.ID, payload *eth.ExecutionPayloadEnvelope) { + received = append(received, payload.ExecutionPayload.BlockHash) + } + cfg.Nodes["sequencer"].Tracer = seqTracer + cfg.Nodes["verifier"].Tracer = verifTracer + + sys, err := cfg.Start(t) + require.Nil(t, err, "Error starting up system") + + // Enable the sequencer now that everyone is ready to receive payloads. + rollupClient := sys.RollupClient("sequencer") + + verifierPeerID := sys.RollupNodes["verifier"].P2P().Host().ID() + check := func() bool { + sequencerBlocksTopicPeers := sys.RollupNodes["sequencer"].P2P().GossipOut().AllBlockTopicsPeers() + return slices.Contains[[]peer.ID](sequencerBlocksTopicPeers, verifierPeerID) + } + + // poll to see if the verifier node is connected & meshed on gossip. + // Without this verifier, we shouldn't start sending blocks around, or we'll miss them and fail the test. + backOffStrategy := retry.Exponential() + for i := 0; i < 10; i++ { + if check() { + break + } + time.Sleep(backOffStrategy.Duration(i)) + } + require.True(t, check(), "verifier must be meshed with sequencer for gossip test to proceed") + + require.NoError(t, rollupClient.StartSequencer(context.Background(), sys.L2GenesisCfg.ToBlock().Hash())) + + l2Seq := sys.NodeClient("sequencer") + l2Verif := sys.NodeClient("verifier") + + // Transactor Account + ethPrivKey := cfg.Secrets.Alice + + // Submit TX to L2 sequencer node + receiptSeq := helpers.SendL2Tx(t, cfg, l2Seq, ethPrivKey, func(opts *helpers.TxOpts) { + opts.ToAddr = &common.Address{0xff, 0xff} + opts.Value = big.NewInt(1_000_000_000) + + // Wait until the block it was first included in shows up in the safe chain on the verifier + opts.VerifyOnClients(l2Verif) + }) + + // Verify that everything that was received was published + require.GreaterOrEqual(t, len(published), len(received)) + require.Subset(t, published, received) + + // Verify that the tx was received via p2p + require.Contains(t, received, receiptSeq.BlockHash) +} + +// TestSystemDenseTopology sets up a dense p2p topology with 3 verifier nodes and 1 sequencer node. +func TestSystemDenseTopology(t *testing.T) { + t.Skip("Skipping dense topology test to avoid flakiness. @refcell address in p2p scoring pr.") + + op_e2e.InitParallel(t) + + cfg := e2esys.DefaultSystemConfig(t) + // slow down L1 blocks so we can see the L2 blocks arrive well before the L1 blocks do. + // Keep the seq window small so the L2 chain is started quick + cfg.DeployConfig.L1BlockTime = 10 + + // Append additional nodes to the system to construct a dense p2p network + cfg.Nodes["verifier2"] = &rollupNode.Config{ + Driver: driver.Config{ + VerifierConfDepth: 0, + SequencerConfDepth: 0, + SequencerEnabled: false, + }, + L1EpochPollInterval: time.Second * 4, + } + cfg.Nodes["verifier3"] = &rollupNode.Config{ + Driver: driver.Config{ + VerifierConfDepth: 0, + SequencerConfDepth: 0, + SequencerEnabled: false, + }, + L1EpochPollInterval: time.Second * 4, + } + 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{ + "verifier": {"sequencer", "verifier2", "verifier3"}, + "verifier2": {"sequencer", "verifier", "verifier3"}, + "verifier3": {"sequencer", "verifier", "verifier2"}, + } + + // Set peer scoring for each node, but without banning + for _, node := range cfg.Nodes { + params, err := p2p.GetScoringParams("light", &node.Rollup) + require.NoError(t, err) + node.P2P = &p2p.Config{ + ScoringParams: params, + BanningEnabled: false, + } + } + + var published, received1, received2, received3 []common.Hash + seqTracer, verifTracer, verifTracer2, verifTracer3 := new(opnode.FnTracer), new(opnode.FnTracer), new(opnode.FnTracer), new(opnode.FnTracer) + seqTracer.OnPublishL2PayloadFn = func(ctx context.Context, payload *eth.ExecutionPayloadEnvelope) { + published = append(published, payload.ExecutionPayload.BlockHash) + } + verifTracer.OnUnsafeL2PayloadFn = func(ctx context.Context, from peer.ID, payload *eth.ExecutionPayloadEnvelope) { + received1 = append(received1, payload.ExecutionPayload.BlockHash) + } + verifTracer2.OnUnsafeL2PayloadFn = func(ctx context.Context, from peer.ID, payload *eth.ExecutionPayloadEnvelope) { + received2 = append(received2, payload.ExecutionPayload.BlockHash) + } + verifTracer3.OnUnsafeL2PayloadFn = func(ctx context.Context, from peer.ID, payload *eth.ExecutionPayloadEnvelope) { + received3 = append(received3, payload.ExecutionPayload.BlockHash) + } + cfg.Nodes["sequencer"].Tracer = seqTracer + cfg.Nodes["verifier"].Tracer = verifTracer + cfg.Nodes["verifier2"].Tracer = verifTracer2 + cfg.Nodes["verifier3"].Tracer = verifTracer3 + + sys, err := cfg.Start(t) + require.Nil(t, err, "Error starting up system") + + l2Seq := sys.NodeClient("sequencer") + l2Verif := sys.NodeClient("verifier") + l2Verif2 := sys.NodeClient("verifier2") + l2Verif3 := sys.NodeClient("verifier3") + + // Transactor Account + ethPrivKey := cfg.Secrets.Alice + + // Submit TX to L2 sequencer node + receiptSeq := helpers.SendL2Tx(t, cfg, l2Seq, ethPrivKey, func(opts *helpers.TxOpts) { + opts.ToAddr = &common.Address{0xff, 0xff} + opts.Value = big.NewInt(1_000_000_000) + + // Wait until the block it was first included in shows up in the safe chain on the verifiers + opts.VerifyOnClients(l2Verif, l2Verif2, l2Verif3) + }) + + // Verify that everything that was received was published + require.GreaterOrEqual(t, len(published), len(received1)) + require.GreaterOrEqual(t, len(published), len(received2)) + require.GreaterOrEqual(t, len(published), len(received3)) + require.ElementsMatch(t, published, received1[:len(published)]) + require.ElementsMatch(t, published, received2[:len(published)]) + require.ElementsMatch(t, published, received3[:len(published)]) + + // Verify that the tx was received via p2p + require.Contains(t, received1, receiptSeq.BlockHash) + require.Contains(t, received2, receiptSeq.BlockHash) + require.Contains(t, received3, receiptSeq.BlockHash) +} diff --git a/op-e2e/system/p2p/p2p_test.go b/op-e2e/system/p2p/p2p_test.go new file mode 100644 index 0000000000000..e7aa7b0b9b736 --- /dev/null +++ b/op-e2e/system/p2p/p2p_test.go @@ -0,0 +1,11 @@ +package p2p + +import ( + "testing" + + op_e2e "github.com/ethereum-optimism/optimism/op-e2e" +) + +func TestMain(m *testing.M) { + op_e2e.RunMain(m) +} diff --git a/op-e2e/system/p2p/reqresp_test.go b/op-e2e/system/p2p/reqresp_test.go new file mode 100644 index 0000000000000..d3245d8fd257c --- /dev/null +++ b/op-e2e/system/p2p/reqresp_test.go @@ -0,0 +1,168 @@ +package p2p + +import ( + "context" + "math/big" + "testing" + "time" + + op_e2e "github.com/ethereum-optimism/optimism/op-e2e" + + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/opnode" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" + "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" + "github.com/ethereum-optimism/optimism/op-e2e/system/helpers" + "github.com/ethereum-optimism/optimism/op-node/metrics" + rollupNode "github.com/ethereum-optimism/optimism/op-node/node" + "github.com/ethereum-optimism/optimism/op-node/p2p" + "github.com/ethereum-optimism/optimism/op-node/rollup/driver" + "github.com/ethereum-optimism/optimism/op-service/endpoint" + "github.com/ethereum-optimism/optimism/op-service/eth" + "github.com/ethereum-optimism/optimism/op-service/oppprof" + "github.com/ethereum-optimism/optimism/op-service/testlog" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/log" + "github.com/libp2p/go-libp2p/core/peer" + "github.com/stretchr/testify/require" +) + +func TestSystemP2PAltSync(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + op_e2e.InitParallel(t) + + cfg := e2esys.DefaultSystemConfig(t) + + // remove default verifier node + delete(cfg.Nodes, "verifier") + // Add more verifier nodes + cfg.Nodes["alice"] = &rollupNode.Config{ + Driver: driver.Config{ + VerifierConfDepth: 0, + SequencerConfDepth: 0, + SequencerEnabled: false, + }, + L1EpochPollInterval: time.Second * 4, + } + cfg.Nodes["bob"] = &rollupNode.Config{ + Driver: driver.Config{ + VerifierConfDepth: 0, + SequencerConfDepth: 0, + SequencerEnabled: false, + }, + L1EpochPollInterval: time.Second * 4, + } + 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{ + "sequencer": {"alice", "bob"}, + "alice": {"sequencer", "bob"}, + "bob": {"alice", "sequencer"}, + } + // Enable the P2P req-resp based sync + cfg.P2PReqRespSync = true + + // Disable batcher, so there will not be any L1 data to sync from + cfg.DisableBatcher = true + + var published []string + seqTracer := new(opnode.FnTracer) + // The sequencer still publishes the blocks to the tracer, even if they do not reach the network due to disabled P2P + seqTracer.OnPublishL2PayloadFn = func(ctx context.Context, payload *eth.ExecutionPayloadEnvelope) { + published = append(published, payload.ExecutionPayload.ID().String()) + } + // Blocks are now received via the RPC based alt-sync method + cfg.Nodes["sequencer"].Tracer = seqTracer + + sys, err := cfg.Start(t) + require.Nil(t, err, "Error starting up system") + + l2Seq := sys.NodeClient("sequencer") + + // Transactor Account + ethPrivKey := cfg.Secrets.Alice + + // Submit a TX to L2 sequencer node + receiptSeq := helpers.SendL2Tx(t, cfg, l2Seq, ethPrivKey, func(opts *helpers.TxOpts) { + opts.ToAddr = &common.Address{0xff, 0xff} + opts.Value = big.NewInt(1_000_000_000) + }) + + // Gossip is able to respond to IWANT messages for the duration of heartbeat_time * message_window = 0.5 * 12 = 6 + // Wait till we pass that, and then we'll have missed some blocks that cannot be retrieved in any way from gossip + time.Sleep(time.Second * 10) + + // set up our syncer node, connect it to alice/bob + cfg.Loggers["syncer"] = testlog.Logger(t, log.LevelInfo).New("role", "syncer") + + // Create a peer, and hook up alice and bob + h, err := sys.NewMockNetPeer() + require.NoError(t, err) + _, err = sys.Mocknet.LinkPeers(sys.RollupNodes["alice"].P2P().Host().ID(), h.ID()) + require.NoError(t, err) + _, err = sys.Mocknet.LinkPeers(sys.RollupNodes["bob"].P2P().Host().ID(), h.ID()) + require.NoError(t, err) + + // Configure the new rollup node that'll be syncing + var syncedPayloads []string + syncNodeCfg := &rollupNode.Config{ + Driver: driver.Config{VerifierConfDepth: 0}, + Rollup: *sys.RollupConfig, + P2PSigner: nil, + RPC: rollupNode.RPCConfig{ + ListenAddr: "127.0.0.1", + ListenPort: 0, + EnableAdmin: true, + }, + P2P: &p2p.Prepared{HostP2P: h, EnableReqRespSync: true}, + Metrics: rollupNode.MetricsConfig{Enabled: false}, // no metrics server + Pprof: oppprof.CLIConfig{}, + L1EpochPollInterval: time.Second * 10, + Tracer: &opnode.FnTracer{ + OnUnsafeL2PayloadFn: func(ctx context.Context, from peer.ID, payload *eth.ExecutionPayloadEnvelope) { + syncedPayloads = append(syncedPayloads, payload.ExecutionPayload.ID().String()) + }, + }, + } + e2esys.ConfigureL1(syncNodeCfg, sys.EthInstances["l1"], sys.L1BeaconEndpoint()) + syncerL2Engine, err := geth.InitL2("syncer", sys.L2GenesisCfg, cfg.JWTFilePath) + require.NoError(t, err) + require.NoError(t, syncerL2Engine.Node.Start()) + + e2esys.ConfigureL2(syncNodeCfg, syncerL2Engine, cfg.JWTSecret) + + syncerNode, err := rollupNode.New(ctx, syncNodeCfg, cfg.Loggers["syncer"], "", metrics.NewMetrics("")) + require.NoError(t, err) + 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()) + require.NoError(t, err) + _, err = sys.Mocknet.ConnectPeers(sys.RollupNodes["bob"].P2P().Host().ID(), syncerNode.P2P().Host().ID()) + require.NoError(t, err) + + rpc := syncerL2Engine.UserRPC().(endpoint.ClientRPC).ClientRPC() + l2Verif := ethclient.NewClient(rpc) + + // It may take a while to sync, but eventually we should see the sequenced data show up + receiptVerif, err := wait.ForReceiptOK(ctx, l2Verif, receiptSeq.TxHash) + require.Nil(t, err, "Waiting for L2 tx on verifier") + + require.Equal(t, receiptSeq, receiptVerif) + + // Verify that the tx was received via P2P sync + require.Contains(t, syncedPayloads, eth.BlockID{Hash: receiptVerif.BlockHash, Number: receiptVerif.BlockNumber.Uint64()}.String()) + + // Verify that everything that was received was published + require.GreaterOrEqual(t, len(published), len(syncedPayloads)) + require.Subset(t, published, syncedPayloads) +} diff --git a/op-e2e/l2_gossip_test.go b/op-e2e/system/p2p/txpool_test.go similarity index 74% rename from op-e2e/l2_gossip_test.go rename to op-e2e/system/p2p/txpool_test.go index 401b30af31741..dde89ecdefb11 100644 --- a/op-e2e/l2_gossip_test.go +++ b/op-e2e/system/p2p/txpool_test.go @@ -1,18 +1,23 @@ -package op_e2e +package p2p import ( "math/big" "testing" "time" + op_e2e "github.com/ethereum-optimism/optimism/op-e2e" + + "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" + "github.com/ethereum-optimism/optimism/op-e2e/system/helpers" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" ) func TestTxGossip(t *testing.T) { - InitParallel(t) - cfg := DefaultSystemConfig(t) + op_e2e.InitParallel(t) + cfg := e2esys.DefaultSystemConfig(t) gethOpts := []geth.GethOption{ geth.WithP2P(), } @@ -30,7 +35,7 @@ func TestTxGossip(t *testing.T) { require.NoError(t, err) // Send a transaction to the verifier and it should be gossiped to the sequencer and included in a block. - SendL2Tx(t, cfg, verifClient, cfg.Secrets.Alice, func(opts *TxOpts) { + helpers.SendL2Tx(t, cfg, verifClient, cfg.Secrets.Alice, func(opts *helpers.TxOpts) { opts.ToAddr = &common.Address{0xaa} opts.Value = common.Big1 opts.VerifyOnClients(seqClient, verifClient) diff --git a/op-e2e/build_helper.go b/op-e2e/system/proofs/build_helper.go similarity index 86% rename from op-e2e/build_helper.go rename to op-e2e/system/proofs/build_helper.go index b84240135c68d..42201279867b0 100644 --- a/op-e2e/build_helper.go +++ b/op-e2e/system/proofs/build_helper.go @@ -1,4 +1,4 @@ -package op_e2e +package proofs import ( "context" @@ -16,11 +16,11 @@ func BuildOpProgramClient(t *testing.T) string { ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) defer cancel() cmd := exec.CommandContext(ctx, "make", "op-program-client") - cmd.Dir = "../op-program" + cmd.Dir = "../../../op-program" var out strings.Builder cmd.Stdout = &out cmd.Stderr = &out require.NoErrorf(t, cmd.Run(), "Failed to build op-program-client: %v", &out) t.Log("Built op-program-client successfully") - return "../op-program/bin/op-program-client" + return "../../../op-program/bin/op-program-client" } diff --git a/op-e2e/system/proofs/proofs_test.go b/op-e2e/system/proofs/proofs_test.go new file mode 100644 index 0000000000000..6fff52bd465f9 --- /dev/null +++ b/op-e2e/system/proofs/proofs_test.go @@ -0,0 +1,11 @@ +package proofs + +import ( + "testing" + + op_e2e "github.com/ethereum-optimism/optimism/op-e2e" +) + +func TestMain(m *testing.M) { + op_e2e.RunMain(m) +} diff --git a/op-e2e/system/proofs/proposer_fp_test.go b/op-e2e/system/proofs/proposer_fp_test.go new file mode 100644 index 0000000000000..4916d9d521a0c --- /dev/null +++ b/op-e2e/system/proofs/proposer_fp_test.go @@ -0,0 +1,77 @@ +package proofs + +import ( + "context" + "math/big" + "testing" + "time" + + op_e2e "github.com/ethereum-optimism/optimism/op-e2e" + + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts" + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts/metrics" + "github.com/ethereum-optimism/optimism/op-e2e/bindings" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" + "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" + "github.com/ethereum-optimism/optimism/op-service/sources/batching" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" +) + +func TestL2OutputSubmitterFaultProofs(t *testing.T) { + op_e2e.InitParallel(t, op_e2e.SkipOnL2OO) + + cfg := e2esys.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") + + l1Client := sys.NodeClient("l1") + + rollupClient := sys.RollupClient("sequencer") + + disputeGameFactory, err := bindings.NewDisputeGameFactoryCaller(cfg.L1Deployments.DisputeGameFactoryProxy, l1Client) + require.Nil(t, err) + + initialGameCount, err := disputeGameFactory.GameCount(&bind.CallOpts{}) + require.Nil(t, err) + + l2Verif := sys.NodeClient("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 { + caller := batching.NewMultiCaller(l1Client.Client(), batching.DefaultBatchSize) + committedL2Output, err := disputeGameFactory.GameAtIndex(&bind.CallOpts{}, new(big.Int).Sub(latestGameCount, common.Big1)) + require.Nil(t, err) + proxy, err := contracts.NewFaultDisputeGameContract(context.Background(), metrics.NoopContractMetrics, committedL2Output.Proxy, caller) + require.Nil(t, err) + claim, err := proxy.GetClaim(context.Background(), 0) + require.Nil(t, err) + + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + _, gameBlockNumber, err := proxy.GetBlockRange(ctx) + require.Nil(t, err) + l2Output, err := rollupClient.OutputAtBlock(ctx, gameBlockNumber) + require.Nil(t, err) + require.EqualValues(t, l2Output.OutputRoot, claim.Value) + break + } + + select { + case <-timeoutCh: + t.Fatalf("State root oracle not updated") + case <-ticker.C: + } + } +} diff --git a/op-e2e/system/proofs/proposer_l2oo_test.go b/op-e2e/system/proofs/proposer_l2oo_test.go new file mode 100644 index 0000000000000..3b737e0971b59 --- /dev/null +++ b/op-e2e/system/proofs/proposer_l2oo_test.go @@ -0,0 +1,82 @@ +package proofs + +import ( + "context" + "math/big" + "testing" + "time" + + op_e2e "github.com/ethereum-optimism/optimism/op-e2e" + + "github.com/ethereum-optimism/optimism/op-e2e/bindings" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" + "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/stretchr/testify/require" +) + +func TestL2OutputSubmitter(t *testing.T) { + op_e2e.InitParallel(t, op_e2e.SkipOnFaultProofs) + + cfg := e2esys.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") + + l1Client := sys.NodeClient("l1") + + rollupClient := sys.RollupClient("sequencer") + + // OutputOracle is already deployed + l2OutputOracle, err := bindings.NewL2OutputOracleCaller(cfg.L1Deployments.L2OutputOracleProxy, l1Client) + require.Nil(t, err) + + initialOutputBlockNumber, err := l2OutputOracle.LatestBlockNumber(&bind.CallOpts{}) + require.Nil(t, err) + + // Wait until the second output submission from L2. The output submitter submits outputs from the + // unsafe portion of the chain which gets reorged on startup. The sequencer has an out of date view + // when it creates it's first block and uses and old L1 Origin. It then does not submit a batch + // for that block and subsequently reorgs to match what the verifier derives when running the + // reconcillation process. + l2Verif := sys.NodeClient("verifier") + _, err = geth.WaitForBlock(big.NewInt(6), l2Verif, 10*time.Duration(cfg.DeployConfig.L2BlockTime)*time.Second) + require.Nil(t, err) + + // Wait for batch submitter to update L2 output oracle. + timeoutCh := time.After(15 * time.Second) + ticker := time.NewTicker(1 * time.Second) + defer ticker.Stop() + for { + l2ooBlockNumber, err := l2OutputOracle.LatestBlockNumber(&bind.CallOpts{}) + require.Nil(t, err) + + // Wait for the L2 output oracle to have been changed from the initial + // timestamp set in the contract constructor. + if l2ooBlockNumber.Cmp(initialOutputBlockNumber) > 0 { + // Retrieve the l2 output committed at this updated timestamp. + committedL2Output, err := l2OutputOracle.GetL2OutputAfter(&bind.CallOpts{}, l2ooBlockNumber) + require.NotEqual(t, [32]byte{}, committedL2Output.OutputRoot, "Empty L2 Output") + require.Nil(t, err) + + // Fetch the corresponding L2 block and assert the committed L2 + // output matches the block's state root. + // + // NOTE: This assertion will change once the L2 output format is + // finalized. + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + l2Output, err := rollupClient.OutputAtBlock(ctx, l2ooBlockNumber.Uint64()) + require.Nil(t, err) + require.Equal(t, l2Output.OutputRoot[:], committedL2Output.OutputRoot[:]) + break + } + + select { + case <-timeoutCh: + t.Fatalf("State root oracle not updated") + case <-ticker.C: + } + } +} diff --git a/op-e2e/system_fpp_test.go b/op-e2e/system/proofs/system_fpp_test.go similarity index 91% rename from op-e2e/system_fpp_test.go rename to op-e2e/system/proofs/system_fpp_test.go index c3598880b0cfe..8729f2c7055c2 100644 --- a/op-e2e/system_fpp_test.go +++ b/op-e2e/system/proofs/system_fpp_test.go @@ -1,4 +1,4 @@ -package op_e2e +package proofs import ( "context" @@ -6,6 +6,11 @@ import ( "testing" "time" + op_e2e "github.com/ethereum-optimism/optimism/op-e2e" + + "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" + "github.com/ethereum-optimism/optimism/op-e2e/system/helpers" + "github.com/stretchr/testify/require" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -86,10 +91,10 @@ func applySpanBatchActivation(active bool, dp *genesis.DeployConfig) { // - update the state root via a tx // - run program func testVerifyL2OutputRootEmptyBlock(t *testing.T, detached bool, spanBatchActivated bool) { - InitParallel(t) + op_e2e.InitParallel(t) ctx := context.Background() - cfg := DefaultSystemConfig(t) + cfg := e2esys.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 @@ -117,7 +122,7 @@ func testVerifyL2OutputRootEmptyBlock(t *testing.T, detached bool, spanBatchActi t.Log("Sending transactions to setup existing state, prior to challenged period") aliceKey := cfg.Secrets.Alice - receipt := SendL2Tx(t, cfg, l2Seq, aliceKey, func(opts *TxOpts) { + receipt := helpers.SendL2Tx(t, cfg, l2Seq, aliceKey, func(opts *helpers.TxOpts) { opts.ToAddr = &cfg.Secrets.Addresses().Bob opts.Value = big.NewInt(1_000) }) @@ -163,7 +168,7 @@ func testVerifyL2OutputRootEmptyBlock(t *testing.T, detached bool, spanBatchActi require.NoError(t, err, "could not start batch submitter") t.Log("Add a transaction to the next batch after sequence of empty blocks") - receipt = SendL2Tx(t, cfg, l2Seq, aliceKey, func(opts *TxOpts) { + receipt = helpers.SendL2Tx(t, cfg, l2Seq, aliceKey, func(opts *helpers.TxOpts) { opts.ToAddr = &cfg.Secrets.Addresses().Bob opts.Value = big.NewInt(1_000) opts.Nonce = 1 @@ -186,10 +191,10 @@ func testVerifyL2OutputRootEmptyBlock(t *testing.T, detached bool, spanBatchActi } func testVerifyL2OutputRoot(t *testing.T, detached bool, spanBatchActivated bool) { - InitParallel(t) + op_e2e.InitParallel(t) ctx := context.Background() - cfg := DefaultSystemConfig(t) + cfg := e2esys.DefaultSystemConfig(t) // We don't need a verifier - just the sequencer is enough delete(cfg.Nodes, "verifier") applySpanBatchActivation(spanBatchActivated, cfg.DeployConfig) @@ -209,15 +214,15 @@ func testVerifyL2OutputRoot(t *testing.T, detached bool, spanBatchActivated bool aliceKey := cfg.Secrets.Alice opts, err := bind.NewKeyedTransactorWithChainID(aliceKey, cfg.L1ChainIDBig()) require.Nil(t, err) - SendDepositTx(t, cfg, l1Client, l2Seq, opts, func(l2Opts *DepositTxOpts) { + helpers.SendDepositTx(t, cfg, l1Client, l2Seq, opts, func(l2Opts *helpers.DepositTxOpts) { l2Opts.Value = big.NewInt(100_000_000) }) - SendL2Tx(t, cfg, l2Seq, aliceKey, func(opts *TxOpts) { + helpers.SendL2Tx(t, cfg, l2Seq, aliceKey, func(opts *helpers.TxOpts) { opts.ToAddr = &cfg.Secrets.Addresses().Bob opts.Value = big.NewInt(1_000) opts.Nonce = 1 }) - SendWithdrawal(t, cfg, l2Seq, aliceKey, func(opts *WithdrawalTxOpts) { + helpers.SendWithdrawal(t, cfg, l2Seq, aliceKey, func(opts *helpers.WithdrawalTxOpts) { opts.Value = big.NewInt(500) opts.Nonce = 2 }) @@ -231,14 +236,14 @@ func testVerifyL2OutputRoot(t *testing.T, detached bool, spanBatchActivated bool l2OutputRoot := agreedL2Output.OutputRoot t.Log("Sending transactions to modify existing state, within challenged period") - SendDepositTx(t, cfg, l1Client, l2Seq, opts, func(l2Opts *DepositTxOpts) { + helpers.SendDepositTx(t, cfg, l1Client, l2Seq, opts, func(l2Opts *helpers.DepositTxOpts) { l2Opts.Value = big.NewInt(5_000) }) - SendL2Tx(t, cfg, l2Seq, cfg.Secrets.Bob, func(opts *TxOpts) { + helpers.SendL2Tx(t, cfg, l2Seq, cfg.Secrets.Bob, func(opts *helpers.TxOpts) { opts.ToAddr = &cfg.Secrets.Addresses().Alice opts.Value = big.NewInt(100) }) - SendWithdrawal(t, cfg, l2Seq, aliceKey, func(opts *WithdrawalTxOpts) { + helpers.SendWithdrawal(t, cfg, l2Seq, aliceKey, func(opts *helpers.WithdrawalTxOpts) { opts.Value = big.NewInt(100) opts.Nonce = 4 }) @@ -276,11 +281,12 @@ type FaultProofProgramTestScenario struct { } // testFaultProofProgramScenario runs the fault proof program in several contexts, given a test scenario. -func testFaultProofProgramScenario(t *testing.T, ctx context.Context, sys *System, s *FaultProofProgramTestScenario) { +func testFaultProofProgramScenario(t *testing.T, ctx context.Context, sys *e2esys.System, s *FaultProofProgramTestScenario) { preimageDir := t.TempDir() fppConfig := oppconf.NewConfig(sys.RollupConfig, sys.L2GenesisCfg.Config, s.L1Head, s.L2Head, s.L2OutputRoot, common.Hash(s.L2Claim), s.L2ClaimBlockNumber) fppConfig.L1URL = sys.NodeEndpoint("l1").RPC() fppConfig.L2URL = sys.NodeEndpoint("sequencer").RPC() + fppConfig.L1BeaconURL = sys.L1BeaconEndpoint().RestHTTP() fppConfig.DataDir = preimageDir if s.Detached { // When running in detached mode we need to compile the client executable since it will be called directly. diff --git a/op-e2e/system/runcfg/p2p_signer_test.go b/op-e2e/system/runcfg/p2p_signer_test.go new file mode 100644 index 0000000000000..91ebfb941319c --- /dev/null +++ b/op-e2e/system/runcfg/p2p_signer_test.go @@ -0,0 +1,62 @@ +package runcfg + +import ( + "context" + "fmt" + "testing" + "time" + + op_e2e "github.com/ethereum-optimism/optimism/op-e2e" + + "github.com/ethereum-optimism/optimism/op-e2e/bindings" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" + "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" + "github.com/ethereum-optimism/optimism/op-service/retry" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" +) + +func TestRuntimeConfigReload(t *testing.T) { + op_e2e.InitParallel(t) + + cfg := e2esys.DefaultSystemConfig(t) + // to speed up the test, make it reload the config more often, and do not impose a long conf depth + cfg.Nodes["verifier"].RuntimeConfigReloadInterval = time.Second * 5 + cfg.Nodes["verifier"].Driver.VerifierConfDepth = 1 + + sys, err := cfg.Start(t) + require.Nil(t, err, "Error starting up system") + + initialRuntimeConfig := sys.RollupNodes["verifier"].RuntimeConfig() + + // close the EL node, since we want to block derivation, to solely rely on the reloading mechanism for updates. + sys.EthInstances["verifier"].Close() + + l1 := sys.NodeClient("l1") + + // Change the system-config via L1 + sysCfgContract, err := bindings.NewSystemConfig(cfg.L1Deployments.SystemConfigProxy, l1) + require.NoError(t, err) + newUnsafeBlocksSigner := common.Address{0x12, 0x23, 0x45} + require.NotEqual(t, initialRuntimeConfig.P2PSequencerAddress(), newUnsafeBlocksSigner, "changing to a different address") + opts, err := bind.NewKeyedTransactorWithChainID(cfg.Secrets.SysCfgOwner, cfg.L1ChainIDBig()) + require.Nil(t, err) + // the unsafe signer address is part of the runtime config + tx, err := sysCfgContract.SetUnsafeBlockSigner(opts, newUnsafeBlocksSigner) + require.NoError(t, err) + + // wait for the change to confirm + _, err = wait.ForReceiptOK(context.Background(), l1, tx.Hash()) + require.NoError(t, err) + + // wait for the address to change + _, err = retry.Do(context.Background(), 10, retry.Fixed(time.Second*10), func() (struct{}, error) { + v := sys.RollupNodes["verifier"].RuntimeConfig().P2PSequencerAddress() + if v == newUnsafeBlocksSigner { + return struct{}{}, nil + } + return struct{}{}, fmt.Errorf("no change yet, seeing %s but looking for %s", v, newUnsafeBlocksSigner) + }) + require.NoError(t, err) +} diff --git a/op-e2e/system/runcfg/protocol_versions_test.go b/op-e2e/system/runcfg/protocol_versions_test.go new file mode 100644 index 0000000000000..14e056b044354 --- /dev/null +++ b/op-e2e/system/runcfg/protocol_versions_test.go @@ -0,0 +1,141 @@ +package runcfg + +import ( + "context" + "errors" + "fmt" + "math/big" + "testing" + "time" + + op_e2e "github.com/ethereum-optimism/optimism/op-e2e" + + "github.com/ethereum-optimism/optimism/op-e2e/bindings" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" + "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" + "github.com/ethereum-optimism/optimism/op-service/client" + "github.com/ethereum-optimism/optimism/op-service/endpoint" + "github.com/ethereum-optimism/optimism/op-service/retry" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/eth/ethconfig" + "github.com/ethereum/go-ethereum/node" + "github.com/ethereum/go-ethereum/params" + "github.com/stretchr/testify/require" +) + +func TestRecommendedProtocolVersionChange(t *testing.T) { + op_e2e.InitParallel(t) + + cfg := e2esys.DefaultSystemConfig(t) + require.NotEqual(t, common.Address{}, cfg.L1Deployments.ProtocolVersions, "need ProtocolVersions contract deployment") + // to speed up the test, make it reload the config more often, and do not impose a long conf depth + cfg.Nodes["verifier"].RuntimeConfigReloadInterval = time.Second * 5 + cfg.Nodes["verifier"].Driver.VerifierConfDepth = 1 + + sys, err := cfg.Start(t) + require.Nil(t, err, "Error starting up system") + + runtimeConfig := sys.RollupNodes["verifier"].RuntimeConfig() + + // Change the superchain-config via L1 + l1 := sys.NodeClient("l1") + + _, build, major, minor, patch, preRelease := params.OPStackSupport.Parse() + newRecommendedProtocolVersion := params.ProtocolVersionV0{Build: build, Major: major + 1, Minor: minor, Patch: patch, PreRelease: preRelease}.Encode() + require.NotEqual(t, runtimeConfig.RecommendedProtocolVersion(), newRecommendedProtocolVersion, "changing to a different protocol version") + + protVersions, err := bindings.NewProtocolVersions(cfg.L1Deployments.ProtocolVersionsProxy, l1) + require.NoError(t, err) + + // ProtocolVersions contract is owned by same key as SystemConfig in devnet + opts, err := bind.NewKeyedTransactorWithChainID(cfg.Secrets.SysCfgOwner, cfg.L1ChainIDBig()) + require.NoError(t, err) + + // Change recommended protocol version + tx, err := protVersions.SetRecommended(opts, new(big.Int).SetBytes(newRecommendedProtocolVersion[:])) + require.NoError(t, err) + + // wait for the change to confirm + _, err = wait.ForReceiptOK(context.Background(), l1, tx.Hash()) + require.NoError(t, err) + + // wait for the recommended protocol version to change + _, err = retry.Do(context.Background(), 10, retry.Fixed(time.Second*10), func() (struct{}, error) { + v := sys.RollupNodes["verifier"].RuntimeConfig().RecommendedProtocolVersion() + if v == newRecommendedProtocolVersion { + return struct{}{}, nil + } + return struct{}{}, fmt.Errorf("no change yet, seeing %s but looking for %s", v, newRecommendedProtocolVersion) + }) + require.NoError(t, err) +} + +func TestRequiredProtocolVersionChangeAndHalt(t *testing.T) { + op_e2e.InitParallel(t) + + cfg := e2esys.DefaultSystemConfig(t) + // to speed up the test, make it reload the config more often, and do not impose a long conf depth + cfg.Nodes["verifier"].RuntimeConfigReloadInterval = time.Second * 5 + cfg.Nodes["verifier"].Driver.VerifierConfDepth = 1 + // configure halt in verifier op-node + cfg.Nodes["verifier"].RollupHalt = "major" + // configure halt in verifier op-geth node + cfg.GethOptions["verifier"] = append(cfg.GethOptions["verifier"], []geth.GethOption{ + func(ethCfg *ethconfig.Config, nodeCfg *node.Config) error { + ethCfg.RollupHaltOnIncompatibleProtocolVersion = "major" + return nil + }, + }...) + + sys, err := cfg.Start(t) + require.Nil(t, err, "Error starting up system") + + runtimeConfig := sys.RollupNodes["verifier"].RuntimeConfig() + + // Change the superchain-config via L1 + l1 := sys.NodeClient("l1") + + _, build, major, minor, patch, preRelease := params.OPStackSupport.Parse() + newRequiredProtocolVersion := params.ProtocolVersionV0{Build: build, Major: major + 1, Minor: minor, Patch: patch, PreRelease: preRelease}.Encode() + require.NotEqual(t, runtimeConfig.RequiredProtocolVersion(), newRequiredProtocolVersion, "changing to a different protocol version") + + protVersions, err := bindings.NewProtocolVersions(cfg.L1Deployments.ProtocolVersionsProxy, l1) + require.NoError(t, err) + + // ProtocolVersions contract is owned by same key as SystemConfig in devnet + opts, err := bind.NewKeyedTransactorWithChainID(cfg.Secrets.SysCfgOwner, cfg.L1ChainIDBig()) + require.NoError(t, err) + + // Change required protocol version + tx, err := protVersions.SetRequired(opts, new(big.Int).SetBytes(newRequiredProtocolVersion[:])) + require.NoError(t, err) + + // wait for the change to confirm + _, err = wait.ForReceiptOK(context.Background(), l1, tx.Hash()) + require.NoError(t, err) + + // wait for the required protocol version to take effect by halting the verifier that opted in, and halting the op-geth node that opted in. + _, err = retry.Do(context.Background(), 10, retry.Fixed(time.Second*10), func() (struct{}, error) { + if !sys.RollupNodes["verifier"].Stopped() { + return struct{}{}, errors.New("verifier rollup node is not closed yet") + } + return struct{}{}, nil + }) + require.NoError(t, err) + t.Log("verified that op-node closed!") + // 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(), 10*time.Second) + defer cancel() + available := client.IsURLAvailable(ctx, sys.NodeEndpoint("verifier").(endpoint.HttpRPC).HttpRPC()) + if !available && ctx.Err() == nil { // waiting for client to stop responding to RPC requests (slow dials with timeout don't count) + return struct{}{}, nil + } + return struct{}{}, errors.New("verifier EL node is not closed yet") + }) + require.NoError(t, err) + t.Log("verified that op-geth closed!") +} diff --git a/op-e2e/system/runcfg/runcfg_test.go b/op-e2e/system/runcfg/runcfg_test.go new file mode 100644 index 0000000000000..62cb755538169 --- /dev/null +++ b/op-e2e/system/runcfg/runcfg_test.go @@ -0,0 +1,11 @@ +package runcfg + +import ( + "testing" + + op_e2e "github.com/ethereum-optimism/optimism/op-e2e" +) + +func TestMain(m *testing.M) { + op_e2e.RunMain(m) +} diff --git a/op-e2e/system/verifier/basic_test.go b/op-e2e/system/verifier/basic_test.go new file mode 100644 index 0000000000000..effe1f4121462 --- /dev/null +++ b/op-e2e/system/verifier/basic_test.go @@ -0,0 +1,113 @@ +package verifier + +import ( + "context" + "math/big" + "testing" + "time" + + op_e2e "github.com/ethereum-optimism/optimism/op-e2e" + + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" + "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" + "github.com/ethereum-optimism/optimism/op-e2e/system/helpers" + "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/common/hexutil" + "github.com/ethereum/go-ethereum/log" + "github.com/stretchr/testify/require" +) + +func TestSystemE2EDencunAtGenesis(t *testing.T) { + op_e2e.InitParallel(t) + + cfg := e2esys.DefaultSystemConfig(t) + cfg.DeployConfig.L1CancunTimeOffset = new(hexutil.Uint64) + + sys, err := cfg.Start(t) + require.Nil(t, err, "Error starting up system") + + runE2ESystemTest(t, sys) + head, err := sys.NodeClient("l1").BlockByNumber(context.Background(), big.NewInt(0)) + require.NoError(t, err) + require.NotNil(t, head.ExcessBlobGas(), "L1 is building dencun blocks since genesis") +} + +// TestSystemE2E sets up a L1 Geth node, a rollup node, and a L2 geth node and then confirms that L1 deposits are reflected on L2. +// All nodes are run in process (but are the full nodes, not mocked or stubbed). +func TestSystemE2E(t *testing.T) { + op_e2e.InitParallel(t) + + cfg := e2esys.DefaultSystemConfig(t) + + sys, err := cfg.Start(t) + require.Nil(t, err, "Error starting up system") + runE2ESystemTest(t, sys) + +} + +func runE2ESystemTest(t *testing.T, sys *e2esys.System) { + 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.NodeClient("l1") + l2Seq := sys.NodeClient("sequencer") + l2Verif := sys.NodeClient("verifier") + + // Transactor Account + ethPrivKey := sys.Cfg.Secrets.Alice + + // Send Transaction & wait for success + fromAddr := sys.Cfg.Secrets.Addresses().Alice + + ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) + defer cancel() + startBalance, err := l2Verif.BalanceAt(ctx, fromAddr, nil) + require.Nil(t, err) + + // Send deposit transaction + opts, err := bind.NewKeyedTransactorWithChainID(ethPrivKey, sys.Cfg.L1ChainIDBig()) + require.Nil(t, err) + mintAmount := big.NewInt(1_000_000_000_000) + opts.Value = mintAmount + helpers.SendDepositTx(t, sys.Cfg, l1Client, l2Verif, opts, func(l2Opts *helpers.DepositTxOpts) {}) + + // Confirm balance + ctx, cancel = context.WithTimeout(context.Background(), 15*time.Second) + defer cancel() + + endBalance, err := wait.ForBalanceChange(ctx, l2Verif, fromAddr, startBalance) + require.Nil(t, err) + + diff := new(big.Int) + diff = diff.Sub(endBalance, startBalance) + require.Equal(t, mintAmount, diff, "Did not get expected balance change") + + // Submit TX to L2 sequencer node + receipt := helpers.SendL2Tx(t, sys.Cfg, l2Seq, ethPrivKey, func(opts *helpers.TxOpts) { + opts.Value = big.NewInt(1_000_000_000) + opts.Nonce = 1 // Already have deposit + opts.ToAddr = &common.Address{0xff, 0xff} + opts.VerifyOnClients(l2Verif) + }) + + // Verify blocks match after batch submission on verifiers and sequencers + verifBlock, err := l2Verif.BlockByNumber(context.Background(), receipt.BlockNumber) + require.Nil(t, err) + seqBlock, err := l2Seq.BlockByNumber(context.Background(), receipt.BlockNumber) + require.Nil(t, err) + require.Equal(t, verifBlock.NumberU64(), seqBlock.NumberU64(), "Verifier and sequencer blocks not the same after including a batch tx") + require.Equal(t, verifBlock.ParentHash(), seqBlock.ParentHash(), "Verifier and sequencer blocks parent hashes not the same after including a batch tx") + require.Equal(t, verifBlock.Hash(), seqBlock.Hash(), "Verifier and sequencer blocks not the same after including a batch tx") + + rollupClient := sys.RollupClient("sequencer") + // basic check that sync status works + seqStatus, err := rollupClient.SyncStatus(context.Background()) + require.Nil(t, err) + require.LessOrEqual(t, seqBlock.NumberU64(), seqStatus.UnsafeL2.Number) + // basic check that version endpoint works + seqVersion, err := rollupClient.Version(context.Background()) + require.Nil(t, err) + require.NotEqual(t, "", seqVersion) +} diff --git a/op-e2e/system/verifier/confdepth_test.go b/op-e2e/system/verifier/confdepth_test.go new file mode 100644 index 0000000000000..698496c683319 --- /dev/null +++ b/op-e2e/system/verifier/confdepth_test.go @@ -0,0 +1,61 @@ +package verifier + +import ( + "context" + "testing" + "time" + + op_e2e "github.com/ethereum-optimism/optimism/op-e2e" + + "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" + "github.com/ethereum-optimism/optimism/op-node/rollup/derive" + "github.com/ethereum-optimism/optimism/op-service/testlog" + "github.com/ethereum/go-ethereum/log" + "github.com/stretchr/testify/require" +) + +// TestConfirmationDepth runs the rollup with both sequencer and verifier not immediately processing the tip of the chain. +func TestConfirmationDepth(t *testing.T) { + op_e2e.InitParallel(t) + + cfg := e2esys.DefaultSystemConfig(t) + cfg.DeployConfig.SequencerWindowSize = 4 + cfg.DeployConfig.MaxSequencerDrift = 10 * cfg.DeployConfig.L1BlockTime + seqConfDepth := uint64(2) + verConfDepth := uint64(5) + cfg.Nodes["sequencer"].Driver.SequencerConfDepth = seqConfDepth + cfg.Nodes["sequencer"].Driver.VerifierConfDepth = 0 + cfg.Nodes["verifier"].Driver.VerifierConfDepth = verConfDepth + + sys, err := cfg.Start(t) + require.Nil(t, err, "Error starting up system") + + 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.NodeClient("l1") + l2Seq := sys.NodeClient("sequencer") + l2Verif := sys.NodeClient("verifier") + + // Wait enough time for the sequencer to submit a block with distance from L1 head, submit it, + // and for the slower verifier to read a full sequence window and cover confirmation depth for reading and some margin + <-time.After(time.Duration((cfg.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(), 30*time.Second) + defer cancel() + l1Head, err := l1Client.BlockByNumber(ctx, nil) + require.NoError(t, err) + l2SeqHead, err := l2Seq.BlockByNumber(ctx, nil) + require.NoError(t, err) + l2VerHead, err := l2Verif.BlockByNumber(ctx, nil) + require.NoError(t, err) + + seqInfo, err := derive.L1BlockInfoFromBytes(sys.RollupConfig, l2SeqHead.Time(), l2SeqHead.Transactions()[0].Data()) + require.NoError(t, err) + require.LessOrEqual(t, seqInfo.Number+seqConfDepth, l1Head.NumberU64(), "the seq L2 head block should have an origin older than the L1 head block by at least the sequencer conf depth") + + verInfo, err := derive.L1BlockInfoFromBytes(sys.RollupConfig, l2VerHead.Time(), l2VerHead.Transactions()[0].Data()) + require.NoError(t, err) + require.LessOrEqual(t, verInfo.Number+verConfDepth, l1Head.NumberU64(), "the ver L2 head block should have an origin older than the L1 head block by at least the verifier conf depth") +} diff --git a/op-e2e/system/verifier/finalize_test.go b/op-e2e/system/verifier/finalize_test.go new file mode 100644 index 0000000000000..976d9a9077bf7 --- /dev/null +++ b/op-e2e/system/verifier/finalize_test.go @@ -0,0 +1,29 @@ +package verifier + +import ( + "math/big" + "testing" + "time" + + op_e2e "github.com/ethereum-optimism/optimism/op-e2e" + + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" + "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" + "github.com/stretchr/testify/require" +) + +// TestFinalize tests if L2 finalizes after sufficient time after L1 finalizes +func TestFinalize(t *testing.T) { + op_e2e.InitParallel(t) + + cfg := e2esys.DefaultSystemConfig(t) + + sys, err := cfg.Start(t) + require.Nil(t, err, "Error starting up system") + + l2Seq := sys.NodeClient("sequencer") + + l2Finalized, err := geth.WaitForBlockToBeFinalized(big.NewInt(12), l2Seq, 1*time.Minute) + require.NoError(t, err, "must be able to fetch a finalized L2 block") + require.NotZerof(t, l2Finalized.NumberU64(), "must have finalized L2 block") +} diff --git a/op-e2e/system/verifier/legacy_pending_test.go b/op-e2e/system/verifier/legacy_pending_test.go new file mode 100644 index 0000000000000..8a3afee5e091d --- /dev/null +++ b/op-e2e/system/verifier/legacy_pending_test.go @@ -0,0 +1,120 @@ +package verifier + +import ( + "context" + "math/big" + "testing" + "time" + + op_e2e "github.com/ethereum-optimism/optimism/op-e2e" + + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" + "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" + "github.com/ethereum-optimism/optimism/op-service/testlog" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/eth/ethconfig" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/node" + "github.com/ethereum/go-ethereum/rpc" + "github.com/stretchr/testify/require" +) + +// TestPendingGasLimit tests the configuration of the gas limit of the pending block, +// and if it does not conflict with the regular gas limit on the verifier or sequencer. +func TestPendingGasLimit(t *testing.T) { + op_e2e.InitParallel(t) + + cfg := e2esys.DefaultSystemConfig(t) + + // configure the L2 gas limit to be high, and the pending gas limits to be lower for resource saving. + cfg.DeployConfig.L2GenesisBlockGasLimit = 30_000_000 + cfg.GethOptions["sequencer"] = append(cfg.GethOptions["sequencer"], []geth.GethOption{ + func(ethCfg *ethconfig.Config, nodeCfg *node.Config) error { + ethCfg.Miner.GasCeil = 10_000_000 + ethCfg.Miner.RollupComputePendingBlock = true + return nil + }, + }...) + cfg.GethOptions["verifier"] = append(cfg.GethOptions["verifier"], []geth.GethOption{ + func(ethCfg *ethconfig.Config, nodeCfg *node.Config) error { + ethCfg.Miner.GasCeil = 9_000_000 + ethCfg.Miner.RollupComputePendingBlock = true + return nil + }, + }...) + + sys, err := cfg.Start(t) + require.Nil(t, err, "Error starting up system") + + 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.NodeClient("verifier") + l2Seq := sys.NodeClient("sequencer") + + checkGasLimit := func(client *ethclient.Client, number *big.Int, expected uint64) *types.Header { + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + header, err := client.HeaderByNumber(ctx, number) + cancel() + require.NoError(t, err) + require.Equal(t, expected, header.GasLimit) + return header + } + + // check if the gaslimits are matching the expected values, + // and that the verifier/sequencer can use their locally configured gas limit for the pending block. + for { + checkGasLimit(l2Seq, big.NewInt(-1), 10_000_000) + checkGasLimit(l2Verif, big.NewInt(-1), 9_000_000) + checkGasLimit(l2Seq, nil, 30_000_000) + latestVerifHeader := checkGasLimit(l2Verif, nil, 30_000_000) + + // Stop once the verifier passes genesis: + // this implies we checked a new block from the sequencer, on both sequencer and verifier nodes. + if latestVerifHeader.Number.Uint64() > 0 { + break + } + time.Sleep(500 * time.Millisecond) + } +} + +// TestPendingBlockIsLatest tests that we serve the latest block as pending block +func TestPendingBlockIsLatest(t *testing.T) { + op_e2e.InitParallel(t) + + cfg := e2esys.DefaultSystemConfig(t) + sys, err := cfg.Start(t) + require.Nil(t, err, "Error starting up system") + + l2Seq := sys.NodeClient("sequencer") + + t.Run("block", func(t *testing.T) { + for i := 0; i < 10; i++ { + pending, err := l2Seq.BlockByNumber(context.Background(), big.NewInt(rpc.PendingBlockNumber.Int64())) + require.NoError(t, err) + latest, err := l2Seq.BlockByNumber(context.Background(), nil) + require.NoError(t, err) + if pending.NumberU64() == latest.NumberU64() { + require.Equal(t, pending.Hash(), latest.Hash(), "pending must exactly match latest block") + return + } + // re-try until we have the same number, as the requests are not an atomic bundle, and the sequencer may create a block. + } + t.Fatal("failed to get pending block with same number as latest block") + }) + t.Run("header", func(t *testing.T) { + for i := 0; i < 10; i++ { + pending, err := l2Seq.HeaderByNumber(context.Background(), big.NewInt(rpc.PendingBlockNumber.Int64())) + require.NoError(t, err) + latest, err := l2Seq.HeaderByNumber(context.Background(), nil) + require.NoError(t, err) + if pending.Number.Uint64() == latest.Number.Uint64() { + require.Equal(t, pending.Hash(), latest.Hash(), "pending must exactly match latest header") + return + } + // re-try until we have the same number, as the requests are not an atomic bundle, and the sequencer may create a block. + } + t.Fatal("failed to get pending header with same number as latest header") + }) +} diff --git a/op-e2e/system/verifier/sequencer_window_test.go b/op-e2e/system/verifier/sequencer_window_test.go new file mode 100644 index 0000000000000..aa836402e99b8 --- /dev/null +++ b/op-e2e/system/verifier/sequencer_window_test.go @@ -0,0 +1,73 @@ +package verifier + +import ( + "context" + "math/big" + "testing" + "time" + + op_e2e "github.com/ethereum-optimism/optimism/op-e2e" + + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" + "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" + "github.com/ethereum-optimism/optimism/op-e2e/system/helpers" + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" +) + +func TestMissingBatchE2E(t *testing.T) { + op_e2e.InitParallel(t) + // Note this test zeroes the balance of the batch-submitter to make the batches unable to go into L1. + // The test logs may look scary, but this is expected: + // 'batcher unable to publish transaction role=batcher err="insufficient funds for gas * price + value"' + + cfg := e2esys.DefaultSystemConfig(t) + // small sequence window size so the test does not take as long + cfg.DeployConfig.SequencerWindowSize = 4 + + // Specifically set batch submitter balance to stop batches from being included + cfg.Premine[cfg.Secrets.Addresses().Batcher] = big.NewInt(0) + + sys, err := cfg.Start(t) + require.Nil(t, err, "Error starting up system") + + l2Seq := sys.NodeClient("sequencer") + l2Verif := sys.NodeClient("verifier") + + seqRollupClient := sys.RollupClient("sequencer") + + // Transactor Account + ethPrivKey := cfg.Secrets.Alice + + // Submit TX to L2 sequencer node + receipt := helpers.SendL2Tx(t, cfg, l2Seq, ethPrivKey, func(opts *helpers.TxOpts) { + opts.ToAddr = &common.Address{0xff, 0xff} + opts.Value = big.NewInt(1_000_000_000) + }) + + // Wait until the block it was first included in shows up in the safe chain on the verifier + _, err = geth.WaitForBlock(receipt.BlockNumber, l2Verif, time.Duration((sys.RollupConfig.SeqWindowSize+4)*cfg.DeployConfig.L1BlockTime)*time.Second) + 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(), 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") + + // Wait a short time for the L2 reorg to occur on the sequencer as well. + err = wait.ForSafeBlock(ctx, seqRollupClient, receipt.BlockNumber.Uint64()) + 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(), 30*time.Second) + defer cancel() + block, err := l2Seq.BlockByNumber(ctx2, receipt.BlockNumber) + if err != nil { + require.Equal(t, "not found", err.Error(), "A not found error indicates the chain must have re-orged back before it") + } else { + require.NotEqual(t, block.Hash(), receipt.BlockHash, "L2 Sequencer did not reorg out transaction on it's safe chain") + } +} diff --git a/op-e2e/system/verifier/verifier_test.go b/op-e2e/system/verifier/verifier_test.go new file mode 100644 index 0000000000000..33527b62da24d --- /dev/null +++ b/op-e2e/system/verifier/verifier_test.go @@ -0,0 +1,11 @@ +package verifier + +import ( + "testing" + + op_e2e "github.com/ethereum-optimism/optimism/op-e2e" +) + +func TestMain(m *testing.M) { + op_e2e.RunMain(m) +} diff --git a/op-e2e/system_test.go b/op-e2e/system_test.go deleted file mode 100644 index a168a8c90df62..0000000000000 --- a/op-e2e/system_test.go +++ /dev/null @@ -1,1612 +0,0 @@ -package op_e2e - -import ( - "context" - "errors" - "fmt" - "math/big" - "os" - "runtime" - "slices" - "testing" - "time" - - "github.com/libp2p/go-libp2p/core/peer" - "github.com/stretchr/testify/require" - - "github.com/ethereum/go-ethereum" - "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/consensus/misc/eip4844" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/eth/ethconfig" - "github.com/ethereum/go-ethereum/ethclient" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/node" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rpc" - - "github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts" - metrics2 "github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts/metrics" - "github.com/ethereum-optimism/optimism/op-e2e/bindings" - "github.com/ethereum-optimism/optimism/op-e2e/config" - "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" - "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/metrics" - rollupNode "github.com/ethereum-optimism/optimism/op-node/node" - "github.com/ethereum-optimism/optimism/op-node/p2p" - "github.com/ethereum-optimism/optimism/op-node/rollup/derive" - "github.com/ethereum-optimism/optimism/op-node/rollup/driver" - "github.com/ethereum-optimism/optimism/op-service/client" - "github.com/ethereum-optimism/optimism/op-service/endpoint" - "github.com/ethereum-optimism/optimism/op-service/eth" - "github.com/ethereum-optimism/optimism/op-service/oppprof" - "github.com/ethereum-optimism/optimism/op-service/predeploys" - "github.com/ethereum-optimism/optimism/op-service/retry" - "github.com/ethereum-optimism/optimism/op-service/sources/batching" - "github.com/ethereum-optimism/optimism/op-service/testlog" -) - -// TestSystemBatchType run each system e2e test case in singular batch mode and span batch mode. -// If the test case tests batch submission and advancing safe head, it should be tested in both singular and span batch mode. -func TestSystemBatchType(t *testing.T) { - tests := []struct { - name string - f func(*testing.T, func(*SystemConfig)) - }{ - {"StopStartBatcher", StopStartBatcher}, - } - for _, test := range tests { - test := test - t.Run(test.name+"_SingularBatch", func(t *testing.T) { - test.f(t, func(sc *SystemConfig) { - sc.BatcherBatchType = derive.SingularBatchType - }) - }) - t.Run(test.name+"_SpanBatch", func(t *testing.T) { - test.f(t, func(sc *SystemConfig) { - sc.BatcherBatchType = derive.SpanBatchType - }) - }) - t.Run(test.name+"_SpanBatchMaxBlocks", func(t *testing.T) { - test.f(t, func(sc *SystemConfig) { - sc.BatcherBatchType = derive.SpanBatchType - sc.BatcherMaxBlocksPerSpanBatch = 2 - }) - }) - } -} - -func TestMain(m *testing.M) { - if config.ExternalL2Shim != "" { - fmt.Println("Running tests with external L2 process adapter at ", config.ExternalL2Shim) - // As these are integration tests which launch many other processes, the - // default parallelism makes the tests flaky. This change aims to - // reduce the flakiness of these tests. - maxProcs := runtime.NumCPU() / 4 - if maxProcs == 0 { - maxProcs = 1 - } - runtime.GOMAXPROCS(maxProcs) - } - - os.Exit(m.Run()) -} - -func TestL2OutputSubmitter(t *testing.T) { - InitParallel(t, SkipOnFaultProofs) - - 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") - - l1Client := sys.NodeClient("l1") - - rollupClient := sys.RollupClient("sequencer") - - // OutputOracle is already deployed - l2OutputOracle, err := bindings.NewL2OutputOracleCaller(cfg.L1Deployments.L2OutputOracleProxy, l1Client) - require.Nil(t, err) - - initialOutputBlockNumber, err := l2OutputOracle.LatestBlockNumber(&bind.CallOpts{}) - require.Nil(t, err) - - // Wait until the second output submission from L2. The output submitter submits outputs from the - // unsafe portion of the chain which gets reorged on startup. The sequencer has an out of date view - // when it creates it's first block and uses and old L1 Origin. It then does not submit a batch - // for that block and subsequently reorgs to match what the verifier derives when running the - // reconcillation process. - l2Verif := sys.NodeClient("verifier") - _, err = geth.WaitForBlock(big.NewInt(6), l2Verif, 10*time.Duration(cfg.DeployConfig.L2BlockTime)*time.Second) - require.Nil(t, err) - - // Wait for batch submitter to update L2 output oracle. - timeoutCh := time.After(15 * time.Second) - ticker := time.NewTicker(1 * time.Second) - defer ticker.Stop() - for { - l2ooBlockNumber, err := l2OutputOracle.LatestBlockNumber(&bind.CallOpts{}) - require.Nil(t, err) - - // Wait for the L2 output oracle to have been changed from the initial - // timestamp set in the contract constructor. - if l2ooBlockNumber.Cmp(initialOutputBlockNumber) > 0 { - // Retrieve the l2 output committed at this updated timestamp. - committedL2Output, err := l2OutputOracle.GetL2OutputAfter(&bind.CallOpts{}, l2ooBlockNumber) - require.NotEqual(t, [32]byte{}, committedL2Output.OutputRoot, "Empty L2 Output") - require.Nil(t, err) - - // Fetch the corresponding L2 block and assert the committed L2 - // output matches the block's state root. - // - // NOTE: This assertion will change once the L2 output format is - // finalized. - ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) - defer cancel() - l2Output, err := rollupClient.OutputAtBlock(ctx, l2ooBlockNumber.Uint64()) - require.Nil(t, err) - require.Equal(t, l2Output.OutputRoot[:], committedL2Output.OutputRoot[:]) - break - } - - select { - case <-timeoutCh: - t.Fatalf("State root oracle not updated") - case <-ticker.C: - } - } -} - -func TestL2OutputSubmitterFaultProofs(t *testing.T) { - InitParallel(t, SkipOnL2OO) - - 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") - - l1Client := sys.NodeClient("l1") - - rollupClient := sys.RollupClient("sequencer") - - disputeGameFactory, err := bindings.NewDisputeGameFactoryCaller(cfg.L1Deployments.DisputeGameFactoryProxy, l1Client) - require.Nil(t, err) - - initialGameCount, err := disputeGameFactory.GameCount(&bind.CallOpts{}) - require.Nil(t, err) - - l2Verif := sys.NodeClient("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 { - caller := batching.NewMultiCaller(l1Client.Client(), batching.DefaultBatchSize) - committedL2Output, err := disputeGameFactory.GameAtIndex(&bind.CallOpts{}, new(big.Int).Sub(latestGameCount, common.Big1)) - require.Nil(t, err) - proxy, err := contracts.NewFaultDisputeGameContract(context.Background(), metrics2.NoopContractMetrics, committedL2Output.Proxy, caller) - require.Nil(t, err) - claim, err := proxy.GetClaim(context.Background(), 0) - require.Nil(t, err) - - ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) - defer cancel() - _, gameBlockNumber, err := proxy.GetBlockRange(ctx) - require.Nil(t, err) - l2Output, err := rollupClient.OutputAtBlock(ctx, gameBlockNumber) - require.Nil(t, err) - require.EqualValues(t, l2Output.OutputRoot, claim.Value) - break - } - - select { - case <-timeoutCh: - t.Fatalf("State root oracle not updated") - case <-ticker.C: - } - } -} - -func TestSystemE2EDencunAtGenesis(t *testing.T) { - InitParallel(t) - - cfg := DefaultSystemConfig(t) - cfg.DeployConfig.L1CancunTimeOffset = &genesisTime - - sys, err := cfg.Start(t) - require.Nil(t, err, "Error starting up system") - - runE2ESystemTest(t, sys) - head, err := sys.NodeClient("l1").BlockByNumber(context.Background(), big.NewInt(0)) - require.NoError(t, err) - require.NotNil(t, head.ExcessBlobGas(), "L1 is building dencun blocks since genesis") -} - -// 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) - cfg.DeployConfig.L1CancunTimeOffset = &genesisTime - - sys, err := cfg.Start(t) - require.Nil(t, err, "Error starting up system") - - // send a blob-containing txn on l1 - ethPrivKey := sys.Cfg.Secrets.Alice - txData := transactions.CreateEmptyBlobTx(true, sys.Cfg.L1ChainIDBig().Uint64()) - tx := types.MustSignNewTx(ethPrivKey, types.LatestSignerForChainID(cfg.L1ChainIDBig()), txData) - // send blob-containing txn - sendCtx, sendCancel := context.WithTimeout(context.Background(), 15*time.Second) - defer sendCancel() - - l1Client := sys.NodeClient("l1") - err = l1Client.SendTransaction(sendCtx, tx) - require.NoError(t, err, "Sending L1 empty blob tx") - // Wait for transaction on L1 - 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.NodeClient("sequencer") - finalizedBlock, err := geth.WaitForL1OriginOnL2(sys.RollupConfig, blockContainsBlob.BlockNumber.Uint64(), l2Client, 30*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) - require.Nil(t, err, "Waiting for L1 origin of blob tx on L2") - finalizationTimeout := 30 * time.Duration(cfg.DeployConfig.L1BlockTime) * time.Second - _, err = geth.WaitForBlockToBeSafe(finalizedBlock.Header().Number, l2Client, finalizationTimeout) - require.Nil(t, err, "Waiting for safety of L2 block") -} - -// TestSystemE2E sets up a L1 Geth node, a rollup node, and a L2 geth node and then confirms that L1 deposits are reflected on L2. -// All nodes are run in process (but are the full nodes, not mocked or stubbed). -func TestSystemE2E(t *testing.T) { - InitParallel(t) - - cfg := DefaultSystemConfig(t) - - sys, err := cfg.Start(t) - require.Nil(t, err, "Error starting up system") - runE2ESystemTest(t, sys) - -} - -func runE2ESystemTest(t *testing.T, sys *System) { - 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.NodeClient("l1") - l2Seq := sys.NodeClient("sequencer") - l2Verif := sys.NodeClient("verifier") - - // Transactor Account - ethPrivKey := sys.Cfg.Secrets.Alice - - // Send Transaction & wait for success - fromAddr := sys.Cfg.Secrets.Addresses().Alice - - ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) - defer cancel() - startBalance, err := l2Verif.BalanceAt(ctx, fromAddr, nil) - require.Nil(t, err) - - // Send deposit transaction - opts, err := bind.NewKeyedTransactorWithChainID(ethPrivKey, sys.Cfg.L1ChainIDBig()) - require.Nil(t, err) - mintAmount := big.NewInt(1_000_000_000_000) - opts.Value = mintAmount - SendDepositTx(t, sys.Cfg, l1Client, l2Verif, opts, func(l2Opts *DepositTxOpts) {}) - - // Confirm balance - ctx, cancel = context.WithTimeout(context.Background(), 15*time.Second) - defer cancel() - - endBalance, err := wait.ForBalanceChange(ctx, l2Verif, fromAddr, startBalance) - require.Nil(t, err) - - diff := new(big.Int) - diff = diff.Sub(endBalance, startBalance) - require.Equal(t, mintAmount, diff, "Did not get expected balance change") - - // Submit TX to L2 sequencer node - receipt := SendL2Tx(t, sys.Cfg, l2Seq, ethPrivKey, func(opts *TxOpts) { - opts.Value = big.NewInt(1_000_000_000) - opts.Nonce = 1 // Already have deposit - opts.ToAddr = &common.Address{0xff, 0xff} - opts.VerifyOnClients(l2Verif) - }) - - // Verify blocks match after batch submission on verifiers and sequencers - verifBlock, err := l2Verif.BlockByNumber(context.Background(), receipt.BlockNumber) - require.Nil(t, err) - seqBlock, err := l2Seq.BlockByNumber(context.Background(), receipt.BlockNumber) - require.Nil(t, err) - require.Equal(t, verifBlock.NumberU64(), seqBlock.NumberU64(), "Verifier and sequencer blocks not the same after including a batch tx") - require.Equal(t, verifBlock.ParentHash(), seqBlock.ParentHash(), "Verifier and sequencer blocks parent hashes not the same after including a batch tx") - require.Equal(t, verifBlock.Hash(), seqBlock.Hash(), "Verifier and sequencer blocks not the same after including a batch tx") - - rollupClient := sys.RollupClient("sequencer") - // basic check that sync status works - seqStatus, err := rollupClient.SyncStatus(context.Background()) - require.Nil(t, err) - require.LessOrEqual(t, seqBlock.NumberU64(), seqStatus.UnsafeL2.Number) - // basic check that version endpoint works - seqVersion, err := rollupClient.Version(context.Background()) - require.Nil(t, err) - require.NotEqual(t, "", seqVersion) -} - -// TestConfirmationDepth runs the rollup with both sequencer and verifier not immediately processing the tip of the chain. -func TestConfirmationDepth(t *testing.T) { - InitParallel(t) - - cfg := DefaultSystemConfig(t) - cfg.DeployConfig.SequencerWindowSize = 4 - cfg.DeployConfig.MaxSequencerDrift = 10 * cfg.DeployConfig.L1BlockTime - seqConfDepth := uint64(2) - verConfDepth := uint64(5) - cfg.Nodes["sequencer"].Driver.SequencerConfDepth = seqConfDepth - cfg.Nodes["sequencer"].Driver.VerifierConfDepth = 0 - cfg.Nodes["verifier"].Driver.VerifierConfDepth = verConfDepth - - sys, err := cfg.Start(t) - require.Nil(t, err, "Error starting up system") - - 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.NodeClient("l1") - l2Seq := sys.NodeClient("sequencer") - l2Verif := sys.NodeClient("verifier") - - // Wait enough time for the sequencer to submit a block with distance from L1 head, submit it, - // and for the slower verifier to read a full sequence window and cover confirmation depth for reading and some margin - <-time.After(time.Duration((cfg.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(), 30*time.Second) - defer cancel() - l1Head, err := l1Client.BlockByNumber(ctx, nil) - require.NoError(t, err) - l2SeqHead, err := l2Seq.BlockByNumber(ctx, nil) - require.NoError(t, err) - l2VerHead, err := l2Verif.BlockByNumber(ctx, nil) - require.NoError(t, err) - - seqInfo, err := derive.L1BlockInfoFromBytes(sys.RollupConfig, l2SeqHead.Time(), l2SeqHead.Transactions()[0].Data()) - require.NoError(t, err) - require.LessOrEqual(t, seqInfo.Number+seqConfDepth, l1Head.NumberU64(), "the seq L2 head block should have an origin older than the L1 head block by at least the sequencer conf depth") - - verInfo, err := derive.L1BlockInfoFromBytes(sys.RollupConfig, l2VerHead.Time(), l2VerHead.Transactions()[0].Data()) - require.NoError(t, err) - require.LessOrEqual(t, verInfo.Number+verConfDepth, l1Head.NumberU64(), "the ver L2 head block should have an origin older than the L1 head block by at least the verifier conf depth") -} - -// TestPendingGasLimit tests the configuration of the gas limit of the pending block, -// and if it does not conflict with the regular gas limit on the verifier or sequencer. -func TestPendingGasLimit(t *testing.T) { - InitParallel(t) - - cfg := DefaultSystemConfig(t) - - // configure the L2 gas limit to be high, and the pending gas limits to be lower for resource saving. - cfg.DeployConfig.L2GenesisBlockGasLimit = 30_000_000 - cfg.GethOptions["sequencer"] = append(cfg.GethOptions["sequencer"], []geth.GethOption{ - func(ethCfg *ethconfig.Config, nodeCfg *node.Config) error { - ethCfg.Miner.GasCeil = 10_000_000 - ethCfg.Miner.RollupComputePendingBlock = true - return nil - }, - }...) - cfg.GethOptions["verifier"] = append(cfg.GethOptions["verifier"], []geth.GethOption{ - func(ethCfg *ethconfig.Config, nodeCfg *node.Config) error { - ethCfg.Miner.GasCeil = 9_000_000 - ethCfg.Miner.RollupComputePendingBlock = true - return nil - }, - }...) - - sys, err := cfg.Start(t) - require.Nil(t, err, "Error starting up system") - - 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.NodeClient("verifier") - l2Seq := sys.NodeClient("sequencer") - - checkGasLimit := func(client *ethclient.Client, number *big.Int, expected uint64) *types.Header { - ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) - header, err := client.HeaderByNumber(ctx, number) - cancel() - require.NoError(t, err) - require.Equal(t, expected, header.GasLimit) - return header - } - - // check if the gaslimits are matching the expected values, - // and that the verifier/sequencer can use their locally configured gas limit for the pending block. - for { - checkGasLimit(l2Seq, big.NewInt(-1), 10_000_000) - checkGasLimit(l2Verif, big.NewInt(-1), 9_000_000) - checkGasLimit(l2Seq, nil, 30_000_000) - latestVerifHeader := checkGasLimit(l2Verif, nil, 30_000_000) - - // Stop once the verifier passes genesis: - // this implies we checked a new block from the sequencer, on both sequencer and verifier nodes. - if latestVerifHeader.Number.Uint64() > 0 { - break - } - time.Sleep(500 * time.Millisecond) - } -} - -// TestFinalize tests if L2 finalizes after sufficient time after L1 finalizes -func TestFinalize(t *testing.T) { - InitParallel(t) - - cfg := DefaultSystemConfig(t) - - sys, err := cfg.Start(t) - require.Nil(t, err, "Error starting up system") - - l2Seq := sys.NodeClient("sequencer") - - l2Finalized, err := geth.WaitForBlockToBeFinalized(big.NewInt(12), l2Seq, 1*time.Minute) - require.NoError(t, err, "must be able to fetch a finalized L2 block") - require.NotZerof(t, l2Finalized.NumberU64(), "must have finalized L2 block") -} - -func TestMissingBatchE2E(t *testing.T) { - InitParallel(t) - // Note this test zeroes the balance of the batch-submitter to make the batches unable to go into L1. - // The test logs may look scary, but this is expected: - // 'batcher unable to publish transaction role=batcher err="insufficient funds for gas * price + value"' - - cfg := DefaultSystemConfig(t) - // small sequence window size so the test does not take as long - cfg.DeployConfig.SequencerWindowSize = 4 - - // Specifically set batch submitter balance to stop batches from being included - cfg.Premine[cfg.Secrets.Addresses().Batcher] = big.NewInt(0) - - sys, err := cfg.Start(t) - require.Nil(t, err, "Error starting up system") - - l2Seq := sys.NodeClient("sequencer") - l2Verif := sys.NodeClient("verifier") - - seqRollupClient := sys.RollupClient("sequencer") - - // Transactor Account - ethPrivKey := cfg.Secrets.Alice - - // Submit TX to L2 sequencer node - receipt := SendL2Tx(t, cfg, l2Seq, ethPrivKey, func(opts *TxOpts) { - opts.ToAddr = &common.Address{0xff, 0xff} - opts.Value = big.NewInt(1_000_000_000) - }) - - // Wait until the block it was first included in shows up in the safe chain on the verifier - _, err = geth.WaitForBlock(receipt.BlockNumber, l2Verif, time.Duration((sys.RollupConfig.SeqWindowSize+4)*cfg.DeployConfig.L1BlockTime)*time.Second) - 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(), 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") - - // Wait a short time for the L2 reorg to occur on the sequencer as well. - err = wait.ForSafeBlock(ctx, seqRollupClient, receipt.BlockNumber.Uint64()) - 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(), 30*time.Second) - defer cancel() - block, err := l2Seq.BlockByNumber(ctx2, receipt.BlockNumber) - if err != nil { - require.Equal(t, "not found", err.Error(), "A not found error indicates the chain must have re-orged back before it") - } else { - require.NotEqual(t, block.Hash(), receipt.BlockHash, "L2 Sequencer did not reorg out transaction on it's safe chain") - } -} - -func L1InfoFromState(ctx context.Context, contract *bindings.L1Block, l2Number *big.Int, ecotone bool) (*derive.L1BlockInfo, error) { - var err error - out := &derive.L1BlockInfo{} - opts := bind.CallOpts{ - BlockNumber: l2Number, - Context: ctx, - } - - out.Number, err = contract.Number(&opts) - if err != nil { - return nil, fmt.Errorf("failed to get number: %w", err) - } - - out.Time, err = contract.Timestamp(&opts) - if err != nil { - return nil, fmt.Errorf("failed to get timestamp: %w", err) - } - - out.BaseFee, err = contract.Basefee(&opts) - if err != nil { - return nil, fmt.Errorf("failed to get base fee: %w", err) - } - - blockHashBytes, err := contract.Hash(&opts) - if err != nil { - return nil, fmt.Errorf("failed to get block hash: %w", err) - } - out.BlockHash = common.BytesToHash(blockHashBytes[:]) - - out.SequenceNumber, err = contract.SequenceNumber(&opts) - if err != nil { - return nil, fmt.Errorf("failed to get sequence number: %w", err) - } - - if !ecotone { - overhead, err := contract.L1FeeOverhead(&opts) - if err != nil { - return nil, fmt.Errorf("failed to get l1 fee overhead: %w", err) - } - out.L1FeeOverhead = eth.Bytes32(common.BigToHash(overhead)) - - scalar, err := contract.L1FeeScalar(&opts) - if err != nil { - return nil, fmt.Errorf("failed to get l1 fee scalar: %w", err) - } - out.L1FeeScalar = eth.Bytes32(common.BigToHash(scalar)) - } - - batcherHash, err := contract.BatcherHash(&opts) - if err != nil { - return nil, fmt.Errorf("failed to get batch sender: %w", err) - } - out.BatcherAddr = common.BytesToAddress(batcherHash[:]) - - if ecotone { - blobBaseFeeScalar, err := contract.BlobBaseFeeScalar(&opts) - if err != nil { - return nil, fmt.Errorf("failed to get blob basefee scalar: %w", err) - } - out.BlobBaseFeeScalar = blobBaseFeeScalar - - baseFeeScalar, err := contract.BaseFeeScalar(&opts) - if err != nil { - return nil, fmt.Errorf("failed to get basefee scalar: %w", err) - } - out.BaseFeeScalar = baseFeeScalar - - blobBaseFee, err := contract.BlobBaseFee(&opts) - if err != nil { - return nil, fmt.Errorf("failed to get blob basefee: %w", err) - } - out.BlobBaseFee = blobBaseFee - } - - return out, nil -} - -// TestSystemMockP2P sets up a L1 Geth node, a rollup node, and a L2 geth node and then confirms that -// the nodes can sync L2 blocks before they are confirmed on L1. -func TestSystemMockP2P(t *testing.T) { - InitParallel(t) - - cfg := DefaultSystemConfig(t) - // Disable batcher, so we don't sync from L1 & set a large sequence window so we only have unsafe blocks - cfg.DisableBatcher = true - cfg.DeployConfig.SequencerWindowSize = 100_000 - cfg.DeployConfig.MaxSequencerDrift = 100_000 - // disable at the start, so we don't miss any gossiped blocks. - cfg.Nodes["sequencer"].Driver.SequencerStopped = true - - // connect the nodes - cfg.P2PTopology = map[string][]string{ - "verifier": {"sequencer"}, - } - - var published, received []common.Hash - seqTracer, verifTracer := new(FnTracer), new(FnTracer) - seqTracer.OnPublishL2PayloadFn = func(ctx context.Context, payload *eth.ExecutionPayloadEnvelope) { - published = append(published, payload.ExecutionPayload.BlockHash) - } - verifTracer.OnUnsafeL2PayloadFn = func(ctx context.Context, from peer.ID, payload *eth.ExecutionPayloadEnvelope) { - received = append(received, payload.ExecutionPayload.BlockHash) - } - cfg.Nodes["sequencer"].Tracer = seqTracer - cfg.Nodes["verifier"].Tracer = verifTracer - - sys, err := cfg.Start(t) - require.Nil(t, err, "Error starting up system") - - // Enable the sequencer now that everyone is ready to receive payloads. - rollupClient := sys.RollupClient("sequencer") - - verifierPeerID := sys.RollupNodes["verifier"].P2P().Host().ID() - check := func() bool { - sequencerBlocksTopicPeers := sys.RollupNodes["sequencer"].P2P().GossipOut().AllBlockTopicsPeers() - return slices.Contains[[]peer.ID](sequencerBlocksTopicPeers, verifierPeerID) - } - - // poll to see if the verifier node is connected & meshed on gossip. - // Without this verifier, we shouldn't start sending blocks around, or we'll miss them and fail the test. - backOffStrategy := retry.Exponential() - for i := 0; i < 10; i++ { - if check() { - break - } - time.Sleep(backOffStrategy.Duration(i)) - } - require.True(t, check(), "verifier must be meshed with sequencer for gossip test to proceed") - - require.NoError(t, rollupClient.StartSequencer(context.Background(), sys.L2GenesisCfg.ToBlock().Hash())) - - l2Seq := sys.NodeClient("sequencer") - l2Verif := sys.NodeClient("verifier") - - // Transactor Account - ethPrivKey := cfg.Secrets.Alice - - // Submit TX to L2 sequencer node - receiptSeq := SendL2Tx(t, cfg, l2Seq, ethPrivKey, func(opts *TxOpts) { - opts.ToAddr = &common.Address{0xff, 0xff} - opts.Value = big.NewInt(1_000_000_000) - - // Wait until the block it was first included in shows up in the safe chain on the verifier - opts.VerifyOnClients(l2Verif) - }) - - // Verify that everything that was received was published - require.GreaterOrEqual(t, len(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) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - InitParallel(t) - - cfg := DefaultSystemConfig(t) - - // remove default verifier node - delete(cfg.Nodes, "verifier") - // Add more verifier nodes - cfg.Nodes["alice"] = &rollupNode.Config{ - Driver: driver.Config{ - VerifierConfDepth: 0, - SequencerConfDepth: 0, - SequencerEnabled: false, - }, - L1EpochPollInterval: time.Second * 4, - } - cfg.Nodes["bob"] = &rollupNode.Config{ - Driver: driver.Config{ - VerifierConfDepth: 0, - SequencerConfDepth: 0, - SequencerEnabled: false, - }, - L1EpochPollInterval: time.Second * 4, - } - 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{ - "sequencer": {"alice", "bob"}, - "alice": {"sequencer", "bob"}, - "bob": {"alice", "sequencer"}, - } - // Enable the P2P req-resp based sync - cfg.P2PReqRespSync = true - - // Disable batcher, so there will not be any L1 data to sync from - cfg.DisableBatcher = true - - var published []string - seqTracer := new(FnTracer) - // The sequencer still publishes the blocks to the tracer, even if they do not reach the network due to disabled P2P - seqTracer.OnPublishL2PayloadFn = func(ctx context.Context, payload *eth.ExecutionPayloadEnvelope) { - published = append(published, payload.ExecutionPayload.ID().String()) - } - // Blocks are now received via the RPC based alt-sync method - cfg.Nodes["sequencer"].Tracer = seqTracer - - sys, err := cfg.Start(t) - require.Nil(t, err, "Error starting up system") - - l2Seq := sys.NodeClient("sequencer") - - // Transactor Account - ethPrivKey := cfg.Secrets.Alice - - // Submit a TX to L2 sequencer node - receiptSeq := SendL2Tx(t, cfg, l2Seq, ethPrivKey, func(opts *TxOpts) { - opts.ToAddr = &common.Address{0xff, 0xff} - opts.Value = big.NewInt(1_000_000_000) - }) - - // Gossip is able to respond to IWANT messages for the duration of heartbeat_time * message_window = 0.5 * 12 = 6 - // Wait till we pass that, and then we'll have missed some blocks that cannot be retrieved in any way from gossip - time.Sleep(time.Second * 10) - - // set up our syncer node, connect it to alice/bob - cfg.Loggers["syncer"] = testlog.Logger(t, log.LevelInfo).New("role", "syncer") - - // Create a peer, and hook up alice and bob - h, err := sys.newMockNetPeer() - require.NoError(t, err) - _, err = sys.Mocknet.LinkPeers(sys.RollupNodes["alice"].P2P().Host().ID(), h.ID()) - require.NoError(t, err) - _, err = sys.Mocknet.LinkPeers(sys.RollupNodes["bob"].P2P().Host().ID(), h.ID()) - require.NoError(t, err) - - // Configure the new rollup node that'll be syncing - var syncedPayloads []string - syncNodeCfg := &rollupNode.Config{ - Driver: driver.Config{VerifierConfDepth: 0}, - Rollup: *sys.RollupConfig, - P2PSigner: nil, - RPC: rollupNode.RPCConfig{ - ListenAddr: "127.0.0.1", - ListenPort: 0, - EnableAdmin: true, - }, - P2P: &p2p.Prepared{HostP2P: h, EnableReqRespSync: true}, - Metrics: rollupNode.MetricsConfig{Enabled: false}, // no metrics server - Pprof: oppprof.CLIConfig{}, - L1EpochPollInterval: time.Second * 10, - Tracer: &FnTracer{ - OnUnsafeL2PayloadFn: func(ctx context.Context, from peer.ID, payload *eth.ExecutionPayloadEnvelope) { - syncedPayloads = append(syncedPayloads, payload.ExecutionPayload.ID().String()) - }, - }, - } - configureL1(syncNodeCfg, sys.EthInstances["l1"], sys.L1BeaconEndpoint()) - syncerL2Engine, err := geth.InitL2("syncer", sys.L2GenesisCfg, cfg.JWTFilePath) - require.NoError(t, err) - require.NoError(t, syncerL2Engine.Node.Start()) - - configureL2(syncNodeCfg, syncerL2Engine, cfg.JWTSecret) - - syncerNode, err := rollupNode.New(ctx, syncNodeCfg, cfg.Loggers["syncer"], "", metrics.NewMetrics("")) - require.NoError(t, err) - 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()) - require.NoError(t, err) - _, err = sys.Mocknet.ConnectPeers(sys.RollupNodes["bob"].P2P().Host().ID(), syncerNode.P2P().Host().ID()) - require.NoError(t, err) - - rpc := syncerL2Engine.UserRPC().(endpoint.ClientRPC).ClientRPC() - l2Verif := ethclient.NewClient(rpc) - - // It may take a while to sync, but eventually we should see the sequenced data show up - receiptVerif, err := wait.ForReceiptOK(ctx, l2Verif, receiptSeq.TxHash) - require.Nil(t, err, "Waiting for L2 tx on verifier") - - require.Equal(t, receiptSeq, receiptVerif) - - // Verify that the tx was received via P2P sync - require.Contains(t, syncedPayloads, eth.BlockID{Hash: receiptVerif.BlockHash, Number: receiptVerif.BlockNumber.Uint64()}.String()) - - // Verify that everything that was received was published - require.GreaterOrEqual(t, len(published), len(syncedPayloads)) - require.Subset(t, published, syncedPayloads) -} - -// TestSystemDenseTopology sets up a dense p2p topology with 3 verifier nodes and 1 sequencer node. -func TestSystemDenseTopology(t *testing.T) { - t.Skip("Skipping dense topology test to avoid flakiness. @refcell address in p2p scoring pr.") - - InitParallel(t) - - cfg := DefaultSystemConfig(t) - // slow down L1 blocks so we can see the L2 blocks arrive well before the L1 blocks do. - // Keep the seq window small so the L2 chain is started quick - cfg.DeployConfig.L1BlockTime = 10 - - // Append additional nodes to the system to construct a dense p2p network - cfg.Nodes["verifier2"] = &rollupNode.Config{ - Driver: driver.Config{ - VerifierConfDepth: 0, - SequencerConfDepth: 0, - SequencerEnabled: false, - }, - L1EpochPollInterval: time.Second * 4, - } - cfg.Nodes["verifier3"] = &rollupNode.Config{ - Driver: driver.Config{ - VerifierConfDepth: 0, - SequencerConfDepth: 0, - SequencerEnabled: false, - }, - L1EpochPollInterval: time.Second * 4, - } - 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{ - "verifier": {"sequencer", "verifier2", "verifier3"}, - "verifier2": {"sequencer", "verifier", "verifier3"}, - "verifier3": {"sequencer", "verifier", "verifier2"}, - } - - // Set peer scoring for each node, but without banning - for _, node := range cfg.Nodes { - params, err := p2p.GetScoringParams("light", &node.Rollup) - require.NoError(t, err) - node.P2P = &p2p.Config{ - ScoringParams: params, - BanningEnabled: false, - } - } - - var published, received1, received2, received3 []common.Hash - seqTracer, verifTracer, verifTracer2, verifTracer3 := new(FnTracer), new(FnTracer), new(FnTracer), new(FnTracer) - seqTracer.OnPublishL2PayloadFn = func(ctx context.Context, payload *eth.ExecutionPayloadEnvelope) { - published = append(published, payload.ExecutionPayload.BlockHash) - } - verifTracer.OnUnsafeL2PayloadFn = func(ctx context.Context, from peer.ID, payload *eth.ExecutionPayloadEnvelope) { - received1 = append(received1, payload.ExecutionPayload.BlockHash) - } - verifTracer2.OnUnsafeL2PayloadFn = func(ctx context.Context, from peer.ID, payload *eth.ExecutionPayloadEnvelope) { - received2 = append(received2, payload.ExecutionPayload.BlockHash) - } - verifTracer3.OnUnsafeL2PayloadFn = func(ctx context.Context, from peer.ID, payload *eth.ExecutionPayloadEnvelope) { - received3 = append(received3, payload.ExecutionPayload.BlockHash) - } - cfg.Nodes["sequencer"].Tracer = seqTracer - cfg.Nodes["verifier"].Tracer = verifTracer - cfg.Nodes["verifier2"].Tracer = verifTracer2 - cfg.Nodes["verifier3"].Tracer = verifTracer3 - - sys, err := cfg.Start(t) - require.Nil(t, err, "Error starting up system") - - l2Seq := sys.NodeClient("sequencer") - l2Verif := sys.NodeClient("verifier") - l2Verif2 := sys.NodeClient("verifier2") - l2Verif3 := sys.NodeClient("verifier3") - - // Transactor Account - ethPrivKey := cfg.Secrets.Alice - - // Submit TX to L2 sequencer node - receiptSeq := SendL2Tx(t, cfg, l2Seq, ethPrivKey, func(opts *TxOpts) { - opts.ToAddr = &common.Address{0xff, 0xff} - opts.Value = big.NewInt(1_000_000_000) - - // Wait until the block it was first included in shows up in the safe chain on the verifiers - opts.VerifyOnClients(l2Verif, l2Verif2, l2Verif3) - }) - - // Verify that everything that was received was published - require.GreaterOrEqual(t, len(published), len(received1)) - require.GreaterOrEqual(t, len(published), len(received2)) - require.GreaterOrEqual(t, len(published), len(received3)) - require.ElementsMatch(t, published, received1[:len(published)]) - require.ElementsMatch(t, published, received2[:len(published)]) - require.ElementsMatch(t, published, received3[:len(published)]) - - // Verify that the tx was received via p2p - require.Contains(t, received1, receiptSeq.BlockHash) - require.Contains(t, received2, receiptSeq.BlockHash) - require.Contains(t, received3, receiptSeq.BlockHash) -} - -func TestL1InfoContract(t *testing.T) { - InitParallel(t) - - cfg := DefaultSystemConfig(t) - - sys, err := cfg.Start(t) - require.Nil(t, err, "Error starting up system") - - l1Client := sys.NodeClient("l1") - l2Seq := sys.NodeClient("sequencer") - l2Verif := sys.NodeClient("verifier") - - endVerifBlockNumber := big.NewInt(4) - endSeqBlockNumber := big.NewInt(6) - endVerifBlock, err := geth.WaitForBlock(endVerifBlockNumber, l2Verif, time.Minute) - require.Nil(t, err) - endSeqBlock, err := geth.WaitForBlock(endSeqBlockNumber, l2Seq, time.Minute) - require.Nil(t, err) - - seqL1Info, err := bindings.NewL1Block(cfg.L1InfoPredeployAddress, l2Seq) - require.Nil(t, err) - - verifL1Info, err := bindings.NewL1Block(cfg.L1InfoPredeployAddress, l2Verif) - require.Nil(t, err) - - ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) - defer cancel() - - fillInfoLists := func(start *types.Block, contract *bindings.L1Block, client *ethclient.Client) ([]*derive.L1BlockInfo, []*derive.L1BlockInfo) { - var txList, stateList []*derive.L1BlockInfo - for b := start; ; { - var infoFromTx *derive.L1BlockInfo - infoFromTx, err := derive.L1BlockInfoFromBytes(sys.RollupConfig, b.Time(), b.Transactions()[0].Data()) - require.NoError(t, err) - txList = append(txList, infoFromTx) - - ecotone := sys.RollupConfig.IsEcotone(b.Time()) && !sys.RollupConfig.IsEcotoneActivationBlock(b.Time()) - infoFromState, err := L1InfoFromState(ctx, contract, b.Number(), ecotone) - require.Nil(t, err) - stateList = append(stateList, infoFromState) - - // Genesis L2 block contains no L1 Deposit TX - if b.NumberU64() == 1 { - return txList, stateList - } - b, err = client.BlockByHash(ctx, b.ParentHash()) - require.Nil(t, err) - } - } - - l1InfosFromSequencerTransactions, l1InfosFromSequencerState := fillInfoLists(endSeqBlock, seqL1Info, l2Seq) - l1InfosFromVerifierTransactions, l1InfosFromVerifierState := fillInfoLists(endVerifBlock, verifL1Info, l2Verif) - - l1blocks := make(map[common.Hash]*derive.L1BlockInfo) - maxL1Hash := l1InfosFromSequencerTransactions[0].BlockHash - for h := maxL1Hash; ; { - b, err := l1Client.BlockByHash(ctx, h) - require.Nil(t, err) - - l1blocks[h] = &derive.L1BlockInfo{ - Number: b.NumberU64(), - Time: b.Time(), - BaseFee: b.BaseFee(), - BlockHash: h, - SequenceNumber: 0, // ignored, will be overwritten - BatcherAddr: sys.RollupConfig.Genesis.SystemConfig.BatcherAddr, - } - if sys.RollupConfig.IsEcotone(b.Time()) && !sys.RollupConfig.IsEcotoneActivationBlock(b.Time()) { - scalars, err := sys.RollupConfig.Genesis.SystemConfig.EcotoneScalars() - require.NoError(t, err) - l1blocks[h].BlobBaseFeeScalar = scalars.BlobBaseFeeScalar - l1blocks[h].BaseFeeScalar = scalars.BaseFeeScalar - if excess := b.ExcessBlobGas(); excess != nil { - l1blocks[h].BlobBaseFee = eip4844.CalcBlobFee(*excess) - } else { - l1blocks[h].BlobBaseFee = big.NewInt(1) - } - } else { - l1blocks[h].L1FeeOverhead = sys.RollupConfig.Genesis.SystemConfig.Overhead - l1blocks[h].L1FeeScalar = sys.RollupConfig.Genesis.SystemConfig.Scalar - } - - h = b.ParentHash() - if b.NumberU64() == 0 { - break - } - } - - checkInfoList := func(name string, list []*derive.L1BlockInfo) { - for _, info := range list { - if expected, ok := l1blocks[info.BlockHash]; ok { - expected.SequenceNumber = info.SequenceNumber // the seq nr is not part of the L1 info we know in advance, so we ignore it. - require.Equal(t, expected, info) - } else { - t.Fatalf("Did not find block hash for L1 Info: %v in test %s", info, name) - } - } - } - - checkInfoList("On sequencer with tx", l1InfosFromSequencerTransactions) - checkInfoList("On sequencer with state", l1InfosFromSequencerState) - checkInfoList("On verifier with tx", l1InfosFromVerifierTransactions) - checkInfoList("On verifier with state", l1InfosFromVerifierState) -} - -// TestWithdrawals checks that a deposit and then withdrawal execution succeeds. It verifies the -// balance changes on L1 and L2 and has to include gas fees in the balance checks. -// It does not check that the withdrawal can be executed prior to the end of the finality period. -func TestWithdrawals(t *testing.T) { - InitParallel(t) - - cfg := DefaultSystemConfig(t) - cfg.DeployConfig.FinalizationPeriodSeconds = 2 // 2s finalization period - cfg.L1FinalizedDistance = 2 // Finalize quick, don't make the proposer wait too long - - sys, err := cfg.Start(t) - require.NoError(t, err, "Error starting up system") - - RunWithdrawalsTest(t, sys) -} - -type stateGetterAdapter struct { - ctx context.Context - t *testing.T - client *ethclient.Client - blockNum *big.Int -} - -func (sga *stateGetterAdapter) GetState(addr common.Address, key common.Hash) common.Hash { - sga.t.Helper() - val, err := sga.client.StorageAt(sga.ctx, addr, key, sga.blockNum) - require.NoError(sga.t, err) - var res common.Hash - copy(res[:], val) - return res -} - -// TestFees checks that L1/L2 fees are handled. -func TestFees(t *testing.T) { - t.Run("pre-regolith", func(t *testing.T) { - InitParallel(t) - cfg := RegolithSystemConfig(t, nil) - cfg.DeployConfig.L1GenesisBlockBaseFeePerGas = (*hexutil.Big)(big.NewInt(7)) - - testFees(t, cfg) - }) - t.Run("regolith", func(t *testing.T) { - InitParallel(t) - cfg := RegolithSystemConfig(t, &genesisTime) - cfg.DeployConfig.L1GenesisBlockBaseFeePerGas = (*hexutil.Big)(big.NewInt(7)) - - testFees(t, cfg) - }) - t.Run("ecotone", func(t *testing.T) { - InitParallel(t) - cfg := EcotoneSystemConfig(t, &genesisTime) - cfg.DeployConfig.L1GenesisBlockBaseFeePerGas = (*hexutil.Big)(big.NewInt(7)) - - testFees(t, cfg) - }) - t.Run("fjord", func(t *testing.T) { - InitParallel(t) - cfg := DefaultSystemConfig(t) - cfg.DeployConfig.L1GenesisBlockBaseFeePerGas = (*hexutil.Big)(big.NewInt(7)) - - cfg.DeployConfig.L2GenesisRegolithTimeOffset = new(hexutil.Uint64) - cfg.DeployConfig.L2GenesisCanyonTimeOffset = new(hexutil.Uint64) - cfg.DeployConfig.L2GenesisDeltaTimeOffset = new(hexutil.Uint64) - cfg.DeployConfig.L2GenesisEcotoneTimeOffset = new(hexutil.Uint64) - cfg.DeployConfig.L2GenesisFjordTimeOffset = new(hexutil.Uint64) - testFees(t, cfg) - }) -} - -func testFees(t *testing.T, cfg SystemConfig) { - sys, err := cfg.Start(t) - require.Nil(t, err, "Error starting up system") - - l2Seq := sys.NodeClient("sequencer") - l2Verif := sys.NodeClient("verifier") - l1 := sys.NodeClient("l1") - - // Wait for first block after genesis. The genesis block has zero L1Block values and will throw off the GPO checks - _, err = geth.WaitForBlock(big.NewInt(1), l2Verif, time.Minute) - require.NoError(t, err) - - config := sys.L2Genesis().Config - - sga := &stateGetterAdapter{ - ctx: context.Background(), - t: t, - client: l2Seq, - } - - l1CostFn := types.NewL1CostFunc(config, sga) - - // Transactor Account - ethPrivKey := cfg.Secrets.Alice - fromAddr := crypto.PubkeyToAddress(ethPrivKey.PublicKey) - - require.NotEqual(t, cfg.DeployConfig.L2OutputOracleProposer, fromAddr) - require.NotEqual(t, cfg.DeployConfig.BatchSenderAddress, fromAddr) - - // Find gaspriceoracle contract - gpoContract, err := bindings.NewGasPriceOracle(predeploys.GasPriceOracleAddr, l2Seq) - require.Nil(t, err) - - if !sys.RollupConfig.IsEcotone(sys.L2GenesisCfg.Timestamp) { - overhead, err := gpoContract.Overhead(&bind.CallOpts{}) - require.Nil(t, err, "reading gpo overhead") - require.Equal(t, overhead.Uint64(), cfg.DeployConfig.GasPriceOracleOverhead, "wrong gpo overhead") - - scalar, err := gpoContract.Scalar(&bind.CallOpts{}) - require.Nil(t, err, "reading gpo scalar") - feeScalar := cfg.DeployConfig.FeeScalar() - require.Equal(t, scalar, new(big.Int).SetBytes(feeScalar[:]), "wrong gpo scalar") - } else { - _, err := gpoContract.Overhead(&bind.CallOpts{}) - require.ErrorContains(t, err, "deprecated") - _, err = gpoContract.Scalar(&bind.CallOpts{}) - require.ErrorContains(t, err, "deprecated") - } - - decimals, err := gpoContract.Decimals(&bind.CallOpts{}) - require.Nil(t, err, "reading gpo decimals") - - require.Equal(t, decimals.Uint64(), uint64(6), "wrong gpo decimals") - - // BaseFee Recipient - baseFeeRecipientStartBalance, err := l2Seq.BalanceAt(context.Background(), predeploys.BaseFeeVaultAddr, big.NewInt(rpc.EarliestBlockNumber.Int64())) - require.Nil(t, err) - - // L1Fee Recipient - l1FeeRecipientStartBalance, err := l2Seq.BalanceAt(context.Background(), predeploys.L1FeeVaultAddr, big.NewInt(rpc.EarliestBlockNumber.Int64())) - require.Nil(t, err) - - sequencerFeeVaultStartBalance, err := l2Seq.BalanceAt(context.Background(), predeploys.SequencerFeeVaultAddr, big.NewInt(rpc.EarliestBlockNumber.Int64())) - require.Nil(t, err) - - genesisBlock, err := l2Seq.BlockByNumber(context.Background(), big.NewInt(rpc.EarliestBlockNumber.Int64())) - require.NoError(t, err) - - coinbaseStartBalance, err := l2Seq.BalanceAt(context.Background(), genesisBlock.Coinbase(), big.NewInt(rpc.EarliestBlockNumber.Int64())) - require.NoError(t, err) - - // Simple transfer from signer to random account - startBalance, err := l2Seq.BalanceAt(context.Background(), fromAddr, big.NewInt(rpc.EarliestBlockNumber.Int64())) - require.Nil(t, err) - require.Greater(t, startBalance.Uint64(), big.NewInt(params.Ether).Uint64()) - - transferAmount := big.NewInt(params.Ether) - gasTip := big.NewInt(10) - receipt := SendL2Tx(t, cfg, l2Seq, ethPrivKey, func(opts *TxOpts) { - opts.ToAddr = &common.Address{0xff, 0xff} - opts.Value = transferAmount - opts.GasTipCap = gasTip - opts.Gas = 21000 - opts.GasFeeCap = big.NewInt(200) - opts.VerifyOnClients(l2Verif) - }) - - require.Equal(t, receipt.Status, types.ReceiptStatusSuccessful) - - header, err := l2Seq.HeaderByNumber(context.Background(), receipt.BlockNumber) - require.Nil(t, err) - - coinbaseEndBalance, err := l2Seq.BalanceAt(context.Background(), header.Coinbase, header.Number) - require.Nil(t, err) - - endBalance, err := l2Seq.BalanceAt(context.Background(), fromAddr, header.Number) - require.Nil(t, err) - - baseFeeRecipientEndBalance, err := l2Seq.BalanceAt(context.Background(), predeploys.BaseFeeVaultAddr, header.Number) - require.Nil(t, err) - - l1Header, err := l1.HeaderByNumber(context.Background(), nil) - require.Nil(t, err) - - l1FeeRecipientEndBalance, err := l2Seq.BalanceAt(context.Background(), predeploys.L1FeeVaultAddr, header.Number) - require.Nil(t, err) - - sequencerFeeVaultEndBalance, err := l2Seq.BalanceAt(context.Background(), predeploys.SequencerFeeVaultAddr, header.Number) - require.Nil(t, err) - - // Diff fee recipient + coinbase balances - baseFeeRecipientDiff := new(big.Int).Sub(baseFeeRecipientEndBalance, baseFeeRecipientStartBalance) - l1FeeRecipientDiff := new(big.Int).Sub(l1FeeRecipientEndBalance, l1FeeRecipientStartBalance) - sequencerFeeVaultDiff := new(big.Int).Sub(sequencerFeeVaultEndBalance, sequencerFeeVaultStartBalance) - coinbaseDiff := new(big.Int).Sub(coinbaseEndBalance, coinbaseStartBalance) - - // Tally L2 Fee - l2Fee := gasTip.Mul(gasTip, new(big.Int).SetUint64(receipt.GasUsed)) - require.Equal(t, sequencerFeeVaultDiff, coinbaseDiff, "coinbase is always sequencer fee vault") - require.Equal(t, l2Fee, coinbaseDiff, "l2 fee mismatch") - require.Equal(t, l2Fee, sequencerFeeVaultDiff) - - // Tally BaseFee - baseFee := new(big.Int).Mul(header.BaseFee, new(big.Int).SetUint64(receipt.GasUsed)) - require.Equal(t, baseFee, baseFeeRecipientDiff, "base fee mismatch") - - // Tally L1 Fee - tx, _, err := l2Seq.TransactionByHash(context.Background(), receipt.TxHash) - require.NoError(t, err, "Should be able to get transaction") - bytes, err := tx.MarshalBinary() - require.Nil(t, err) - - l1Fee := l1CostFn(tx.RollupCostData(), header.Time) - require.Equalf(t, l1Fee, l1FeeRecipientDiff, "L1 fee mismatch: start balance %v, end balance %v", l1FeeRecipientStartBalance, l1FeeRecipientEndBalance) - - gpoEcotone, err := gpoContract.IsEcotone(nil) - require.NoError(t, err) - require.Equal(t, sys.RollupConfig.IsEcotone(header.Time), gpoEcotone, "GPO and chain must have same ecotone view") - - gpoFjord, err := gpoContract.IsFjord(nil) - require.NoError(t, err) - require.Equal(t, sys.RollupConfig.IsFjord(header.Time), gpoFjord, "GPO and chain must have same fjord view") - - gpoL1Fee, err := gpoContract.GetL1Fee(&bind.CallOpts{}, bytes) - require.Nil(t, err) - - adjustedGPOFee := gpoL1Fee - if sys.RollupConfig.IsFjord(header.Time) { - // The fastlz size of the transaction is 102 bytes - require.Equal(t, uint64(102), tx.RollupCostData().FastLzSize) - // Which results in both the fjord cost function and GPO using the minimum value for the fastlz regression: - // Geth Linear Regression: -42.5856 + 102 * 0.8365 = 42.7374 - // GPO Linear Regression: -42.5856 + 170 * 0.8365 = 99.6194 - // The additional 68 (170 vs. 102) is due to the GPO adding 68 bytes to account for the signature. - require.Greater(t, types.MinTransactionSize.Uint64(), uint64(99)) - // Because of this, we don't need to do any adjustment as the GPO and cost func are both bounded to the minimum value. - // However, if the fastlz regression output is ever larger than the minimum, this will require an adjustment. - } else if sys.RollupConfig.IsRegolith(header.Time) { - // if post-regolith, adjust the GPO fee by removing the overhead it adds because of signature data - artificialGPOOverhead := big.NewInt(68 * 16) // it adds 68 bytes to cover signature and RLP data - l1BaseFee := big.NewInt(7) // we assume the L1 basefee is the minimum, 7 - // in our case we already include that, so we subtract it, to do a 1:1 comparison - adjustedGPOFee = new(big.Int).Sub(gpoL1Fee, new(big.Int).Mul(artificialGPOOverhead, l1BaseFee)) - } - require.Equal(t, l1Fee, adjustedGPOFee, "GPO reports L1 fee mismatch") - - require.Equal(t, receipt.L1Fee, l1Fee, "l1 fee in receipt is correct") - if !sys.RollupConfig.IsEcotone(header.Time) { // FeeScalar receipt attribute is removed as of Ecotone - require.Equal(t, - new(big.Float).Mul( - new(big.Float).SetInt(l1Header.BaseFee), - new(big.Float).Mul(new(big.Float).SetInt(receipt.L1GasUsed), receipt.FeeScalar), - ), - new(big.Float).SetInt(receipt.L1Fee), "fee field in receipt matches gas used times scalar times base fee") - } - - // Calculate total fee - baseFeeRecipientDiff.Add(baseFeeRecipientDiff, coinbaseDiff) - totalFee := new(big.Int).Add(baseFeeRecipientDiff, l1FeeRecipientDiff) - balanceDiff := new(big.Int).Sub(startBalance, endBalance) - balanceDiff.Sub(balanceDiff, transferAmount) - require.Equal(t, balanceDiff, totalFee, "balances should add up") -} - -func StopStartBatcher(t *testing.T, cfgMod func(*SystemConfig)) { - InitParallel(t) - - cfg := DefaultSystemConfig(t) - cfgMod(&cfg) - sys, err := cfg.Start(t) - require.NoError(t, err, "Error starting up system") - - rollupClient := sys.RollupClient("verifier") - - l2Seq := sys.NodeClient("sequencer") - l2Verif := sys.NodeClient("verifier") - - // retrieve the initial sync status - seqStatus, err := rollupClient.SyncStatus(context.Background()) - require.NoError(t, err) - - nonce := uint64(0) - sendTx := func() *types.Receipt { - // Submit TX to L2 sequencer node - receipt := SendL2Tx(t, cfg, l2Seq, cfg.Secrets.Alice, func(opts *TxOpts) { - opts.ToAddr = &common.Address{0xff, 0xff} - opts.Value = big.NewInt(1_000_000_000) - opts.Nonce = nonce - }) - nonce++ - return receipt - } - // send a transaction - receipt := sendTx() - - // 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.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.NoError(t, err) - require.Greater(t, newSeqStatus.SafeL2.Number, seqStatus.SafeL2.Number, "Safe chain did not advance") - - driver := sys.BatchSubmitter.TestDriver() - // stop the batch submission - err = driver.StopBatchSubmitting(context.Background()) - 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.NoError(t, err) - - // send another tx - sendTx() - time.Sleep(safeBlockInclusionDuration) - - // ensure that the safe chain does not advance while the batcher is stopped - newSeqStatus, err = rollupClient.SyncStatus(context.Background()) - 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 = driver.StartBatchSubmitting() - require.NoError(t, err) - time.Sleep(safeBlockInclusionDuration) - - // send a third tx - receipt = sendTx() - - // 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.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.NoError(t, err) - require.Greater(t, newSeqStatus.SafeL2.Number, seqStatus.SafeL2.Number, "Safe chain did not advance after batcher was restarted") -} - -func TestBatcherMultiTx(t *testing.T) { - InitParallel(t) - - cfg := DefaultSystemConfig(t) - 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.NoError(t, err, "Error starting up system") - - l1Client := sys.NodeClient("l1") - l2Seq := sys.NodeClient("sequencer") - - _, err = geth.WaitForBlock(big.NewInt(10), l2Seq, time.Duration(cfg.DeployConfig.L2BlockTime*15)*time.Second) - require.NoError(t, err, "Waiting for L2 blocks") - - ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) - defer cancel() - l1Number, err := l1Client.BlockNumber(ctx) - require.NoError(t, err) - - // start batch submission - driver := sys.BatchSubmitter.TestDriver() - err = driver.StartBatchSubmitting() - require.NoError(t, err) - - totalTxCount := 0 - // wait for up to 10 L1 blocks, usually only 3 is required, but it's - // possible additional L1 blocks will be created before the batcher starts, - // 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.NoError(t, err, "Waiting for l1 blocks") - totalTxCount += len(block.Transactions()) - - if totalTxCount >= 10 { - return - } - } - - t.Fatal("Expected at least 10 transactions from the batcher") -} - -func latestBlock(t *testing.T, client *ethclient.Client) uint64 { - ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) - defer cancel() - blockAfter, err := client.BlockNumber(ctx) - require.Nil(t, err, "Error getting latest block") - return blockAfter -} - -// TestPendingBlockIsLatest tests that we serve the latest block as pending block -func TestPendingBlockIsLatest(t *testing.T) { - InitParallel(t) - - cfg := DefaultSystemConfig(t) - sys, err := cfg.Start(t) - require.Nil(t, err, "Error starting up system") - - l2Seq := sys.NodeClient("sequencer") - - t.Run("block", func(t *testing.T) { - for i := 0; i < 10; i++ { - // TODO(CLI-4044): pending-block ID change - pending, err := l2Seq.BlockByNumber(context.Background(), big.NewInt(-1)) - require.NoError(t, err) - latest, err := l2Seq.BlockByNumber(context.Background(), nil) - require.NoError(t, err) - if pending.NumberU64() == latest.NumberU64() { - require.Equal(t, pending.Hash(), latest.Hash(), "pending must exactly match latest block") - return - } - // re-try until we have the same number, as the requests are not an atomic bundle, and the sequencer may create a block. - } - t.Fatal("failed to get pending block with same number as latest block") - }) - t.Run("header", func(t *testing.T) { - for i := 0; i < 10; i++ { - // TODO(CLI-4044): pending-block ID change - pending, err := l2Seq.HeaderByNumber(context.Background(), big.NewInt(-1)) - require.NoError(t, err) - latest, err := l2Seq.HeaderByNumber(context.Background(), nil) - require.NoError(t, err) - if pending.Number.Uint64() == latest.Number.Uint64() { - require.Equal(t, pending.Hash(), latest.Hash(), "pending must exactly match latest header") - return - } - // re-try until we have the same number, as the requests are not an atomic bundle, and the sequencer may create a block. - } - t.Fatal("failed to get pending header with same number as latest header") - }) -} - -func TestRuntimeConfigReload(t *testing.T) { - InitParallel(t) - - cfg := DefaultSystemConfig(t) - // to speed up the test, make it reload the config more often, and do not impose a long conf depth - cfg.Nodes["verifier"].RuntimeConfigReloadInterval = time.Second * 5 - cfg.Nodes["verifier"].Driver.VerifierConfDepth = 1 - - sys, err := cfg.Start(t) - require.Nil(t, err, "Error starting up system") - - initialRuntimeConfig := sys.RollupNodes["verifier"].RuntimeConfig() - - // close the EL node, since we want to block derivation, to solely rely on the reloading mechanism for updates. - sys.EthInstances["verifier"].Close() - - l1 := sys.NodeClient("l1") - - // Change the system-config via L1 - sysCfgContract, err := bindings.NewSystemConfig(cfg.L1Deployments.SystemConfigProxy, l1) - require.NoError(t, err) - newUnsafeBlocksSigner := common.Address{0x12, 0x23, 0x45} - require.NotEqual(t, initialRuntimeConfig.P2PSequencerAddress(), newUnsafeBlocksSigner, "changing to a different address") - opts, err := bind.NewKeyedTransactorWithChainID(cfg.Secrets.SysCfgOwner, cfg.L1ChainIDBig()) - require.Nil(t, err) - // the unsafe signer address is part of the runtime config - tx, err := sysCfgContract.SetUnsafeBlockSigner(opts, newUnsafeBlocksSigner) - require.NoError(t, err) - - // wait for the change to confirm - _, err = wait.ForReceiptOK(context.Background(), l1, tx.Hash()) - require.NoError(t, err) - - // wait for the address to change - _, err = retry.Do(context.Background(), 10, retry.Fixed(time.Second*10), func() (struct{}, error) { - v := sys.RollupNodes["verifier"].RuntimeConfig().P2PSequencerAddress() - if v == newUnsafeBlocksSigner { - return struct{}{}, nil - } - return struct{}{}, fmt.Errorf("no change yet, seeing %s but looking for %s", v, newUnsafeBlocksSigner) - }) - require.NoError(t, err) -} - -func TestRecommendedProtocolVersionChange(t *testing.T) { - InitParallel(t) - - cfg := DefaultSystemConfig(t) - require.NotEqual(t, common.Address{}, cfg.L1Deployments.ProtocolVersions, "need ProtocolVersions contract deployment") - // to speed up the test, make it reload the config more often, and do not impose a long conf depth - cfg.Nodes["verifier"].RuntimeConfigReloadInterval = time.Second * 5 - cfg.Nodes["verifier"].Driver.VerifierConfDepth = 1 - - sys, err := cfg.Start(t) - require.Nil(t, err, "Error starting up system") - - runtimeConfig := sys.RollupNodes["verifier"].RuntimeConfig() - - // Change the superchain-config via L1 - l1 := sys.NodeClient("l1") - - _, build, major, minor, patch, preRelease := params.OPStackSupport.Parse() - newRecommendedProtocolVersion := params.ProtocolVersionV0{Build: build, Major: major + 1, Minor: minor, Patch: patch, PreRelease: preRelease}.Encode() - require.NotEqual(t, runtimeConfig.RecommendedProtocolVersion(), newRecommendedProtocolVersion, "changing to a different protocol version") - - protVersions, err := bindings.NewProtocolVersions(cfg.L1Deployments.ProtocolVersionsProxy, l1) - require.NoError(t, err) - - // ProtocolVersions contract is owned by same key as SystemConfig in devnet - opts, err := bind.NewKeyedTransactorWithChainID(cfg.Secrets.SysCfgOwner, cfg.L1ChainIDBig()) - require.NoError(t, err) - - // Change recommended protocol version - tx, err := protVersions.SetRecommended(opts, new(big.Int).SetBytes(newRecommendedProtocolVersion[:])) - require.NoError(t, err) - - // wait for the change to confirm - _, err = wait.ForReceiptOK(context.Background(), l1, tx.Hash()) - require.NoError(t, err) - - // wait for the recommended protocol version to change - _, err = retry.Do(context.Background(), 10, retry.Fixed(time.Second*10), func() (struct{}, error) { - v := sys.RollupNodes["verifier"].RuntimeConfig().RecommendedProtocolVersion() - if v == newRecommendedProtocolVersion { - return struct{}{}, nil - } - return struct{}{}, fmt.Errorf("no change yet, seeing %s but looking for %s", v, newRecommendedProtocolVersion) - }) - require.NoError(t, err) -} - -func TestRequiredProtocolVersionChangeAndHalt(t *testing.T) { - InitParallel(t) - - cfg := DefaultSystemConfig(t) - // to speed up the test, make it reload the config more often, and do not impose a long conf depth - cfg.Nodes["verifier"].RuntimeConfigReloadInterval = time.Second * 5 - cfg.Nodes["verifier"].Driver.VerifierConfDepth = 1 - // configure halt in verifier op-node - cfg.Nodes["verifier"].RollupHalt = "major" - // configure halt in verifier op-geth node - cfg.GethOptions["verifier"] = append(cfg.GethOptions["verifier"], []geth.GethOption{ - func(ethCfg *ethconfig.Config, nodeCfg *node.Config) error { - ethCfg.RollupHaltOnIncompatibleProtocolVersion = "major" - return nil - }, - }...) - - sys, err := cfg.Start(t) - require.Nil(t, err, "Error starting up system") - - runtimeConfig := sys.RollupNodes["verifier"].RuntimeConfig() - - // Change the superchain-config via L1 - l1 := sys.NodeClient("l1") - - _, build, major, minor, patch, preRelease := params.OPStackSupport.Parse() - newRequiredProtocolVersion := params.ProtocolVersionV0{Build: build, Major: major + 1, Minor: minor, Patch: patch, PreRelease: preRelease}.Encode() - require.NotEqual(t, runtimeConfig.RequiredProtocolVersion(), newRequiredProtocolVersion, "changing to a different protocol version") - - protVersions, err := bindings.NewProtocolVersions(cfg.L1Deployments.ProtocolVersionsProxy, l1) - require.NoError(t, err) - - // ProtocolVersions contract is owned by same key as SystemConfig in devnet - opts, err := bind.NewKeyedTransactorWithChainID(cfg.Secrets.SysCfgOwner, cfg.L1ChainIDBig()) - require.NoError(t, err) - - // Change required protocol version - tx, err := protVersions.SetRequired(opts, new(big.Int).SetBytes(newRequiredProtocolVersion[:])) - require.NoError(t, err) - - // wait for the change to confirm - _, err = wait.ForReceiptOK(context.Background(), l1, tx.Hash()) - require.NoError(t, err) - - // wait for the required protocol version to take effect by halting the verifier that opted in, and halting the op-geth node that opted in. - _, err = retry.Do(context.Background(), 10, retry.Fixed(time.Second*10), func() (struct{}, error) { - if !sys.RollupNodes["verifier"].Stopped() { - return struct{}{}, errors.New("verifier rollup node is not closed yet") - } - return struct{}{}, nil - }) - require.NoError(t, err) - t.Log("verified that op-node closed!") - // 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(), 10*time.Second) - defer cancel() - available := client.IsURLAvailable(ctx, sys.NodeEndpoint("verifier").(endpoint.HttpRPC).HttpRPC()) - if !available && ctx.Err() == nil { // waiting for client to stop responding to RPC requests (slow dials with timeout don't count) - return struct{}{}, nil - } - return struct{}{}, errors.New("verifier EL node is not closed yet") - }) - require.NoError(t, err) - t.Log("verified that op-geth closed!") -} diff --git a/op-node/benchmarks/batchbuilding_test.go b/op-node/benchmarks/batchbuilding_test.go index 54690eabb152d..57a5382d749b4 100644 --- a/op-node/benchmarks/batchbuilding_test.go +++ b/op-node/benchmarks/batchbuilding_test.go @@ -87,15 +87,16 @@ var ( // channelOutByType returns a channel out of the given type as a helper for the benchmarks func channelOutByType(b *testing.B, batchType uint, cd compressorDetails) (derive.ChannelOut, error) { - chainID := big.NewInt(333) - rollupConfig := new(rollup.Config) + rollupConfig := &rollup.Config{ + L2ChainID: big.NewInt(333), + } if batchType == derive.SingularBatchType { compressor, err := cd.Compressor() require.NoError(b, err) return derive.NewSingularChannelOut(compressor, rollup.NewChainSpec(rollupConfig)) } if batchType == derive.SpanBatchType { - return derive.NewSpanChannelOut(0, chainID, cd.config.TargetOutputSize, cd.config.CompressionAlgo, rollup.NewChainSpec(rollupConfig)) + return derive.NewSpanChannelOut(cd.config.TargetOutputSize, cd.config.CompressionAlgo, rollup.NewChainSpec(rollupConfig)) } return nil, fmt.Errorf("unsupported batch type: %d", batchType) } diff --git a/op-node/cmd/batch_decoder/reassemble/reassemble.go b/op-node/cmd/batch_decoder/reassemble/reassemble.go index 8844b2ab8fba3..d8fc136b50438 100644 --- a/op-node/cmd/batch_decoder/reassemble/reassemble.go +++ b/op-node/cmd/batch_decoder/reassemble/reassemble.go @@ -72,7 +72,7 @@ func Channels(config Config, rollupCfg *rollup.Config) { framesByChannel[frame.Frame.ID] = append(framesByChannel[frame.Frame.ID], frame) } for id, frames := range framesByChannel { - ch := processFrames(config, rollupCfg, id, frames) + ch := ProcessFrames(config, rollupCfg, id, frames) filename := path.Join(config.OutDirectory, fmt.Sprintf("%s.json", id.String())) if err := writeChannel(ch, filename); err != nil { log.Fatal(err) @@ -90,7 +90,9 @@ func writeChannel(ch ChannelWithMetadata, filename string) error { return enc.Encode(ch) } -func processFrames(cfg Config, rollupCfg *rollup.Config, id derive.ChannelID, frames []FrameWithMetadata) ChannelWithMetadata { +// ProcessFrames processes the frames for a given channel and reads batches and other relevant metadata +// from the channel. Returns a ChannelWithMetadata struct containing all the relevant data. +func ProcessFrames(cfg Config, rollupCfg *rollup.Config, id derive.ChannelID, frames []FrameWithMetadata) ChannelWithMetadata { spec := rollup.NewChainSpec(rollupCfg) ch := derive.NewChannel(id, eth.L1BlockRef{Number: frames[0].InclusionBlock}) invalidFrame := false diff --git a/op-node/cmd/genesis/cmd.go b/op-node/cmd/genesis/cmd.go index 6d11fd8e7f5ee..054f29310619d 100644 --- a/op-node/cmd/genesis/cmd.go +++ b/op-node/cmd/genesis/cmd.go @@ -5,6 +5,7 @@ import ( "fmt" "time" + "github.com/ethereum-optimism/optimism/op-service/ioutil" "github.com/ethereum-optimism/optimism/op-service/retry" "github.com/ethereum-optimism/optimism/op-service/sources/batching" "github.com/urfave/cli/v2" @@ -120,7 +121,7 @@ var Subcommands = cli.Commands{ return err } - return jsonutil.WriteJSON(ctx.String(outfileL1Flag.Name), l1Genesis, 0o666) + return jsonutil.WriteJSON(l1Genesis, ioutil.ToStdOutOrFileOrNoop(ctx.String(outfileL1Flag.Name), 0o666)) }, }, { @@ -190,13 +191,13 @@ var Subcommands = cli.Commands{ } // Build the L2 genesis block - l2Genesis, err := genesis.BuildL2Genesis(config, l2Allocs, l1StartBlock) + l2Genesis, err := genesis.BuildL2Genesis(config, l2Allocs, l1StartBlock.Header()) if err != nil { return fmt.Errorf("error creating l2 genesis: %w", err) } l2GenesisBlock := l2Genesis.ToBlock() - rollupConfig, err := config.RollupConfig(l1StartBlock, l2GenesisBlock.Hash(), l2GenesisBlock.Number().Uint64()) + rollupConfig, err := config.RollupConfig(l1StartBlock.Header(), l2GenesisBlock.Hash(), l2GenesisBlock.Number().Uint64()) if err != nil { return err } @@ -204,10 +205,10 @@ var Subcommands = cli.Commands{ return fmt.Errorf("generated rollup config does not pass validation: %w", err) } - if err := jsonutil.WriteJSON(ctx.String(outfileL2Flag.Name), l2Genesis, 0o666); err != nil { + if err := jsonutil.WriteJSON(l2Genesis, ioutil.ToAtomicFile(ctx.String(outfileL2Flag.Name), 0o666)); err != nil { return err } - return jsonutil.WriteJSON(ctx.String(outfileRollupFlag.Name), rollupConfig, 0o666) + return jsonutil.WriteJSON(rollupConfig, ioutil.ToAtomicFile(ctx.String(outfileRollupFlag.Name), 0o666)) }, }, } diff --git a/op-node/cmd/main.go b/op-node/cmd/main.go index adb3d3aeb6364..8f6688b51cbf0 100644 --- a/op-node/cmd/main.go +++ b/op-node/cmd/main.go @@ -20,9 +20,9 @@ import ( "github.com/ethereum-optimism/optimism/op-node/version" opservice "github.com/ethereum-optimism/optimism/op-service" "github.com/ethereum-optimism/optimism/op-service/cliapp" + "github.com/ethereum-optimism/optimism/op-service/ctxinterrupt" oplog "github.com/ethereum-optimism/optimism/op-service/log" "github.com/ethereum-optimism/optimism/op-service/metrics/doc" - "github.com/ethereum-optimism/optimism/op-service/opio" ) var ( @@ -64,7 +64,7 @@ func main() { }, } - ctx := opio.WithInterruptBlocker(context.Background()) + ctx := ctxinterrupt.WithSignalWaiterMain(context.Background()) err := app.RunContext(ctx, os.Args) if err != nil { log.Crit("Application failed", "message", err) diff --git a/op-node/flags/flags.go b/op-node/flags/flags.go index 6ea12000cc374..54334c150296a 100644 --- a/op-node/flags/flags.go +++ b/op-node/flags/flags.go @@ -73,6 +73,13 @@ var ( EnvVars: prefixEnvVars("L1_BEACON"), Category: RollupCategory, } + SupervisorAddr = &cli.StringFlag{ + Name: "supervisor", + Usage: "RPC address of interop supervisor service for cross-chain safety verification." + + "Applies only to Interop-enabled networks.", + Hidden: true, // hidden for now during early testing. + EnvVars: prefixEnvVars("SUPERVISOR"), + } /* Optional Flags */ BeaconHeader = &cli.StringFlag{ Name: "l1.beacon-header", @@ -157,13 +164,6 @@ var ( }(), Category: L1RPCCategory, } - L1RethDBPath = &cli.StringFlag{ - Name: "l1.rethdb", - Usage: "The L1 RethDB path, used to fetch receipts for L1 blocks.", - 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.", @@ -259,7 +259,7 @@ var ( MetricsAddrFlag = &cli.StringFlag{ Name: "metrics.addr", Usage: "Metrics listening address", - Value: "0.0.0.0", // TODO(CLI-4159): Switch to 127.0.0.1 + Value: "0.0.0.0", // TODO: Switch to 127.0.0.1 EnvVars: prefixEnvVars("METRICS_ADDR"), Category: OperationsCategory, } @@ -381,6 +381,7 @@ var requiredFlags = []cli.Flag{ } var optionalFlags = []cli.Flag{ + SupervisorAddr, BeaconAddr, BeaconHeader, BeaconFallbackAddrs, @@ -413,7 +414,6 @@ var optionalFlags = []cli.Flag{ HeartbeatURLFlag, RollupHalt, RollupLoadProtocolVersions, - L1RethDBPath, ConductorEnabledFlag, ConductorRpcFlag, ConductorRpcTimeoutFlag, diff --git a/op-node/node/client.go b/op-node/node/client.go index a1c4754616c53..a561a7678d24d 100644 --- a/op-node/node/client.go +++ b/op-node/node/client.go @@ -230,3 +230,29 @@ func parseHTTPHeader(headerStr string) (http.Header, error) { h.Add(s[0], s[1]) return h, nil } + +type SupervisorEndpointSetup interface { + SupervisorClient(ctx context.Context, log log.Logger) (*sources.SupervisorClient, error) + Check() error +} + +type SupervisorEndpointConfig struct { + SupervisorAddr string +} + +var _ SupervisorEndpointSetup = (*SupervisorEndpointConfig)(nil) + +func (cfg *SupervisorEndpointConfig) Check() error { + if cfg.SupervisorAddr == "" { + return errors.New("supervisor RPC address is not set") + } + return nil +} + +func (cfg *SupervisorEndpointConfig) SupervisorClient(ctx context.Context, log log.Logger) (*sources.SupervisorClient, error) { + cl, err := client.NewRPC(ctx, log, cfg.SupervisorAddr, client.WithLazyDial()) + if err != nil { + return nil, fmt.Errorf("failed to create supervisor RPC: %w", err) + } + return sources.NewSupervisorClient(cl), nil +} diff --git a/op-node/node/config.go b/op-node/node/config.go index 5ca724d905c68..a78b55853aa25 100644 --- a/op-node/node/config.go +++ b/op-node/node/config.go @@ -23,6 +23,8 @@ type Config struct { Beacon L1BeaconEndpointSetup + Supervisor SupervisorEndpointSetup + Driver driver.Config Rollup rollup.Config @@ -65,9 +67,6 @@ type Config struct { // Cancel to request a premature shutdown of the node itself, e.g. when halting. This may be nil. Cancel context.CancelCauseFunc - // [OPTIONAL] The reth DB path to read receipts from - RethDBPath string - // Conductor is used to determine this node is the leader sequencer. ConductorEnabled bool ConductorRpc string @@ -133,12 +132,20 @@ func (cfg *Config) Check() error { } if cfg.Rollup.EcotoneTime != nil { if cfg.Beacon == nil { - return fmt.Errorf("the Ecotone upgrade is scheduled but no L1 Beacon API endpoint is configured") + return fmt.Errorf("the Ecotone upgrade is scheduled (timestamp = %d) but no L1 Beacon API endpoint is configured", *cfg.Rollup.EcotoneTime) } if err := cfg.Beacon.Check(); err != nil { return fmt.Errorf("misconfigured L1 Beacon API endpoint: %w", err) } } + if cfg.Rollup.InteropTime != nil { + if cfg.Supervisor == nil { + return fmt.Errorf("the Interop upgrade is scheduled (timestamp = %d) but no supervisor RPC endpoint is configured", *cfg.Rollup.InteropTime) + } + if err := cfg.Supervisor.Check(); err != nil { + return fmt.Errorf("misconfigured supervisor RPC endpoint: %w", err) + } + } if err := cfg.Rollup.Check(); err != nil { return fmt.Errorf("rollup config error: %w", err) } @@ -172,3 +179,7 @@ func (cfg *Config) Check() error { } return nil } + +func (cfg *Config) P2PEnabled() bool { + return cfg.P2P != nil && !cfg.P2P.Disabled() +} diff --git a/op-node/node/node.go b/op-node/node/node.go index a4fd3e8db08fe..6d7cb9968fdda 100644 --- a/op-node/node/node.go +++ b/op-node/node/node.go @@ -12,7 +12,7 @@ import ( "github.com/libp2p/go-libp2p/core/peer" "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/event" + gethevent "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/log" altda "github.com/ethereum-optimism/optimism/op-alt-da" @@ -22,6 +22,8 @@ import ( "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-node/rollup/conductor" "github.com/ethereum-optimism/optimism/op-node/rollup/driver" + "github.com/ethereum-optimism/optimism/op-node/rollup/event" + "github.com/ethereum-optimism/optimism/op-node/rollup/sequencing" "github.com/ethereum-optimism/optimism/op-node/rollup/sync" "github.com/ethereum-optimism/optimism/op-service/client" "github.com/ethereum-optimism/optimism/op-service/eth" @@ -40,6 +42,8 @@ type closableSafeDB interface { } type OpNode struct { + // Retain the config to test for active features rather than test for runtime state. + cfg *Config log log.Logger appVersion string metrics *metrics.Metrics @@ -48,6 +52,9 @@ type OpNode struct { l1SafeSub ethereum.Subscription // Subscription to get L1 safe blocks, a.k.a. justified data (polling) l1FinalizedSub ethereum.Subscription // Subscription to get L1 safe blocks, a.k.a. justified data (polling) + eventSys event.System + eventDrain event.Drainer + l1Source *sources.L1Client // L1 Client to fetch data from l2Driver *driver.Driver // L2 Engine to Sync l2Source *sources.EngineClient // L2 Execution Engine RPC bindings @@ -66,6 +73,8 @@ type OpNode struct { beacon *sources.L1BeaconClient + supervisor *sources.SupervisorClient + // some resources cannot be stopped directly, like the p2p gossipsub router (not our design), // and depend on this ctx to be closed. resourcesCtx context.Context @@ -93,6 +102,7 @@ func New(ctx context.Context, cfg *Config, log log.Logger, appVersion string, m } n := &OpNode{ + cfg: cfg, log: log, appVersion: appVersion, metrics: m, @@ -119,6 +129,7 @@ func (n *OpNode) init(ctx context.Context, cfg *Config) error { if err := n.initTracer(ctx, cfg); err != nil { return fmt.Errorf("failed to init the trace: %w", err) } + n.initEventSystem() if err := n.initL1(ctx, cfg); err != nil { return fmt.Errorf("failed to init L1: %w", err) } @@ -134,7 +145,7 @@ func (n *OpNode) init(ctx context.Context, cfg *Config) error { if err := n.initP2PSigner(ctx, cfg); err != nil { return fmt.Errorf("failed to init the P2P signer: %w", err) } - if err := n.initP2P(ctx, cfg); err != nil { + if err := n.initP2P(cfg); err != nil { 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. @@ -152,6 +163,16 @@ func (n *OpNode) init(ctx context.Context, cfg *Config) error { return nil } +func (n *OpNode) initEventSystem() { + // This executor will be configurable in the future, for parallel event processing + executor := event.NewParallelExec() + sys := event.NewSystem(n.log, executor) + sys.AddTracer(event.NewMetricsTracer(n.metrics)) + sys.Register("node", event.DeriverFunc(n.onEvent), event.DefaultRegisterOpts()) + n.eventSys = sys + n.eventDrain = executor +} + func (n *OpNode) initTracer(ctx context.Context, cfg *Config) error { if cfg.Tracer != nil { n.tracer = cfg.Tracer @@ -167,9 +188,6 @@ func (n *OpNode) initL1(ctx context.Context, cfg *Config) error { return fmt.Errorf("failed to get L1 RPC client: %w", err) } - // Set the RethDB path in the EthClientConfig, if there is one configured. - rpcCfg.EthClientConfig.RethDBPath = cfg.RethDBPath - n.l1Source, err = sources.NewL1Client( client.NewInstrumentedRPC(l1Node, &n.metrics.RPCMetrics.RPCClientMetrics), n.log, n.metrics.L1SourceCache, rpcCfg) if err != nil { @@ -181,7 +199,7 @@ func (n *OpNode) initL1(ctx context.Context, cfg *Config) error { } // Keep subscribed to the L1 heads, which keeps the L1 maintainer pointing to the best headers to sync - n.l1HeadsSub = event.ResubscribeErr(time.Second*10, func(ctx context.Context, err error) (event.Subscription, error) { + n.l1HeadsSub = gethevent.ResubscribeErr(time.Second*10, func(ctx context.Context, err error) (gethevent.Subscription, error) { if err != nil { n.log.Warn("resubscribing after failed L1 subscription", "err", err) } @@ -377,6 +395,14 @@ func (n *OpNode) initL2(ctx context.Context, cfg *Config) error { return err } + if cfg.Rollup.InteropTime != nil { + cl, err := cfg.Supervisor.SupervisorClient(ctx, n.log) + if err != nil { + return fmt.Errorf("failed to setup supervisor RPC client: %w", err) + } + n.supervisor = cl + } + var sequencerConductor conductor.SequencerConductor = &conductor.NoOpConductor{} if cfg.ConductorEnabled { sequencerConductor = NewConductorClient(cfg, n.log, n.metrics) @@ -398,7 +424,8 @@ func (n *OpNode) initL2(ctx context.Context, cfg *Config) error { } else { n.safeDB = safedb.Disabled } - n.l2Driver = driver.NewDriver(&cfg.Driver, &cfg.Rollup, n.l2Source, n.l1Source, n.beacon, n, n, n.log, n.metrics, cfg.ConfigPersistence, n.safeDB, &cfg.Sync, sequencerConductor, altDA) + n.l2Driver = driver.NewDriver(n.eventSys, n.eventDrain, &cfg.Driver, &cfg.Rollup, n.l2Source, n.l1Source, + n.supervisor, n.beacon, n, n, n.log, n.metrics, cfg.ConfigPersistence, n.safeDB, &cfg.Sync, sequencerConductor, altDA) return nil } @@ -407,7 +434,7 @@ func (n *OpNode) initRPCServer(cfg *Config) error { if err != nil { return err } - if n.p2pNode != nil { + if n.p2pEnabled() { server.EnableP2P(p2p.NewP2PAPIBackend(n.p2pNode, n.log, n.metrics)) } if cfg.RPC.EnableAdmin { @@ -454,14 +481,20 @@ func (n *OpNode) initPProf(cfg *Config) error { return nil } -func (n *OpNode) initP2P(ctx context.Context, cfg *Config) error { - if cfg.P2P != nil { - // TODO(protocol-quest/97): Use EL Sync instead of CL Alt sync for fetching missing blocks in the payload queue. - p2pNode, err := p2p.NewNodeP2P(n.resourcesCtx, &cfg.Rollup, n.log, cfg.P2P, n, n.l2Source, n.runCfg, n.metrics, false) - if err != nil || p2pNode == nil { - return err +func (n *OpNode) p2pEnabled() bool { + return n.cfg.P2PEnabled() +} + +func (n *OpNode) initP2P(cfg *Config) (err error) { + if n.p2pNode != nil { + panic("p2p node already initialized") + } + if n.p2pEnabled() { + // TODO(protocol-quest#97): Use EL Sync instead of CL Alt sync for fetching missing blocks in the payload queue. + n.p2pNode, err = p2p.NewNodeP2P(n.resourcesCtx, &cfg.Rollup, n.log, cfg.P2P, n, n.l2Source, n.runCfg, n.metrics, false) + if err != nil { + return } - n.p2pNode = p2pNode if n.p2pNode.Dv5Udp() != nil { go n.p2pNode.DiscoveryProcess(n.resourcesCtx, n.log, &cfg.Rollup, cfg.P2P.TargetPeers()) } @@ -469,15 +502,14 @@ func (n *OpNode) initP2P(ctx context.Context, cfg *Config) error { return nil } -func (n *OpNode) initP2PSigner(ctx context.Context, cfg *Config) error { +func (n *OpNode) initP2PSigner(ctx context.Context, cfg *Config) (err error) { // the p2p signer setup is optional if cfg.P2PSigner == nil { - return nil + return } // p2pSigner may still be nil, the signer setup may not create any signer, the signer is optional - var err error n.p2pSigner, err = cfg.P2PSigner.SetupSigner(ctx) - return err + return } func (n *OpNode) Start(ctx context.Context) error { @@ -491,6 +523,20 @@ func (n *OpNode) Start(ctx context.Context) error { return nil } +// onEvent handles broadcast events. +// The OpNode itself is a deriver to catch system-critical events. +// Other event-handling should be encapsulated into standalone derivers. +func (n *OpNode) onEvent(ev event.Event) bool { + switch x := ev.(type) { + case rollup.CriticalErrorEvent: + n.log.Error("Critical error", "err", x.Err) + n.cancel(fmt.Errorf("critical error: %w", x.Err)) + return true + default: + return false + } +} + func (n *OpNode) OnNewL1Head(ctx context.Context, sig eth.L1BlockRef) { n.tracer.OnNewL1Head(ctx, sig) @@ -533,7 +579,7 @@ func (n *OpNode) PublishL2Payload(ctx context.Context, envelope *eth.ExecutionPa n.tracer.OnPublishL2Payload(ctx, envelope) // publish to p2p, if we are running p2p at all - if n.p2pNode != nil { + if n.p2pEnabled() { payload := envelope.ExecutionPayload if n.p2pSigner == nil { return fmt.Errorf("node has no p2p signer, payload %s cannot be published", payload.ID()) @@ -547,7 +593,7 @@ func (n *OpNode) PublishL2Payload(ctx context.Context, envelope *eth.ExecutionPa func (n *OpNode) OnUnsafeL2Payload(ctx context.Context, from peer.ID, envelope *eth.ExecutionPayloadEnvelope) error { // ignore if it's from ourselves - if n.p2pNode != nil && from == n.p2pNode.Host().ID() { + if n.p2pEnabled() && from == n.p2pNode.Host().ID() { return nil } @@ -568,9 +614,13 @@ func (n *OpNode) OnUnsafeL2Payload(ctx context.Context, from peer.ID, envelope * } func (n *OpNode) RequestL2Range(ctx context.Context, start, end eth.L2BlockRef) error { - if n.p2pNode != nil && n.p2pNode.AltSyncEnabled() { + if n.p2pEnabled() && n.p2pNode.AltSyncEnabled() { if unixTimeStale(start.Time, 12*time.Hour) { - n.log.Debug("ignoring request to sync L2 range, timestamp is too old for p2p", "start", start, "end", end, "start_time", start.Time) + n.log.Debug( + "ignoring request to sync L2 range, timestamp is too old for p2p", + "start", start, + "end", end, + "start_time", start.Time) return nil } return n.p2pNode.RequestL2Range(ctx, start, end) @@ -606,10 +656,26 @@ func (n *OpNode) Stop(ctx context.Context) error { result = multierror.Append(result, fmt.Errorf("failed to close RPC server: %w", err)) } } + + // Stop sequencer and report last hash. l2Driver can be nil if we're cleaning up a failed init. + if n.l2Driver != nil { + latestHead, err := n.l2Driver.StopSequencer(ctx) + switch { + case errors.Is(err, sequencing.ErrSequencerNotEnabled): + case errors.Is(err, driver.ErrSequencerAlreadyStopped): + n.log.Info("stopping node: sequencer already stopped", "latestHead", latestHead) + case err == nil: + n.log.Info("stopped sequencer", "latestHead", latestHead) + default: + result = multierror.Append(result, fmt.Errorf("error stopping sequencer: %w", err)) + } + } if n.p2pNode != nil { if err := n.p2pNode.Close(); err != nil { result = multierror.Append(result, fmt.Errorf("failed to close p2p node: %w", err)) } + // Prevent further use of p2p. + n.p2pNode = nil } if n.p2pSigner != nil { if err := n.p2pSigner.Close(); err != nil { @@ -641,6 +707,10 @@ func (n *OpNode) Stop(ctx context.Context) error { } } + if n.eventSys != nil { + n.eventSys.Stop() + } + 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)) @@ -657,6 +727,11 @@ func (n *OpNode) Stop(ctx context.Context) error { n.l2Source.Close() } + // close the supervisor RPC client + if n.supervisor != nil { + n.supervisor.Close() + } + // close L1 data source if n.l1Source != nil { n.l1Source.Close() diff --git a/op-node/p2p/config.go b/op-node/p2p/config.go index 94b75a95de263..ee21ba20fc395 100644 --- a/op-node/p2p/config.go +++ b/op-node/p2p/config.go @@ -48,6 +48,7 @@ type HostMetrics interface { // SetupP2P provides a host and discovery service for usage in the rollup node. type SetupP2P interface { Check() error + // Looks like this was started to prevent partially inited p2p. Disabled() bool // Host creates a libp2p host service. Returns nil, nil if p2p is disabled. Host(log log.Logger, reporter metrics.Reporter, metrics HostMetrics) (host.Host, error) diff --git a/op-node/p2p/node.go b/op-node/p2p/node.go index 4c88556ddd9c6..85da1686acd71 100644 --- a/op-node/p2p/node.go +++ b/op-node/p2p/node.go @@ -52,10 +52,23 @@ type NodeP2P struct { // NewNodeP2P creates a new p2p node, and returns a reference to it. If the p2p is disabled, it returns nil. // If metrics are configured, a bandwidth monitor will be spawned in a goroutine. -func NewNodeP2P(resourcesCtx context.Context, rollupCfg *rollup.Config, log log.Logger, setup SetupP2P, gossipIn GossipIn, l2Chain L2Chain, runCfg GossipRuntimeConfig, metrics metrics.Metricer, elSyncEnabled bool) (*NodeP2P, error) { +func NewNodeP2P( + resourcesCtx context.Context, + rollupCfg *rollup.Config, + log log.Logger, + setup SetupP2P, + gossipIn GossipIn, + l2Chain L2Chain, + runCfg GossipRuntimeConfig, + metrics metrics.Metricer, + elSyncEnabled bool, +) (*NodeP2P, error) { if setup == nil { return nil, errors.New("p2p node cannot be created without setup") } + if setup.Disabled() { + return nil, errors.New("SetupP2P.Disabled is true") + } var n NodeP2P if err := n.init(resourcesCtx, rollupCfg, log, setup, gossipIn, l2Chain, runCfg, metrics, elSyncEnabled); err != nil { closeErr := n.Close() @@ -65,12 +78,24 @@ func NewNodeP2P(resourcesCtx context.Context, rollupCfg *rollup.Config, log log. return nil, err } if n.host == nil { - return nil, nil + // See prior comment about n.host optionality: + // TODO: host is not optional, NodeP2P as a whole is. + panic("host is not optional if p2p is enabled") } return &n, nil } -func (n *NodeP2P) init(resourcesCtx context.Context, rollupCfg *rollup.Config, log log.Logger, setup SetupP2P, gossipIn GossipIn, l2Chain L2Chain, runCfg GossipRuntimeConfig, metrics metrics.Metricer, elSyncEnabled bool) error { +func (n *NodeP2P) init( + resourcesCtx context.Context, + rollupCfg *rollup.Config, + log log.Logger, + setup SetupP2P, + gossipIn GossipIn, + l2Chain L2Chain, + runCfg GossipRuntimeConfig, + metrics metrics.Metricer, + elSyncEnabled bool, +) error { bwc := p2pmetrics.NewBandwidthCounter() n.log = log @@ -85,86 +110,83 @@ func (n *NodeP2P) init(resourcesCtx context.Context, rollupCfg *rollup.Config, l return fmt.Errorf("failed to start p2p host: %w", err) } - // TODO(CLI-4016): host is not optional, NodeP2P as a whole is. This if statement is wrong - if n.host != nil { - // Enable extra features, if any. During testing we don't setup the most advanced host all the time. - if extra, ok := n.host.(ExtraHostFeatures); ok { - n.gater = extra.ConnectionGater() - n.connMgr = extra.ConnectionManager() - } - eps, ok := n.host.Peerstore().(store.ExtendedPeerstore) - if !ok { - return fmt.Errorf("cannot init without extended peerstore: %w", err) - } - n.store = eps - scoreParams := setup.PeerScoringParams() + // Enable extra features, if any. During testing we don't setup the most advanced host all the time. + if extra, ok := n.host.(ExtraHostFeatures); ok { + n.gater = extra.ConnectionGater() + n.connMgr = extra.ConnectionManager() + } + eps, ok := n.host.Peerstore().(store.ExtendedPeerstore) + if !ok { + return fmt.Errorf("cannot init without extended peerstore: %w", err) + } + n.store = eps + scoreParams := setup.PeerScoringParams() - if scoreParams != nil { - n.appScorer = newPeerApplicationScorer(resourcesCtx, log, clock.SystemClock, &scoreParams.ApplicationScoring, eps, n.host.Network().Peers) - } else { - n.appScorer = &NoopApplicationScorer{} - } - // Activate the P2P req-resp sync if enabled by feature-flag. - if setup.ReqRespSyncEnabled() && !elSyncEnabled { - n.syncCl = NewSyncClient(log, rollupCfg, n.host, gossipIn.OnUnsafeL2Payload, metrics, n.appScorer) - n.host.Network().Notify(&network.NotifyBundle{ - ConnectedF: func(nw network.Network, conn network.Conn) { - n.syncCl.AddPeer(conn.RemotePeer()) - }, - DisconnectedF: func(nw network.Network, conn network.Conn) { - // only when no connection is available, we can remove the peer - if nw.Connectedness(conn.RemotePeer()) == network.NotConnected { - n.syncCl.RemovePeer(conn.RemotePeer()) - } - }, - }) - n.syncCl.Start() - // the host may already be connected to peers, add them all to the sync client - for _, peerID := range n.host.Network().Peers() { - n.syncCl.AddPeer(peerID) - } - if l2Chain != nil { // Only enable serving side of req-resp sync if we have a data-source, to make minimal P2P testing easy - n.syncSrv = NewReqRespServer(rollupCfg, l2Chain, metrics) - // register the sync protocol with libp2p host - payloadByNumber := MakeStreamHandler(resourcesCtx, log.New("serve", "payloads_by_number"), n.syncSrv.HandleSyncRequest) - n.host.SetStreamHandler(PayloadByNumberProtocolID(rollupCfg.L2ChainID), payloadByNumber) - } + if scoreParams != nil { + n.appScorer = newPeerApplicationScorer(resourcesCtx, log, clock.SystemClock, &scoreParams.ApplicationScoring, eps, n.host.Network().Peers) + } else { + n.appScorer = &NoopApplicationScorer{} + } + // Activate the P2P req-resp sync if enabled by feature-flag. + if setup.ReqRespSyncEnabled() && !elSyncEnabled { + n.syncCl = NewSyncClient(log, rollupCfg, n.host, gossipIn.OnUnsafeL2Payload, metrics, n.appScorer) + n.host.Network().Notify(&network.NotifyBundle{ + ConnectedF: func(nw network.Network, conn network.Conn) { + n.syncCl.AddPeer(conn.RemotePeer()) + }, + DisconnectedF: func(nw network.Network, conn network.Conn) { + // only when no connection is available, we can remove the peer + if nw.Connectedness(conn.RemotePeer()) == network.NotConnected { + n.syncCl.RemovePeer(conn.RemotePeer()) + } + }, + }) + n.syncCl.Start() + // the host may already be connected to peers, add them all to the sync client + for _, peerID := range n.host.Network().Peers() { + n.syncCl.AddPeer(peerID) } - n.scorer = NewScorer(rollupCfg, eps, metrics, n.appScorer, log) - // notify of any new connections/streams/etc. - n.host.Network().Notify(NewNetworkNotifier(log, metrics)) - // note: the IDDelta functionality was removed from libP2P, and no longer needs to be explicitly disabled. - n.gs, err = NewGossipSub(resourcesCtx, n.host, rollupCfg, setup, n.scorer, metrics, log) - if err != nil { - return fmt.Errorf("failed to start gossipsub router: %w", err) + if l2Chain != nil { // Only enable serving side of req-resp sync if we have a data-source, to make minimal P2P testing easy + n.syncSrv = NewReqRespServer(rollupCfg, l2Chain, metrics) + // register the sync protocol with libp2p host + payloadByNumber := MakeStreamHandler(resourcesCtx, log.New("serve", "payloads_by_number"), n.syncSrv.HandleSyncRequest) + n.host.SetStreamHandler(PayloadByNumberProtocolID(rollupCfg.L2ChainID), payloadByNumber) } - n.gsOut, err = JoinGossip(n.host.ID(), n.gs, log, rollupCfg, runCfg, gossipIn) - if err != nil { - return fmt.Errorf("failed to join blocks gossip topic: %w", err) - } - log.Info("started p2p host", "addrs", n.host.Addrs(), "peerID", n.host.ID().String()) + } + n.scorer = NewScorer(rollupCfg, eps, metrics, n.appScorer, log) + // notify of any new connections/streams/etc. + n.host.Network().Notify(NewNetworkNotifier(log, metrics)) + // note: the IDDelta functionality was removed from libP2P, and no longer needs to be explicitly disabled. + n.gs, err = NewGossipSub(resourcesCtx, n.host, rollupCfg, setup, n.scorer, metrics, log) + if err != nil { + return fmt.Errorf("failed to start gossipsub router: %w", err) + } + n.gsOut, err = JoinGossip(n.host.ID(), n.gs, log, rollupCfg, runCfg, gossipIn) + if err != nil { + return fmt.Errorf("failed to join blocks gossip topic: %w", err) + } + log.Info("started p2p host", "addrs", n.host.Addrs(), "peerID", n.host.ID().String()) - tcpPort, err := FindActiveTCPPort(n.host) - if err != nil { - log.Warn("failed to find what TCP port p2p is binded to", "err", err) - } + tcpPort, err := FindActiveTCPPort(n.host) + if err != nil { + log.Warn("failed to find what TCP port p2p is binded to", "err", err) + } - // All nil if disabled. - n.dv5Local, n.dv5Udp, err = setup.Discovery(log.New("p2p", "discv5"), rollupCfg, tcpPort) - if err != nil { - return fmt.Errorf("failed to start discv5: %w", err) - } + // All nil if disabled. + n.dv5Local, n.dv5Udp, err = setup.Discovery(log.New("p2p", "discv5"), rollupCfg, tcpPort) + if err != nil { + return fmt.Errorf("failed to start discv5: %w", err) + } - if metrics != nil { - go metrics.RecordBandwidth(resourcesCtx, bwc) - } + if metrics != nil { + go metrics.RecordBandwidth(resourcesCtx, bwc) + } - if setup.BanPeers() { - n.peerMonitor = monitor.NewPeerMonitor(resourcesCtx, log, clock.SystemClock, n, setup.BanThreshold(), setup.BanDuration()) - n.peerMonitor.Start() - } - n.appScorer.start() + if setup.BanPeers() { + n.peerMonitor = monitor.NewPeerMonitor(resourcesCtx, log, clock.SystemClock, n, setup.BanThreshold(), setup.BanDuration()) + n.peerMonitor.Start() } + n.appScorer.start() return nil } diff --git a/op-node/p2p/sync.go b/op-node/p2p/sync.go index b838d000caf40..c8777fe51f928 100644 --- a/op-node/p2p/sync.go +++ b/op-node/p2p/sync.go @@ -57,7 +57,7 @@ const ( // If the client hits a request error, it counts as a lot of rate-limit tokens for syncing from that peer: // we rather sync from other servers. We'll try again later, // and eventually kick the peer based on degraded scoring if it's really not serving us well. - // TODO(CLI-4009): Use a backoff rather than this mechanism. + // TODO: Use a backoff rather than this mechanism. clientErrRateCost = peerServerBlocksBurst ) @@ -310,7 +310,7 @@ func NewSyncClient(log log.Logger, cfg *rollup.Config, host HostNewStream, rcv r } // never errors with positive LRU cache size - // TODO(CLI-3733): if we had an LRU based on on total payloads size, instead of payload count, + // TODO: if we had an LRU based on on total payloads size, instead of payload count, // we can safely buffer more data in the happy case. q, _ := simplelru.NewLRU[common.Hash, syncResult](100, c.onQuarantineEvict) c.quarantine = q diff --git a/op-node/rollup/chain_spec.go b/op-node/rollup/chain_spec.go index 95d9c3b197983..66d2e526d0d12 100644 --- a/op-node/rollup/chain_spec.go +++ b/op-node/rollup/chain_spec.go @@ -1,6 +1,8 @@ package rollup import ( + "math/big" + "github.com/ethereum-optimism/optimism/op-node/params" "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum/go-ethereum/log" @@ -63,6 +65,16 @@ func NewChainSpec(config *Config) *ChainSpec { return &ChainSpec{config: config} } +// L2ChainID returns the chain ID of the L2 chain. +func (s *ChainSpec) L2ChainID() *big.Int { + return s.config.L2ChainID +} + +// L2GenesisTime returns the genesis time of the L2 chain. +func (s *ChainSpec) L2GenesisTime() uint64 { + return s.config.Genesis.L2Time +} + // IsCanyon returns true if t >= canyon_time func (s *ChainSpec) IsCanyon(t uint64) bool { return s.config.IsCanyon(t) diff --git a/op-node/rollup/derive/attributes.go b/op-node/rollup/derive/attributes.go index c65198bcec733..cc38a31b9c54f 100644 --- a/op-node/rollup/derive/attributes.go +++ b/op-node/rollup/derive/attributes.go @@ -121,9 +121,19 @@ func (ba *FetchingAttributesBuilder) PreparePayloadAttributes(ctx context.Contex return nil, NewCriticalError(fmt.Errorf("failed to create l1InfoTx: %w", err)) } - txs := make([]hexutil.Bytes, 0, 1+len(depositTxs)+len(upgradeTxs)) + var afterForceIncludeTxs []hexutil.Bytes + if ba.rollupCfg.IsInterop(nextL2Time) { + depositsCompleteTx, err := DepositsCompleteBytes(seqNumber, l1Info) + if err != nil { + return nil, NewCriticalError(fmt.Errorf("failed to create depositsCompleteTx: %w", err)) + } + afterForceIncludeTxs = append(afterForceIncludeTxs, depositsCompleteTx) + } + + txs := make([]hexutil.Bytes, 0, 1+len(depositTxs)+len(afterForceIncludeTxs)+len(upgradeTxs)) txs = append(txs, l1InfoTx) txs = append(txs, depositTxs...) + txs = append(txs, afterForceIncludeTxs...) txs = append(txs, upgradeTxs...) var withdrawals *types.Withdrawals diff --git a/op-node/rollup/derive/attributes_test.go b/op-node/rollup/derive/attributes_test.go index 68c7c71aa1e13..64fcec556343c 100644 --- a/op-node/rollup/derive/attributes_test.go +++ b/op-node/rollup/derive/attributes_test.go @@ -195,6 +195,98 @@ func TestPreparePayloadAttributes(t *testing.T) { require.Equal(t, l1InfoTx, []byte(attrs.Transactions[0])) require.True(t, attrs.NoTxPool) }) + t.Run("new origin with deposits on post-Isthmus", func(t *testing.T) { + rng := rand.New(rand.NewSource(1234)) + l1Fetcher := &testutils.MockL1Source{} + defer l1Fetcher.AssertExpectations(t) + l2Parent := testutils.RandomL2BlockRef(rng) + l1CfgFetcher := &testutils.MockL2Client{} + l1CfgFetcher.ExpectSystemConfigByL2Hash(l2Parent.Hash, testSysCfg, nil) + defer l1CfgFetcher.AssertExpectations(t) + + l1Info := testutils.RandomBlockInfo(rng) + l1Info.InfoParentHash = l2Parent.L1Origin.Hash + l1Info.InfoNum = l2Parent.L1Origin.Number + 1 // next origin, where deposits may be + + receipts, depositTxs, err := makeReceipts(rng, l1Info.InfoHash, cfg.DepositContractAddress, []receiptData{ + {goodReceipt: true, DepositLogs: []bool{true, false}}, + {goodReceipt: true, DepositLogs: []bool{true}}, + {goodReceipt: false, DepositLogs: []bool{true}}, + {goodReceipt: false, DepositLogs: []bool{false}}, + }) + require.NoError(t, err) + userDepositTxs, err := encodeDeposits(depositTxs) + require.NoError(t, err) + + // sets config to post-interop + cfg.ActivateAtGenesis(rollup.Interop) + + seqNumber := uint64(0) + epoch := l1Info.ID() + l1InfoTx, err := L1InfoDepositBytes(cfg, testSysCfg, seqNumber, l1Info, 0) + require.NoError(t, err) + depositsComplete, err := DepositsCompleteBytes(seqNumber, l1Info) + require.NoError(t, err) + + var l2Txs []eth.Data + l2Txs = append(l2Txs, l1InfoTx) + l2Txs = append(l2Txs, userDepositTxs...) + l2Txs = append(l2Txs, depositsComplete) + + l1Fetcher.ExpectFetchReceipts(epoch.Hash, l1Info, receipts, nil) + attrBuilder := NewFetchingAttributesBuilder(cfg, l1Fetcher, l1CfgFetcher) + attrs, err := attrBuilder.PreparePayloadAttributes(context.Background(), l2Parent, epoch) + require.NoError(t, err) + require.NotNil(t, attrs) + require.Equal(t, l2Parent.Time+cfg.BlockTime, uint64(attrs.Timestamp)) + require.Equal(t, eth.Bytes32(l1Info.InfoMixDigest), attrs.PrevRandao) + require.Equal(t, predeploys.SequencerFeeVaultAddr, attrs.SuggestedFeeRecipient) + require.Equal(t, len(l2Txs), len(attrs.Transactions), "Expected txs to equal l1 info tx + user deposit txs + DepositsComplete") + require.Equal(t, eth.Data(depositsComplete).String(), attrs.Transactions[len(l2Txs)-1].String()) + require.Equal(t, l2Txs, attrs.Transactions) + require.True(t, attrs.NoTxPool) + }) + + t.Run("same origin without deposits on post-Isthmus", func(t *testing.T) { + rng := rand.New(rand.NewSource(1234)) + l1Fetcher := &testutils.MockL1Source{} + defer l1Fetcher.AssertExpectations(t) + l2Parent := testutils.RandomL2BlockRef(rng) + l1CfgFetcher := &testutils.MockL2Client{} + l1CfgFetcher.ExpectSystemConfigByL2Hash(l2Parent.Hash, testSysCfg, nil) + defer l1CfgFetcher.AssertExpectations(t) + l1Info := testutils.RandomBlockInfo(rng) + l1Info.InfoHash = l2Parent.L1Origin.Hash + l1Info.InfoNum = l2Parent.L1Origin.Number // same origin again, so the sequence number is not reset + + // sets config to post-interop + cfg.ActivateAtGenesis(rollup.Interop) + + seqNumber := l2Parent.SequenceNumber + 1 + epoch := l1Info.ID() + l1InfoTx, err := L1InfoDepositBytes(cfg, testSysCfg, seqNumber, l1Info, 0) + require.NoError(t, err) + depositsComplete, err := DepositsCompleteBytes(seqNumber, l1Info) + require.NoError(t, err) + + var l2Txs []eth.Data + l2Txs = append(l2Txs, l1InfoTx) + l2Txs = append(l2Txs, depositsComplete) + + l1Fetcher.ExpectInfoByHash(epoch.Hash, l1Info, nil) + attrBuilder := NewFetchingAttributesBuilder(cfg, l1Fetcher, l1CfgFetcher) + attrs, err := attrBuilder.PreparePayloadAttributes(context.Background(), l2Parent, epoch) + require.NoError(t, err) + require.NotNil(t, attrs) + require.Equal(t, l2Parent.Time+cfg.BlockTime, uint64(attrs.Timestamp)) + require.Equal(t, eth.Bytes32(l1Info.InfoMixDigest), attrs.PrevRandao) + require.Equal(t, predeploys.SequencerFeeVaultAddr, attrs.SuggestedFeeRecipient) + require.Equal(t, len(l2Txs), len(attrs.Transactions), "Expected txs to equal l1 info tx + user deposit txs + DepositsComplete") + require.Equal(t, eth.Data(depositsComplete).String(), attrs.Transactions[len(l2Txs)-1].String()) + require.Equal(t, l2Txs, attrs.Transactions) + require.True(t, attrs.NoTxPool) + }) + // Test that the payload attributes builder changes the deposit format based on L2-time-based regolith activation t.Run("regolith", func(t *testing.T) { testCases := []struct { diff --git a/op-node/rollup/derive/batch_queue.go b/op-node/rollup/derive/batch_queue.go index 3dbfe20d305da..4ca49907c7de9 100644 --- a/op-node/rollup/derive/batch_queue.go +++ b/op-node/rollup/derive/batch_queue.go @@ -109,21 +109,6 @@ func (bq *BatchQueue) NextBatch(ctx context.Context, parent eth.L2BlockRef) (*Si } } - // If the epoch is advanced, update bq.l1Blocks - // Advancing epoch must be done after the pipeline successfully apply the entire span batch to the chain. - // Because the span batch can be reverted during processing the batch, then we must preserve existing l1Blocks - // to verify the epochs of the next candidate batch. - if len(bq.l1Blocks) > 0 && parent.L1Origin.Number > bq.l1Blocks[0].Number { - for i, l1Block := range bq.l1Blocks { - if parent.L1Origin.Number == l1Block.Number { - bq.l1Blocks = bq.l1Blocks[i:] - bq.log.Debug("Advancing internal L1 blocks", "next_epoch", bq.l1Blocks[0].ID(), "next_epoch_time", bq.l1Blocks[0].Time) - break - } - } - // If we can't find the origin of parent block, we have to advance bq.origin. - } - // Note: We use the origin that we will have to determine if it's behind. This is important // because it's the future origin that gets saved into the l1Blocks array. // We always update the origin of this stage if it is not the same so after the update code @@ -146,6 +131,21 @@ func (bq *BatchQueue) NextBatch(ctx context.Context, parent eth.L2BlockRef) (*Si bq.log.Info("Advancing bq origin", "origin", bq.origin, "originBehind", originBehind) } + // If the epoch is advanced, update bq.l1Blocks + // Advancing epoch must be done after the pipeline successfully apply the entire span batch to the chain. + // Because the span batch can be reverted during processing the batch, then we must preserve existing l1Blocks + // to verify the epochs of the next candidate batch. + if len(bq.l1Blocks) > 0 && parent.L1Origin.Number > bq.l1Blocks[0].Number { + for i, l1Block := range bq.l1Blocks { + if parent.L1Origin.Number == l1Block.Number { + bq.l1Blocks = bq.l1Blocks[i:] + bq.log.Debug("Advancing internal L1 blocks", "next_epoch", bq.l1Blocks[0].ID(), "next_epoch_time", bq.l1Blocks[0].Time) + break + } + } + // If we can't find the origin of parent block, we have to advance bq.origin. + } + // Load more data into the batch queue outOfData := false if batch, err := bq.prev.NextBatch(ctx); err == io.EOF { diff --git a/op-node/rollup/derive/batch_queue_test.go b/op-node/rollup/derive/batch_queue_test.go index 6712ae15a6805..f047f0a7d4fef 100644 --- a/op-node/rollup/derive/batch_queue_test.go +++ b/op-node/rollup/derive/batch_queue_test.go @@ -147,6 +147,7 @@ func TestBatchQueue(t *testing.T) { {"BatchQueueMissing", BatchQueueMissing}, {"BatchQueueAdvancedEpoch", BatchQueueAdvancedEpoch}, {"BatchQueueShuffle", BatchQueueShuffle}, + {"BatchQueueResetOneBlockBeforeOrigin", BatchQueueResetOneBlockBeforeOrigin}, } for _, test := range tests { test := test @@ -224,6 +225,67 @@ func BatchQueueNewOrigin(t *testing.T, batchType int) { require.Equal(t, l1[2], bq.origin) } +// BatchQueueResetOneBlockBeforeOrigin tests that the batch queue properly +// prunes the l1Block recorded as part of a reset when the starting origin +// is exactly one block prior to the safe head origin. +func BatchQueueResetOneBlockBeforeOrigin(t *testing.T, batchType int) { + log := testlog.Logger(t, log.LevelTrace) + l1 := L1Chain([]uint64{10, 15, 20, 25}) + safeHead := eth.L2BlockRef{ + Hash: mockHash(10, 2), + Number: 0, + ParentHash: common.Hash{}, + Time: 20, + L1Origin: l1[1].ID(), + SequenceNumber: 0, + } + cfg := &rollup.Config{ + Genesis: rollup.Genesis{ + L2Time: 10, + }, + BlockTime: 2, + MaxSequencerDrift: 600, + SeqWindowSize: 2, + DeltaTime: getDeltaTime(batchType), + } + + input := &fakeBatchQueueInput{ + batches: []Batch{nil}, + errors: []error{io.EOF}, + origin: l1[0], + } + + bq := NewBatchQueue(log, cfg, input, nil) + _ = bq.Reset(context.Background(), l1[0], eth.SystemConfig{}) + require.Equal(t, []eth.L1BlockRef{l1[0]}, bq.l1Blocks) + + // Prev Origin: 0; Safehead Origin: 1; Internal Origin: 0 + // Should return no data but keep the same origin + data, _, err := bq.NextBatch(context.Background(), safeHead) + require.Nil(t, data) + require.Equal(t, io.EOF, err) + require.Equal(t, []eth.L1BlockRef{l1[0]}, bq.l1Blocks) + require.Equal(t, l1[0], bq.origin) + + // Prev Origin: 1; Safehead Origin: 1; Internal Origin: 0 + // Should record new l1 origin in l1blocks, prune block 0 and advance internal origin + input.origin = l1[1] + data, _, err = bq.NextBatch(context.Background(), safeHead) + require.Nil(t, data) + require.Equalf(t, io.EOF, err, "expected io.EOF but got %v", err) + require.Equal(t, []eth.L1BlockRef{l1[1]}, bq.l1Blocks) + require.Equal(t, l1[1], bq.origin) + + // Prev Origin: 2; Safehead Origin: 1; Internal Origin: 1 + // Should add to l1Blocks + advance internal origin + input.origin = l1[2] + data, _, err = bq.NextBatch(context.Background(), safeHead) + require.Nil(t, data) + require.Equal(t, io.EOF, err) + require.Equal(t, []eth.L1BlockRef{l1[1], l1[2]}, bq.l1Blocks) + require.Equal(t, l1[2], bq.origin) +} + // 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) { diff --git a/op-node/rollup/derive/blob_data_source.go b/op-node/rollup/derive/blob_data_source.go index 7780b6065063e..2c4626941b8b5 100644 --- a/op-node/rollup/derive/blob_data_source.go +++ b/op-node/rollup/derive/blob_data_source.go @@ -86,7 +86,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.log) if len(hashes) == 0 { // there are no blobs to fetch so we can return immediately @@ -115,13 +115,13 @@ 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, logger log.Logger) ([]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 { // skip any non-batcher transactions - if !isValidBatchTx(tx, config.l1Signer, config.batchInboxAddress, batcherAddr) { + if !isValidBatchTx(tx, config.l1Signer, config.batchInboxAddress, batcherAddr, logger) { blobIndex += len(tx.BlobHashes()) continue } diff --git a/op-node/rollup/derive/blob_data_source_test.go b/op-node/rollup/derive/blob_data_source_test.go index aa9ef82cb991a..e5e31dc957b90 100644 --- a/op-node/rollup/derive/blob_data_source_test.go +++ b/op-node/rollup/derive/blob_data_source_test.go @@ -13,7 +13,9 @@ import ( "github.com/ethereum/go-ethereum/crypto" "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" ) func TestDataAndHashesFromTxs(t *testing.T) { @@ -23,6 +25,7 @@ func TestDataAndHashesFromTxs(t *testing.T) { publicKey, _ := privateKey.Public().(*ecdsa.PublicKey) batcherAddr := crypto.PubkeyToAddress(*publicKey) batchInboxAddr := testutils.RandomAddress(rng) + logger := testlog.Logger(t, log.LvlInfo) chainId := new(big.Int).SetUint64(rng.Uint64()) signer := types.NewCancunSigner(chainId) @@ -42,7 +45,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, logger) require.Equal(t, 1, len(data)) require.Equal(t, 0, len(blobHashes)) @@ -57,14 +60,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, logger) 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, logger) require.Equal(t, 2, len(data)) require.Equal(t, 1, len(blobHashes)) require.NotNil(t, data[1].calldata) @@ -72,7 +75,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, logger) require.Equal(t, 0, len(data)) require.Equal(t, 0, len(blobHashes)) @@ -81,7 +84,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, logger) 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 0a5d7915770d6..0e8147261e93e 100644 --- a/op-node/rollup/derive/calldata_source.go +++ b/op-node/rollup/derive/calldata_source.go @@ -79,7 +79,7 @@ func (ds *CalldataSource) Next(ctx context.Context) (eth.Data, error) { func DataFromEVMTransactions(dsCfg DataSourceConfig, batcherAddr common.Address, txs types.Transactions, log log.Logger) []eth.Data { out := []eth.Data{} for _, tx := range txs { - if isValidBatchTx(tx, dsCfg.l1Signer, dsCfg.batchInboxAddress, batcherAddr) { + if isValidBatchTx(tx, dsCfg.l1Signer, dsCfg.batchInboxAddress, batcherAddr, log) { out = append(out, tx.Data()) } } diff --git a/op-node/rollup/derive/channel_bank.go b/op-node/rollup/derive/channel_bank.go index b2efb0d3ce169..8dd689dfadaae 100644 --- a/op-node/rollup/derive/channel_bank.go +++ b/op-node/rollup/derive/channel_bank.go @@ -37,14 +37,13 @@ type ChannelBank struct { channels map[ChannelID]*Channel // channels by ID channelQueue []ChannelID // channels in FIFO order - prev NextFrameProvider - fetcher L1Fetcher + prev NextFrameProvider } var _ ResettableStage = (*ChannelBank)(nil) // NewChannelBank creates a ChannelBank, which should be Reset(origin) before use. -func NewChannelBank(log log.Logger, cfg *rollup.Config, prev NextFrameProvider, fetcher L1Fetcher, m Metrics) *ChannelBank { +func NewChannelBank(log log.Logger, cfg *rollup.Config, prev NextFrameProvider, m Metrics) *ChannelBank { return &ChannelBank{ log: log, spec: rollup.NewChainSpec(cfg), @@ -52,7 +51,6 @@ func NewChannelBank(log log.Logger, cfg *rollup.Config, prev NextFrameProvider, channels: make(map[ChannelID]*Channel), channelQueue: make([]ChannelID, 0, 10), prev: prev, - fetcher: fetcher, } } diff --git a/op-node/rollup/derive/channel_bank_test.go b/op-node/rollup/derive/channel_bank_test.go index 59c82c308f01c..33763c23c5e01 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{ChannelTimeoutBedrock: 10} - cb := NewChannelBank(testlog.Logger(t, log.LevelCrit), cfg, input, nil, metrics.NoopMetrics) + cb := NewChannelBank(testlog.Logger(t, log.LevelCrit), cfg, input, metrics.NoopMetrics) // Load the first frame out, err := cb.NextData(context.Background()) @@ -146,7 +146,7 @@ func TestChannelBankInterleavedPreCanyon(t *testing.T) { cfg := &rollup.Config{ChannelTimeoutBedrock: 10, CanyonTime: nil} - cb := NewChannelBank(testlog.Logger(t, log.LevelCrit), cfg, input, nil, metrics.NoopMetrics) + cb := NewChannelBank(testlog.Logger(t, log.LevelCrit), cfg, input, 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{ChannelTimeoutBedrock: 10, CanyonTime: &ct} - cb := NewChannelBank(testlog.Logger(t, log.LevelCrit), cfg, input, nil, metrics.NoopMetrics) + cb := NewChannelBank(testlog.Logger(t, log.LevelCrit), cfg, input, metrics.NoopMetrics) // Load a:0 out, err := cb.NextData(context.Background()) @@ -271,7 +271,7 @@ func TestChannelBankDuplicates(t *testing.T) { cfg := &rollup.Config{ChannelTimeoutBedrock: 10} - cb := NewChannelBank(testlog.Logger(t, log.LevelCrit), cfg, input, nil, metrics.NoopMetrics) + cb := NewChannelBank(testlog.Logger(t, log.LevelCrit), cfg, input, metrics.NoopMetrics) // Load the first frame out, err := cb.NextData(context.Background()) diff --git a/op-node/rollup/derive/channel_out_test.go b/op-node/rollup/derive/channel_out_test.go index 53fedef03e645..34aa58400fdd0 100644 --- a/op-node/rollup/derive/channel_out_test.go +++ b/op-node/rollup/derive/channel_out_test.go @@ -61,7 +61,7 @@ var channelTypes = []struct { { Name: "Span", ChannelOut: func(t *testing.T, rcfg *rollup.Config) ChannelOut { - cout, err := NewSpanChannelOut(0, big.NewInt(0), 128_000, Zlib, rollup.NewChainSpec(rcfg)) + cout, err := NewSpanChannelOut(128_000, Zlib, rollup.NewChainSpec(rcfg)) require.NoError(t, err) return cout }, @@ -111,9 +111,8 @@ func TestOutputFrameNoEmptyLastFrame(t *testing.T) { cout := tcase.ChannelOut(t, &rollupCfg) rng := rand.New(rand.NewSource(0x543331)) - chainID := big.NewInt(0) txCount := 1 - singularBatch := RandomSingularBatch(rng, txCount, chainID) + singularBatch := RandomSingularBatch(rng, txCount, rollupCfg.L2ChainID) err := cout.AddSingularBatch(singularBatch, 0) var written uint64 @@ -236,7 +235,7 @@ func SpanChannelAndBatches(t *testing.T, targetOutputSize uint64, numBatches int chainID := rollupCfg.L2ChainID txCount := 1 genesisTime := rollupCfg.Genesis.L2Time - cout, err := NewSpanChannelOut(genesisTime, chainID, targetOutputSize, algo, rollup.NewChainSpec(&rollupCfg), opts...) + cout, err := NewSpanChannelOut(targetOutputSize, algo, rollup.NewChainSpec(&rollupCfg), opts...) require.NoError(t, err) batches := make([]*SingularBatch, 0, numBatches) // adding the first batch should not cause an error diff --git a/op-node/rollup/derive/data_source.go b/op-node/rollup/derive/data_source.go index b4ab76dc64bc4..8d064a7cdb8ca 100644 --- a/op-node/rollup/derive/data_source.go +++ b/op-node/rollup/derive/data_source.go @@ -93,19 +93,19 @@ type DataSourceConfig struct { // isValidBatchTx returns true if: // 1. the transaction has a To() address that matches the batch inbox address, and // 2. the transaction has a valid signature from the batcher address -func isValidBatchTx(tx *types.Transaction, l1Signer types.Signer, batchInboxAddr, batcherAddr common.Address) bool { +func isValidBatchTx(tx *types.Transaction, l1Signer types.Signer, batchInboxAddr, batcherAddr common.Address, logger log.Logger) bool { to := tx.To() if to == nil || *to != batchInboxAddr { return false } seqDataSubmitter, err := l1Signer.Sender(tx) // optimization: only derive sender if To is correct if err != nil { - log.Warn("tx in inbox with invalid signature", "hash", tx.Hash(), "err", err) + logger.Warn("tx in inbox with invalid signature", "hash", tx.Hash(), "err", err) return false } // some random L1 user might have sent a transaction to our batch inbox, ignore them if seqDataSubmitter != batcherAddr { - log.Warn("tx in inbox with unauthorized submitter", "addr", seqDataSubmitter, "hash", tx.Hash(), "err", err) + logger.Warn("tx in inbox with unauthorized submitter", "addr", seqDataSubmitter, "hash", tx.Hash(), "err", err) return false } return true diff --git a/op-node/rollup/derive/deposit_source.go b/op-node/rollup/derive/deposit_source.go index f7a9730ad026c..8b4e49590e3c5 100644 --- a/op-node/rollup/derive/deposit_source.go +++ b/op-node/rollup/derive/deposit_source.go @@ -13,9 +13,10 @@ type UserDepositSource struct { } const ( - UserDepositSourceDomain = 0 - L1InfoDepositSourceDomain = 1 - UpgradeDepositSourceDomain = 2 + UserDepositSourceDomain = 0 + L1InfoDepositSourceDomain = 1 + UpgradeDepositSourceDomain = 2 + AfterForceIncludeSourceDomain = 3 ) func (dep *UserDepositSource) SourceHash() common.Hash { @@ -63,3 +64,21 @@ func (dep *UpgradeDepositSource) SourceHash() common.Hash { copy(domainInput[32:], intentHash[:]) return crypto.Keccak256Hash(domainInput[:]) } + +// AfterForceIncludeSource identifies the DepositsComplete post-user-deposits deposit-transaction. +type AfterForceIncludeSource struct { + L1BlockHash common.Hash + SeqNumber uint64 // without this the Deposit tx would have the same tx hash for every time the L1 info repeats. +} + +func (dep *AfterForceIncludeSource) SourceHash() common.Hash { + var input [32 * 2]byte + copy(input[:32], dep.L1BlockHash[:]) + binary.BigEndian.PutUint64(input[32*2-8:], dep.SeqNumber) + depositIDHash := crypto.Keccak256Hash(input[:]) + + var domainInput [32 * 2]byte + binary.BigEndian.PutUint64(domainInput[32-8:32], AfterForceIncludeSourceDomain) + copy(domainInput[32:], depositIDHash[:]) + return crypto.Keccak256Hash(domainInput[:]) +} diff --git a/op-node/rollup/derive/deposit_source_test.go b/op-node/rollup/derive/deposit_source_test.go index 10fb7048a2a26..fb30e89188291 100644 --- a/op-node/rollup/derive/deposit_source_test.go +++ b/op-node/rollup/derive/deposit_source_test.go @@ -3,6 +3,7 @@ package derive import ( "testing" + "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" ) @@ -34,3 +35,33 @@ func TestEcotone4788ContractSourceHash(t *testing.T) { assert.Equal(t, expected, actual.Hex()) } + +// TestL1InfoDepositSource +// cast keccak $(cast concat-hex 0x0000000000000000000000000000000000000000000000000000000000000001 $(cast keccak $(cast concat-hex 0xc00e5d67c2755389aded7d8b151cbd5bcdf7ed275ad5e028b664880fc7581c77 0x0000000000000000000000000000000000000000000000000000000000000004))) +// # 0x0586c503340591999b8b38bc9834bb16aec7d5bc00eb5587ab139c9ddab81977 +func TestL1InfoDepositSource(t *testing.T) { + source := L1InfoDepositSource{ + L1BlockHash: common.HexToHash("0xc00e5d67c2755389aded7d8b151cbd5bcdf7ed275ad5e028b664880fc7581c77"), + SeqNumber: 4, + } + + actual := source.SourceHash() + expected := "0x0586c503340591999b8b38bc9834bb16aec7d5bc00eb5587ab139c9ddab81977" + + assert.Equal(t, expected, actual.Hex()) +} + +// TestAfterForceIncludeSourceHash +// cast keccak $(cast concat-hex 0x0000000000000000000000000000000000000000000000000000000000000003 $(cast keccak $(cast concat-hex 0xc00e5d67c2755389aded7d8b151cbd5bcdf7ed275ad5e028b664880fc7581c77 0x0000000000000000000000000000000000000000000000000000000000000004))) +// # 0x0d165c391384b29c29f655e3f32315755b8c1e4c1147d1824d1243420dda5ec3 +func TestAfterForceIncludeSource(t *testing.T) { + source := AfterForceIncludeSource{ + L1BlockHash: common.HexToHash("0xc00e5d67c2755389aded7d8b151cbd5bcdf7ed275ad5e028b664880fc7581c77"), + SeqNumber: 4, + } + + actual := source.SourceHash() + expected := "0x0d165c391384b29c29f655e3f32315755b8c1e4c1147d1824d1243420dda5ec3" + + assert.Equal(t, expected, actual.Hex()) +} diff --git a/op-node/rollup/derive/fuzz_parsers_test.go b/op-node/rollup/derive/fuzz_parsers_test.go index 95ce94bc7cc85..4f76c4ac7420a 100644 --- a/op-node/rollup/derive/fuzz_parsers_test.go +++ b/op-node/rollup/derive/fuzz_parsers_test.go @@ -83,15 +83,26 @@ func FuzzL1InfoEcotoneRoundTrip(f *testing.F) { } enc, err := in.marshalBinaryEcotone() if err != nil { - t.Fatalf("Failed to marshal binary: %v", err) + t.Fatalf("Failed to marshal Ecotone binary: %v", err) } var out L1BlockInfo err = out.unmarshalBinaryEcotone(enc) if err != nil { - t.Fatalf("Failed to unmarshal binary: %v", err) + t.Fatalf("Failed to unmarshal Ecotone binary: %v", err) } if !cmp.Equal(in, out, cmp.Comparer(testutils.BigEqual)) { - t.Fatalf("The data did not round trip correctly. in: %v. out: %v", in, out) + t.Fatalf("The Ecotone data did not round trip correctly. in: %v. out: %v", in, out) + } + enc, err = in.marshalBinaryIsthmus() + if err != nil { + t.Fatalf("Failed to marshal Isthmus binary: %v", err) + } + err = out.unmarshalBinaryIsthmus(enc) + if err != nil { + t.Fatalf("Failed to unmarshal Isthmus binary: %v", err) + } + if !cmp.Equal(in, out, cmp.Comparer(testutils.BigEqual)) { + t.Fatalf("The Isthmus data did not round trip correctly. in: %v. out: %v", in, out) } }) diff --git a/op-node/rollup/derive/l1_block_info.go b/op-node/rollup/derive/l1_block_info.go index 26f3f6711f557..43ea9b29bedc4 100644 --- a/op-node/rollup/derive/l1_block_info.go +++ b/op-node/rollup/derive/l1_block_info.go @@ -20,14 +20,25 @@ import ( const ( L1InfoFuncBedrockSignature = "setL1BlockValues(uint64,uint64,uint256,bytes32,uint64,bytes32,uint256,uint256)" L1InfoFuncEcotoneSignature = "setL1BlockValuesEcotone()" + L1InfoFuncIsthmusSignature = "setL1BlockValuesIsthmus()" + DepositsCompleteSignature = "depositsComplete()" L1InfoArguments = 8 L1InfoBedrockLen = 4 + 32*L1InfoArguments L1InfoEcotoneLen = 4 + 32*5 // after Ecotone upgrade, args are packed into 5 32-byte slots + DepositsCompleteLen = 4 // only the selector + // DepositsCompleteGas allocates 21k gas for intrinsic tx costs, and + // an additional 15k to ensure that the DepositsComplete call does not run out of gas. + // GasBenchMark_L1BlockIsthmus_DepositsComplete:test_depositsComplete_benchmark() (gas: 7768) + // GasBenchMark_L1BlockIsthmus_DepositsComplete_Warm:test_depositsComplete_benchmark() (gas: 5768) + // see `test_depositsComplete_benchmark` at: `/packages/contracts-bedrock/test/BenchmarkTest.t.sol` + DepositsCompleteGas = uint64(21_000 + 15_000) ) var ( L1InfoFuncBedrockBytes4 = crypto.Keccak256([]byte(L1InfoFuncBedrockSignature))[:4] L1InfoFuncEcotoneBytes4 = crypto.Keccak256([]byte(L1InfoFuncEcotoneSignature))[:4] + L1InfoFuncIsthmusBytes4 = crypto.Keccak256([]byte(L1InfoFuncIsthmusSignature))[:4] + DepositsCompleteBytes4 = crypto.Keccak256([]byte(DepositsCompleteSignature))[:4] L1InfoDepositerAddress = common.HexToAddress("0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001") L1BlockAddress = predeploys.L1BlockAddr ErrInvalidFormat = errors.New("invalid ecotone l1 block info format") @@ -144,7 +155,7 @@ func (info *L1BlockInfo) unmarshalBinaryBedrock(data []byte) error { return nil } -// Ecotone Binary Format +// Isthmus & Ecotone Binary Format // +---------+--------------------------+ // | Bytes | Field | // +---------+--------------------------+ @@ -161,8 +172,24 @@ func (info *L1BlockInfo) unmarshalBinaryBedrock(data []byte) error { // +---------+--------------------------+ func (info *L1BlockInfo) marshalBinaryEcotone() ([]byte, error) { - w := bytes.NewBuffer(make([]byte, 0, L1InfoEcotoneLen)) - if err := solabi.WriteSignature(w, L1InfoFuncEcotoneBytes4); err != nil { + out, err := marshalBinaryWithSignature(info, L1InfoFuncEcotoneBytes4) + if err != nil { + return nil, fmt.Errorf("failed to marshal Ecotone l1 block info: %w", err) + } + return out, nil +} + +func (info *L1BlockInfo) marshalBinaryIsthmus() ([]byte, error) { + out, err := marshalBinaryWithSignature(info, L1InfoFuncIsthmusBytes4) + if err != nil { + return nil, fmt.Errorf("failed to marshal Isthmus l1 block info: %w", err) + } + return out, nil +} + +func marshalBinaryWithSignature(info *L1BlockInfo, signature []byte) ([]byte, error) { + w := bytes.NewBuffer(make([]byte, 0, L1InfoEcotoneLen)) // Ecotone and Isthmus have the same length + if err := solabi.WriteSignature(w, signature); err != nil { return nil, err } if err := binary.Write(w, binary.BigEndian, info.BaseFeeScalar); err != nil { @@ -201,13 +228,21 @@ func (info *L1BlockInfo) marshalBinaryEcotone() ([]byte, error) { } func (info *L1BlockInfo) unmarshalBinaryEcotone(data []byte) error { + return unmarshalBinaryWithSignatureAndData(info, L1InfoFuncEcotoneBytes4, data) +} + +func (info *L1BlockInfo) unmarshalBinaryIsthmus(data []byte) error { + return unmarshalBinaryWithSignatureAndData(info, L1InfoFuncIsthmusBytes4, data) +} + +func unmarshalBinaryWithSignatureAndData(info *L1BlockInfo, signature []byte, data []byte) error { if len(data) != L1InfoEcotoneLen { return fmt.Errorf("data is unexpected length: %d", len(data)) } r := bytes.NewReader(data) var err error - if _, err := solabi.ReadAndValidateSignature(r, L1InfoFuncEcotoneBytes4); err != nil { + if _, err := solabi.ReadAndValidateSignature(r, signature); err != nil { return err } if err := binary.Read(r, binary.BigEndian, &info.BaseFeeScalar); err != nil { @@ -245,14 +280,28 @@ func (info *L1BlockInfo) unmarshalBinaryEcotone(data []byte) error { } // isEcotoneButNotFirstBlock returns whether the specified block is subject to the Ecotone upgrade, -// but is not the actiation block itself. -func isEcotoneButNotFirstBlock(rollupCfg *rollup.Config, l2BlockTime uint64) bool { - return rollupCfg.IsEcotone(l2BlockTime) && !rollupCfg.IsEcotoneActivationBlock(l2BlockTime) +// but is not the activation block itself. +func isEcotoneButNotFirstBlock(rollupCfg *rollup.Config, l2Timestamp uint64) bool { + return rollupCfg.IsEcotone(l2Timestamp) && !rollupCfg.IsEcotoneActivationBlock(l2Timestamp) +} + +// isInteropButNotFirstBlock returns whether the specified block is subject to the Isthmus upgrade, +// but is not the activation block itself. +func isInteropButNotFirstBlock(rollupCfg *rollup.Config, l2Timestamp uint64) bool { + // Since we use the pre-interop L1 tx one last time during the upgrade block, + // we must disallow the deposit-txs from using the CrossL2Inbox during this block. + // If the CrossL2Inbox does not exist yet, then it is safe, + // but we have to ensure that the spec and code puts any Interop upgrade-txs after the user deposits. + return rollupCfg.IsInterop(l2Timestamp) && !rollupCfg.IsInteropActivationBlock(l2Timestamp) } // L1BlockInfoFromBytes is the inverse of L1InfoDeposit, to see where the L2 chain is derived from func L1BlockInfoFromBytes(rollupCfg *rollup.Config, l2BlockTime uint64, data []byte) (*L1BlockInfo, error) { var info L1BlockInfo + // Important, this should be ordered from most recent to oldest + if isInteropButNotFirstBlock(rollupCfg, l2BlockTime) { + return &info, info.unmarshalBinaryIsthmus(data) + } if isEcotoneButNotFirstBlock(rollupCfg, l2BlockTime) { return &info, info.unmarshalBinaryEcotone(data) } @@ -261,7 +310,7 @@ func L1BlockInfoFromBytes(rollupCfg *rollup.Config, l2BlockTime uint64, data []b // L1InfoDeposit creates a L1 Info deposit transaction based on the L1 block, // and the L2 block-height difference with the start of the epoch. -func L1InfoDeposit(rollupCfg *rollup.Config, sysCfg eth.SystemConfig, seqNumber uint64, block eth.BlockInfo, l2BlockTime uint64) (*types.DepositTx, error) { +func L1InfoDeposit(rollupCfg *rollup.Config, sysCfg eth.SystemConfig, seqNumber uint64, block eth.BlockInfo, l2Timestamp uint64) (*types.DepositTx, error) { l1BlockInfo := L1BlockInfo{ Number: block.NumberU64(), Time: block.Time(), @@ -271,7 +320,7 @@ func L1InfoDeposit(rollupCfg *rollup.Config, sysCfg eth.SystemConfig, seqNumber BatcherAddr: sysCfg.BatcherAddr, } var data []byte - if isEcotoneButNotFirstBlock(rollupCfg, l2BlockTime) { + if isEcotoneButNotFirstBlock(rollupCfg, l2Timestamp) { l1BlockInfo.BlobBaseFee = block.BlobBaseFee() if l1BlockInfo.BlobBaseFee == nil { // The L2 spec states to use the MIN_BLOB_GASPRICE from EIP-4844 if not yet active on L1. @@ -283,11 +332,19 @@ func L1InfoDeposit(rollupCfg *rollup.Config, sysCfg eth.SystemConfig, seqNumber } l1BlockInfo.BlobBaseFeeScalar = scalars.BlobBaseFeeScalar l1BlockInfo.BaseFeeScalar = scalars.BaseFeeScalar - out, err := l1BlockInfo.marshalBinaryEcotone() - if err != nil { - return nil, fmt.Errorf("failed to marshal Ecotone l1 block info: %w", err) + if isInteropButNotFirstBlock(rollupCfg, l2Timestamp) { + out, err := l1BlockInfo.marshalBinaryIsthmus() + if err != nil { + return nil, fmt.Errorf("failed to marshal Isthmus l1 block info: %w", err) + } + data = out + } else { + out, err := l1BlockInfo.marshalBinaryEcotone() + if err != nil { + return nil, fmt.Errorf("failed to marshal Ecotone l1 block info: %w", err) + } + data = out } - data = out } else { l1BlockInfo.L1FeeOverhead = sysCfg.Overhead l1BlockInfo.L1FeeScalar = sysCfg.Scalar @@ -315,7 +372,7 @@ func L1InfoDeposit(rollupCfg *rollup.Config, sysCfg eth.SystemConfig, seqNumber Data: data, } // With the regolith fork we disable the IsSystemTx functionality, and allocate real gas - if rollupCfg.IsRegolith(l2BlockTime) { + if rollupCfg.IsRegolith(l2Timestamp) { out.IsSystemTransaction = false out.Gas = RegolithSystemTxGas } @@ -323,8 +380,8 @@ func L1InfoDeposit(rollupCfg *rollup.Config, sysCfg eth.SystemConfig, seqNumber } // L1InfoDepositBytes returns a serialized L1-info attributes transaction. -func L1InfoDepositBytes(rollupCfg *rollup.Config, sysCfg eth.SystemConfig, seqNumber uint64, l1Info eth.BlockInfo, l2BlockTime uint64) ([]byte, error) { - dep, err := L1InfoDeposit(rollupCfg, sysCfg, seqNumber, l1Info, l2BlockTime) +func L1InfoDepositBytes(rollupCfg *rollup.Config, sysCfg eth.SystemConfig, seqNumber uint64, l1Info eth.BlockInfo, l2Timestamp uint64) ([]byte, error) { + dep, err := L1InfoDeposit(rollupCfg, sysCfg, seqNumber, l1Info, l2Timestamp) if err != nil { return nil, fmt.Errorf("failed to create L1 info tx: %w", err) } @@ -335,3 +392,34 @@ func L1InfoDepositBytes(rollupCfg *rollup.Config, sysCfg eth.SystemConfig, seqNu } return opaqueL1Tx, nil } + +func DepositsCompleteDeposit(seqNumber uint64, block eth.BlockInfo) (*types.DepositTx, error) { + source := AfterForceIncludeSource{ + L1BlockHash: block.Hash(), + SeqNumber: seqNumber, + } + out := &types.DepositTx{ + SourceHash: source.SourceHash(), + From: L1InfoDepositerAddress, + To: &L1BlockAddress, + Mint: nil, + Value: big.NewInt(0), + Gas: DepositsCompleteGas, + IsSystemTransaction: false, + Data: DepositsCompleteBytes4, + } + return out, nil +} + +func DepositsCompleteBytes(seqNumber uint64, l1Info eth.BlockInfo) ([]byte, error) { + dep, err := DepositsCompleteDeposit(seqNumber, l1Info) + if err != nil { + return nil, fmt.Errorf("failed to create DepositsComplete tx: %w", err) + } + depositsCompleteTx := types.NewTx(dep) + opaqueDepositsCompleteTx, err := depositsCompleteTx.MarshalBinary() + if err != nil { + return nil, fmt.Errorf("failed to encode DepositsComplete tx: %w", err) + } + return opaqueDepositsCompleteTx, nil +} diff --git a/op-node/rollup/derive/l1_block_info_test.go b/op-node/rollup/derive/l1_block_info_test.go index e5c9253ce1c65..b98e8a7d4c635 100644 --- a/op-node/rollup/derive/l1_block_info_test.go +++ b/op-node/rollup/derive/l1_block_info_test.go @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/require" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-service/eth" @@ -109,10 +110,8 @@ func TestParseL1InfoDepositTxData(t *testing.T) { t.Run("regolith", func(t *testing.T) { rng := rand.New(rand.NewSource(1234)) info := testutils.MakeBlockInfo(nil)(rng) - zero := uint64(0) - rollupCfg := rollup.Config{ - RegolithTime: &zero, - } + rollupCfg := rollup.Config{} + rollupCfg.ActivateAtGenesis(rollup.Regolith) depTx, err := L1InfoDeposit(&rollupCfg, randomL1Cfg(rng, info), randomSeqNr(rng), info, 0) require.NoError(t, err) require.False(t, depTx.IsSystemTransaction) @@ -121,27 +120,24 @@ func TestParseL1InfoDepositTxData(t *testing.T) { t.Run("ecotone", func(t *testing.T) { rng := rand.New(rand.NewSource(1234)) info := testutils.MakeBlockInfo(nil)(rng) - zero := uint64(0) - rollupCfg := rollup.Config{ - RegolithTime: &zero, - EcotoneTime: &zero, - } - depTx, err := L1InfoDeposit(&rollupCfg, randomL1Cfg(rng, info), randomSeqNr(rng), info, 1) + rollupCfg := rollup.Config{BlockTime: 2, Genesis: rollup.Genesis{L2Time: 1000}} + rollupCfg.ActivateAtGenesis(rollup.Ecotone) + // run 1 block after ecotone transition + timestamp := rollupCfg.Genesis.L2Time + rollupCfg.BlockTime + depTx, err := L1InfoDeposit(&rollupCfg, randomL1Cfg(rng, info), randomSeqNr(rng), info, timestamp) require.NoError(t, err) require.False(t, depTx.IsSystemTransaction) require.Equal(t, depTx.Gas, uint64(RegolithSystemTxGas)) require.Equal(t, L1InfoEcotoneLen, len(depTx.Data)) }) - t.Run("first-block ecotone", func(t *testing.T) { + t.Run("activation-block ecotone", func(t *testing.T) { rng := rand.New(rand.NewSource(1234)) info := testutils.MakeBlockInfo(nil)(rng) - zero := uint64(2) - rollupCfg := rollup.Config{ - RegolithTime: &zero, - EcotoneTime: &zero, - BlockTime: 2, - } - depTx, err := L1InfoDeposit(&rollupCfg, randomL1Cfg(rng, info), randomSeqNr(rng), info, 2) + rollupCfg := rollup.Config{BlockTime: 2, Genesis: rollup.Genesis{L2Time: 1000}} + rollupCfg.ActivateAtGenesis(rollup.Delta) + ecotoneTime := rollupCfg.Genesis.L2Time + rollupCfg.BlockTime // activate ecotone just after genesis + rollupCfg.EcotoneTime = &ecotoneTime + depTx, err := L1InfoDeposit(&rollupCfg, randomL1Cfg(rng, info), randomSeqNr(rng), info, ecotoneTime) require.NoError(t, err) require.False(t, depTx.IsSystemTransaction) require.Equal(t, depTx.Gas, uint64(RegolithSystemTxGas)) @@ -150,16 +146,88 @@ func TestParseL1InfoDepositTxData(t *testing.T) { t.Run("genesis-block ecotone", func(t *testing.T) { rng := rand.New(rand.NewSource(1234)) info := testutils.MakeBlockInfo(nil)(rng) - zero := uint64(0) - rollupCfg := rollup.Config{ - RegolithTime: &zero, - EcotoneTime: &zero, - BlockTime: 2, - } - depTx, err := L1InfoDeposit(&rollupCfg, randomL1Cfg(rng, info), randomSeqNr(rng), info, 0) + rollupCfg := rollup.Config{BlockTime: 2, Genesis: rollup.Genesis{L2Time: 1000}} + rollupCfg.ActivateAtGenesis(rollup.Ecotone) + depTx, err := L1InfoDeposit(&rollupCfg, randomL1Cfg(rng, info), randomSeqNr(rng), info, rollupCfg.Genesis.L2Time) + require.NoError(t, err) + require.False(t, depTx.IsSystemTransaction) + require.Equal(t, depTx.Gas, uint64(RegolithSystemTxGas)) + require.Equal(t, L1InfoEcotoneLen, len(depTx.Data)) + }) + t.Run("isthmus", func(t *testing.T) { + rng := rand.New(rand.NewSource(1234)) + info := testutils.MakeBlockInfo(nil)(rng) + rollupCfg := rollup.Config{BlockTime: 2, Genesis: rollup.Genesis{L2Time: 1000}} + rollupCfg.ActivateAtGenesis(rollup.Interop) + // run 1 block after interop transition + timestamp := rollupCfg.Genesis.L2Time + rollupCfg.BlockTime + depTx, err := L1InfoDeposit(&rollupCfg, randomL1Cfg(rng, info), randomSeqNr(rng), info, timestamp) + require.NoError(t, err) + require.False(t, depTx.IsSystemTransaction) + require.Equal(t, depTx.Gas, uint64(RegolithSystemTxGas)) + require.Equal(t, L1InfoEcotoneLen, len(depTx.Data), "the length is same in isthmus") + require.Equal(t, L1InfoFuncIsthmusBytes4, depTx.Data[:4], "upgrade is active, need isthmus signature") + }) + t.Run("activation-block isthmus", func(t *testing.T) { + rng := rand.New(rand.NewSource(1234)) + info := testutils.MakeBlockInfo(nil)(rng) + rollupCfg := rollup.Config{BlockTime: 2, Genesis: rollup.Genesis{L2Time: 1000}} + rollupCfg.ActivateAtGenesis(rollup.Fjord) + isthmusTime := rollupCfg.Genesis.L2Time + rollupCfg.BlockTime // activate isthmus just after genesis + rollupCfg.InteropTime = &isthmusTime + depTx, err := L1InfoDeposit(&rollupCfg, randomL1Cfg(rng, info), randomSeqNr(rng), info, isthmusTime) + require.NoError(t, err) + require.False(t, depTx.IsSystemTransaction) + require.Equal(t, depTx.Gas, uint64(RegolithSystemTxGas)) + // Isthmus activates, but ecotone L1 info is still used at this upgrade block + require.Equal(t, L1InfoEcotoneLen, len(depTx.Data)) + require.Equal(t, L1InfoFuncEcotoneBytes4, depTx.Data[:4]) + }) + t.Run("genesis-block isthmus", func(t *testing.T) { + rng := rand.New(rand.NewSource(1234)) + info := testutils.MakeBlockInfo(nil)(rng) + rollupCfg := rollup.Config{BlockTime: 2, Genesis: rollup.Genesis{L2Time: 1000}} + rollupCfg.ActivateAtGenesis(rollup.Interop) + depTx, err := L1InfoDeposit(&rollupCfg, randomL1Cfg(rng, info), randomSeqNr(rng), info, rollupCfg.Genesis.L2Time) require.NoError(t, err) require.False(t, depTx.IsSystemTransaction) require.Equal(t, depTx.Gas, uint64(RegolithSystemTxGas)) require.Equal(t, L1InfoEcotoneLen, len(depTx.Data)) }) } + +func TestDepositsCompleteBytes(t *testing.T) { + randomSeqNr := func(rng *rand.Rand) uint64 { + return rng.Uint64() + } + t.Run("valid return bytes", func(t *testing.T) { + rng := rand.New(rand.NewSource(1234)) + info := testutils.MakeBlockInfo(nil)(rng) + depTxByes, err := DepositsCompleteBytes(randomSeqNr(rng), info) + require.NoError(t, err) + var depTx types.Transaction + require.NoError(t, depTx.UnmarshalBinary(depTxByes)) + require.Equal(t, uint8(types.DepositTxType), depTx.Type()) + require.Equal(t, depTx.Data(), DepositsCompleteBytes4) + require.Equal(t, DepositsCompleteLen, len(depTx.Data())) + require.Equal(t, DepositsCompleteGas, depTx.Gas()) + require.False(t, depTx.IsSystemTx()) + require.Equal(t, depTx.Value(), big.NewInt(0)) + signer := types.LatestSignerForChainID(depTx.ChainId()) + sender, err := signer.Sender(&depTx) + require.NoError(t, err) + require.Equal(t, L1InfoDepositerAddress, sender) + }) + t.Run("valid return Transaction", func(t *testing.T) { + rng := rand.New(rand.NewSource(1234)) + info := testutils.MakeBlockInfo(nil)(rng) + depTx, err := DepositsCompleteDeposit(randomSeqNr(rng), info) + require.NoError(t, err) + require.Equal(t, depTx.Data, DepositsCompleteBytes4) + require.Equal(t, DepositsCompleteLen, len(depTx.Data)) + require.Equal(t, DepositsCompleteGas, depTx.Gas) + require.False(t, depTx.IsSystemTransaction) + require.Equal(t, depTx.Value, big.NewInt(0)) + require.Equal(t, L1InfoDepositerAddress, depTx.From) + }) +} diff --git a/op-node/rollup/derive/pipeline.go b/op-node/rollup/derive/pipeline.go index a3f7e43e546e5..69420a354c9d5 100644 --- a/op-node/rollup/derive/pipeline.go +++ b/op-node/rollup/derive/pipeline.go @@ -71,8 +71,7 @@ type DerivationPipeline struct { origin eth.L1BlockRef resetL2Safe eth.L2BlockRef resetSysConfig eth.SystemConfig - // Its value is only 1 or 0 - engineIsReset atomic.Bool + engineIsReset atomic.Bool metrics Metrics } @@ -86,7 +85,7 @@ func NewDerivationPipeline(log log.Logger, rollupCfg *rollup.Config, l1Fetcher L dataSrc := NewDataSourceFactory(log, rollupCfg, l1Fetcher, l1Blobs, altDA) // auxiliary stage for L1Retrieval l1Src := NewL1Retrieval(log, dataSrc, l1Traversal) frameQueue := NewFrameQueue(log, l1Src) - bank := NewChannelBank(log, rollupCfg, frameQueue, l1Fetcher, metrics) + bank := NewChannelBank(log, rollupCfg, frameQueue, metrics) chInReader := NewChannelInReader(rollupCfg, log, bank, metrics) batchQueue := NewBatchQueue(log, rollupCfg, chInReader, l2Source) attrBuilder := NewFetchingAttributesBuilder(rollupCfg, l1Fetcher, l2Source) diff --git a/op-node/rollup/derive/singular_batch.go b/op-node/rollup/derive/singular_batch.go index fdb867efbe727..9993c351bf23e 100644 --- a/op-node/rollup/derive/singular_batch.go +++ b/op-node/rollup/derive/singular_batch.go @@ -23,7 +23,7 @@ type SingularBatch struct { ParentHash common.Hash // parent L2 block hash EpochNum rollup.Epoch // aka l1 num EpochHash common.Hash // l1 block hash - Timestamp uint64 + Timestamp uint64 // l2 block timestamp Transactions []hexutil.Bytes } diff --git a/op-node/rollup/derive/span_channel_out.go b/op-node/rollup/derive/span_channel_out.go index aa2eae04b2d19..9950fe29c413b 100644 --- a/op-node/rollup/derive/span_channel_out.go +++ b/op-node/rollup/derive/span_channel_out.go @@ -5,7 +5,6 @@ import ( "crypto/rand" "fmt" "io" - "math/big" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/rlp" @@ -65,11 +64,11 @@ func WithMaxBlocksPerSpanBatch(maxBlock int) SpanChannelOutOption { } } -func NewSpanChannelOut(genesisTimestamp uint64, chainID *big.Int, targetOutputSize uint64, compressionAlgo CompressionAlgo, chainSpec *rollup.ChainSpec, opts ...SpanChannelOutOption) (*SpanChannelOut, error) { +func NewSpanChannelOut(targetOutputSize uint64, compressionAlgo CompressionAlgo, chainSpec *rollup.ChainSpec, opts ...SpanChannelOutOption) (*SpanChannelOut, error) { c := &SpanChannelOut{ id: ChannelID{}, frame: 0, - spanBatch: NewSpanBatch(genesisTimestamp, chainID), + spanBatch: NewSpanBatch(chainSpec.L2GenesisTime(), chainSpec.L2ChainID()), rlp: [2]*bytes.Buffer{{}, {}}, target: targetOutputSize, chainSpec: chainSpec, diff --git a/op-node/rollup/driver/driver.go b/op-node/rollup/driver/driver.go index ca5d1641522b6..81607e612d5a2 100644 --- a/op-node/rollup/driver/driver.go +++ b/op-node/rollup/driver/driver.go @@ -17,6 +17,7 @@ import ( "github.com/ethereum-optimism/optimism/op-node/rollup/engine" "github.com/ethereum-optimism/optimism/op-node/rollup/event" "github.com/ethereum-optimism/optimism/op-node/rollup/finality" + "github.com/ethereum-optimism/optimism/op-node/rollup/interop" "github.com/ethereum-optimism/optimism/op-node/rollup/sequencing" "github.com/ethereum-optimism/optimism/op-node/rollup/status" "github.com/ethereum-optimism/optimism/op-node/rollup/sync" @@ -149,12 +150,19 @@ type SequencerStateListener interface { SequencerStopped() error } +type Drain interface { + Drain() error +} + // NewDriver composes an events handler that tracks L1 state, triggers L2 Derivation, and optionally sequences new L2 blocks. func NewDriver( + sys event.Registry, + drain Drain, driverCfg *Config, cfg *rollup.Config, l2 L2Chain, l1 L1Chain, + supervisor interop.InteropBackend, // may be nil pre-interop. l1Blobs derive.L1BlobsFetcher, altSync AltSync, network Network, @@ -168,18 +176,16 @@ func NewDriver( ) *Driver { driverCtx, driverCancel := context.WithCancel(context.Background()) - var executor event.Executor - var drain func() error - // This instantiation will be one of more options: soon there will be a parallel events executor - { - executor = event.NewParallelExec() - drain = func() error { return nil } // no-op - } - sys := event.NewSystem(log, executor) - sys.AddTracer(event.NewMetricsTracer(metrics)) - opts := event.DefaultRegisterOpts() + // If interop is scheduled we start the driver. + // It will then be ready to pick up verification work + // as soon as we reach the upgrade time (if the upgrade is not already active). + if cfg.InteropTime != nil { + interopDeriver := interop.NewInteropDeriver(log, cfg, driverCtx, supervisor, l2) + sys.Register("interop", interopDeriver, opts) + } + statusTracker := status.NewStatusTracker(log, metrics) sys.Register("status", statusTracker, opts) @@ -225,7 +231,7 @@ func NewDriver( L2: l2, Log: log, Ctx: driverCtx, - Drain: drain, + Drain: drain.Drain, } sys.Register("sync", syncDeriver, opts) @@ -249,12 +255,11 @@ func NewDriver( driverEmitter := sys.Register("driver", nil, opts) driver := &Driver{ - eventSys: sys, statusTracker: statusTracker, SyncDeriver: syncDeriver, sched: schedDeriv, emitter: driverEmitter, - drain: drain, + drain: drain.Drain, stateReq: make(chan chan struct{}), forceReset: make(chan chan struct{}, 10), driverConfig: driverCfg, diff --git a/op-node/rollup/driver/state.go b/op-node/rollup/driver/state.go index b93fa14b04f1a..a958062ef3595 100644 --- a/op-node/rollup/driver/state.go +++ b/op-node/rollup/driver/state.go @@ -26,8 +26,6 @@ import ( type SyncStatus = eth.SyncStatus type Driver struct { - eventSys event.System - statusTracker SyncStatusTracker *SyncDeriver @@ -100,7 +98,6 @@ func (s *Driver) Start() error { func (s *Driver) Close() error { s.driverCancel() s.wg.Wait() - s.eventSys.Stop() s.sequencer.Close() return nil } @@ -287,27 +284,6 @@ func (s *Driver) eventLoop() { } } -// OnEvent handles broadcasted events. -// The Driver itself is a deriver to catch system-critical events. -// Other event-handling should be encapsulated into standalone derivers. -func (s *Driver) OnEvent(ev event.Event) bool { - switch x := ev.(type) { - case rollup.CriticalErrorEvent: - s.Log.Error("Derivation process critical error", "err", x.Err) - // we need to unblock event-processing to be able to close - go func() { - logger := s.Log - err := s.Close() - if err != nil { - logger.Error("Failed to shutdown driver on critical error", "err", err) - } - }() - return true - default: - return false - } -} - type SyncDeriver struct { // The derivation pipeline is reset whenever we reorg. // The derivation pipeline determines the new l2Safe. @@ -470,6 +446,12 @@ func (s *SyncDeriver) SyncStep() { // Upon the pending-safe signal the attributes deriver can then ask the pipeline // to generate new attributes, if no attributes are known already. s.Emitter.Emit(engine.PendingSafeRequestEvent{}) + + // If interop is configured, we have to run the engine events, + // to ensure cross-L2 safety is continuously verified against the interop-backend. + if s.Config.InteropTime != nil { + s.Emitter.Emit(engine.CrossUpdateRequestEvent{}) + } } // ResetDerivationPipeline forces a reset of the derivation pipeline. diff --git a/op-node/rollup/engine/build_start.go b/op-node/rollup/engine/build_start.go index c1f9df5a98d6c..22c178d36cd0f 100644 --- a/op-node/rollup/engine/build_start.go +++ b/op-node/rollup/engine/build_start.go @@ -34,6 +34,11 @@ func (eq *EngDeriver) onBuildStart(ev BuildStartEvent) { SafeL2Head: eq.ec.safeHead, FinalizedL2Head: eq.ec.finalizedHead, } + if fcEvent.UnsafeL2Head.Number < fcEvent.FinalizedL2Head.Number { + err := fmt.Errorf("invalid block-building pre-state, unsafe head %s is behind finalized head %s", fcEvent.UnsafeL2Head, fcEvent.FinalizedL2Head) + eq.emitter.Emit(rollup.CriticalErrorEvent{Err: err}) // make the node exit, things are very wrong. + return + } fc := eth.ForkchoiceState{ HeadBlockHash: fcEvent.UnsafeL2Head.Hash, SafeBlockHash: fcEvent.SafeL2Head.Hash, diff --git a/op-node/rollup/engine/engine_controller.go b/op-node/rollup/engine/engine_controller.go index d8db9cad949c6..4ac8b88a50cf4 100644 --- a/op-node/rollup/engine/engine_controller.go +++ b/op-node/rollup/engine/engine_controller.go @@ -25,7 +25,7 @@ const ( // We transition between the 4 EL states linearly. We spend the majority of the time in the second & fourth. // We only want to EL sync if there is no finalized block & once we finish EL sync we need to mark the last block // as finalized so we can switch to consolidation - // TODO(protocol-quest/91): We can restart EL sync & still consolidate if there finalized blocks on the execution client if the + // TODO(protocol-quest#91): We can restart EL sync & still consolidate if there finalized blocks on the execution client if the // execution client is running in archive mode. In some cases we may want to switch back from CL to EL sync, but that is complicated. syncStatusWillStartEL // First if we are directed to EL sync, check that nothing has been finalized yet syncStatusStartedEL // Perform our EL sync @@ -56,12 +56,27 @@ type EngineController struct { emitter event.Emitter // 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 + unsafeHead eth.L2BlockRef + // Cross-verified unsafeHead, always equal to unsafeHead pre-interop + crossUnsafeHead eth.L2BlockRef + // Pending localSafeHead + // L2 block processed from the middle of a span batch, + // but not marked as the safe block yet. + pendingSafeHead eth.L2BlockRef + // Derived from L1, and known to be a completed span-batch, + // but not cross-verified yet. + localSafeHead eth.L2BlockRef + // Derived from L1 and cross-verified to have cross-safe dependencies. + safeHead eth.L2BlockRef + // Derived from finalized L1 data, + // and cross-verified to only have finalized dependencies. + finalizedHead eth.L2BlockRef + // The unsafe head to roll back to, + // after the pendingSafeHead fails to become safe. + // This is changing in the Holocene fork. backupUnsafeHead eth.L2BlockRef - needFCUCall bool + + 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 @@ -96,10 +111,18 @@ func (e *EngineController) UnsafeL2Head() eth.L2BlockRef { return e.unsafeHead } +func (e *EngineController) CrossUnsafeL2Head() eth.L2BlockRef { + return e.crossUnsafeHead +} + func (e *EngineController) PendingSafeL2Head() eth.L2BlockRef { return e.pendingSafeHead } +func (e *EngineController) LocalSafeL2Head() eth.L2BlockRef { + return e.localSafeHead +} + func (e *EngineController) SafeL2Head() eth.L2BlockRef { return e.safeHead } @@ -131,14 +154,20 @@ func (e *EngineController) SetPendingSafeL2Head(r eth.L2BlockRef) { e.pendingSafeHead = r } -// SetSafeHead implements LocalEngineControl. +// SetLocalSafeHead sets the local-safe head. +func (e *EngineController) SetLocalSafeHead(r eth.L2BlockRef) { + e.metrics.RecordL2Ref("l2_local_safe", r) + e.localSafeHead = r +} + +// SetSafeHead sets the cross-safe head. func (e *EngineController) SetSafeHead(r eth.L2BlockRef) { e.metrics.RecordL2Ref("l2_safe", r) e.safeHead = r e.needFCUCall = true } -// SetUnsafeHead implements LocalEngineControl. +// SetUnsafeHead sets the local-unsafe head. func (e *EngineController) SetUnsafeHead(r eth.L2BlockRef) { e.metrics.RecordL2Ref("l2_unsafe", r) e.unsafeHead = r @@ -146,6 +175,12 @@ func (e *EngineController) SetUnsafeHead(r eth.L2BlockRef) { e.chainSpec.CheckForkActivation(e.log, r) } +// SetCrossUnsafeHead the cross-unsafe head. +func (e *EngineController) SetCrossUnsafeHead(r eth.L2BlockRef) { + e.metrics.RecordL2Ref("l2_cross_unsafe", r) + e.crossUnsafeHead = r +} + // SetBackupUnsafeL2Head implements LocalEngineControl. func (e *EngineController) SetBackupUnsafeL2Head(r eth.L2BlockRef, triggerReorg bool) { e.metrics.RecordL2Ref("l2_backup_unsafe", r) @@ -234,6 +269,11 @@ func (e *EngineController) TryUpdateEngine(ctx context.Context) error { if e.IsEngineSyncing() { e.log.Warn("Attempting to update forkchoice state while EL syncing") } + if e.unsafeHead.Number < e.finalizedHead.Number { + err := fmt.Errorf("invalid forkchoice state, unsafe head %s is behind finalized head %s", e.unsafeHead, e.finalizedHead) + e.emitter.Emit(rollup.CriticalErrorEvent{Err: err}) // make the node exit, things are very wrong. + return err + } fc := eth.ForkchoiceState{ HeadBlockHash: e.unsafeHead.Hash, SafeBlockHash: e.safeHead.Hash, @@ -310,7 +350,11 @@ func (e *EngineController) InsertUnsafePayload(ctx context.Context, envelope *et if e.syncStatus == syncStatusFinishedELButNotFinalized { fc.SafeBlockHash = envelope.ExecutionPayload.BlockHash fc.FinalizedBlockHash = envelope.ExecutionPayload.BlockHash + e.SetUnsafeHead(ref) // ensure that the unsafe head stays ahead of safe/finalized labels. + e.emitter.Emit(UnsafeUpdateEvent{Ref: ref}) + e.SetLocalSafeHead(ref) e.SetSafeHead(ref) + e.emitter.Emit(CrossSafeUpdateEvent{LocalSafe: ref, CrossSafe: ref}) e.SetFinalizedHead(ref) } logFn := e.logSyncProgressMaybe() @@ -336,6 +380,7 @@ func (e *EngineController) InsertUnsafePayload(ctx context.Context, envelope *et } e.SetUnsafeHead(ref) e.needFCUCall = false + e.emitter.Emit(UnsafeUpdateEvent{Ref: ref}) if e.syncStatus == syncStatusFinishedELButNotFinalized { e.log.Info("Finished EL sync", "sync_duration", e.clock.Since(e.elStart), "finalized_block", ref.ID().String()) diff --git a/op-node/rollup/engine/engine_update.go b/op-node/rollup/engine/engine_update.go index 8f100709bcc16..c79dbdcd0f4d0 100644 --- a/op-node/rollup/engine/engine_update.go +++ b/op-node/rollup/engine/engine_update.go @@ -104,7 +104,7 @@ func startPayload(ctx context.Context, eng ExecEngine, fc eth.ForkchoiceState, a } switch fcRes.PayloadStatus.Status { - // TODO(proto): snap sync - specify explicit different error type if node is syncing + // TODO: snap sync - specify explicit different error type if node is syncing case eth.ExecutionInvalid, eth.ExecutionInvalidBlockHash: return eth.PayloadID{}, BlockInsertPayloadErr, eth.ForkchoiceUpdateErr(fcRes.PayloadStatus) case eth.ExecutionValid: diff --git a/op-node/rollup/engine/events.go b/op-node/rollup/engine/events.go index 325118825fcee..b5e010280ebc9 100644 --- a/op-node/rollup/engine/events.go +++ b/op-node/rollup/engine/events.go @@ -40,6 +40,55 @@ func (ev ForkchoiceUpdateEvent) String() string { return "forkchoice-update" } +// PromoteUnsafeEvent signals that the given block may now become a canonical unsafe block. +// This is pre-forkchoice update; the change may not be reflected yet in the EL. +// Note that the legacy pre-event-refactor code-path (processing P2P blocks) does fire this, +// but manually, duplicate with the newer events processing code-path. +// See EngineController.InsertUnsafePayload. +type PromoteUnsafeEvent struct { + Ref eth.L2BlockRef +} + +func (ev PromoteUnsafeEvent) String() string { + return "promote-unsafe" +} + +// RequestCrossUnsafeEvent signals that a CrossUnsafeUpdateEvent is needed. +type RequestCrossUnsafeEvent struct{} + +func (ev RequestCrossUnsafeEvent) String() string { + return "request-cross-unsafe" +} + +// UnsafeUpdateEvent signals that the given block is now considered safe. +// This is pre-forkchoice update; the change may not be reflected yet in the EL. +type UnsafeUpdateEvent struct { + Ref eth.L2BlockRef +} + +func (ev UnsafeUpdateEvent) String() string { + return "unsafe-update" +} + +// PromoteCrossUnsafeEvent signals that the given block may be promoted to cross-unsafe. +type PromoteCrossUnsafeEvent struct { + Ref eth.L2BlockRef +} + +func (ev PromoteCrossUnsafeEvent) String() string { + return "promote-cross-unsafe" +} + +// CrossUnsafeUpdateEvent signals that the given block is now considered cross-unsafe. +type CrossUnsafeUpdateEvent struct { + CrossUnsafe eth.L2BlockRef + LocalUnsafe eth.L2BlockRef +} + +func (ev CrossUnsafeUpdateEvent) String() string { + return "cross-unsafe-update" +} + type PendingSafeUpdateEvent struct { PendingSafe eth.L2BlockRef Unsafe eth.L2BlockRef // tip, added to the signal, to determine if there are existing blocks to consolidate @@ -60,7 +109,54 @@ func (ev PromotePendingSafeEvent) String() string { return "promote-pending-safe" } -// SafeDerivedEvent signals that a block was determined to be safe, and derived from the given L1 block +// PromoteLocalSafeEvent signals that a block can be promoted to local-safe. +type PromoteLocalSafeEvent struct { + Ref eth.L2BlockRef + DerivedFrom eth.L1BlockRef +} + +func (ev PromoteLocalSafeEvent) String() string { + return "promote-local-safe" +} + +// RequestCrossSafeEvent signals that a CrossSafeUpdate is needed. +type RequestCrossSafeEvent struct{} + +func (ev RequestCrossSafeEvent) String() string { + return "request-cross-safe-update" +} + +type CrossSafeUpdateEvent struct { + CrossSafe eth.L2BlockRef + LocalSafe eth.L2BlockRef +} + +func (ev CrossSafeUpdateEvent) String() string { + return "cross-safe-update" +} + +// LocalSafeUpdateEvent signals that a block is now considered to be local-safe. +type LocalSafeUpdateEvent struct { + Ref eth.L2BlockRef + DerivedFrom eth.L1BlockRef +} + +func (ev LocalSafeUpdateEvent) String() string { + return "local-safe-update" +} + +// PromoteSafeEvent signals that a block can be promoted to cross-safe. +type PromoteSafeEvent struct { + Ref eth.L2BlockRef + DerivedFrom eth.L1BlockRef +} + +func (ev PromoteSafeEvent) String() string { + return "promote-safe" +} + +// SafeDerivedEvent signals that a block was determined to be safe, and derived from the given L1 block. +// This is signaled upon successful processing of PromoteSafeEvent. type SafeDerivedEvent struct { Safe eth.L2BlockRef DerivedFrom eth.L1BlockRef @@ -133,6 +229,16 @@ func (ev PromoteFinalizedEvent) String() string { return "promote-finalized" } +// CrossUpdateRequestEvent triggers update events to be emitted, repeating the current state. +type CrossUpdateRequestEvent struct { + CrossUnsafe bool + CrossSafe bool +} + +func (ev CrossUpdateRequestEvent) String() string { + return "cross-update-request" +} + type EngDeriver struct { metrics Metrics @@ -234,6 +340,36 @@ func (d *EngDeriver) OnEvent(ev event.Event) bool { "safeHead", x.Safe, "unsafe", x.Unsafe, "safe_timestamp", x.Safe.Time, "unsafe_timestamp", x.Unsafe.Time) d.emitter.Emit(EngineResetConfirmedEvent(x)) + case PromoteUnsafeEvent: + // Backup unsafeHead when new block is not built on original unsafe head. + if d.ec.unsafeHead.Number >= x.Ref.Number { + d.ec.SetBackupUnsafeL2Head(d.ec.unsafeHead, false) + } + d.ec.SetUnsafeHead(x.Ref) + d.emitter.Emit(UnsafeUpdateEvent(x)) + case UnsafeUpdateEvent: + // pre-interop everything that is local-unsafe is also immediately cross-unsafe. + if !d.cfg.IsInterop(x.Ref.Time) { + d.emitter.Emit(PromoteCrossUnsafeEvent(x)) + } + // Try to apply the forkchoice changes + d.emitter.Emit(TryUpdateEngineEvent{}) + case PromoteCrossUnsafeEvent: + d.ec.SetCrossUnsafeHead(x.Ref) + d.emitter.Emit(CrossUnsafeUpdateEvent{ + CrossUnsafe: x.Ref, + LocalUnsafe: d.ec.UnsafeL2Head(), + }) + case RequestCrossUnsafeEvent: + d.emitter.Emit(CrossUnsafeUpdateEvent{ + CrossUnsafe: d.ec.CrossUnsafeL2Head(), + LocalUnsafe: d.ec.UnsafeL2Head(), + }) + case RequestCrossSafeEvent: + d.emitter.Emit(CrossSafeUpdateEvent{ + CrossSafe: d.ec.SafeL2Head(), + LocalSafe: d.ec.LocalSafeL2Head(), + }) case PendingSafeRequestEvent: d.emitter.Emit(PendingSafeUpdateEvent{ PendingSafe: d.ec.PendingSafeL2Head(), @@ -249,12 +385,30 @@ func (d *EngDeriver) OnEvent(ev event.Event) bool { Unsafe: d.ec.UnsafeL2Head(), }) } - if x.Safe && x.Ref.Number > d.ec.SafeL2Head().Number { - d.ec.SetSafeHead(x.Ref) - d.emitter.Emit(SafeDerivedEvent{Safe: x.Ref, DerivedFrom: x.DerivedFrom}) - // Try to apply the forkchoice changes - d.emitter.Emit(TryUpdateEngineEvent{}) + if x.Safe && x.Ref.Number > d.ec.LocalSafeL2Head().Number { + d.emitter.Emit(PromoteLocalSafeEvent{ + Ref: x.Ref, + DerivedFrom: x.DerivedFrom, + }) + } + case PromoteLocalSafeEvent: + d.ec.SetLocalSafeHead(x.Ref) + d.emitter.Emit(LocalSafeUpdateEvent(x)) + case LocalSafeUpdateEvent: + // pre-interop everything that is local-safe is also immediately cross-safe. + if !d.cfg.IsInterop(x.Ref.Time) { + d.emitter.Emit(PromoteSafeEvent(x)) } + case PromoteSafeEvent: + d.ec.SetSafeHead(x.Ref) + // Finalizer can pick up this safe cross-block now + d.emitter.Emit(SafeDerivedEvent{Safe: x.Ref, DerivedFrom: x.DerivedFrom}) + d.emitter.Emit(CrossSafeUpdateEvent{ + CrossSafe: d.ec.SafeL2Head(), + LocalSafe: d.ec.LocalSafeL2Head(), + }) + // Try to apply the forkchoice changes + d.emitter.Emit(TryUpdateEngineEvent{}) case PromoteFinalizedEvent: if x.Ref.Number < d.ec.Finalized().Number { d.log.Error("Cannot rewind finality,", "ref", x.Ref, "finalized", d.ec.Finalized()) @@ -267,6 +421,19 @@ func (d *EngDeriver) OnEvent(ev event.Event) bool { d.ec.SetFinalizedHead(x.Ref) // Try to apply the forkchoice changes d.emitter.Emit(TryUpdateEngineEvent{}) + case CrossUpdateRequestEvent: + if x.CrossUnsafe { + d.emitter.Emit(CrossUnsafeUpdateEvent{ + CrossUnsafe: d.ec.CrossUnsafeL2Head(), + LocalUnsafe: d.ec.UnsafeL2Head(), + }) + } + if x.CrossSafe { + d.emitter.Emit(CrossSafeUpdateEvent{ + CrossSafe: d.ec.SafeL2Head(), + LocalSafe: d.ec.LocalSafeL2Head(), + }) + } case BuildStartEvent: d.onBuildStart(x) case BuildStartedEvent: @@ -295,6 +462,8 @@ type ResetEngineControl interface { SetUnsafeHead(eth.L2BlockRef) SetSafeHead(eth.L2BlockRef) SetFinalizedHead(eth.L2BlockRef) + SetLocalSafeHead(ref eth.L2BlockRef) + SetCrossUnsafeHead(ref eth.L2BlockRef) SetBackupUnsafeL2Head(block eth.L2BlockRef, triggerReorg bool) SetPendingSafeL2Head(eth.L2BlockRef) } @@ -302,8 +471,10 @@ type ResetEngineControl interface { // ForceEngineReset is not to be used. The op-program needs it for now, until event processing is adopted there. func ForceEngineReset(ec ResetEngineControl, x ForceEngineResetEvent) { ec.SetUnsafeHead(x.Unsafe) - ec.SetSafeHead(x.Safe) + ec.SetLocalSafeHead(x.Safe) ec.SetPendingSafeL2Head(x.Safe) ec.SetFinalizedHead(x.Finalized) + ec.SetSafeHead(x.Safe) + ec.SetCrossUnsafeHead(x.Safe) ec.SetBackupUnsafeL2Head(eth.L2BlockRef{}, false) } diff --git a/op-node/rollup/engine/payload_success.go b/op-node/rollup/engine/payload_success.go index cdd2ee2d030b3..7bb4a38307e13 100644 --- a/op-node/rollup/engine/payload_success.go +++ b/op-node/rollup/engine/payload_success.go @@ -19,23 +19,14 @@ func (ev PayloadSuccessEvent) String() string { } func (eq *EngDeriver) onPayloadSuccess(ev PayloadSuccessEvent) { - - // Backup unsafeHead when new block is not built on original unsafe head. - if eq.ec.unsafeHead.Number >= ev.Ref.Number { - eq.ec.SetBackupUnsafeL2Head(eq.ec.unsafeHead, false) - } - eq.ec.SetUnsafeHead(ev.Ref) + eq.emitter.Emit(PromoteUnsafeEvent{Ref: ev.Ref}) // If derived from L1, then it can be considered (pending) safe if ev.DerivedFrom != (eth.L1BlockRef{}) { - if ev.IsLastInSpan { - eq.ec.SetSafeHead(ev.Ref) - eq.emitter.Emit(SafeDerivedEvent{Safe: ev.Ref, DerivedFrom: ev.DerivedFrom}) - } - eq.ec.SetPendingSafeL2Head(ev.Ref) - eq.emitter.Emit(PendingSafeUpdateEvent{ - PendingSafe: eq.ec.PendingSafeL2Head(), - Unsafe: eq.ec.UnsafeL2Head(), + eq.emitter.Emit(PromotePendingSafeEvent{ + Ref: ev.Ref, + Safe: ev.IsLastInSpan, + DerivedFrom: ev.DerivedFrom, }) } diff --git a/op-node/rollup/event.go b/op-node/rollup/event.go index bcab847451d8d..3d12c34a9f6b4 100644 --- a/op-node/rollup/event.go +++ b/op-node/rollup/event.go @@ -37,12 +37,5 @@ func (ev ResetEvent) String() string { return "reset-event" } -type CriticalErrorEvent struct { - Err error -} - -var _ event.Event = CriticalErrorEvent{} - -func (ev CriticalErrorEvent) String() string { - return "critical-error" -} +// CriticalErrorEvent is an alias for event.CriticalErrorEvent +type CriticalErrorEvent = event.CriticalErrorEvent diff --git a/op-node/rollup/event/events.go b/op-node/rollup/event/events.go index ac550e203e551..6fed3859a64ee 100644 --- a/op-node/rollup/event/events.go +++ b/op-node/rollup/event/events.go @@ -75,3 +75,13 @@ func (fn DeriverFunc) OnEvent(ev Event) bool { type NoopEmitter struct{} func (e NoopEmitter) Emit(ev Event) {} + +type CriticalErrorEvent struct { + Err error +} + +var _ Event = CriticalErrorEvent{} + +func (ev CriticalErrorEvent) String() string { + return "critical-error" +} diff --git a/op-node/rollup/event/executor_parallel.go b/op-node/rollup/event/executor_parallel.go index 6b90e4efe8d79..76ec7dfe1dec4 100644 --- a/op-node/rollup/event/executor_parallel.go +++ b/op-node/rollup/event/executor_parallel.go @@ -48,6 +48,14 @@ func (p *ParallelExec) Enqueue(ev AnnotatedEvent) error { return nil } +func (p *ParallelExec) Drain() error { + return nil +} + +func (p *ParallelExec) DrainUntil(fn func(ev Event) bool, excl bool) error { + return nil +} + type worker struct { // ctx signals when the worker is exiting. // No additional events will be accepted after cancellation. diff --git a/op-node/rollup/event/system.go b/op-node/rollup/event/system.go index be133f311c41b..7b67258fd2b06 100644 --- a/op-node/rollup/event/system.go +++ b/op-node/rollup/event/system.go @@ -11,7 +11,7 @@ import ( "github.com/ethereum/go-ethereum/log" ) -type System interface { +type Registry interface { // Register registers a named event-emitter, optionally processing events itself: // deriver may be nil, not all registrants have to process events. // A non-nil deriver may implement AttachEmitter to automatically attach the Emitter to it, @@ -20,6 +20,10 @@ type System interface { // Unregister removes a named emitter, // also removing it from the set of events-receiving derivers (if registered with non-nil deriver). Unregister(name string) (old Emitter) +} + +type System interface { + Registry // AddTracer registers a tracer to capture all event deriver/emitter work. It runs until RemoveTracer is called. // Duplicate tracers are allowed. AddTracer(t Tracer) @@ -73,6 +77,10 @@ func (r *systemActor) RunEvent(ev AnnotatedEvent) { if r.ctx.Err() != nil { return } + if r.sys.abort.Load() && !Is[CriticalErrorEvent](ev.Event) { + // if aborting, and not the CriticalErrorEvent itself, then do not process the event + return + } prev := r.currentEvent.Load() start := time.Now() @@ -99,6 +107,9 @@ type Sys struct { tracers []Tracer tracersLock sync.RWMutex + + // if true, no events may be processed, except CriticalError itself + abort atomic.Bool } func NewSystem(log log.Logger, ex Executor) *Sys { @@ -240,6 +251,12 @@ func (s *Sys) emit(name string, derivContext uint64, ev Event) { emitContext := s.emitContext.Add(1) annotated := AnnotatedEvent{Event: ev, EmitContext: emitContext} + // As soon as anything emits a critical event, + // make the system aware, before the executor event schedules it for processing. + if Is[CriticalErrorEvent](ev) { + s.abort.Store(true) + } + emitTime := time.Now() s.recordEmit(name, annotated, derivContext, emitTime) diff --git a/op-node/rollup/event/system_test.go b/op-node/rollup/event/system_test.go index 9feef96285319..749eb681a75c4 100644 --- a/op-node/rollup/event/system_test.go +++ b/op-node/rollup/event/system_test.go @@ -2,6 +2,7 @@ package event import ( "context" + "errors" "testing" "github.com/stretchr/testify/require" @@ -104,3 +105,46 @@ func TestSystemBroadcast(t *testing.T) { require.Equal(t, 3, fooCount) require.Equal(t, 3, barCount) } + +func TestCriticalError(t *testing.T) { + logger := testlog.Logger(t, log.LevelError) + count := 0 + seenCrit := 0 + deriverFn := DeriverFunc(func(ev Event) bool { + switch ev.(type) { + case CriticalErrorEvent: + seenCrit += 1 + default: + count += 1 + } + return true + }) + exec := NewGlobalSynchronous(context.Background()) + sys := NewSystem(logger, exec) + emitterA := sys.Register("a", deriverFn, DefaultRegisterOpts()) + emitterB := sys.Register("b", deriverFn, DefaultRegisterOpts()) + + require.NoError(t, exec.Drain(), "can drain, even if empty") + emitterA.Emit(TestEvent{}) + require.Equal(t, 0, count, "no processing yet, queued event") + require.NoError(t, exec.Drain()) + require.Equal(t, 2, count, "both A and B processed the event") + + emitterA.Emit(TestEvent{}) + emitterB.Emit(TestEvent{}) + testErr := errors.New("test crit error") + emitterB.Emit(CriticalErrorEvent{Err: testErr}) + require.Equal(t, 2, count, "no processing yet, queued events") + require.Equal(t, 0, seenCrit, "critical error events are still scheduled like normal") + require.True(t, sys.abort.Load(), "we are aware of the crit") + require.NoError(t, exec.Drain()) + require.Equal(t, 2, count, "still no processing, since we hit a crit error, the events are ignored") + require.Equal(t, 2, seenCrit, "but everyone has seen the crit now") + + // We are able to stop the processing now + sys.Stop() + + emitterA.Emit(TestEvent{}) + require.NoError(t, exec.Drain(), "system is closed, no further event processing") + require.Equal(t, 2, count) +} diff --git a/op-node/rollup/interop/interop.go b/op-node/rollup/interop/interop.go new file mode 100644 index 0000000000000..c6c170478f21e --- /dev/null +++ b/op-node/rollup/interop/interop.go @@ -0,0 +1,161 @@ +package interop + +import ( + "context" + "sync" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/log" + + "github.com/ethereum-optimism/optimism/op-node/rollup" + "github.com/ethereum-optimism/optimism/op-node/rollup/engine" + "github.com/ethereum-optimism/optimism/op-node/rollup/event" + "github.com/ethereum-optimism/optimism/op-service/eth" + "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" +) + +const checkBlockTimeout = time.Second * 10 + +type InteropBackend interface { + CheckBlock(ctx context.Context, + chainID types.ChainID, blockHash common.Hash, blockNumber uint64) (types.SafetyLevel, error) +} + +type L2Source interface { + L2BlockRefByNumber(context.Context, uint64) (eth.L2BlockRef, error) +} + +// InteropDeriver watches for update events (either real changes to block safety, +// or updates published upon request), checks if there is some local data to cross-verify, +// and then checks with the interop-backend, to try to promote to cross-verified safety. +type InteropDeriver struct { + log log.Logger + cfg *rollup.Config + + // we cache the chainID, + // to not continuously convert from the type in the rollup-config to this type. + chainID types.ChainID + + driverCtx context.Context + + // L2 blockhash -> derived from L1 block ref. + // Added to when a block is local-safe. + // Removed from when it is promoted to cross-safe. + derivedFrom map[common.Hash]eth.L1BlockRef + + backend InteropBackend + l2 L2Source + + emitter event.Emitter + + mu sync.Mutex +} + +var _ event.Deriver = (*InteropDeriver)(nil) +var _ event.AttachEmitter = (*InteropDeriver)(nil) + +func NewInteropDeriver(log log.Logger, cfg *rollup.Config, + driverCtx context.Context, backend InteropBackend, l2 L2Source) *InteropDeriver { + return &InteropDeriver{ + log: log, + cfg: cfg, + chainID: types.ChainIDFromBig(cfg.L2ChainID), + driverCtx: driverCtx, + derivedFrom: make(map[common.Hash]eth.L1BlockRef), + backend: backend, + l2: l2, + } +} + +func (d *InteropDeriver) AttachEmitter(em event.Emitter) { + d.emitter = em +} + +func (d *InteropDeriver) OnEvent(ev event.Event) bool { + d.mu.Lock() + defer d.mu.Unlock() + + switch x := ev.(type) { + case engine.UnsafeUpdateEvent: + d.emitter.Emit(engine.RequestCrossUnsafeEvent{}) + case engine.CrossUnsafeUpdateEvent: + if x.CrossUnsafe.Number >= x.LocalUnsafe.Number { + break // nothing left to promote + } + // Pre-interop the engine itself handles promotion to cross-unsafe. + // Check if the next block (still unsafe) can be promoted to cross-unsafe. + if !d.cfg.IsInterop(d.cfg.TimestampForBlock(x.CrossUnsafe.Number + 1)) { + return false + } + ctx, cancel := context.WithTimeout(d.driverCtx, checkBlockTimeout) + defer cancel() + candidate, err := d.l2.L2BlockRefByNumber(ctx, x.CrossUnsafe.Number+1) + if err != nil { + d.log.Warn("Failed to fetch next cross-unsafe candidate", "err", err) + break + } + blockSafety, err := d.backend.CheckBlock(ctx, d.chainID, candidate.Hash, candidate.Number) + if err != nil { + d.log.Warn("Failed to check interop safety of unsafe block", "err", err) + break + } + switch blockSafety { + case types.CrossUnsafe, types.CrossSafe, types.CrossFinalized: + // Hold off on promoting higher than cross-unsafe, + // this will happen once we verify it to be local-safe first. + d.emitter.Emit(engine.PromoteCrossUnsafeEvent{Ref: candidate}) + } + case engine.LocalSafeUpdateEvent: + d.derivedFrom[x.Ref.Hash] = x.DerivedFrom + d.emitter.Emit(engine.RequestCrossSafeEvent{}) + case engine.CrossSafeUpdateEvent: + if x.CrossSafe.Number >= x.LocalSafe.Number { + break // nothing left to promote + } + // Pre-interop the engine itself handles promotion to cross-safe. + // Check if the next block (not yet cross-safe) can be promoted to cross-safe. + if !d.cfg.IsInterop(d.cfg.TimestampForBlock(x.CrossSafe.Number + 1)) { + return false + } + ctx, cancel := context.WithTimeout(d.driverCtx, checkBlockTimeout) + defer cancel() + candidate, err := d.l2.L2BlockRefByNumber(ctx, x.CrossSafe.Number+1) + if err != nil { + d.log.Warn("Failed to fetch next cross-safe candidate", "err", err) + break + } + blockSafety, err := d.backend.CheckBlock(ctx, d.chainID, candidate.Hash, candidate.Number) + if err != nil { + d.log.Warn("Failed to check interop safety of local-safe block", "err", err) + break + } + derivedFrom, ok := d.derivedFrom[candidate.Hash] + if !ok { + break + } + switch blockSafety { + case types.CrossSafe: + // TODO(#11673): once we have interop reorg support, we need to clean stale blocks also. + delete(d.derivedFrom, candidate.Hash) + d.emitter.Emit(engine.PromoteSafeEvent{ + Ref: candidate, + DerivedFrom: derivedFrom, + }) + case types.Finalized: + // TODO(#11673): once we have interop reorg support, we need to clean stale blocks also. + delete(d.derivedFrom, candidate.Hash) + d.emitter.Emit(engine.PromoteSafeEvent{ + Ref: candidate, + DerivedFrom: derivedFrom, + }) + d.emitter.Emit(engine.PromoteFinalizedEvent{ + Ref: candidate, + }) + } + // no reorg support yet; the safe L2 head will finalize eventually, no exceptions + default: + return false + } + return true +} diff --git a/op-node/rollup/interop/interop_test.go b/op-node/rollup/interop/interop_test.go new file mode 100644 index 0000000000000..62b71140770e1 --- /dev/null +++ b/op-node/rollup/interop/interop_test.go @@ -0,0 +1,136 @@ +package interop + +import ( + "context" + "math/big" + "math/rand" // nosemgrep + "testing" + + "github.com/stretchr/testify/require" + + "github.com/ethereum/go-ethereum/log" + + "github.com/ethereum-optimism/optimism/op-node/rollup" + "github.com/ethereum-optimism/optimism/op-node/rollup/engine" + "github.com/ethereum-optimism/optimism/op-service/testlog" + "github.com/ethereum-optimism/optimism/op-service/testutils" + supervisortypes "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" +) + +func TestInteropDeriver(t *testing.T) { + logger := testlog.Logger(t, log.LevelInfo) + l2Source := &testutils.MockL2Client{} + emitter := &testutils.MockEmitter{} + interopBackend := &testutils.MockInteropBackend{} + cfg := &rollup.Config{ + InteropTime: new(uint64), + L2ChainID: big.NewInt(42), + } + chainID := supervisortypes.ChainIDFromBig(cfg.L2ChainID) + interopDeriver := NewInteropDeriver(logger, cfg, context.Background(), interopBackend, l2Source) + interopDeriver.AttachEmitter(emitter) + rng := rand.New(rand.NewSource(123)) + + t.Run("unsafe blocks trigger cross-unsafe check attempts", func(t *testing.T) { + emitter.ExpectOnce(engine.RequestCrossUnsafeEvent{}) + interopDeriver.OnEvent(engine.UnsafeUpdateEvent{ + Ref: testutils.RandomL2BlockRef(rng), + }) + emitter.AssertExpectations(t) + }) + t.Run("establish cross-unsafe", func(t *testing.T) { + crossUnsafe := testutils.RandomL2BlockRef(rng) + firstLocalUnsafe := testutils.NextRandomL2Ref(rng, 2, crossUnsafe, crossUnsafe.L1Origin) + lastLocalUnsafe := testutils.NextRandomL2Ref(rng, 2, firstLocalUnsafe, firstLocalUnsafe.L1Origin) + interopBackend.ExpectCheckBlock( + chainID, firstLocalUnsafe.Number, supervisortypes.CrossUnsafe, nil) + emitter.ExpectOnce(engine.PromoteCrossUnsafeEvent{ + Ref: firstLocalUnsafe, + }) + l2Source.ExpectL2BlockRefByNumber(firstLocalUnsafe.Number, firstLocalUnsafe, nil) + interopDeriver.OnEvent(engine.CrossUnsafeUpdateEvent{ + CrossUnsafe: crossUnsafe, + LocalUnsafe: lastLocalUnsafe, + }) + interopBackend.AssertExpectations(t) + emitter.AssertExpectations(t) + l2Source.AssertExpectations(t) + }) + t.Run("deny cross-unsafe", func(t *testing.T) { + crossUnsafe := testutils.RandomL2BlockRef(rng) + firstLocalUnsafe := testutils.NextRandomL2Ref(rng, 2, crossUnsafe, crossUnsafe.L1Origin) + lastLocalUnsafe := testutils.NextRandomL2Ref(rng, 2, firstLocalUnsafe, firstLocalUnsafe.L1Origin) + interopBackend.ExpectCheckBlock( + chainID, firstLocalUnsafe.Number, supervisortypes.Unsafe, nil) + l2Source.ExpectL2BlockRefByNumber(firstLocalUnsafe.Number, firstLocalUnsafe, nil) + interopDeriver.OnEvent(engine.CrossUnsafeUpdateEvent{ + CrossUnsafe: crossUnsafe, + LocalUnsafe: lastLocalUnsafe, + }) + interopBackend.AssertExpectations(t) + // no cross-unsafe promote event is expected + emitter.AssertExpectations(t) + l2Source.AssertExpectations(t) + }) + t.Run("register local-safe", func(t *testing.T) { + derivedFrom := testutils.RandomBlockRef(rng) + localSafe := testutils.RandomL2BlockRef(rng) + emitter.ExpectOnce(engine.RequestCrossSafeEvent{}) + interopDeriver.OnEvent(engine.LocalSafeUpdateEvent{ + Ref: localSafe, + DerivedFrom: derivedFrom, + }) + require.Contains(t, interopDeriver.derivedFrom, localSafe.Hash) + require.Equal(t, derivedFrom, interopDeriver.derivedFrom[localSafe.Hash]) + emitter.AssertExpectations(t) + }) + t.Run("establish cross-safe", func(t *testing.T) { + derivedFrom := testutils.RandomBlockRef(rng) + crossSafe := testutils.RandomL2BlockRef(rng) + firstLocalSafe := testutils.NextRandomL2Ref(rng, 2, crossSafe, crossSafe.L1Origin) + lastLocalSafe := testutils.NextRandomL2Ref(rng, 2, firstLocalSafe, firstLocalSafe.L1Origin) + emitter.ExpectOnce(engine.RequestCrossSafeEvent{}) + // The local safe block must be known, for the derived-from mapping to work + interopDeriver.OnEvent(engine.LocalSafeUpdateEvent{ + Ref: firstLocalSafe, + DerivedFrom: derivedFrom, + }) + interopBackend.ExpectCheckBlock( + chainID, firstLocalSafe.Number, supervisortypes.CrossSafe, nil) + emitter.ExpectOnce(engine.PromoteSafeEvent{ + Ref: firstLocalSafe, + DerivedFrom: derivedFrom, + }) + l2Source.ExpectL2BlockRefByNumber(firstLocalSafe.Number, firstLocalSafe, nil) + interopDeriver.OnEvent(engine.CrossSafeUpdateEvent{ + CrossSafe: crossSafe, + LocalSafe: lastLocalSafe, + }) + interopBackend.AssertExpectations(t) + emitter.AssertExpectations(t) + l2Source.AssertExpectations(t) + }) + t.Run("deny cross-safe", func(t *testing.T) { + derivedFrom := testutils.RandomBlockRef(rng) + crossSafe := testutils.RandomL2BlockRef(rng) + firstLocalSafe := testutils.NextRandomL2Ref(rng, 2, crossSafe, crossSafe.L1Origin) + lastLocalSafe := testutils.NextRandomL2Ref(rng, 2, firstLocalSafe, firstLocalSafe.L1Origin) + emitter.ExpectOnce(engine.RequestCrossSafeEvent{}) + // The local safe block must be known, for the derived-from mapping to work + interopDeriver.OnEvent(engine.LocalSafeUpdateEvent{ + Ref: firstLocalSafe, + DerivedFrom: derivedFrom, + }) + interopBackend.ExpectCheckBlock( + chainID, firstLocalSafe.Number, supervisortypes.Safe, nil) + l2Source.ExpectL2BlockRefByNumber(firstLocalSafe.Number, firstLocalSafe, nil) + interopDeriver.OnEvent(engine.CrossSafeUpdateEvent{ + CrossSafe: crossSafe, + LocalSafe: lastLocalSafe, + }) + interopBackend.AssertExpectations(t) + // no cross-safe promote event is expected + emitter.AssertExpectations(t) + l2Source.AssertExpectations(t) + }) +} diff --git a/op-node/rollup/sequencing/sequencer.go b/op-node/rollup/sequencing/sequencer.go index e816f41a31faf..16ac5ae617fbf 100644 --- a/op-node/rollup/sequencing/sequencer.go +++ b/op-node/rollup/sequencing/sequencer.go @@ -112,8 +112,11 @@ type Sequencer struct { nextActionOK bool nextActionCh chan struct{} - latest BuildingState - latestHead eth.L2BlockRef + latest BuildingState + latestSealed eth.L2BlockRef + latestHead eth.L2BlockRef + + latestHeadSet chan struct{} // toBlockRef converts a payload to a block-ref, and is only configurable for test-purposes toBlockRef func(rollupCfg *rollup.Config, payload *eth.ExecutionPayload) (eth.L2BlockRef, error) @@ -297,6 +300,7 @@ func (d *Sequencer) onBuildSealed(x engine.BuildSealedEvent) { Ref: x.Ref, }) d.latest.Ref = x.Ref + d.latestSealed = x.Ref } func (d *Sequencer) onPayloadSealInvalid(x engine.PayloadSealInvalidEvent) { @@ -359,6 +363,8 @@ func (d *Sequencer) onSequencerAction(x SequencerActionEvent) { d.asyncGossip.Clear() // bad payload return } + d.log.Info("Resuming sequencing with previously async-gossip confirmed payload", + "payload", payload.ExecutionPayload.ID()) // Payload is known, we must have resumed sequencer-actions after a temporary error, // meaning that we have seen BuildSealedEvent already. // We can retry processing to make it canonical. @@ -445,7 +451,7 @@ func (d *Sequencer) onForkchoiceUpdate(x engine.ForkchoiceUpdateEvent) { d.log.Debug("Sequencer is processing forkchoice update", "unsafe", x.UnsafeL2Head, "latest", d.latestHead) if !d.active.Load() { - d.latestHead = x.UnsafeL2Head + d.setLatestHead(x.UnsafeL2Head) return } // If the safe head has fallen behind by a significant number of blocks, delay creating new blocks @@ -480,7 +486,15 @@ func (d *Sequencer) onForkchoiceUpdate(x engine.ForkchoiceUpdateEvent) { default: } } - d.latestHead = x.UnsafeL2Head + d.setLatestHead(x.UnsafeL2Head) +} + +func (d *Sequencer) setLatestHead(head eth.L2BlockRef) { + d.latestHead = head + if d.latestHeadSet != nil { + close(d.latestHeadSet) + d.latestHeadSet = nil + } } // StartBuildingBlock initiates a block building job on top of the given L2 head, safe and finalized blocks, and using the provided l1Origin. @@ -553,7 +567,7 @@ func (d *Sequencer) startBuildingBlock() { d.log.Info("Sequencing Fjord upgrade block") } - // For the Fjord activation block we shouldn't include any sequencer transactions. + // For the Granite activation block we shouldn't include any sequencer transactions. if d.rollupCfg.IsGraniteActivationBlock(uint64(attrs.Timestamp)) { d.log.Info("Sequencing Granite upgrade block") } @@ -642,9 +656,27 @@ func (d *Sequencer) Init(ctx context.Context, active bool) error { // forceStart skips all the checks, and just starts the sequencer func (d *Sequencer) forceStart() error { + if d.latestHead == (eth.L2BlockRef{}) { + // This happens if sequencing is activated on op-node startup. + // The op-conductor check and choice of sequencing with this pre-state already happened before op-node startup. + d.log.Info("Starting sequencing, without known pre-state") + d.asyncGossip.Clear() // if we are starting from an unknown pre-state, just clear gossip out of caution. + } else { + // This happens when we start sequencing on an already-running node. + d.log.Info("Starting sequencing on top of known pre-state", "head", d.latestHead) + if payload := d.asyncGossip.Get(); payload != nil && + payload.ExecutionPayload.BlockHash != d.latestHead.Hash { + d.log.Warn("Cleared old block from async-gossip buffer, sequencing pre-state is different", + "buffered", payload.ExecutionPayload.ID(), "prestate", d.latestHead) + d.asyncGossip.Clear() + } + } + if err := d.listener.SequencerStarted(); err != nil { return fmt.Errorf("failed to notify sequencer-state listener of start: %w", err) } + // clear the building state; interrupting any existing sequencing job (there should never be one) + d.latest = BuildingState{} d.nextActionOK = true d.nextAction = d.timeNow() select { @@ -656,12 +688,33 @@ func (d *Sequencer) forceStart() error { return nil } -func (d *Sequencer) Stop(ctx context.Context) (hash common.Hash, err error) { +func (d *Sequencer) Stop(ctx context.Context) (common.Hash, error) { if err := d.l.LockCtx(ctx); err != nil { return common.Hash{}, err } + + if !d.active.Load() { + d.l.Unlock() + return common.Hash{}, ErrSequencerAlreadyStopped + } + + // ensure latestHead has been updated to the latest sealed/gossiped block before stopping the sequencer + for d.latestHead.Hash != d.latestSealed.Hash { + latestHeadSet := make(chan struct{}) + d.latestHeadSet = latestHeadSet + d.l.Unlock() + select { + case <-ctx.Done(): + return common.Hash{}, ctx.Err() + case <-latestHeadSet: + } + if err := d.l.LockCtx(ctx); err != nil { + return common.Hash{}, err + } + } defer d.l.Unlock() + // Stop() may have been called twice, so check if we are active after reacquiring the lock if !d.active.Load() { return common.Hash{}, ErrSequencerAlreadyStopped } diff --git a/op-node/rollup/sequencing/sequencer_test.go b/op-node/rollup/sequencing/sequencer_test.go index 234049096a839..7b410e644ad2b 100644 --- a/op-node/rollup/sequencing/sequencer_test.go +++ b/op-node/rollup/sequencing/sequencer_test.go @@ -170,11 +170,37 @@ func TestSequencer_StartStop(t *testing.T) { require.True(t, deps.asyncGossip.started, "async gossip is always started on initialization") require.False(t, deps.seqState.active, "sequencer not active yet") + // latest refs should all be empty + require.Equal(t, common.Hash{}, seq.latest.Ref.Hash) + require.Equal(t, common.Hash{}, seq.latestSealed.Hash) + require.Equal(t, common.Hash{}, seq.latestHead.Hash) + + // update the latestSealed + envelope := ð.ExecutionPayloadEnvelope{ + ExecutionPayload: ð.ExecutionPayload{}, + } + emitter.ExpectOnce(engine.PayloadProcessEvent{ + Envelope: envelope, + Ref: eth.L2BlockRef{Hash: common.Hash{0xaa}}, + }) + seq.OnEvent(engine.BuildSealedEvent{ + Envelope: envelope, + Ref: eth.L2BlockRef{Hash: common.Hash{0xaa}}, + }) + require.Equal(t, common.Hash{0xaa}, seq.latest.Ref.Hash) + require.Equal(t, common.Hash{0xaa}, seq.latestSealed.Hash) + require.Equal(t, common.Hash{}, seq.latestHead.Hash) + + // update latestHead + emitter.AssertExpectations(t) seq.OnEvent(engine.ForkchoiceUpdateEvent{ UnsafeL2Head: eth.L2BlockRef{Hash: common.Hash{0xaa}}, SafeL2Head: eth.L2BlockRef{}, FinalizedL2Head: eth.L2BlockRef{}, }) + require.Equal(t, common.Hash{0xaa}, seq.latest.Ref.Hash) + require.Equal(t, common.Hash{0xaa}, seq.latestSealed.Hash) + require.Equal(t, common.Hash{0xaa}, seq.latestHead.Hash) require.False(t, seq.Active()) // no action scheduled @@ -210,6 +236,221 @@ func TestSequencer_StartStop(t *testing.T) { require.NoError(t, err) } +// TestSequencer_StaleBuild stops the sequencer after block-building, +// but before processing the block locally, +// and then continues it again, to check if the async-gossip gets cleared, +// instead of trying to re-insert the block. +func TestSequencer_StaleBuild(t *testing.T) { + logger := testlog.Logger(t, log.LevelError) + seq, deps := createSequencer(logger) + + testClock := clock.NewSimpleClock() + seq.timeNow = testClock.Now + testClock.SetTime(30000) + + emitter := &testutils.MockEmitter{} + seq.AttachEmitter(emitter) + deps.conductor.leader = true + + emitter.ExpectOnce(engine.ForkchoiceRequestEvent{}) + require.NoError(t, seq.Init(context.Background(), false)) + emitter.AssertExpectations(t) + require.False(t, deps.conductor.closed, "conductor is ready") + require.True(t, deps.asyncGossip.started, "async gossip is always started on initialization") + require.False(t, deps.seqState.active, "sequencer not active yet") + + head := eth.L2BlockRef{ + Hash: common.Hash{0x22}, + Number: 100, + L1Origin: eth.BlockID{ + Hash: common.Hash{0x11, 0xa}, + Number: 1000, + }, + Time: uint64(testClock.Now().Unix()), + } + seq.OnEvent(engine.ForkchoiceUpdateEvent{UnsafeL2Head: head}) + + require.NoError(t, seq.Start(context.Background(), head.Hash)) + require.True(t, seq.Active()) + require.True(t, deps.seqState.active, "sequencer signaled it is active") + + // sequencer is active now, wants to build. + _, ok := seq.NextAction() + require.True(t, ok) + + // pretend we progress to the next L1 origin, catching up with the L2 time + l1Origin := eth.L1BlockRef{ + Hash: common.Hash{0x11, 0xb}, + ParentHash: head.L1Origin.Hash, + Number: head.L1Origin.Number + 1, + Time: head.Time + 2, + } + deps.l1OriginSelector.l1OriginFn = func(l2Head eth.L2BlockRef) (eth.L1BlockRef, error) { + return l1Origin, nil + } + var sentAttributes *derive.AttributesWithParent + emitter.ExpectOnceRun(func(ev event.Event) { + x, ok := ev.(engine.BuildStartEvent) + require.True(t, ok) + require.Equal(t, head, x.Attributes.Parent) + require.Equal(t, head.Time+deps.cfg.BlockTime, uint64(x.Attributes.Attributes.Timestamp)) + require.Equal(t, eth.L1BlockRef{}, x.Attributes.DerivedFrom) + sentAttributes = x.Attributes + }) + seq.OnEvent(SequencerActionEvent{}) + emitter.AssertExpectations(t) + + // Now report the block was started + startedTime := time.Unix(int64(head.Time), 0).Add(time.Millisecond * 150) + testClock.Set(startedTime) + payloadInfo := eth.PayloadInfo{ + ID: eth.PayloadID{0x42}, + Timestamp: head.Time + deps.cfg.BlockTime, + } + seq.OnEvent(engine.BuildStartedEvent{ + Info: payloadInfo, + BuildStarted: startedTime, + Parent: head, + IsLastInSpan: false, + DerivedFrom: eth.L1BlockRef{}, + }) + + _, ok = seq.NextAction() + require.True(t, ok, "must be ready to seal the block now") + + emitter.ExpectOnce(engine.BuildSealEvent{ + Info: payloadInfo, + BuildStarted: startedTime, + IsLastInSpan: false, + DerivedFrom: eth.L1BlockRef{}, + }) + seq.OnEvent(SequencerActionEvent{}) + emitter.AssertExpectations(t) + + _, ok = seq.NextAction() + require.False(t, ok, "cannot act until sealing completes/fails") + + payloadEnvelope := ð.ExecutionPayloadEnvelope{ + ParentBeaconBlockRoot: sentAttributes.Attributes.ParentBeaconBlockRoot, + ExecutionPayload: ð.ExecutionPayload{ + ParentHash: head.Hash, + FeeRecipient: sentAttributes.Attributes.SuggestedFeeRecipient, + BlockNumber: eth.Uint64Quantity(sentAttributes.Parent.Number + 1), + BlockHash: common.Hash{0x12, 0x34}, + Timestamp: sentAttributes.Attributes.Timestamp, + Transactions: sentAttributes.Attributes.Transactions, + // Not all attributes matter to sequencer. We can leave these nil. + }, + } + payloadRef := eth.L2BlockRef{ + Hash: payloadEnvelope.ExecutionPayload.BlockHash, + Number: uint64(payloadEnvelope.ExecutionPayload.BlockNumber), + ParentHash: payloadEnvelope.ExecutionPayload.ParentHash, + Time: uint64(payloadEnvelope.ExecutionPayload.Timestamp), + L1Origin: l1Origin.ID(), + SequenceNumber: 0, + } + emitter.ExpectOnce(engine.PayloadProcessEvent{ + IsLastInSpan: false, + DerivedFrom: eth.L1BlockRef{}, + Envelope: payloadEnvelope, + Ref: payloadRef, + }) + // And report back the sealing result to the engine + seq.OnEvent(engine.BuildSealedEvent{ + IsLastInSpan: false, + DerivedFrom: eth.L1BlockRef{}, + Info: payloadInfo, + Envelope: payloadEnvelope, + Ref: payloadRef, + }) + // The sequencer should start processing the payload + emitter.AssertExpectations(t) + // But also optimistically give it to the conductor and the async gossip + require.Equal(t, payloadEnvelope, deps.conductor.committed, "must commit to conductor") + require.Equal(t, payloadEnvelope, deps.asyncGossip.payload, "must send to async gossip") + _, ok = seq.NextAction() + require.False(t, ok, "optimistically published, but not ready to sequence next, until local processing completes") + + // attempting to stop block building here should timeout, because the sealed block is different from the latestHead + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) + defer cancel() + _, err := seq.Stop(ctx) + require.Error(t, err, "stop should have timed out") + require.ErrorIs(t, err, ctx.Err()) + + // reset latestSealed to the previous head + emitter.ExpectOnce(engine.PayloadProcessEvent{ + Envelope: payloadEnvelope, + Ref: head, + }) + seq.OnEvent(engine.BuildSealedEvent{ + Info: payloadInfo, + Envelope: payloadEnvelope, + Ref: head, + }) + emitter.AssertExpectations(t) + + // Now we stop the block building, + // before successful local processing of the committed block! + stopHead, err := seq.Stop(context.Background()) + require.NoError(t, err) + require.Equal(t, head.Hash, stopHead, "sequencer should not have accepted any new block yet") + require.False(t, deps.seqState.active, "sequencer signaled it is no longer active") + + // Async-gossip will try to publish this committed block + require.NotNil(t, deps.asyncGossip.payload, "still holding on to async-gossip block") + + // Now let's say another sequencer built a bunch of blocks, + // can we continue from there? We'll have to wipe the old in-flight block, + // if we continue on top of a chain that had it already included a while ago. + + // Signal the new chain we are building on + testClock.Set(testClock.Now().Add(time.Second * 100 * 2)) + + newL1Origin := eth.L1BlockRef{ + Hash: common.Hash{0x11, 0x11, 0x44}, + ParentHash: head.L1Origin.Hash, + Number: head.L1Origin.Number + 50, + Time: uint64(testClock.Now().Unix()), + } + newHead := eth.L2BlockRef{ + Hash: common.Hash{0x44}, + Number: head.Number + 100, + L1Origin: newL1Origin.ID(), + Time: uint64(testClock.Now().Unix()), + } + seq.OnEvent(engine.ForkchoiceUpdateEvent{UnsafeL2Head: newHead}) + + // Regression check: async-gossip is cleared upon sequencer un-pause. + // We could clear it earlier. But absolutely have to clear it upon Start(), + // to not continue from this older point. + require.NotNil(t, deps.asyncGossip.payload, "async-gossip still not cleared") + + // start sequencing on top of the new chain + require.NoError(t, seq.Start(context.Background(), newHead.Hash), "must continue from new block") + + // regression check: no stale async gossip is continued + require.Nil(t, deps.asyncGossip.payload, "async gossip should be cleared on Start") + + // Start building the block with the new L1 origin + deps.l1OriginSelector.l1OriginFn = func(l2Head eth.L2BlockRef) (eth.L1BlockRef, error) { + return newL1Origin, nil + } + // Sequencer action, assert we build on top of something new, + // and don't try to seal what was previously. + _, ok = seq.NextAction() + require.True(t, ok, "ready to sequence again") + // start, not seal, when continuing to sequence. + emitter.ExpectOnceRun(func(ev event.Event) { + buildEv, ok := ev.(engine.BuildStartEvent) + require.True(t, ok) + require.Equal(t, newHead, buildEv.Attributes.Parent, "build on the new L2 head") + }) + seq.OnEvent(SequencerActionEvent{}) + emitter.AssertExpectations(t) +} + func TestSequencerBuild(t *testing.T) { logger := testlog.Logger(t, log.LevelError) seq, deps := createSequencer(logger) diff --git a/op-node/rollup/status/status.go b/op-node/rollup/status/status.go index 54ad03f3c1a64..ef6254c0876e2 100644 --- a/op-node/rollup/status/status.go +++ b/op-node/rollup/status/status.go @@ -74,6 +74,14 @@ func (st *StatusTracker) OnEvent(ev event.Event) bool { case engine.PendingSafeUpdateEvent: st.data.UnsafeL2 = x.Unsafe st.data.PendingSafeL2 = x.PendingSafe + case engine.CrossUnsafeUpdateEvent: + st.data.CrossUnsafeL2 = x.CrossUnsafe + st.data.UnsafeL2 = x.LocalUnsafe + case engine.LocalSafeUpdateEvent: + st.data.LocalSafeL2 = x.Ref + case engine.CrossSafeUpdateEvent: + st.data.SafeL2 = x.CrossSafe + st.data.LocalSafeL2 = x.LocalSafe case derive.DeriverL1StatusEvent: st.data.CurrentL1 = x.Origin case L1UnsafeEvent: diff --git a/op-node/rollup/superchain.go b/op-node/rollup/superchain.go index b0aa47635f817..21a74323c05f7 100644 --- a/op-node/rollup/superchain.go +++ b/op-node/rollup/superchain.go @@ -46,10 +46,18 @@ func LoadOPStackRollupConfig(chainID uint64) (*Config, error) { var altDA *AltDAConfig if chConfig.AltDA != nil { - altDA = &AltDAConfig{ - DAChallengeAddress: common.Address(*chConfig.AltDA.DAChallengeAddress), - DAChallengeWindow: *chConfig.AltDA.DAChallengeWindow, - DAResolveWindow: *chConfig.AltDA.DAResolveWindow, + altDA = &AltDAConfig{} + if chConfig.AltDA.DAChallengeAddress != nil { + altDA.DAChallengeAddress = common.Address(*chConfig.AltDA.DAChallengeAddress) + } + if chConfig.AltDA.DAChallengeWindow != nil { + altDA.DAChallengeWindow = *chConfig.AltDA.DAChallengeWindow + } + if chConfig.AltDA.DAResolveWindow != nil { + altDA.DAResolveWindow = *chConfig.AltDA.DAResolveWindow + } + if chConfig.AltDA.DACommitmentType != nil { + altDA.CommitmentType = *chConfig.AltDA.DACommitmentType } } diff --git a/op-node/rollup/sync/start.go b/op-node/rollup/sync/start.go index e9a53806080c8..15a811bce57f4 100644 --- a/op-node/rollup/sync/start.go +++ b/op-node/rollup/sync/start.go @@ -214,6 +214,8 @@ func FindL2Heads(ctx context.Context, cfg *rollup.Config, l1 L1Chain, l2 L2Chain } if ahead { + // discard previous candidate + highestL2WithCanonicalL1Origin = eth.L2BlockRef{} // keep the unsafe head if we can't tell if its L1 origin is canonical or not yet. } else if l1Block.Hash == n.L1Origin.Hash { // if L2 matches canonical chain, even if unsafe, diff --git a/op-node/rollup/sync/start_test.go b/op-node/rollup/sync/start_test.go index 0c202543c5de9..e2cfee7712ccd 100644 --- a/op-node/rollup/sync/start_test.go +++ b/op-node/rollup/sync/start_test.go @@ -26,7 +26,7 @@ func (c *syncStartTestCase) generateFakeL2(t *testing.T) (*testutils.FakeChainSo 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)) + genesis := testutils.FakeGenesis(c.GenesisL1, c.GenesisL2, c.GenesisL1Num) chain.ReorgL1() for i := 0; i < len(c.NewL1)-1; i++ { chain.AdvanceL1() diff --git a/op-node/rollup/types.go b/op-node/rollup/types.go index fec118567c569..0c611a5d8d35a 100644 --- a/op-node/rollup/types.go +++ b/op-node/rollup/types.go @@ -463,6 +463,40 @@ func (c *Config) IsInteropActivationBlock(l2BlockTime uint64) bool { !c.IsInterop(l2BlockTime-c.BlockTime) } +func (c *Config) ActivateAtGenesis(hardfork ForkName) { + // IMPORTANT! ordered from newest to oldest + switch hardfork { + case Interop: + c.InteropTime = new(uint64) + fallthrough + case Holocene: + c.HoloceneTime = new(uint64) + fallthrough + case Granite: + c.GraniteTime = new(uint64) + fallthrough + case Fjord: + c.FjordTime = new(uint64) + fallthrough + case Ecotone: + c.EcotoneTime = new(uint64) + fallthrough + case Delta: + c.DeltaTime = new(uint64) + fallthrough + case Canyon: + c.CanyonTime = new(uint64) + fallthrough + case Regolith: + c.RegolithTime = new(uint64) + fallthrough + case Bedrock: + // default + case None: + break + } +} + // ForkchoiceUpdatedVersion returns the EngineAPIMethod suitable for the chain hard fork version. func (c *Config) ForkchoiceUpdatedVersion(attr *eth.PayloadAttributes) eth.EngineAPIMethod { if attr == nil { diff --git a/op-node/service.go b/op-node/service.go index cae25afd381f0..b24e2a638335d 100644 --- a/op-node/service.go +++ b/op-node/service.go @@ -82,11 +82,12 @@ func NewConfig(ctx *cli.Context, log log.Logger) (*node.Config, error) { } cfg := &node.Config{ - L1: l1Endpoint, - L2: l2Endpoint, - Rollup: *rollupConfig, - Driver: *driverConfig, - Beacon: NewBeaconEndpointConfig(ctx), + L1: l1Endpoint, + L2: l2Endpoint, + Rollup: *rollupConfig, + Driver: *driverConfig, + Beacon: NewBeaconEndpointConfig(ctx), + Supervisor: NewSupervisorEndpointConfig(ctx), RPC: node.RPCConfig{ ListenAddr: ctx.String(flags.RPCListenAddr.Name), ListenPort: ctx.Int(flags.RPCListenPort.Name), @@ -106,7 +107,6 @@ func NewConfig(ctx *cli.Context, log log.Logger) (*node.Config, error) { SafeDBPath: ctx.String(flags.SafeDBPath.Name), Sync: *syncConfig, RollupHalt: haltOption, - RethDBPath: ctx.String(flags.L1RethDBPath.Name), ConductorEnabled: ctx.Bool(flags.ConductorEnabledFlag.Name), ConductorRpc: ctx.String(flags.ConductorRpcFlag.Name), @@ -130,6 +130,12 @@ func NewConfig(ctx *cli.Context, log log.Logger) (*node.Config, error) { return cfg, nil } +func NewSupervisorEndpointConfig(ctx *cli.Context) node.SupervisorEndpointSetup { + return &node.SupervisorEndpointConfig{ + SupervisorAddr: ctx.String(flags.SupervisorAddr.Name), + } +} + func NewBeaconEndpointConfig(ctx *cli.Context) node.L1BeaconEndpointSetup { return &node.L1BeaconEndpointConfig{ BeaconAddr: ctx.String(flags.BeaconAddr.Name), diff --git a/op-preimage/filechan.go b/op-preimage/filechan.go index 1b5f3e6286c96..3d844c58b6b50 100644 --- a/op-preimage/filechan.go +++ b/op-preimage/filechan.go @@ -1,8 +1,11 @@ package preimage import ( + "errors" + "fmt" "io" "os" + "syscall" ) // FileChannel is a unidirectional channel for file I/O @@ -41,10 +44,14 @@ func (rw *ReadWritePair) Writer() *os.File { } func (rw *ReadWritePair) Close() error { + var combinedErr error if err := rw.r.Close(); err != nil { - return err + combinedErr = errors.Join(fmt.Errorf("failed to close reader: %w", err)) } - return rw.w.Close() + if err := rw.w.Close(); err != nil { + combinedErr = errors.Join(fmt.Errorf("failed to close writer: %w", err)) + } + return combinedErr } // CreateBidirectionalChannel creates a pair of FileChannels that are connected to each other. @@ -68,14 +75,21 @@ const ( ) func ClientHinterChannel() *ReadWritePair { - r := os.NewFile(HClientRFd, "preimage-hint-read") - w := os.NewFile(HClientWFd, "preimage-hint-write") + r := newFileNonBlocking(HClientRFd, "preimage-hint-read") + w := newFileNonBlocking(HClientWFd, "preimage-hint-write") return NewReadWritePair(r, w) } // ClientPreimageChannel returns a FileChannel for the preimage oracle in a detached context func ClientPreimageChannel() *ReadWritePair { - r := os.NewFile(PClientRFd, "preimage-oracle-read") - w := os.NewFile(PClientWFd, "preimage-oracle-write") + r := newFileNonBlocking(PClientRFd, "preimage-oracle-read") + w := newFileNonBlocking(PClientWFd, "preimage-oracle-write") return NewReadWritePair(r, w) } + +func newFileNonBlocking(fd int, name string) *os.File { + // Try to enable non-blocking mode for IO so that read calls return when the file is closed + // This may not be possible on all systems so errors are ignored. + _ = syscall.SetNonblock(fd, true) + return os.NewFile(uintptr(fd), name) +} diff --git a/op-program/Dockerfile.repro b/op-program/Dockerfile.repro index 7d9dfc807240b..57f65bb72b81e 100644 --- a/op-program/Dockerfile.repro +++ b/op-program/Dockerfile.repro @@ -35,12 +35,16 @@ RUN --mount=type=cache,target=/root/.cache/go-build cd op-program && make op-pro GOOS=linux GOARCH=mips GOMIPS=softfloat GITCOMMIT=$GIT_COMMIT GITDATE=$GIT_DATE VERSION="$OP_PROGRAM_VERSION" # Run the op-program-client.elf binary directly through cannon's load-elf subcommand. -RUN /app/cannon/bin/cannon load-elf --path /app/op-program/bin/op-program-client.elf --out /app/op-program/bin/prestate.json --meta "" +RUN /app/cannon/bin/cannon load-elf --type singlethreaded --path /app/op-program/bin/op-program-client.elf --out /app/op-program/bin/prestate.json --meta "" +RUN /app/cannon/bin/cannon load-elf --type multithreaded --path /app/op-program/bin/op-program-client.elf --out /app/op-program/bin/prestate-mt.bin.gz --meta "" # Generate the prestate proof containing the absolute pre-state hash. RUN /app/cannon/bin/cannon run --proof-at '=0' --stop-at '=1' --input /app/op-program/bin/prestate.json --meta "" --proof-fmt '/app/op-program/bin/%d.json' --output "" RUN mv /app/op-program/bin/0.json /app/op-program/bin/prestate-proof.json +RUN /app/cannon/bin/cannon run --proof-at '=0' --stop-at '=1' --input /app/op-program/bin/prestate-mt.bin.gz --meta "" --proof-fmt '/app/op-program/bin/%d-mt.json' --output "" +RUN mv /app/op-program/bin/0-mt.json /app/op-program/bin/prestate-proof-mt.json + # Exports files to the specified output location. # Writing files to host requires buildkit to be enabled. # e.g. `BUILDKIT=1 docker build ...` @@ -49,3 +53,5 @@ COPY --from=builder /app/op-program/bin/op-program . COPY --from=builder /app/op-program/bin/op-program-client.elf . COPY --from=builder /app/op-program/bin/prestate.json . COPY --from=builder /app/op-program/bin/prestate-proof.json . +COPY --from=builder /app/op-program/bin/prestate-mt.bin.gz . +COPY --from=builder /app/op-program/bin/prestate-proof-mt.json . diff --git a/op-program/Makefile b/op-program/Makefile index 29e439a28f446..d8c134d9656a3 100644 --- a/op-program/Makefile +++ b/op-program/Makefile @@ -36,8 +36,10 @@ op-program-client-riscv: reproducible-prestate: @docker build --output ./bin/ --progress plain -f Dockerfile.repro ../ - @echo "Absolute prestate hash:" + @echo "Cannon Absolute prestate hash: " @cat ./bin/prestate-proof.json | jq -r .pre + @echo "MT-Cannon Absolute prestate hash: " + @cat ./bin/prestate-proof-mt.json | jq -r .pre .PHONY: reproducible-prestate clean: diff --git a/op-program/client/l2/engine_backend_test.go b/op-program/client/l2/engine_backend_test.go index 63eeba9285f9f..427f256d0a459 100644 --- a/op-program/client/l2/engine_backend_test.go +++ b/op-program/client/l2/engine_backend_test.go @@ -312,7 +312,7 @@ func setupOracle(t *testing.T, blockCount int, headBlockNumber int, enableEcoton } l1Genesis, err := genesis.NewL1Genesis(deployConfig) require.NoError(t, err) - l2Genesis, err := genesis.NewL2Genesis(deployConfig, l1Genesis.ToBlock()) + l2Genesis, err := genesis.NewL2Genesis(deployConfig, l1Genesis.ToBlock().Header()) require.NoError(t, err) l2Genesis.Alloc[fundedAddress] = types.Account{ diff --git a/op-program/client/program.go b/op-program/client/program.go index a539c1aff4a90..75d5fa93aa301 100644 --- a/op-program/client/program.go +++ b/op-program/client/program.go @@ -6,10 +6,6 @@ import ( "io" "os" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum-optimism/optimism/op-node/rollup" preimage "github.com/ethereum-optimism/optimism/op-preimage" "github.com/ethereum-optimism/optimism/op-program/client/claim" @@ -17,14 +13,17 @@ import ( "github.com/ethereum-optimism/optimism/op-program/client/l1" "github.com/ethereum-optimism/optimism/op-program/client/l2" "github.com/ethereum-optimism/optimism/op-service/eth" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/params" ) // Main executes the client program in a detached context and exits the current process. // The client runtime environment must be preset before calling this function. func Main(logger log.Logger) { log.Info("Starting fault proof program client") - preimageOracle := CreatePreimageChannel() - preimageHinter := CreateHinterChannel() + preimageOracle := preimage.ClientPreimageChannel() + preimageHinter := preimage.ClientHinterChannel() if err := RunProgram(logger, preimageOracle, preimageHinter); errors.Is(err, claim.ErrClaimNotValid) { log.Error("Claim is invalid", "err", err) os.Exit(1) @@ -76,16 +75,3 @@ func runDerivation(logger log.Logger, cfg *rollup.Config, l2Cfg *params.ChainCon } return claim.ValidateClaim(logger, l2ClaimBlockNum, eth.Bytes32(l2Claim), l2Source) } - -func CreateHinterChannel() preimage.FileChannel { - r := os.NewFile(HClientRFd, "preimage-hint-read") - w := os.NewFile(HClientWFd, "preimage-hint-write") - return preimage.NewReadWritePair(r, w) -} - -// CreatePreimageChannel returns a FileChannel for the preimage oracle in a detached context -func CreatePreimageChannel() preimage.FileChannel { - r := os.NewFile(PClientRFd, "preimage-oracle-read") - w := os.NewFile(PClientWFd, "preimage-oracle-write") - return preimage.NewReadWritePair(r, w) -} diff --git a/op-program/host/cmd/main_test.go b/op-program/host/cmd/main_test.go index 0bff6513ffc59..6c91bf13365d3 100644 --- a/op-program/host/cmd/main_test.go +++ b/op-program/host/cmd/main_test.go @@ -2,6 +2,7 @@ package main import ( "encoding/json" + "fmt" "os" "strconv" "testing" @@ -9,6 +10,7 @@ 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" + "github.com/ethereum-optimism/optimism/op-program/host/types" oplog "github.com/ethereum-optimism/optimism/op-service/log" "github.com/ethereum-optimism/optimism/op-service/sources" @@ -119,6 +121,20 @@ func TestDataDir(t *testing.T) { require.Equal(t, expected, cfg.DataDir) } +func TestDataFormat(t *testing.T) { + for _, format := range types.SupportedDataFormats { + format := format + t.Run(fmt.Sprintf("Valid-%v", format), func(t *testing.T) { + cfg := configForArgs(t, addRequiredArgs("--data.format", string(format))) + require.Equal(t, format, cfg.DataFormat) + }) + } + + t.Run("Invalid", func(t *testing.T) { + verifyArgsInvalid(t, "invalid data format: foo", addRequiredArgs("--data.format", "foo")) + }) +} + func TestL2(t *testing.T) { expected := "https://example.com:8545" cfg := configForArgs(t, addRequiredArgs("--l2", expected)) diff --git a/op-program/host/config/config.go b/op-program/host/config/config.go index 25f1a75724c9a..c04f959a8b7de 100644 --- a/op-program/host/config/config.go +++ b/op-program/host/config/config.go @@ -5,8 +5,10 @@ import ( "errors" "fmt" "os" + "slices" "github.com/ethereum-optimism/optimism/op-node/chaincfg" + "github.com/ethereum-optimism/optimism/op-program/host/types" opnode "github.com/ethereum-optimism/optimism/op-node" "github.com/ethereum-optimism/optimism/op-node/rollup" @@ -30,6 +32,7 @@ var ( ErrInvalidL2ClaimBlock = errors.New("invalid l2 claim block number") ErrDataDirRequired = errors.New("datadir must be specified when in non-fetching mode") ErrNoExecInServerMode = errors.New("exec command must not be set when in server mode") + ErrInvalidDataFormat = errors.New("invalid data format") ) type Config struct { @@ -38,6 +41,9 @@ type Config struct { // If not set, an in-memory key-value store is used and fetching data must be enabled DataDir string + // DataFormat specifies the format to use for on-disk storage. Only applies when DataDir is set. + DataFormat types.DataFormat + // L1Head is the block hash of the L1 chain head block L1Head common.Hash L1URL string @@ -100,12 +106,14 @@ func (c *Config) Check() error { if c.ServerMode && c.ExecCmd != "" { return ErrNoExecInServerMode } + if c.DataDir != "" && !slices.Contains(types.SupportedDataFormats, c.DataFormat) { + return ErrInvalidDataFormat + } return nil } func (c *Config) FetchingEnabled() bool { - // TODO: Include Beacon URL once cancun is active on all chains we fault prove. - return c.L1URL != "" && c.L2URL != "" + return c.L1URL != "" && c.L2URL != "" && c.L1BeaconURL != "" } // NewConfig creates a Config with all optional values set to the CLI default value @@ -130,6 +138,7 @@ func NewConfig( L2ClaimBlockNumber: l2ClaimBlockNum, L1RPCKind: sources.RPCKindStandard, IsCustomChainConfig: isCustomConfig, + DataFormat: types.DataFormatDirectory, } } @@ -183,9 +192,14 @@ func NewConfigFromCLI(log log.Logger, ctx *cli.Context) (*Config, error) { if err != nil { return nil, fmt.Errorf("invalid genesis: %w", err) } + dbFormat := types.DataFormat(ctx.String(flags.DataFormat.Name)) + if !slices.Contains(types.SupportedDataFormats, dbFormat) { + return nil, fmt.Errorf("invalid %w: %v", ErrInvalidDataFormat, dbFormat) + } return &Config{ Rollup: rollupCfg, DataDir: ctx.String(flags.DataDir.Name), + DataFormat: dbFormat, L2URL: ctx.String(flags.L2NodeAddr.Name), L2ChainConfig: l2ChainConfig, L2Head: l2Head, diff --git a/op-program/host/config/config_test.go b/op-program/host/config/config_test.go index 7497b5db4bd97..e9cc54edd6a68 100644 --- a/op-program/host/config/config_test.go +++ b/op-program/host/config/config_test.go @@ -1,12 +1,14 @@ package config import ( + "fmt" "math/big" "testing" "github.com/ethereum-optimism/optimism/op-node/chaincfg" "github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-program/chainconfig" + "github.com/ethereum-optimism/optimism/op-program/host/types" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/params" "github.com/stretchr/testify/require" @@ -138,7 +140,8 @@ func TestFetchingEnabled(t *testing.T) { t.Run("FetchingEnabledWhenBothFetcherUrlsSpecified", func(t *testing.T) { cfg := validConfig() cfg.L1URL = "https://example.com:1234" - cfg.L2URL = "https://example.com:5678" + cfg.L1BeaconURL = "https://example.com:5678" + cfg.L2URL = "https://example.com:91011" require.True(t, cfg.FetchingEnabled(), "Should enable fetching when node URL supplied") }) } @@ -173,6 +176,22 @@ func TestIsCustomChainConfig(t *testing.T) { } +func TestDBFormat(t *testing.T) { + t.Run("invalid", func(t *testing.T) { + cfg := validConfig() + cfg.DataFormat = "foo" + require.ErrorIs(t, cfg.Check(), ErrInvalidDataFormat) + }) + for _, format := range types.SupportedDataFormats { + format := format + t.Run(fmt.Sprintf("%v", format), func(t *testing.T) { + cfg := validConfig() + cfg.DataFormat = format + require.NoError(t, cfg.Check()) + }) + } +} + func validConfig() *Config { cfg := NewConfig(validRollupConfig, validL2Genesis, validL1Head, validL2Head, validL2OutputRoot, validL2Claim, validL2ClaimBlockNum) cfg.DataDir = "/tmp/configTest" diff --git a/op-program/host/flags/flags.go b/op-program/host/flags/flags.go index 3356bbfda8a9e..5eb633c7202f5 100644 --- a/op-program/host/flags/flags.go +++ b/op-program/host/flags/flags.go @@ -4,6 +4,7 @@ import ( "fmt" "strings" + "github.com/ethereum-optimism/optimism/op-program/host/types" "github.com/urfave/cli/v2" "github.com/ethereum-optimism/optimism/op-node/chaincfg" @@ -35,6 +36,12 @@ var ( Usage: "Directory to use for preimage data storage. Default uses in-memory storage", EnvVars: prefixEnvVars("DATADIR"), } + DataFormat = &cli.StringFlag{ + Name: "data.format", + Usage: fmt.Sprintf("Format to use for preimage data storage. Available formats: %s", openum.EnumString(types.SupportedDataFormats)), + EnvVars: prefixEnvVars("DATA_FORMAT"), + Value: string(types.DataFormatDirectory), + } L2NodeAddr = &cli.StringFlag{ Name: "l2", Usage: "Address of L2 JSON-RPC endpoint to use (eth and debug namespace required)", @@ -122,6 +129,7 @@ var programFlags = []cli.Flag{ RollupConfig, Network, DataDir, + DataFormat, L2NodeAddr, L2GenesisPath, L1NodeAddr, diff --git a/op-program/host/host.go b/op-program/host/host.go index ddffde7ee513c..a60e451b972d4 100644 --- a/op-program/host/host.go +++ b/op-program/host/host.go @@ -18,6 +18,7 @@ import ( "github.com/ethereum-optimism/optimism/op-program/host/prefetcher" opservice "github.com/ethereum-optimism/optimism/op-service" "github.com/ethereum-optimism/optimism/op-service/client" + "github.com/ethereum-optimism/optimism/op-service/ctxinterrupt" "github.com/ethereum-optimism/optimism/op-service/sources" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" @@ -28,6 +29,24 @@ type L2Source struct { *sources.DebugClient } +type Prefetcher interface { + Hint(hint string) error + GetPreimage(ctx context.Context, key common.Hash) ([]byte, error) +} +type PrefetcherCreator func(ctx context.Context, logger log.Logger, kv kvstore.KV, cfg *config.Config) (Prefetcher, error) + +type creatorsCfg struct { + prefetcher PrefetcherCreator +} + +type ProgramOpt func(c *creatorsCfg) + +func WithPrefetcher(creator PrefetcherCreator) ProgramOpt { + return func(c *creatorsCfg) { + c.prefetcher = creator + } +} + func Main(logger log.Logger, cfg *config.Config) error { if err := cfg.Check(); err != nil { return fmt.Errorf("invalid config: %w", err) @@ -35,11 +54,13 @@ func Main(logger log.Logger, cfg *config.Config) error { opservice.ValidateEnvVars(flags.EnvVarPrefix, flags.Flags, logger) cfg.Rollup.LogDescription(logger, chaincfg.L2ChainIDToNetworkDisplayName) - ctx := context.Background() + hostCtx, stop := ctxinterrupt.WithSignalWaiter(context.Background()) + defer stop() + ctx := ctxinterrupt.WithCancelOnInterrupt(hostCtx) if cfg.ServerMode { - preimageChan := cl.CreatePreimageChannel() - hinterChan := cl.CreateHinterChannel() - return PreimageServer(ctx, logger, cfg, preimageChan, hinterChan) + preimageChan := preimage.ClientPreimageChannel() + hinterChan := preimage.ClientHinterChannel() + return PreimageServer(ctx, logger, cfg, preimageChan, hinterChan, makeDefaultPrefetcher) } if err := FaultProofProgram(ctx, logger, cfg); err != nil { @@ -50,7 +71,13 @@ func Main(logger log.Logger, cfg *config.Config) error { } // FaultProofProgram is the programmatic entry-point for the fault proof program -func FaultProofProgram(ctx context.Context, logger log.Logger, cfg *config.Config) error { +func FaultProofProgram(ctx context.Context, logger log.Logger, cfg *config.Config, opts ...ProgramOpt) error { + creators := &creatorsCfg{ + prefetcher: makeDefaultPrefetcher, + } + for _, opt := range opts { + opt(creators) + } var ( serverErr chan error pClientRW preimage.FileChannel @@ -87,7 +114,7 @@ func FaultProofProgram(ctx context.Context, logger log.Logger, cfg *config.Confi serverErr = make(chan error) go func() { defer close(serverErr) - serverErr <- PreimageServer(ctx, logger, cfg, pHostRW, hHostRW) + serverErr <- PreimageServer(ctx, logger, cfg, pHostRW, hHostRW, creators.prefetcher) }() var cmd *exec.Cmd @@ -119,9 +146,13 @@ func FaultProofProgram(ctx context.Context, logger log.Logger, cfg *config.Confi // This method will block until both the hinter and preimage handlers complete. // If either returns an error both handlers are stopped. // The supplied preimageChannel and hintChannel will be closed before this function returns. -func PreimageServer(ctx context.Context, logger log.Logger, cfg *config.Config, preimageChannel preimage.FileChannel, hintChannel preimage.FileChannel) error { +func PreimageServer(ctx context.Context, logger log.Logger, cfg *config.Config, preimageChannel preimage.FileChannel, hintChannel preimage.FileChannel, prefetcherCreator PrefetcherCreator) error { var serverDone chan error var hinterDone chan error + logger.Info("Starting preimage server") + var kv kvstore.KV + + // Close the preimage/hint channels, and then kv store once the server and hinter have exited. defer func() { preimageChannel.Close() hintChannel.Close() @@ -133,29 +164,35 @@ func PreimageServer(ctx context.Context, logger log.Logger, cfg *config.Config, // Wait for hinter to complete <-hinterDone } + + if kv != nil { + kv.Close() + } }() - logger.Info("Starting preimage server") - var kv kvstore.KV + if cfg.DataDir == "" { logger.Info("Using in-memory storage") kv = kvstore.NewMemKV() } else { - logger.Info("Creating disk storage", "datadir", cfg.DataDir) if err := os.MkdirAll(cfg.DataDir, 0755); err != nil { return fmt.Errorf("creating datadir: %w", err) } - kv = kvstore.NewDiskKV(cfg.DataDir) + store, err := kvstore.NewDiskKV(logger, cfg.DataDir, cfg.DataFormat) + if err != nil { + return fmt.Errorf("creating kvstore: %w", err) + } + kv = store } var ( getPreimage kvstore.PreimageSource hinter preimage.HintHandler ) - if cfg.FetchingEnabled() { - prefetch, err := makePrefetcher(ctx, logger, kv, cfg) - if err != nil { - return fmt.Errorf("failed to create prefetcher: %w", err) - } + prefetch, err := prefetcherCreator(ctx, logger, kv, cfg) + if err != nil { + return fmt.Errorf("failed to create prefetcher: %w", err) + } + if prefetch != nil { getPreimage = func(key common.Hash) ([]byte, error) { return prefetch.GetPreimage(ctx, key) } hinter = prefetch.Hint } else { @@ -178,10 +215,20 @@ func PreimageServer(ctx context.Context, logger log.Logger, cfg *config.Config, return err case err := <-hinterDone: return err + case <-ctx.Done(): + logger.Info("Shutting down") + if errors.Is(ctx.Err(), context.Canceled) { + // We were asked to shutdown by the context being cancelled so don't treat it as an error condition. + return nil + } + return ctx.Err() } } -func makePrefetcher(ctx context.Context, logger log.Logger, kv kvstore.KV, cfg *config.Config) (*prefetcher.Prefetcher, error) { +func makeDefaultPrefetcher(ctx context.Context, logger log.Logger, kv kvstore.KV, cfg *config.Config) (Prefetcher, error) { + if !cfg.FetchingEnabled() { + return nil, nil + } logger.Info("Connecting to L1 node", "l1", cfg.L1URL) l1RPC, err := client.NewRPC(ctx, logger, cfg.L1URL, client.WithDialBackoff(10)) if err != nil { diff --git a/op-program/host/host_test.go b/op-program/host/host_test.go index 9dddfe689cfcd..c5d63e17ab34e 100644 --- a/op-program/host/host_test.go +++ b/op-program/host/host_test.go @@ -37,7 +37,7 @@ func TestServerMode(t *testing.T) { logger := testlog.Logger(t, log.LevelTrace) result := make(chan error) go func() { - result <- PreimageServer(context.Background(), logger, cfg, preimageServer, hintServer) + result <- PreimageServer(context.Background(), logger, cfg, preimageServer, hintServer, makeDefaultPrefetcher) }() pClient := preimage.NewOracleClient(preimageClient) diff --git a/op-program/host/kvstore/directory.go b/op-program/host/kvstore/directory.go new file mode 100644 index 0000000000000..4176a6453d64e --- /dev/null +++ b/op-program/host/kvstore/directory.go @@ -0,0 +1,86 @@ +package kvstore + +import ( + "encoding/hex" + "errors" + "fmt" + "io" + "os" + "path" + "sync" + + "github.com/ethereum/go-ethereum/common" +) + +// directoryKV is a disk-backed key-value store, every key-value pair is a hex-encoded .txt file, with the value as content. +// directoryKV is safe for concurrent use with a single directoryKV instance. +// directoryKV is safe for concurrent use between different directoryKV instances of the same disk directory as long as the +// file system supports atomic renames. +type directoryKV struct { + sync.RWMutex + path string +} + +// newDirectoryKV creates a directoryKV that puts/gets pre-images as files in the given directory path. +// The path must exist, or subsequent Put/Get calls will error when it does not. +func newDirectoryKV(path string) *directoryKV { + return &directoryKV{path: path} +} + +// pathKey returns the file path for the given key. +// This is composed of the first characters of the non-0x-prefixed hex key as a directory, and the rest as the file name. +func (d *directoryKV) pathKey(k common.Hash) string { + key := k.String() + dir, name := key[2:6], key[6:] + return path.Join(d.path, dir, name+".txt") +} + +func (d *directoryKV) Put(k common.Hash, v []byte) error { + d.Lock() + defer d.Unlock() + f, err := openTempFile(d.path, k.String()+".txt.*") + if err != nil { + return fmt.Errorf("failed to open temp file for pre-image %s: %w", k, err) + } + defer os.Remove(f.Name()) // Clean up the temp file if it doesn't actually get moved into place + if _, err := f.Write([]byte(hex.EncodeToString(v))); err != nil { + _ = f.Close() + return fmt.Errorf("failed to write pre-image %s to disk: %w", k, err) + } + if err := f.Close(); err != nil { + return fmt.Errorf("failed to close temp pre-image %s file: %w", k, err) + } + + targetFile := d.pathKey(k) + if err := os.MkdirAll(path.Dir(targetFile), 0777); err != nil { + return fmt.Errorf("failed to create parent directory for pre-image %s: %w", f.Name(), err) + } + if err := os.Rename(f.Name(), targetFile); err != nil { + return fmt.Errorf("failed to move temp file %v to final destination %v: %w", f.Name(), targetFile, err) + } + return nil +} + +func (d *directoryKV) Get(k common.Hash) ([]byte, error) { + d.RLock() + defer d.RUnlock() + f, err := os.OpenFile(d.pathKey(k), os.O_RDONLY, filePermission) + if err != nil { + if errors.Is(err, os.ErrNotExist) { + return nil, ErrNotFound + } + return nil, fmt.Errorf("failed to open pre-image file %s: %w", k, err) + } + defer f.Close() // fine to ignore closing error here + dat, err := io.ReadAll(f) + if err != nil { + return nil, fmt.Errorf("failed to read pre-image from file %s: %w", k, err) + } + return hex.DecodeString(string(dat)) +} + +func (d *directoryKV) Close() error { + return nil +} + +var _ KV = (*directoryKV)(nil) diff --git a/op-program/host/kvstore/directory_test.go b/op-program/host/kvstore/directory_test.go new file mode 100644 index 0000000000000..0a76f5843b539 --- /dev/null +++ b/op-program/host/kvstore/directory_test.go @@ -0,0 +1,28 @@ +package kvstore + +import ( + "path/filepath" + "testing" + + "github.com/ethereum/go-ethereum/crypto" + "github.com/stretchr/testify/require" +) + +func TestDirectoryKV(t *testing.T) { + tmp := t.TempDir() // automatically removed by testing cleanup + kv := newDirectoryKV(tmp) + t.Cleanup(func() { // Can't use defer because kvTest runs tests in parallel. + require.NoError(t, kv.Close()) + }) + kvTest(t, kv) +} + +func TestDirectoryKV_CreateMissingDirectory(t *testing.T) { + tmp := t.TempDir() + dir := filepath.Join(tmp, "data") + kv := newDirectoryKV(dir) + defer kv.Close() + val := []byte{1, 2, 3, 4} + key := crypto.Keccak256Hash(val) + require.NoError(t, kv.Put(key, val)) +} diff --git a/op-program/host/kvstore/disk.go b/op-program/host/kvstore/file.go similarity index 76% rename from op-program/host/kvstore/disk.go rename to op-program/host/kvstore/file.go index 0f6bd19068ae8..9116f83df720e 100644 --- a/op-program/host/kvstore/disk.go +++ b/op-program/host/kvstore/file.go @@ -13,28 +13,28 @@ import ( ) // read/write mode for user/group/other, not executable. -const diskPermission = 0666 +const filePermission = 0666 -// DiskKV is a disk-backed key-value store, every key-value pair is a hex-encoded .txt file, with the value as content. -// DiskKV is safe for concurrent use with a single DiskKV instance. -// DiskKV is safe for concurrent use between different DiskKV instances of the same disk directory as long as the +// fileKV is a disk-backed key-value store, every key-value pair is a hex-encoded .txt file, with the value as content. +// fileKV is safe for concurrent use with a single fileKV instance. +// fileKV is safe for concurrent use between different fileKV instances of the same disk directory as long as the // file system supports atomic renames. -type DiskKV struct { +type fileKV struct { sync.RWMutex path string } -// NewDiskKV creates a DiskKV that puts/gets pre-images as files in the given directory path. +// newFileKV creates a fileKV that puts/gets pre-images as files in the given directory path. // The path must exist, or subsequent Put/Get calls will error when it does not. -func NewDiskKV(path string) *DiskKV { - return &DiskKV{path: path} +func newFileKV(path string) *fileKV { + return &fileKV{path: path} } -func (d *DiskKV) pathKey(k common.Hash) string { +func (d *fileKV) pathKey(k common.Hash) string { return path.Join(d.path, k.String()+".txt") } -func (d *DiskKV) Put(k common.Hash, v []byte) error { +func (d *fileKV) Put(k common.Hash, v []byte) error { d.Lock() defer d.Unlock() f, err := openTempFile(d.path, k.String()+".txt.*") @@ -72,10 +72,10 @@ func openTempFile(dir string, nameTemplate string) (*os.File, error) { return f, nil } -func (d *DiskKV) Get(k common.Hash) ([]byte, error) { +func (d *fileKV) Get(k common.Hash) ([]byte, error) { d.RLock() defer d.RUnlock() - f, err := os.OpenFile(d.pathKey(k), os.O_RDONLY, diskPermission) + f, err := os.OpenFile(d.pathKey(k), os.O_RDONLY, filePermission) if err != nil { if errors.Is(err, os.ErrNotExist) { return nil, ErrNotFound @@ -90,4 +90,8 @@ func (d *DiskKV) Get(k common.Hash) ([]byte, error) { return hex.DecodeString(string(dat)) } -var _ KV = (*DiskKV)(nil) +func (d *fileKV) Close() error { + return nil +} + +var _ KV = (*fileKV)(nil) diff --git a/op-program/host/kvstore/disk_test.go b/op-program/host/kvstore/file_test.go similarity index 58% rename from op-program/host/kvstore/disk_test.go rename to op-program/host/kvstore/file_test.go index 1ea0eaa2dfa87..cb96039bc2ceb 100644 --- a/op-program/host/kvstore/disk_test.go +++ b/op-program/host/kvstore/file_test.go @@ -8,16 +8,20 @@ import ( "github.com/stretchr/testify/require" ) -func TestDiskKV(t *testing.T) { +func TestFileKV(t *testing.T) { tmp := t.TempDir() // automatically removed by testing cleanup - kv := NewDiskKV(tmp) + kv := newFileKV(tmp) + t.Cleanup(func() { // Can't use defer because kvTest runs tests in parallel. + require.NoError(t, kv.Close()) + }) kvTest(t, kv) } -func TestCreateMissingDirectory(t *testing.T) { +func TestFileKV_CreateMissingDirectory(t *testing.T) { tmp := t.TempDir() dir := filepath.Join(tmp, "data") - kv := NewDiskKV(dir) + kv := newFileKV(dir) + defer kv.Close() val := []byte{1, 2, 3, 4} key := crypto.Keccak256Hash(val) require.NoError(t, kv.Put(key, val)) diff --git a/op-program/host/kvstore/format.go b/op-program/host/kvstore/format.go new file mode 100644 index 0000000000000..08cbc1b18c5dc --- /dev/null +++ b/op-program/host/kvstore/format.go @@ -0,0 +1,69 @@ +package kvstore + +import ( + "errors" + "fmt" + "os" + "path/filepath" + "slices" + + "github.com/ethereum-optimism/optimism/op-program/host/types" + "github.com/ethereum/go-ethereum/log" +) + +const formatFilename = "kvformat" + +var ( + ErrFormatUnavailable = errors.New("format unavailable") + ErrUnsupportedFormat = errors.New("unsupported format") +) + +func recordKVFormat(dir string, format types.DataFormat) error { + return os.WriteFile(filepath.Join(dir, formatFilename), []byte(format), 0o644) +} + +func readKVFormat(dir string) (types.DataFormat, error) { + data, err := os.ReadFile(filepath.Join(dir, formatFilename)) + if errors.Is(err, os.ErrNotExist) { + return "", ErrFormatUnavailable + } else if err != nil { + return "", fmt.Errorf("failed to read kv format: %w", err) + } + format := types.DataFormat(data) + if !slices.Contains(types.SupportedDataFormats, format) { + return "", fmt.Errorf("%w: %s", ErrUnsupportedFormat, format) + } + return format, nil +} + +// NewDiskKV creates a new KV implementation. If the specified directly contains an existing KV store +// that has the format recorded, the recorded format is used ensuring compatibility with the existing data. +// If the directory does not contain existing data or doesn't have the format recorded, defaultFormat is used +// which may result in the existing data being unused. +// If the existing data records a format that is not supported, an error is returned. +// The format is automatically recorded if it wasn't previously stored. +func NewDiskKV(logger log.Logger, dir string, defaultFormat types.DataFormat) (KV, error) { + format, err := readKVFormat(dir) + if errors.Is(err, ErrFormatUnavailable) { + format = defaultFormat + logger.Info("Creating disk storage", "datadir", dir, "format", format) + if err := recordKVFormat(dir, format); err != nil { + return nil, fmt.Errorf("failed to record new kv store format: %w", err) + } + } else if err != nil { + return nil, err + } else { + logger.Info("Using existing disk storage", "datadir", dir, "format", format) + } + + switch format { + case types.DataFormatFile: + return newFileKV(dir), nil + case types.DataFormatDirectory: + return newDirectoryKV(dir), nil + case types.DataFormatPebble: + return newPebbleKV(dir), nil + default: + return nil, fmt.Errorf("invalid data format: %s", format) + } +} diff --git a/op-program/host/kvstore/format_test.go b/op-program/host/kvstore/format_test.go new file mode 100644 index 0000000000000..8be0368bd09c4 --- /dev/null +++ b/op-program/host/kvstore/format_test.go @@ -0,0 +1,66 @@ +package kvstore + +import ( + "fmt" + "testing" + + "github.com/ethereum-optimism/optimism/op-program/host/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 TestRecordAndReadKVFormat(t *testing.T) { + for _, format := range types.SupportedDataFormats { + format := format + t.Run(string(format), func(t *testing.T) { + dir := t.TempDir() + require.NoError(t, recordKVFormat(dir, format)) + actual, err := readKVFormat(dir) + require.NoError(t, err) + require.Equal(t, format, actual) + }) + } + + t.Run("Unsupported", func(t *testing.T) { + dir := t.TempDir() + require.NoError(t, recordKVFormat(dir, "nope")) + _, err := readKVFormat(dir) + require.ErrorIs(t, err, ErrUnsupportedFormat) + }) + + t.Run("NotRecorded", func(t *testing.T) { + dir := t.TempDir() + _, err := readKVFormat(dir) + require.ErrorIs(t, err, ErrFormatUnavailable) + }) +} + +func TestNewDiskKV(t *testing.T) { + for _, existingFormat := range types.SupportedDataFormats { + existingFormat := existingFormat + + for _, specifiedFormat := range types.SupportedDataFormats { + specifiedFormat := specifiedFormat + t.Run(fmt.Sprintf("%v->%v", existingFormat, specifiedFormat), func(t *testing.T) { + dir := t.TempDir() + logger := testlog.Logger(t, log.LevelError) + hash := common.Hash{0xaa} + value := []byte{1, 2, 3, 4, 5, 6} + kv1, err := NewDiskKV(logger, dir, existingFormat) + require.NoError(t, err) + require.NoError(t, kv1.Put(hash, value)) + require.NoError(t, kv1.Close()) + + // Should use existing format + kv2, err := NewDiskKV(logger, dir, specifiedFormat) + require.NoError(t, err) + actual, err := kv2.Get(hash) + require.NoError(t, err) + require.Equal(t, value, actual) + require.NoError(t, kv2.Close()) + }) + } + } +} diff --git a/op-program/host/kvstore/kv.go b/op-program/host/kvstore/kv.go index e75dcd699d9f5..054230950d0b0 100644 --- a/op-program/host/kvstore/kv.go +++ b/op-program/host/kvstore/kv.go @@ -19,4 +19,7 @@ type KV interface { // It returns ErrNotFound when the pre-image cannot be found. // KV store implementations may return additional errors specific to the KV storage. Get(k common.Hash) ([]byte, error) + + // Closes the KV store. + Close() error } diff --git a/op-program/host/kvstore/mem.go b/op-program/host/kvstore/mem.go index 9af540e235fa9..0c3b950b7e9c3 100644 --- a/op-program/host/kvstore/mem.go +++ b/op-program/host/kvstore/mem.go @@ -37,3 +37,7 @@ func (m *MemKV) Get(k common.Hash) ([]byte, error) { } return slices.Clone(v), nil } + +func (m *MemKV) Close() error { + return nil +} diff --git a/op-program/host/kvstore/pebble.go b/op-program/host/kvstore/pebble.go new file mode 100644 index 0000000000000..5bc7fcc9f23a7 --- /dev/null +++ b/op-program/host/kvstore/pebble.go @@ -0,0 +1,68 @@ +package kvstore + +import ( + "errors" + "fmt" + "runtime" + "sync" + + "github.com/cockroachdb/pebble" + "github.com/ethereum/go-ethereum/common" +) + +// pebbleKV is a disk-backed key-value store, with PebbleDB as the underlying DBMS. +// pebbleKV is safe for concurrent use with a single pebbleKV instance. +type pebbleKV struct { + sync.RWMutex + db *pebble.DB +} + +// newPebbleKV creates a pebbleKV that puts/gets pre-images as files in the given directory path. +// The path must exist, or subsequent Put/Get calls will error when it does not. +func newPebbleKV(path string) *pebbleKV { + opts := &pebble.Options{ + Cache: pebble.NewCache(int64(32 * 1024 * 1024)), + MaxConcurrentCompactions: runtime.NumCPU, + Levels: []pebble.LevelOptions{ + {Compression: pebble.SnappyCompression}, + }, + } + db, err := pebble.Open(path, opts) + if err != nil { + panic(fmt.Errorf("failed to open pebbledb at %s: %w", path, err)) + } + + return &pebbleKV{db: db} +} + +func (d *pebbleKV) Put(k common.Hash, v []byte) error { + d.Lock() + defer d.Unlock() + return d.db.Set(k.Bytes(), v, pebble.NoSync) +} + +func (d *pebbleKV) Get(k common.Hash) ([]byte, error) { + d.RLock() + defer d.RUnlock() + + dat, closer, err := d.db.Get(k.Bytes()) + if err != nil { + if errors.Is(err, pebble.ErrNotFound) { + return nil, ErrNotFound + } + return nil, err + } + ret := make([]byte, len(dat)) + copy(ret, dat) + closer.Close() + return ret, nil +} + +func (d *pebbleKV) Close() error { + d.Lock() + defer d.Unlock() + + return d.db.Close() +} + +var _ KV = (*pebbleKV)(nil) diff --git a/op-program/host/kvstore/pebble_test.go b/op-program/host/kvstore/pebble_test.go new file mode 100644 index 0000000000000..e009d67970217 --- /dev/null +++ b/op-program/host/kvstore/pebble_test.go @@ -0,0 +1,28 @@ +package kvstore + +import ( + "path/filepath" + "testing" + + "github.com/ethereum/go-ethereum/crypto" + "github.com/stretchr/testify/require" +) + +func TestPebbleKV(t *testing.T) { + tmp := t.TempDir() // automatically removed by testing cleanup + kv := newPebbleKV(tmp) + t.Cleanup(func() { // Can't use defer because kvTest runs tests in parallel. + require.NoError(t, kv.Close()) + }) + kvTest(t, kv) +} + +func TestPebbleKV_CreateMissingDirectory(t *testing.T) { + tmp := t.TempDir() + dir := filepath.Join(tmp, "data") + kv := newPebbleKV(dir) + defer kv.Close() + val := []byte{1, 2, 3, 4} + key := crypto.Keccak256Hash(val) + require.NoError(t, kv.Put(key, val)) +} diff --git a/op-program/host/types/types.go b/op-program/host/types/types.go new file mode 100644 index 0000000000000..7cb24b55f65db --- /dev/null +++ b/op-program/host/types/types.go @@ -0,0 +1,11 @@ +package types + +type DataFormat string + +const ( + DataFormatFile DataFormat = "file" + DataFormatDirectory DataFormat = "directory" + DataFormatPebble DataFormat = "pebble" +) + +var SupportedDataFormats = []DataFormat{DataFormatFile, DataFormatDirectory, DataFormatPebble} diff --git a/op-program/scripts/build-prestates.sh b/op-program/scripts/build-prestates.sh new file mode 100755 index 0000000000000..5394c7a135e05 --- /dev/null +++ b/op-program/scripts/build-prestates.sh @@ -0,0 +1,39 @@ +#!/bin/bash +set -euo pipefail +SCRIPTS_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) + +TMP_DIR=$(mktemp -d) +function cleanup() { + rm -rf "${TMP_DIR}" +} +trap cleanup EXIT +echo "Using temp dir: ${TMP_DIR}" +cd "${TMP_DIR}" + +# Need to check out a fresh copy of the monorepo so we can switch to specific tags without it also affecting the +# contents of this script (which is checked into the repo). +git clone https://github.com/ethereum-optimism/optimism --recurse-submodules + +STATES_DIR="${SCRIPTS_DIR}/../temp/states" +LOGS_DIR="${SCRIPTS_DIR}/../temp/logs" +REPO_DIR="${TMP_DIR}/optimism" +BIN_DIR="${REPO_DIR}/op-program/bin/" + +mkdir -p "${STATES_DIR}" "${LOGS_DIR}" + +cd "${REPO_DIR}" + +VERSIONS=$(git tag | grep 'op-program\/v') + +for VERSION in ${VERSIONS} +do + LOG_FILE="${LOGS_DIR}/build-$(echo "${VERSION}" | cut -c 12-).txt" + echo "Building Version: ${VERSION} Logs: ${LOG_FILE}" + git checkout "${VERSION}" > "${LOG_FILE}" 2>&1 + make reproducible-prestate >> "${LOG_FILE}" 2>&1 + HASH=$(cat "${BIN_DIR}/prestate-proof.json" | jq -r .pre) + cp "${BIN_DIR}/prestate.json" "${STATES_DIR}/${HASH}.json" + echo "Built ${VERSION}: ${HASH}" +done + +echo "All prestates successfully built and available in ${STATES_DIR}" diff --git a/op-program/scripts/run-compat.sh b/op-program/scripts/run-compat.sh index ed853a8d980b2..9849b8da89380 100755 --- a/op-program/scripts/run-compat.sh +++ b/op-program/scripts/run-compat.sh @@ -5,7 +5,7 @@ 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-08-02}" +BASEURL="${2:-https://github.com/ethereum-optimism/chain-test-data/releases/download/2024-09-01}" URL="${BASEURL}/${TESTNAME}.tar.bz" @@ -13,4 +13,4 @@ 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") +"${SCRIPTS_DIR}/../bin/op-program" --data.format=pebble $(cat "${COMPAT_DIR}/${TESTNAME}/args.txt") diff --git a/op-proposer/cmd/main.go b/op-proposer/cmd/main.go index bdfc730b4bf3e..cbb21fb285163 100644 --- a/op-proposer/cmd/main.go +++ b/op-proposer/cmd/main.go @@ -1,8 +1,11 @@ package main import ( + "context" "os" + "github.com/ethereum-optimism/optimism/op-service/ctxinterrupt" + opservice "github.com/ethereum-optimism/optimism/op-service" "github.com/urfave/cli/v2" @@ -38,7 +41,8 @@ func main() { }, } - err := app.Run(os.Args) + ctx := ctxinterrupt.WithSignalWaiterMain(context.Background()) + err := app.RunContext(ctx, os.Args) if err != nil { log.Crit("Application failed", "message", err) } diff --git a/op-service/cliapp/lifecycle.go b/op-service/cliapp/lifecycle.go index 2154c025645d3..a1f1349791345 100644 --- a/op-service/cliapp/lifecycle.go +++ b/op-service/cliapp/lifecycle.go @@ -7,7 +7,7 @@ import ( "github.com/urfave/cli/v2" - "github.com/ethereum-optimism/optimism/op-service/opio" + "github.com/ethereum-optimism/optimism/op-service/ctxinterrupt" ) type Lifecycle interface { @@ -29,36 +29,26 @@ type Lifecycle interface { // a shutdown when the Stop context is not expired. type LifecycleAction func(ctx *cli.Context, close context.CancelCauseFunc) (Lifecycle, error) -var interruptErr = errors.New("interrupt signal") - // LifecycleCmd turns a LifecycleAction into an CLI action, -// by instrumenting it with CLI context and signal based termination. -// The signals are caught with the opio.BlockFn attached to the context, if any. -// If no block function is provided, it adds default interrupt handling. +// by instrumenting it with CLI context and signal based cancellation. +// The signals are caught with the ctxinterrupt.waiter attached to the context, or default +// interrupt signal handling if not already provided. // The app may continue to run post-processing until fully shutting down. // The user can force an early shut-down during post-processing by sending a second interruption signal. func LifecycleCmd(fn LifecycleAction) cli.ActionFunc { return func(ctx *cli.Context) error { - hostCtx := ctx.Context - blockOnInterrupt := opio.BlockerFromContext(hostCtx) - if blockOnInterrupt == nil { // add default interrupt blocker to context if none is set. - hostCtx = opio.WithInterruptBlocker(hostCtx) - blockOnInterrupt = opio.BlockerFromContext(hostCtx) - } - appCtx, appCancel := context.WithCancelCause(hostCtx) + hostCtx, stop := ctxinterrupt.WithSignalWaiter(ctx.Context) + defer stop() + appCtx, appCancel := context.WithCancelCause(ctxinterrupt.WithCancelOnInterrupt(hostCtx)) + // This is updated so the fn callback cli.Context uses the appCtx we just made. ctx.Context = appCtx - go func() { - blockOnInterrupt(appCtx) - appCancel(interruptErr) - }() - appLifecycle, err := fn(ctx, appCancel) if err != nil { // join errors to include context cause (nil errors are dropped) return errors.Join( fmt.Errorf("failed to setup: %w", err), - context.Cause(appCtx), + context.Cause(ctx.Context), ) } @@ -75,15 +65,10 @@ func LifecycleCmd(fn LifecycleAction) cli.ActionFunc { // Graceful stop context. // This allows the service to idle before shutdown, if halted. User may interrupt. - stopCtx, stopCancel := context.WithCancelCause(hostCtx) - go func() { - blockOnInterrupt(stopCtx) - stopCancel(interruptErr) - }() + stopCtx := ctxinterrupt.WithCancelOnInterrupt(hostCtx) // Execute graceful stop. stopErr := appLifecycle.Stop(stopCtx) - stopCancel(nil) // note: Stop implementation may choose to suppress a context error, // if it handles it well (e.g. stop idling after a halt). if stopErr != nil { diff --git a/op-service/cliapp/lifecycle_test.go b/op-service/cliapp/lifecycle_test.go index 4c421a35493e5..d9ffd086ed73f 100644 --- a/op-service/cliapp/lifecycle_test.go +++ b/op-service/cliapp/lifecycle_test.go @@ -9,9 +9,11 @@ import ( "github.com/stretchr/testify/require" "github.com/urfave/cli/v2" - "github.com/ethereum-optimism/optimism/op-service/opio" + "github.com/ethereum-optimism/optimism/op-service/ctxinterrupt" ) +var mockInterruptErr = errors.New("mock interrupt") + type fakeLifecycle struct { startCh, stopCh chan error stopped bool @@ -85,11 +87,14 @@ func TestLifecycleCmd(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), time.Minute) // puppeteer system signal interrupts by hooking up the test signal channel as "blocker" for the app to use. - ctx = opio.WithBlocker(ctx, func(ctx context.Context) { + ctx = ctxinterrupt.WithWaiterFunc(ctx, func(ctx context.Context) (interrupt, ctxErr error) { select { case <-ctx.Done(): + ctxErr = context.Cause(ctx) case <-signalCh: + interrupt = mockInterruptErr } + return }) t.Cleanup(cancel) @@ -124,7 +129,7 @@ func TestLifecycleCmd(t *testing.T) { signalCh, _, _, _, resultCh, _ := appSetup(t) signalCh <- struct{}{} res := <-resultCh - require.ErrorIs(t, res, interruptErr) + require.ErrorIs(t, res, mockInterruptErr) require.ErrorContains(t, res, "failed to setup") }) t.Run("failed init", func(t *testing.T) { @@ -142,7 +147,7 @@ func TestLifecycleCmd(t *testing.T) { require.False(t, app.Stopped()) signalCh <- struct{}{} res := <-resultCh - require.ErrorIs(t, res, interruptErr) + require.ErrorIs(t, res, mockInterruptErr) require.ErrorContains(t, res, "failed to start") require.True(t, app.Stopped()) }) @@ -178,7 +183,7 @@ func TestLifecycleCmd(t *testing.T) { signalCh <- struct{}{} // start graceful shutdown signalCh <- struct{}{} // interrupt before the shutdown process is allowed to complete res := <-resultCh - require.ErrorIs(t, res, interruptErr) + require.ErrorIs(t, res, mockInterruptErr) require.ErrorContains(t, res, "failed to stop") require.True(t, app.Stopped()) // still fully closes, interrupts only accelerate shutdown where possible. }) diff --git a/op-service/client/lazy_dial.go b/op-service/client/lazy_dial.go new file mode 100644 index 0000000000000..9064fbe1fe09d --- /dev/null +++ b/op-service/client/lazy_dial.go @@ -0,0 +1,84 @@ +package client + +import ( + "context" + "errors" + "fmt" + "sync" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/rpc" +) + +// LazyRPC defers connection attempts to the usage of the RPC. +// This allows a websocket connection to be established lazily. +// The underlying RPC should handle reconnects. +type LazyRPC struct { + // mutex to prevent more than one active dial attempt at a time. + mu sync.Mutex + // inner is the actual RPC client. + // It is initialized once. The underlying RPC handles reconnections. + inner RPC + // options to initialize `inner` with. + opts []rpc.ClientOption + endpoint string + // If we have not initialized `inner` yet, + // do not try to do so after closing the client. + closed bool +} + +var _ RPC = (*LazyRPC)(nil) + +func NewLazyRPC(endpoint string, opts ...rpc.ClientOption) *LazyRPC { + return &LazyRPC{ + opts: opts, + endpoint: endpoint, + } +} + +func (l *LazyRPC) dial(ctx context.Context) error { + l.mu.Lock() + defer l.mu.Unlock() + if l.inner != nil { + return nil + } + if l.closed { + return errors.New("cannot dial RPC, client was already closed") + } + underlying, err := rpc.DialOptions(ctx, l.endpoint, l.opts...) + if err != nil { + return fmt.Errorf("failed to dial: %w", err) + } + l.inner = NewBaseRPCClient(underlying) + return nil +} + +func (l *LazyRPC) Close() { + l.mu.Lock() + defer l.mu.Unlock() + if l.inner != nil { + l.inner.Close() + } + l.closed = true +} + +func (l *LazyRPC) CallContext(ctx context.Context, result any, method string, args ...any) error { + if err := l.dial(ctx); err != nil { + return err + } + return l.inner.CallContext(ctx, result, method, args...) +} + +func (l *LazyRPC) BatchCallContext(ctx context.Context, b []rpc.BatchElem) error { + if err := l.dial(ctx); err != nil { + return err + } + return l.inner.BatchCallContext(ctx, b) +} + +func (l *LazyRPC) EthSubscribe(ctx context.Context, channel any, args ...any) (ethereum.Subscription, error) { + if err := l.dial(ctx); err != nil { + return nil, err + } + return l.inner.EthSubscribe(ctx, channel, args...) +} diff --git a/op-service/client/lazy_dial_test.go b/op-service/client/lazy_dial_test.go new file mode 100644 index 0000000000000..79608dc2b236f --- /dev/null +++ b/op-service/client/lazy_dial_test.go @@ -0,0 +1,66 @@ +package client + +import ( + "context" + "net" + "net/http" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "github.com/ethereum/go-ethereum/node" + "github.com/ethereum/go-ethereum/rpc" +) + +type mockServer struct { + count int +} + +func (m *mockServer) Count() { + m.count += 1 +} + +func TestLazyRPC(t *testing.T) { + listener, err := net.Listen("tcp", "127.0.0.1:0") + require.NoError(t, err) + defer listener.Close() + + addr := listener.Addr().String() + + cl := NewLazyRPC("ws://" + addr) + defer cl.Close() + + // At this point the connection is online, but the RPC is not. + // RPC request attempts should fail. + { + ctx, cancel := context.WithTimeout(context.Background(), time.Second*4) + attempt1Err := cl.CallContext(ctx, nil, "foo_count") + cancel() + require.ErrorContains(t, attempt1Err, "i/o timeout") + require.NotNil(t, ctx.Err()) + } + + // Now let's serve a websocket RPC + rpcSrv := rpc.NewServer() + defer rpcSrv.Stop() + wsHandler := rpcSrv.WebsocketHandler([]string{"*"}) + httpSrv := &http.Server{Handler: wsHandler} + defer httpSrv.Close() + + go func() { + _ = httpSrv.Serve(listener) // always non-nil, returned when server exits. + }() + + ms := &mockServer{} + require.NoError(t, node.RegisterApis([]rpc.API{{ + Namespace: "foo", + Service: ms, + }}, nil, rpcSrv)) + + // and see if the lazy-dial client can reach it + require.Equal(t, 0, ms.count) + attempt2Err := cl.CallContext(context.Background(), nil, "foo_count") + require.NoError(t, attempt2Err) + require.Equal(t, 1, ms.count) +} diff --git a/op-service/client/rpc.go b/op-service/client/rpc.go index 0ec2f3896535f..8fb2d4d37b886 100644 --- a/op-service/client/rpc.go +++ b/op-service/client/rpc.go @@ -35,10 +35,27 @@ type rpcConfig struct { backoffAttempts int limit float64 burst int + lazy bool + callTimeout time.Duration + batchCallTimeout time.Duration } type RPCOption func(cfg *rpcConfig) error +func WithCallTimeout(d time.Duration) RPCOption { + return func(cfg *rpcConfig) error { + cfg.callTimeout = d + return nil + } +} + +func WithBatchCallTimeout(d time.Duration) RPCOption { + return func(cfg *rpcConfig) error { + cfg.batchCallTimeout = d + return nil + } +} + // WithDialBackoff configures the number of attempts for the initial dial to the RPC, // attempts are executed with an exponential backoff strategy. func WithDialBackoff(attempts int) RPCOption { @@ -74,6 +91,17 @@ func WithRateLimit(rateLimit float64, burst int) RPCOption { } } +// WithLazyDial makes the RPC client initialization defer the initial connection attempt, +// and defer to later RPC requests upon subsequent dial errors. +// Any dial-backoff option will be ignored if this option is used. +// This is implemented by wrapping the inner RPC client with a LazyRPC. +func WithLazyDial() RPCOption { + return func(cfg *rpcConfig) error { + cfg.lazy = true + return nil + } +} + // NewRPC returns the correct client.RPC instance for a given RPC url. func NewRPC(ctx context.Context, lgr log.Logger, addr string, opts ...RPCOption) (RPC, error) { var cfg rpcConfig @@ -86,13 +114,23 @@ func NewRPC(ctx context.Context, lgr log.Logger, addr string, opts ...RPCOption) if cfg.backoffAttempts < 1 { // default to at least 1 attempt, or it always fails to dial. cfg.backoffAttempts = 1 } - - underlying, err := dialRPCClientWithBackoff(ctx, lgr, addr, cfg.backoffAttempts, cfg.gethRPCOptions...) - if err != nil { - return nil, err + if cfg.callTimeout == 0 { + cfg.callTimeout = 10 * time.Second + } + if cfg.batchCallTimeout == 0 { + cfg.batchCallTimeout = 20 * time.Second } - var wrapped RPC = &BaseRPCClient{c: underlying} + var wrapped RPC + if cfg.lazy { + wrapped = NewLazyRPC(addr, cfg.gethRPCOptions...) + } else { + underlying, err := dialRPCClientWithBackoff(ctx, lgr, addr, cfg.backoffAttempts, cfg.gethRPCOptions...) + if err != nil { + return nil, err + } + wrapped = &BaseRPCClient{c: underlying, callTimeout: cfg.callTimeout, batchCallTimeout: cfg.batchCallTimeout} + } if cfg.limit != 0 { wrapped = NewRateLimitingClient(wrapped, rate.Limit(cfg.limit), cfg.burst) @@ -155,11 +193,13 @@ func IsURLAvailable(ctx context.Context, address string) bool { // with the client.RPC interface. // It sets a timeout of 10s on CallContext & 20s on BatchCallContext made through it. type BaseRPCClient struct { - c *rpc.Client + c *rpc.Client + batchCallTimeout time.Duration + callTimeout time.Duration } func NewBaseRPCClient(c *rpc.Client) *BaseRPCClient { - return &BaseRPCClient{c: c} + return &BaseRPCClient{c: c, callTimeout: 10 * time.Second, batchCallTimeout: 20 * time.Second} } func (b *BaseRPCClient) Close() { @@ -167,13 +207,13 @@ func (b *BaseRPCClient) Close() { } func (b *BaseRPCClient) CallContext(ctx context.Context, result any, method string, args ...any) error { - cCtx, cancel := context.WithTimeout(ctx, 10*time.Second) + cCtx, cancel := context.WithTimeout(ctx, b.callTimeout) defer cancel() return b.c.CallContext(cCtx, result, method, args...) } func (b *BaseRPCClient) BatchCallContext(ctx context.Context, batch []rpc.BatchElem) error { - cCtx, cancel := context.WithTimeout(ctx, 20*time.Second) + cCtx, cancel := context.WithTimeout(ctx, b.batchCallTimeout) defer cancel() return b.c.BatchCallContext(cCtx, batch) } diff --git a/op-service/crypto/secrets.go b/op-service/crypto/secrets.go new file mode 100644 index 0000000000000..410de63cb3ca8 --- /dev/null +++ b/op-service/crypto/secrets.go @@ -0,0 +1,19 @@ +package crypto + +import ( + "crypto/ecdsa" + + "github.com/ethereum/go-ethereum/common/hexutil" +) + +// EncodePrivKey encodes the given private key in 32 bytes +func EncodePrivKey(priv *ecdsa.PrivateKey) hexutil.Bytes { + privkey := make([]byte, 32) + blob := priv.D.Bytes() + copy(privkey[32-len(blob):], blob) + return privkey +} + +func EncodePrivKeyToString(priv *ecdsa.PrivateKey) string { + return hexutil.Encode(EncodePrivKey(priv)) +} diff --git a/op-service/crypto/signature.go b/op-service/crypto/signature.go index 0b0afc02ecef8..a6a7c1cc0d1e2 100644 --- a/op-service/crypto/signature.go +++ b/op-service/crypto/signature.go @@ -35,6 +35,12 @@ func PrivateKeySignerFn(key *ecdsa.PrivateKey, chainID *big.Int) bind.SignerFn { } } +func SignerFnFromBind(fn bind.SignerFn) SignerFn { + return func(_ context.Context, address common.Address, tx *types.Transaction) (*types.Transaction, error) { + return fn(address, tx) + } +} + // SignerFn is a generic transaction signing function. It may be a remote signer so it takes a context. // It also takes the address that should be used to sign the transaction with. type SignerFn func(context.Context, common.Address, *types.Transaction) (*types.Transaction, error) diff --git a/op-service/ctxinterrupt/context.go b/op-service/ctxinterrupt/context.go new file mode 100644 index 0000000000000..d7e7446d0dc33 --- /dev/null +++ b/op-service/ctxinterrupt/context.go @@ -0,0 +1,29 @@ +package ctxinterrupt + +import ( + "context" +) + +// Newtyping empty struct prevents collision with other empty struct keys in the Context. +type interruptWaiterContextKeyType struct{} + +var waiterContextKey = interruptWaiterContextKeyType{} + +// WithInterruptWaiter overrides the interrupt waiter value, e.g. to insert a function that mocks +// interrupt signals for testing CLI shutdown without actual process signals. +func WithWaiterFunc(ctx context.Context, fn WaiterFunc) context.Context { + return withInterruptWaiter(ctx, fn) +} + +func withInterruptWaiter(ctx context.Context, value waiter) context.Context { + return context.WithValue(ctx, waiterContextKey, value) +} + +// contextInterruptWaiter returns a interruptWaiter that blocks on interrupts when called. +func contextInterruptWaiter(ctx context.Context) waiter { + v := ctx.Value(waiterContextKey) + if v == nil { + return nil + } + return v.(waiter) +} diff --git a/op-service/ctxinterrupt/context_test.go b/op-service/ctxinterrupt/context_test.go new file mode 100644 index 0000000000000..c853a3c5f7c6d --- /dev/null +++ b/op-service/ctxinterrupt/context_test.go @@ -0,0 +1,19 @@ +package ctxinterrupt + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestContextKeyIsUnique(t *testing.T) { + ass := require.New(t) + ctx := context.Background() + ass.Nil(ctx.Value(waiterContextKey)) + ctx = context.WithValue(ctx, waiterContextKey, 1) + ass.Equal(ctx.Value(waiterContextKey), 1) + ctx = context.WithValue(ctx, waiterContextKey, 2) + ass.Equal(ctx.Value(waiterContextKey), 2) + ass.Nil(ctx.Value(struct{}{})) +} diff --git a/op-service/ctxinterrupt/doc.go b/op-service/ctxinterrupt/doc.go new file mode 100644 index 0000000000000..4846d544eba89 --- /dev/null +++ b/op-service/ctxinterrupt/doc.go @@ -0,0 +1,3 @@ +// Implements interrupts: events that normally signal intent to cancel a Context, but may be +// repeated to encourage closure of new Contexts used to clean up resources. +package ctxinterrupt diff --git a/op-service/ctxinterrupt/funcs.go b/op-service/ctxinterrupt/funcs.go new file mode 100644 index 0000000000000..90ab19e19df15 --- /dev/null +++ b/op-service/ctxinterrupt/funcs.go @@ -0,0 +1,55 @@ +package ctxinterrupt + +import ( + "context" +) + +// Wait blocks until an interrupt is received, defaulting to interrupting on the default +// signals if no interrupt blocker is present in the Context. Returns nil if an interrupt occurs, +// else the Context error when it's done. +func Wait(ctx context.Context) error { + iw := contextInterruptWaiter(ctx) + if iw == nil { + catcher := newSignalWaiter() + defer catcher.Stop() + iw = catcher + } + return iw.waitForInterrupt(ctx).CtxError +} + +// WithSignalWaiter attaches an interrupt signal handler to the context which continues to receive +// signals after every wait, and also prevents the interrupt signals being handled before we're +// ready to wait for them. This helps functions wait on individual consecutive interrupts. +func WithSignalWaiter(ctx context.Context) (_ context.Context, stop func()) { + if ctx.Value(waiterContextKey) != nil { // already has an interrupt waiter + return ctx, func() {} + } + catcher := newSignalWaiter() + return withInterruptWaiter(ctx, catcher), catcher.Stop +} + +// WithSignalWaiterMain returns a Context with a signal interrupt blocker and leaks the destructor. Intended for use in +// main functions where we exit right after using the returned context anyway. +func WithSignalWaiterMain(ctx context.Context) context.Context { + ctx, _ = WithSignalWaiter(ctx) + return ctx +} + +// WithCancelOnInterrupt returns a Context that is cancelled when Wait returns on the waiter in ctx. +// If there's no waiter, the default interrupt signals are used: In this case the signal hooking is +// not stopped until the original ctx is cancelled. +func WithCancelOnInterrupt(ctx context.Context) context.Context { + interruptWaiter := contextInterruptWaiter(ctx) + ctx, cancel := context.WithCancelCause(ctx) + stop := func() {} + if interruptWaiter == nil { + catcher := newSignalWaiter() + stop = catcher.Stop + interruptWaiter = catcher + } + go func() { + defer stop() + cancel(interruptWaiter.waitForInterrupt(ctx).Cause()) + }() + return ctx +} diff --git a/op-service/ctxinterrupt/signal-waiter.go b/op-service/ctxinterrupt/signal-waiter.go new file mode 100644 index 0000000000000..a37dde7a981ba --- /dev/null +++ b/op-service/ctxinterrupt/signal-waiter.go @@ -0,0 +1,50 @@ +package ctxinterrupt + +import ( + "context" + "fmt" + "os" + "os/signal" + "syscall" +) + +// defaultSignals is a set of default interrupt signals. +var defaultSignals = []os.Signal{ + // Let's not catch SIGQUIT as it's expected to terminate with a stack trace in Go. os.Kill + // should not/cannot be caught on most systems. + os.Interrupt, + syscall.SIGTERM, +} + +type signalWaiter struct { + incoming chan os.Signal +} + +func newSignalWaiter() signalWaiter { + catcher := signalWaiter{ + // Buffer, in case we are slow to act on older signals, + // but still want to handle repeat-signals as special case (e.g. to force shutdown) + incoming: make(chan os.Signal, 10), + } + signal.Notify(catcher.incoming, defaultSignals...) + return catcher +} + +func (me signalWaiter) Stop() { + signal.Stop(me.incoming) +} + +// Block blocks until either an interrupt signal is received, or the context is cancelled. +// No error is returned on interrupt. +func (me signalWaiter) waitForInterrupt(ctx context.Context) waitResult { + select { + case signalValue, ok := <-me.incoming: + if !ok { + // Signal channels are not closed. + panic("signal channel closed") + } + return waitResult{Interrupt: fmt.Errorf("received interrupt signal %v", signalValue)} + case <-ctx.Done(): + return waitResult{CtxError: context.Cause(ctx)} + } +} diff --git a/op-service/ctxinterrupt/waiter.go b/op-service/ctxinterrupt/waiter.go new file mode 100644 index 0000000000000..4e32a84b0a442 --- /dev/null +++ b/op-service/ctxinterrupt/waiter.go @@ -0,0 +1,38 @@ +package ctxinterrupt + +import ( + "context" + "fmt" +) + +// waiter describes a value that can wait for interrupts and context cancellation at the same time. +type waiter interface { + waitForInterrupt(ctx context.Context) waitResult +} + +// Waits for an interrupt or context cancellation. ctxErr should be the context.Cause of ctx when it +// is done. interrupt is only inspected if ctxErr is nil, and is not required to be set. +type WaiterFunc func(ctx context.Context) (interrupt, ctxErr error) + +func (me WaiterFunc) waitForInterrupt(ctx context.Context) (res waitResult) { + res.Interrupt, res.CtxError = me(ctx) + return +} + +// Either CtxError is not nil and is set to the context error cause, or the wait was interrupted. +type waitResult struct { + // Not required to be non-nil on an interrupt. + Interrupt error + // Maybe set this using context.Cause. + CtxError error +} + +func (me waitResult) Cause() error { + if me.CtxError != nil { + return me.CtxError + } + if me.Interrupt != nil { + return fmt.Errorf("interrupted: %w", me.Interrupt) + } + return nil +} diff --git a/op-service/dial/active_l2_provider_test.go b/op-service/dial/active_l2_provider_test.go index 31d5a6cc65217..1533ab6849ff6 100644 --- a/op-service/dial/active_l2_provider_test.go +++ b/op-service/dial/active_l2_provider_test.go @@ -2,6 +2,7 @@ package dial import ( "context" + "errors" "fmt" "testing" "time" @@ -204,7 +205,7 @@ func TestRollupProvider_FailoverOnErroredSequencer(t *testing.T) { require.NoError(t, err) require.Same(t, primarySequencer, firstSequencerUsed) - primarySequencer.ExpectSequencerActive(true, fmt.Errorf("a test error")) // error-out after that + primarySequencer.ExpectSequencerActive(true, errors.New("a test error")) // error-out after that primarySequencer.MaybeClose() secondarySequencer.ExpectSequencerActive(true, nil) secondSequencerUsed, err := rollupProvider.RollupClient(context.Background()) @@ -231,7 +232,7 @@ func TestEndpointProvider_FailoverOnErroredSequencer(t *testing.T) { require.NoError(t, err) require.Same(t, primaryEthClient, firstSequencerUsed) - primarySequencer.ExpectSequencerActive(true, fmt.Errorf("a test error")) // error out after that + primarySequencer.ExpectSequencerActive(true, errors.New("a test error")) // error out after that primarySequencer.MaybeClose() primaryEthClient.MaybeClose() secondarySequencer.ExpectSequencerActive(true, nil) @@ -465,7 +466,7 @@ func TestRollupProvider_ConstructorErrorOnFirstSequencerOffline(t *testing.T) { ept := setupEndpointProviderTest(t, 2) // First sequencer is dead, second sequencer is active - ept.rollupClients[0].ExpectSequencerActive(false, fmt.Errorf("I am offline")) + ept.rollupClients[0].ExpectSequencerActive(false, errors.New("I am offline")) ept.rollupClients[0].MaybeClose() ept.rollupClients[1].ExpectSequencerActive(true, nil) @@ -482,7 +483,7 @@ func TestEndpointProvider_ConstructorErrorOnFirstSequencerOffline(t *testing.T) ept := setupEndpointProviderTest(t, 2) // First sequencer is dead, second sequencer is active - ept.rollupClients[0].ExpectSequencerActive(false, fmt.Errorf("I am offline")) + ept.rollupClients[0].ExpectSequencerActive(false, errors.New("I am offline")) ept.rollupClients[0].MaybeClose() ept.rollupClients[1].ExpectSequencerActive(true, nil) ept.rollupClients[1].ExpectSequencerActive(true, nil) // see comment in other tests about why we expect this twice @@ -533,7 +534,7 @@ func TestRollupProvider_FailOnAllErroredSequencers(t *testing.T) { // All sequencers are inactive for _, sequencer := range ept.rollupClients { - sequencer.ExpectSequencerActive(true, fmt.Errorf("a test error")) + sequencer.ExpectSequencerActive(true, errors.New("a test error")) sequencer.MaybeClose() } @@ -549,7 +550,7 @@ func TestEndpointProvider_FailOnAllErroredSequencers(t *testing.T) { // All sequencers are inactive for _, sequencer := range ept.rollupClients { - sequencer.ExpectSequencerActive(true, fmt.Errorf("a test error")) + sequencer.ExpectSequencerActive(true, errors.New("a test error")) sequencer.MaybeClose() } @@ -711,7 +712,7 @@ func TestRollupProvider_HandlesManyIndexClientMismatch(t *testing.T) { require.NoError(t, err) // primarySequencer goes down - seq0.ExpectSequencerActive(false, fmt.Errorf("I'm offline now")) + seq0.ExpectSequencerActive(false, errors.New("I'm offline now")) seq0.MaybeClose() ept.setRollupDialOutcome(0, false) // primarySequencer fails to dial // secondarySequencer is inactive, but online diff --git a/op-service/eth/status.go b/op-service/eth/status.go index 3baab5725f267..52e2e9c58cc4f 100644 --- a/op-service/eth/status.go +++ b/op-service/eth/status.go @@ -1,18 +1,19 @@ package eth import ( + "errors" "fmt" ) func ForkchoiceUpdateErr(payloadStatus PayloadStatusV1) error { switch payloadStatus.Status { case ExecutionSyncing: - return fmt.Errorf("updated forkchoice, but node is syncing") + return errors.New("updated forkchoice, but node is syncing") case ExecutionAccepted, ExecutionInvalidTerminalBlock, ExecutionInvalidBlockHash: // ACCEPTED, INVALID_TERMINAL_BLOCK, INVALID_BLOCK_HASH are only for execution return fmt.Errorf("unexpected %s status, could not update forkchoice", payloadStatus.Status) case ExecutionInvalid: - return fmt.Errorf("cannot update forkchoice, block is invalid") + return errors.New("cannot update forkchoice, block is invalid") case ExecutionValid: return nil default: diff --git a/op-service/eth/sync_status.go b/op-service/eth/sync_status.go index e6dae130de7f3..f9db1f672b824 100644 --- a/op-service/eth/sync_status.go +++ b/op-service/eth/sync_status.go @@ -22,13 +22,20 @@ type SyncStatus struct { // pointing to block data that has not been submitted to L1 yet. // The sequencer is building this, and verifiers may also be ahead of the // SafeL2 block if they sync blocks via p2p or other offchain sources. + // This is considered to only be local-unsafe post-interop, see CrossUnsafe for cross-L2 guarantees. UnsafeL2 L2BlockRef `json:"unsafe_l2"` // SafeL2 points to the L2 block that was derived from the L1 chain. // This point may still reorg if the L1 chain reorgs. + // This is considered to be cross-safe post-interop, see LocalSafe to ignore cross-L2 guarantees. SafeL2 L2BlockRef `json:"safe_l2"` // FinalizedL2 points to the L2 block that was derived fully from // finalized L1 information, thus irreversible. FinalizedL2 L2BlockRef `json:"finalized_l2"` // PendingSafeL2 points to the L2 block processed from the batch, but not consolidated to the safe block yet. PendingSafeL2 L2BlockRef `json:"pending_safe_l2"` + // CrossUnsafeL2 is an unsafe L2 block, that has been verified to match cross-L2 dependencies. + // Pre-interop every unsafe L2 block is also cross-unsafe. + CrossUnsafeL2 L2BlockRef `json:"cross_unsafe_l2"` + // LocalSafeL2 is an L2 block derived from L1, not yet verified to have valid cross-L2 dependencies. + LocalSafeL2 L2BlockRef `json:"local_safe_l2"` } diff --git a/op-service/ioutil/atomic.go b/op-service/ioutil/atomic.go index 7fc24d01900c1..3cc38c1e6d97b 100644 --- a/op-service/ioutil/atomic.go +++ b/op-service/ioutil/atomic.go @@ -17,6 +17,17 @@ type AtomicWriter struct { // NOTE: It's vital to check if an error is returned from Close() as it may indicate the file could not be renamed // If path ends in .gz the contents written will be gzipped. func NewAtomicWriterCompressed(path string, perm os.FileMode) (*AtomicWriter, error) { + return newAtomicWriter(path, perm, true) +} + +// NewAtomicWriter creates a io.WriteCloser that performs an atomic write. +// The contents are initially written to a temporary file and only renamed into place when the writer is closed. +// NOTE: It's vital to check if an error is returned from Close() as it may indicate the file could not be renamed +func NewAtomicWriter(path string, perm os.FileMode) (*AtomicWriter, error) { + return newAtomicWriter(path, perm, false) +} + +func newAtomicWriter(path string, perm os.FileMode, compressByFileType bool) (*AtomicWriter, error) { f, err := os.CreateTemp(filepath.Dir(path), filepath.Base(path)) if err != nil { return nil, err @@ -25,10 +36,14 @@ func NewAtomicWriterCompressed(path string, perm os.FileMode) (*AtomicWriter, er _ = f.Close() return nil, err } + out := io.WriteCloser(f) + if compressByFileType { + out = CompressByFileType(path, f) + } return &AtomicWriter{ dest: path, temp: f.Name(), - out: CompressByFileType(path, f), + out: out, }, nil } diff --git a/op-service/ioutil/atomic_test.go b/op-service/ioutil/atomic_test.go index 46f2f19a50580..5d46911287a5a 100644 --- a/op-service/ioutil/atomic_test.go +++ b/op-service/ioutil/atomic_test.go @@ -70,7 +70,7 @@ func TestAtomicWriter_AbortAfterClose(t *testing.T) { require.ErrorIs(t, f.Abort(), os.ErrClosed) } -func TestAtomicWriter_ApplyGzip(t *testing.T) { +func TestAtomicWriterCompressed_ApplyGzip(t *testing.T) { tests := []struct { name string filename string @@ -108,3 +108,37 @@ func TestAtomicWriter_ApplyGzip(t *testing.T) { }) } } + +func TestAtomicWriter_ApplyGzip(t *testing.T) { + tests := []struct { + name string + filename string + }{ + {"Uncompressed", "test.notgz"}, + {"Gzipped", "test.gz"}, + } + for _, test := range tests { + test := test + t.Run(test.name, func(t *testing.T) { + data := []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 0} + dir := t.TempDir() + path := filepath.Join(dir, test.filename) + out, err := NewAtomicWriter(path, 0o644) + require.NoError(t, err) + defer out.Close() + _, err = out.Write(data) + require.NoError(t, err) + require.NoError(t, out.Close()) + + writtenData, err := os.ReadFile(path) + require.NoError(t, err) + require.Equal(t, data, writtenData, "should not have compressed data on disk") + + in, err := os.Open(path) + require.NoError(t, err) + readData, err := io.ReadAll(in) + require.NoError(t, err) + require.Equal(t, data, readData) + }) + } +} diff --git a/op-service/ioutil/streams.go b/op-service/ioutil/streams.go new file mode 100644 index 0000000000000..91f122906db0d --- /dev/null +++ b/op-service/ioutil/streams.go @@ -0,0 +1,52 @@ +package ioutil + +import ( + "io" + "os" +) + +var ( + stdOutStream OutputTarget = func() (io.Writer, io.Closer, Aborter, error) { + return os.Stdout, &noopCloser{}, func() {}, nil + } +) + +type Aborter func() + +type OutputTarget func() (io.Writer, io.Closer, Aborter, error) + +func NoOutputStream() OutputTarget { + return func() (io.Writer, io.Closer, Aborter, error) { + return nil, nil, nil, nil + } +} + +func ToAtomicFile(path string, perm os.FileMode) OutputTarget { + return func() (io.Writer, io.Closer, Aborter, error) { + f, err := NewAtomicWriterCompressed(path, perm) + if err != nil { + return nil, nil, nil, err + } + return f, f, func() { _ = f.Abort() }, nil + } +} + +func ToStdOut() OutputTarget { + return stdOutStream +} + +func ToStdOutOrFileOrNoop(outputPath string, perm os.FileMode) OutputTarget { + if outputPath == "" { + return NoOutputStream() + } else if outputPath == "-" { + return ToStdOut() + } else { + return ToAtomicFile(outputPath, perm) + } +} + +type noopCloser struct{} + +func (c *noopCloser) Close() error { + return nil +} diff --git a/op-service/ioutil/streams_test.go b/op-service/ioutil/streams_test.go new file mode 100644 index 0000000000000..cbbed7e621715 --- /dev/null +++ b/op-service/ioutil/streams_test.go @@ -0,0 +1,100 @@ +package ioutil + +import ( + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestNoOutputStream(t *testing.T) { + writer, closer, aborter, err := NoOutputStream()() + require.NoError(t, err) + require.Nil(t, writer) + require.Nil(t, closer) + require.Nil(t, aborter) +} + +func TestToStdOut(t *testing.T) { + writer, closer, aborter, err := ToStdOut()() + require.NoError(t, err) + require.Same(t, os.Stdout, writer) + + // Should not close StdOut + require.NoError(t, closer.Close()) + _, err = os.Stdout.WriteString("TestToStdOut After Close\n") + require.NoError(t, err) + + aborter() + _, err = os.Stdout.WriteString("TestToStdOut After Abort\n") + require.NoError(t, err) +} + +func TestToAtomicFile(t *testing.T) { + t.Run("Abort", func(t *testing.T) { + dir := t.TempDir() + path := filepath.Join(dir, "test.txt") + writer, closer, aborter, err := ToAtomicFile(path, 0o644)() + defer closer.Close() + require.NoError(t, err) + + expected := []byte("test") + _, err = writer.Write(expected) + require.NoError(t, err) + aborter() + + _, err = os.Stat(path) + require.ErrorIs(t, err, os.ErrNotExist, "Should not have written file") + }) + + t.Run("Close", func(t *testing.T) { + dir := t.TempDir() + path := filepath.Join(dir, "test.txt") + writer, closer, _, err := ToAtomicFile(path, 0o644)() + defer closer.Close() + require.NoError(t, err) + + expected := []byte("test") + _, err = writer.Write(expected) + require.NoError(t, err) + + _, err = os.Stat(path) + require.ErrorIs(t, err, os.ErrNotExist, "Target file should not exist prior to Close") + + require.NoError(t, closer.Close()) + actual, err := os.ReadFile(path) + require.NoError(t, err) + require.Equal(t, expected, actual) + }) +} + +func TestToStdOutOrFileOrNoop(t *testing.T) { + t.Run("EmptyOutputPath", func(t *testing.T) { + writer, _, _, err := ToStdOutOrFileOrNoop("", 0o644)() + require.NoError(t, err) + require.Nil(t, writer, "Should use no output stream") + }) + + t.Run("StdOut", func(t *testing.T) { + writer, _, _, err := ToStdOutOrFileOrNoop("-", 0o644)() + require.NoError(t, err) + require.Same(t, os.Stdout, writer, "Should use std out") + }) + + t.Run("File", func(t *testing.T) { + dir := t.TempDir() + path := filepath.Join(dir, "test.txt") + writer, closer, _, err := ToStdOutOrFileOrNoop(path, 0o644)() + defer closer.Close() + require.NoError(t, err) + + expected := []byte("test") + _, err = writer.Write(expected) + require.NoError(t, err) + require.NoError(t, closer.Close()) + actual, err := os.ReadFile(path) + require.NoError(t, err) + require.Equal(t, expected, actual) + }) +} diff --git a/op-service/jsonutil/json.go b/op-service/jsonutil/json.go index 94dcfd91c2528..5993138595b40 100644 --- a/op-service/jsonutil/json.go +++ b/op-service/jsonutil/json.go @@ -5,12 +5,106 @@ import ( "errors" "fmt" "io" - "os" + + "github.com/BurntSushi/toml" "github.com/ethereum-optimism/optimism/op-service/ioutil" ) +type Decoder interface { + Decode(v interface{}) error +} + +type DecoderFactory func(r io.Reader) Decoder + +type Encoder interface { + Encode(v interface{}) error +} + +type EncoderFactory func(w io.Writer) Encoder + +type jsonDecoder struct { + d *json.Decoder +} + +func newJSONDecoder(r io.Reader) Decoder { + return &jsonDecoder{ + d: json.NewDecoder(r), + } +} + +func (d *jsonDecoder) Decode(v interface{}) error { + if err := d.d.Decode(v); err != nil { + return fmt.Errorf("failed to decode JSON: %w", err) + } + if _, err := d.d.Token(); err != io.EOF { + return errors.New("unexpected trailing data") + } + return nil +} + +type tomlDecoder struct { + r io.Reader +} + +func newTOMLDecoder(r io.Reader) Decoder { + return &tomlDecoder{ + r: r, + } +} + +func (d *tomlDecoder) Decode(v interface{}) error { + if _, err := toml.NewDecoder(d.r).Decode(v); err != nil { + return fmt.Errorf("failed to decode TOML: %w", err) + } + return nil +} + +type jsonEncoder struct { + e *json.Encoder +} + +func newJSONEncoder(w io.Writer) Encoder { + e := json.NewEncoder(w) + e.SetIndent("", " ") + return &jsonEncoder{ + e: e, + } +} + +func (e *jsonEncoder) Encode(v interface{}) error { + if err := e.e.Encode(v); err != nil { + return fmt.Errorf("failed to encode JSON: %w", err) + } + return nil +} + +type tomlEncoder struct { + w io.Writer +} + +func newTOMLEncoder(w io.Writer) Encoder { + return &tomlEncoder{ + w: w, + } +} + +func (e *tomlEncoder) Encode(v interface{}) error { + if err := toml.NewEncoder(e.w).Encode(v); err != nil { + return fmt.Errorf("failed to encode TOML: %w", err) + } + return nil +} + func LoadJSON[X any](inputPath string) (*X, error) { + return load[X](inputPath, newJSONDecoder) +} + +func LoadTOML[X any](inputPath string) (*X, error) { + return load[X](inputPath, newTOMLDecoder) +} + +func load[X any](inputPath string, dec DecoderFactory) (*X, error) { if inputPath == "" { return nil, errors.New("no path specified") } @@ -21,49 +115,37 @@ func LoadJSON[X any](inputPath string) (*X, error) { } defer f.Close() var state X - decoder := json.NewDecoder(f) - if err := decoder.Decode(&state); err != nil { + if err := dec(f).Decode(&state); err != nil { return nil, fmt.Errorf("failed to decode file %q: %w", inputPath, err) } - // We are only expecting 1 JSON object - confirm there is no trailing data - if _, err := decoder.Token(); err != io.EOF { - return nil, fmt.Errorf("unexpected trailing data in file %q", inputPath) - } return &state, nil } -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, perm) - if err != nil { - return fmt.Errorf("failed to open output file: %w", err) - } - // Ensure we close the stream without renaming even if failures occur. - defer func() { - _ = f.Abort() - }() - out = f - // Closing the file causes it to be renamed to the final destination - // so make sure we handle any errors it returns - finish = f.Close - } else { - 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) - } - _, err := out.Write([]byte{'\n'}) +func WriteJSON[X any](value X, target ioutil.OutputTarget) error { + return write(value, target, newJSONEncoder) +} + +func WriteTOML[X any](value X, target ioutil.OutputTarget) error { + return write(value, target, newTOMLEncoder) +} + +func write[X any](value X, target ioutil.OutputTarget, enc EncoderFactory) error { + out, closer, abort, err := target() + if err != nil { + return err + } + if out == nil { + return nil // No output stream selected so skip generating the content entirely + } + defer abort() + if err := enc(out).Encode(value); err != nil { + return fmt.Errorf("failed to encode: %w", err) + } + _, err = out.Write([]byte{'\n'}) if err != nil { return fmt.Errorf("failed to append new-line: %w", err) } - if err := finish(); err != nil { + if err := closer.Close(); err != nil { return fmt.Errorf("failed to finish write: %w", err) } return nil diff --git a/op-service/jsonutil/json_test.go b/op-service/jsonutil/json_test.go index 9a143d0c2579c..36bda167491bf 100644 --- a/op-service/jsonutil/json_test.go +++ b/op-service/jsonutil/json_test.go @@ -2,11 +2,11 @@ package jsonutil import ( "encoding/json" - "fmt" "os" "path/filepath" "testing" + "github.com/ethereum-optimism/optimism/op-service/ioutil" "github.com/stretchr/testify/require" ) @@ -14,7 +14,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, 0o755) + err := WriteJSON(data, ioutil.ToAtomicFile(file, 0o755)) require.NoError(t, err) // Confirm the file is uncompressed @@ -33,7 +33,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, 0o755) + err := WriteJSON(data, ioutil.ToAtomicFile(file, 0o755)) require.NoError(t, err) // Confirm the file isn't raw JSON @@ -87,14 +87,14 @@ func TestLoadJSONWithExtraDataAppended(t *testing.T) { require.NoError(t, err) // Write primary json payload + extra data to the file - err = WriteJSON(file, data, 0o755) + err = WriteJSON(data, ioutil.ToAtomicFile(file, 0o755)) require.NoError(t, err) err = appendDataToFile(file, extraData) require.NoError(t, err) var result *jsonTestData result, err = LoadJSON[jsonTestData](file) - require.ErrorContains(t, err, fmt.Sprintf("unexpected trailing data in file %q", file)) + require.ErrorContains(t, err, "unexpected trailing data") require.Nil(t, result) }) } @@ -130,7 +130,7 @@ func TestLoadJSONWithTrailingWhitespace(t *testing.T) { data := &jsonTestData{A: "yay", B: 3} // Write primary json payload + extra data to the file - err := WriteJSON(file, data, 0o755) + err := WriteJSON(data, ioutil.ToAtomicFile(file, 0o755)) require.NoError(t, err) err = appendDataToFile(file, tc.extraData) require.NoError(t, err) diff --git a/op-service/metrics/cli.go b/op-service/metrics/cli.go index dcbe3d0af2edc..d5c8151b889a7 100644 --- a/op-service/metrics/cli.go +++ b/op-service/metrics/cli.go @@ -37,7 +37,7 @@ func CLIFlags(envPrefix string) []cli.Flag { &cli.StringFlag{ Name: ListenAddrFlagName, Usage: "Metrics listening address", - Value: defaultListenAddr, // TODO(CLI-4159): Switch to 127.0.0.1 + Value: defaultListenAddr, // TODO: Switch to 127.0.0.1 EnvVars: opservice.PrefixEnvVar(envPrefix, "METRICS_ADDR"), }, &cli.IntFlag{ diff --git a/op-service/metrics/http.go b/op-service/metrics/http.go index 8640fe02a6f20..60609c563dca9 100644 --- a/op-service/metrics/http.go +++ b/op-service/metrics/http.go @@ -65,7 +65,7 @@ var LatencyBuckets = []float64{.025, .05, .1, .25, .5, 1, 2.5, 5, 10, 25, 50, 10 func NewPromHTTPRecorder(r *prometheus.Registry, ns string) HTTPRecorder { return &PromHTTPRecorder{ - // TODO(INF-509): remove this in the future when services opted in to HTTPRequestLatency + // TODO: remove this in the future when services opted in to HTTPRequestLatency HTTPRequestDuration: promauto.With(r).NewHistogramVec(prometheus.HistogramOpts{ Namespace: ns, Name: "http_request_duration_ms", @@ -104,7 +104,7 @@ func NewPromHTTPRecorder(r *prometheus.Registry, ns string) HTTPRecorder { } func (p *PromHTTPRecorder) RecordHTTPRequestDuration(params *HTTPParams, dur time.Duration) { - // TODO(INF-509): remove this in the future when services opted in to new metric + // TODO: remove this in the future when services opted in to new metric p.HTTPRequestDuration.WithLabelValues(params.Method, strconv.Itoa(params.StatusCode)). Observe(float64(dur.Milliseconds())) diff --git a/op-service/opio/interrupts.go b/op-service/opio/interrupts.go deleted file mode 100644 index cd1b8485791d3..0000000000000 --- a/op-service/opio/interrupts.go +++ /dev/null @@ -1,114 +0,0 @@ -package opio - -import ( - "context" - "os" - "os/signal" - "syscall" -) - -// DefaultInterruptSignals is a set of default interrupt signals. -var DefaultInterruptSignals = []os.Signal{ - os.Interrupt, - os.Kill, - syscall.SIGTERM, - syscall.SIGQUIT, -} - -// BlockOnInterrupts blocks until a SIGTERM is received. -// Passing in signals will override the default signals. -func BlockOnInterrupts(signals ...os.Signal) { - if len(signals) == 0 { - signals = DefaultInterruptSignals - } - interruptChannel := make(chan os.Signal, 1) - signal.Notify(interruptChannel, signals...) - <-interruptChannel -} - -// BlockOnInterruptsContext blocks until a SIGTERM is received. -// Passing in signals will override the default signals. -// The function will stop blocking if the context is closed. -func BlockOnInterruptsContext(ctx context.Context, signals ...os.Signal) { - if len(signals) == 0 { - signals = DefaultInterruptSignals - } - interruptChannel := make(chan os.Signal, 1) - signal.Notify(interruptChannel, signals...) - select { - case <-interruptChannel: - case <-ctx.Done(): - signal.Stop(interruptChannel) - } -} - -type interruptContextKeyType struct{} - -var blockerContextKey = interruptContextKeyType{} - -type interruptCatcher struct { - incoming chan os.Signal -} - -// Block blocks until either an interrupt signal is received, or the context is cancelled. -// No error is returned on interrupt. -func (c *interruptCatcher) Block(ctx context.Context) { - select { - case <-c.incoming: - case <-ctx.Done(): - } -} - -// WithInterruptBlocker attaches an interrupt handler to the context, -// which continues to receive signals after every block. -// This helps functions block on individual consecutive interrupts. -func WithInterruptBlocker(ctx context.Context) context.Context { - if ctx.Value(blockerContextKey) != nil { // already has an interrupt handler - return ctx - } - catcher := &interruptCatcher{ - incoming: make(chan os.Signal, 10), - } - signal.Notify(catcher.incoming, DefaultInterruptSignals...) - - return context.WithValue(ctx, blockerContextKey, BlockFn(catcher.Block)) -} - -// WithBlocker overrides the interrupt blocker value, -// e.g. to insert a block-function for testing CLI shutdown without actual process signals. -func WithBlocker(ctx context.Context, fn BlockFn) context.Context { - return context.WithValue(ctx, blockerContextKey, fn) -} - -// BlockFn simply blocks until the implementation of the blocker interrupts it, or till the given context is cancelled. -type BlockFn func(ctx context.Context) - -// BlockerFromContext returns a BlockFn that blocks on interrupts when called. -func BlockerFromContext(ctx context.Context) BlockFn { - v := ctx.Value(blockerContextKey) - if v == nil { - return nil - } - return v.(BlockFn) -} - -// CancelOnInterrupt cancels the given context on interrupt. -// If a BlockFn is attached to the context, this is used as interrupt-blocking. -// If not, then the context blocks on a manually handled interrupt signal. -func CancelOnInterrupt(ctx context.Context) context.Context { - inner, cancel := context.WithCancel(ctx) - - blockOnInterrupt := BlockerFromContext(ctx) - if blockOnInterrupt == nil { - blockOnInterrupt = func(ctx context.Context) { - BlockOnInterruptsContext(ctx) // default signals - } - } - - go func() { - blockOnInterrupt(ctx) - cancel() - }() - - return inner -} diff --git a/op-service/oppprof/cli.go b/op-service/oppprof/cli.go index d6ccb8566960c..6c2c33a147114 100644 --- a/op-service/oppprof/cli.go +++ b/op-service/oppprof/cli.go @@ -76,7 +76,7 @@ func CLIFlagsWithCategory(envPrefix string, category string) []cli.Flag { &cli.StringFlag{ Name: ListenAddrFlagName, Usage: "pprof listening address", - Value: defaultListenAddr, // TODO(CLI-4159): Switch to 127.0.0.1 + Value: defaultListenAddr, // TODO: Switch to 127.0.0.1 EnvVars: opservice.PrefixEnvVar(envPrefix, "PPROF_ADDR"), Category: category, }, diff --git a/op-service/predeploys/addresses.go b/op-service/predeploys/addresses.go index a03fcf29188a5..0b69df3bb8343 100644 --- a/op-service/predeploys/addresses.go +++ b/op-service/predeploys/addresses.go @@ -27,6 +27,8 @@ const ( EAS = "0x4200000000000000000000000000000000000021" CrossL2Inbox = "0x4200000000000000000000000000000000000022" L2toL2CrossDomainMessenger = "0x4200000000000000000000000000000000000023" + SuperchainWETH = "0x4200000000000000000000000000000000000024" + ETHLiquidity = "0x4200000000000000000000000000000000000025" Create2Deployer = "0x13b0D85CcB8bf860b6b79AF3029fCA081AE9beF2" MultiCall3 = "0xcA11bde05977b3631167028862bE2a173976CA11" Safe_v130 = "0x69f4D1788e39c87893C980c06EdF4b7f686e2938" @@ -64,6 +66,8 @@ var ( EASAddr = common.HexToAddress(EAS) CrossL2InboxAddr = common.HexToAddress(CrossL2Inbox) L2toL2CrossDomainMessengerAddr = common.HexToAddress(L2toL2CrossDomainMessenger) + SuperchainWETHAddr = common.HexToAddress(SuperchainWETH) + ETHLiquidityAddr = common.HexToAddress(ETHLiquidity) Create2DeployerAddr = common.HexToAddress(Create2Deployer) MultiCall3Addr = common.HexToAddress(MultiCall3) Safe_v130Addr = common.HexToAddress(Safe_v130) @@ -95,6 +99,8 @@ func init() { Predeploys["L1Block"] = &Predeploy{Address: L1BlockAddr} Predeploys["CrossL2Inbox"] = &Predeploy{Address: CrossL2InboxAddr} Predeploys["L2toL2CrossDomainMessenger"] = &Predeploy{Address: L2toL2CrossDomainMessengerAddr} + Predeploys["SuperchainWETH"] = &Predeploy{Address: SuperchainWETHAddr} + Predeploys["ETHLiquidity"] = &Predeploy{Address: ETHLiquidityAddr} Predeploys["GovernanceToken"] = &Predeploy{ Address: GovernanceTokenAddr, ProxyDisabled: true, diff --git a/op-service/rethdb-reader/.gitignore b/op-service/rethdb-reader/.gitignore deleted file mode 100644 index 360eaff0efc3d..0000000000000 --- a/op-service/rethdb-reader/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -# Target -target/ - -# Bindings -rdb.h - -# Testdata DB -testdata/db diff --git a/op-service/rethdb-reader/Cargo.lock b/op-service/rethdb-reader/Cargo.lock deleted file mode 100644 index 0b66063c3372b..0000000000000 --- a/op-service/rethdb-reader/Cargo.lock +++ /dev/null @@ -1,4909 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "aead" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877" -dependencies = [ - "generic-array", -] - -[[package]] -name = "aes" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" -dependencies = [ - "cfg-if", - "cipher 0.3.0", - "cpufeatures", - "ctr 0.8.0", - "opaque-debug", -] - -[[package]] -name = "aes" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" -dependencies = [ - "cfg-if", - "cipher 0.4.4", - "cpufeatures", -] - -[[package]] -name = "aes-gcm" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc3be92e19a7ef47457b8e6f90707e12b6ac5d20c6f3866584fa3be0787d839f" -dependencies = [ - "aead", - "aes 0.7.5", - "cipher 0.3.0", - "ctr 0.7.0", - "ghash", - "subtle", -] - -[[package]] -name = "ahash" -version = "0.8.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b79b82693f705137f8fb9b37871d99e4f9a7df12b917eed79c3d3954830a60b" -dependencies = [ - "cfg-if", - "once_cell", - "version_check", - "zerocopy", -] - -[[package]] -name = "aho-corasick" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" -dependencies = [ - "memchr", -] - -[[package]] -name = "allocator-api2" -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.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef197eb250c64962003cb08b90b17f0882c192f4a6f2f544809d424fd7cb0e7d" -dependencies = [ - "alloy-rlp", - "bytes", - "cfg-if", - "const-hex", - "derive_more", - "getrandom 0.2.12", - "hex-literal", - "itoa", - "k256", - "keccak-asm", - "proptest", - "rand 0.8.5", - "ruint", - "serde", - "tiny-keccak", -] - -[[package]] -name = "alloy-rlp" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d58d9f5da7b40e9bfff0b7e7816700be4019db97d4b6359fe7f94a9e22e42ac" -dependencies = [ - "alloy-rlp-derive", - "arrayvec", - "bytes", -] - -[[package]] -name = "alloy-rlp-derive" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a047897373be4bbb0224c1afdabca92648dc57a9c9ef6e7b0be3aff7a859c83" -dependencies = [ - "proc-macro2", - "quote", - "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.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82e92100dee7fd1e44abbe0ef6607f18758cf0ad4e483f4c65ff5c8d85428a6d" -dependencies = [ - "const-hex", - "dunce", - "heck", - "indexmap 2.2.3", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 2.0.52", - "syn-solidity", - "tiny-keccak", -] - -[[package]] -name = "alloy-sol-types" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e7c6a8c492b1d6a4f92a8fc6a13cf39473978dd7d459d7221969ce5a73d97cd" -dependencies = [ - "alloy-primitives", - "alloy-sol-macro", - "const-hex", - "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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" - -[[package]] -name = "android_system_properties" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" -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.80" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1" - -[[package]] -name = "aquamarine" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21cc1548309245035eb18aa7f0967da6bc65587005170c56e6ef2788a4cf3f4e" -dependencies = [ - "include_dir", - "itertools 0.10.5", - "proc-macro-error", - "proc-macro2", - "quote", - "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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b3235cc41ee7a12aaaf2c575a2ad7b46713a8a50bda2fc3b003a04845c05dd6" -dependencies = [ - "ark-ff-asm 0.3.0", - "ark-ff-macros 0.3.0", - "ark-serialize 0.3.0", - "ark-std 0.3.0", - "derivative", - "num-bigint", - "num-traits", - "paste", - "rustc_version 0.3.3", - "zeroize", -] - -[[package]] -name = "ark-ff" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" -dependencies = [ - "ark-ff-asm 0.4.2", - "ark-ff-macros 0.4.2", - "ark-serialize 0.4.2", - "ark-std 0.4.0", - "derivative", - "digest 0.10.7", - "itertools 0.10.5", - "num-bigint", - "num-traits", - "paste", - "rustc_version 0.4.0", - "zeroize", -] - -[[package]] -name = "ark-ff-asm" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db02d390bf6643fb404d3d22d31aee1c4bc4459600aef9113833d17e786c6e44" -dependencies = [ - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ark-ff-asm" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" -dependencies = [ - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ark-ff-macros" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2fd794a08ccb318058009eefdf15bcaaaaf6f8161eb3345f907222bac38b20" -dependencies = [ - "num-bigint", - "num-traits", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ark-ff-macros" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" -dependencies = [ - "num-bigint", - "num-traits", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ark-serialize" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6c2b318ee6e10f8c2853e73a83adc0ccb88995aa978d8a3408d492ab2ee671" -dependencies = [ - "ark-std 0.3.0", - "digest 0.9.0", -] - -[[package]] -name = "ark-serialize" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" -dependencies = [ - "ark-std 0.4.0", - "digest 0.10.7", - "num-bigint", -] - -[[package]] -name = "ark-std" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c" -dependencies = [ - "num-traits", - "rand 0.8.5", -] - -[[package]] -name = "ark-std" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" -dependencies = [ - "num-traits", - "rand 0.8.5", -] - -[[package]] -name = "arrayvec" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" - -[[package]] -name = "async-trait" -version = "0.1.77" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.52", -] - -[[package]] -name = "attohttpc" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d9a9bf8b79a749ee0b911b91b671cc2b6c670bdbc7e3dfd537576ddc94bb2a2" -dependencies = [ - "http", - "log", - "url", -] - -[[package]] -name = "aurora-engine-modexp" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfacad86e9e138fca0670949eb8ed4ffdf73a55bded8887efe0863cd1a3a6f70" -dependencies = [ - "hex", - "num", -] - -[[package]] -name = "auto_impl" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.52", -] - -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - -[[package]] -name = "backtrace" -version = "0.3.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - -[[package]] -name = "base16ct" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" - -[[package]] -name = "base64" -version = "0.21.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" - -[[package]] -name = "base64ct" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" - -[[package]] -name = "beef" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" -dependencies = [ - "serde", -] - -[[package]] -name = "bincode" -version = "1.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" -dependencies = [ - "serde", -] - -[[package]] -name = "bindgen" -version = "0.69.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" -dependencies = [ - "bitflags 2.4.2", - "cexpr", - "clang-sys", - "itertools 0.12.1", - "lazy_static", - "lazycell", - "proc-macro2", - "quote", - "regex", - "rustc-hash", - "shlex", - "syn 2.0.52", -] - -[[package]] -name = "binout" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b60b1af88a588fca5fe424ae7d735bc52814f80ff57614f57043cc4e2024f2ea" - -[[package]] -name = "bit-set" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" -dependencies = [ - "bit-vec", -] - -[[package]] -name = "bit-vec" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" -dependencies = [ - "serde", -] - -[[package]] -name = "bitm" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31b9ea263f0faf826a1c9de0e8bf8f32f5986c05f5e3abcf6bcde74616009586" -dependencies = [ - "dyn_size_of", -] - -[[package]] -name = "bitvec" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" -dependencies = [ - "funty", - "radium", - "serde", - "tap", - "wyz", -] - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - -[[package]] -name = "block-padding" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" -dependencies = [ - "generic-array", -] - -[[package]] -name = "blst" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c94087b935a822949d3291a9989ad2b2051ea141eda0fd4e478a75f6aa3e604b" -dependencies = [ - "cc", - "glob", - "threadpool", - "zeroize", -] - -[[package]] -name = "bumpalo" -version = "3.15.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea184aa71bb362a1157c896979544cc23974e08fd265f29ea96b59f0b4a555b" - -[[package]] -name = "byte-slice-cast" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - -[[package]] -name = "bytes" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" -dependencies = [ - "serde", -] - -[[package]] -name = "c-kzg" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94a4bc5367b6284358d2a6a6a1dc2d92ec4b86034561c3b9d3341909752fd848" -dependencies = [ - "blst", - "cc", - "glob", - "hex", - "libc", - "serde", -] - -[[package]] -name = "cc" -version = "1.0.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" -dependencies = [ - "jobserver", - "libc", -] - -[[package]] -name = "cexpr" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" -dependencies = [ - "nom", -] - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "chrono" -version = "0.4.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bc015644b92d5890fab7489e49d21f879d5c990186827d42ec511919404f38b" -dependencies = [ - "android-tzdata", - "iana-time-zone", - "js-sys", - "num-traits", - "serde", - "wasm-bindgen", - "windows-targets 0.52.4", -] - -[[package]] -name = "cipher" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" -dependencies = [ - "generic-array", -] - -[[package]] -name = "cipher" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" -dependencies = [ - "crypto-common", - "inout", -] - -[[package]] -name = "clang-sys" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1" -dependencies = [ - "glob", - "libc", - "libloading", -] - -[[package]] -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 = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" - -[[package]] -name = "codecs-derive" -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.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.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efbd12d49ab0eaf8193ba9175e45f56bbc2e4b27d57b8cfe62aa47942a46b9a9" -dependencies = [ - "cfg-if", - "cpufeatures", - "hex", - "proptest", - "serde", -] - -[[package]] -name = "const-oid" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" - -[[package]] -name = "convert_case" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" - -[[package]] -name = "convert_case" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" -dependencies = [ - "unicode-segmentation", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" - -[[package]] -name = "cpufeatures" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" -dependencies = [ - "libc", -] - -[[package]] -name = "crc" -version = "3.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86ec7a15cbe22e59248fc7eadb1907dab5ba09372595da4d73dd805ed4417dfe" -dependencies = [ - "crc-catalog", -] - -[[package]] -name = "crc-catalog" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" - -[[package]] -name = "crossbeam-channel" -version = "0.5.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" - -[[package]] -name = "crunchy" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" - -[[package]] -name = "crypto-bigint" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" -dependencies = [ - "generic-array", - "rand_core 0.6.4", - "subtle", - "zeroize", -] - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "ctr" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a232f92a03f37dd7d7dd2adc67166c77e9cd88de5b019b9a9eecfaeaf7bfd481" -dependencies = [ - "cipher 0.3.0", -] - -[[package]] -name = "ctr" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "049bb91fb4aaf0e3c7efa6cd5ef877dbbbd15b39dad06d9948de4ec8a75761ea" -dependencies = [ - "cipher 0.3.0", -] - -[[package]] -name = "ctr" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" -dependencies = [ - "cipher 0.4.4", -] - -[[package]] -name = "cuckoofilter" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b810a8449931679f64cd7eef1bbd0fa315801b6d5d9cdc1ace2804d6529eee18" -dependencies = [ - "byteorder", - "fnv", - "rand 0.7.3", - "serde", - "serde_bytes", - "serde_derive", -] - -[[package]] -name = "curve25519-dalek" -version = "4.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" -dependencies = [ - "cfg-if", - "cpufeatures", - "curve25519-dalek-derive", - "digest 0.10.7", - "fiat-crypto", - "rustc_version 0.4.0", - "subtle", - "zeroize", -] - -[[package]] -name = "curve25519-dalek-derive" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.52", -] - -[[package]] -name = "darling" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d706e75d87e35569db781a9b5e2416cff1236a47ed380831f959382ccd5f858" -dependencies = [ - "darling_core 0.10.2", - "darling_macro 0.10.2", -] - -[[package]] -name = "darling" -version = "0.20.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" -dependencies = [ - "darling_core 0.20.8", - "darling_macro 0.20.8", -] - -[[package]] -name = "darling_core" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0c960ae2da4de88a91b2d920c2a7233b400bc33cb28453a2987822d8392519b" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim 0.9.3", - "syn 1.0.109", -] - -[[package]] -name = "darling_core" -version = "0.20.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim 0.10.0", - "syn 2.0.52", -] - -[[package]] -name = "darling_macro" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72" -dependencies = [ - "darling_core 0.10.2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "darling_macro" -version = "0.20.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" -dependencies = [ - "darling_core 0.20.8", - "quote", - "syn 2.0.52", -] - -[[package]] -name = "dashmap" -version = "5.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" -dependencies = [ - "cfg-if", - "hashbrown 0.14.3", - "lock_api", - "once_cell", - "parking_lot_core 0.9.9", -] - -[[package]] -name = "data-encoding" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" - -[[package]] -name = "delay_map" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4355c25cbf99edcb6b4a0e906f6bdc6956eda149e84455bea49696429b2f8e8" -dependencies = [ - "futures", - "tokio-util", -] - -[[package]] -name = "der" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" -dependencies = [ - "const-oid", - "zeroize", -] - -[[package]] -name = "deranged" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" -dependencies = [ - "powerfmt", - "serde", -] - -[[package]] -name = "derivative" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "derive_builder" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2658621297f2cf68762a6f7dc0bb7e1ff2cfd6583daef8ee0fed6f7ec468ec0" -dependencies = [ - "darling 0.10.2", - "derive_builder_core", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "derive_builder_core" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2791ea3e372c8495c0bc2033991d76b512cd799d07491fbd6890124db9458bef" -dependencies = [ - "darling 0.10.2", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "derive_more" -version = "0.99.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" -dependencies = [ - "convert_case 0.4.0", - "proc-macro2", - "quote", - "rustc_version 0.4.0", - "syn 1.0.109", -] - -[[package]] -name = "digest" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" -dependencies = [ - "generic-array", -] - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer", - "const-oid", - "crypto-common", - "subtle", -] - -[[package]] -name = "discv5" -version = "0.3.1" -source = "git+https://github.com/sigp/discv5?rev=f289bbd4c57d499bb1bdb393af3c249600a1c662#f289bbd4c57d499bb1bdb393af3c249600a1c662" -dependencies = [ - "aes 0.7.5", - "aes-gcm", - "arrayvec", - "delay_map", - "enr", - "fnv", - "futures", - "hashlink", - "hex", - "hkdf", - "lazy_static", - "lru", - "more-asserts", - "parking_lot 0.11.2", - "rand 0.8.5", - "rlp", - "smallvec", - "socket2 0.4.10", - "tokio", - "tracing", - "tracing-subscriber", - "uint", - "zeroize", -] - -[[package]] -name = "dns-lookup" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53ecafc952c4528d9b51a458d1a8904b81783feff9fde08ab6ed2545ff396872" -dependencies = [ - "cfg-if", - "libc", - "socket2 0.4.10", - "winapi", -] - -[[package]] -name = "dunce" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" - -[[package]] -name = "dyn_size_of" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33d4f78a40b1ec35bf8cafdaaf607ba2f773c366b0b3bda48937cacd7a8d5134" - -[[package]] -name = "ecdsa" -version = "0.16.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" -dependencies = [ - "der", - "digest 0.10.7", - "elliptic-curve", - "rfc6979", - "signature", - "spki", -] - -[[package]] -name = "ed25519" -version = "2.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" -dependencies = [ - "pkcs8", - "signature", -] - -[[package]] -name = "ed25519-dalek" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" -dependencies = [ - "curve25519-dalek", - "ed25519", - "rand_core 0.6.4", - "serde", - "sha2", - "subtle", - "zeroize", -] - -[[package]] -name = "educe" -version = "0.4.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f0042ff8246a363dbe77d2ceedb073339e85a804b9a47636c6e016a9a32c05f" -dependencies = [ - "enum-ordinalize", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "either" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" - -[[package]] -name = "elliptic-curve" -version = "0.13.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" -dependencies = [ - "base16ct", - "crypto-bigint", - "digest 0.10.7", - "ff", - "generic-array", - "group", - "pkcs8", - "rand_core 0.6.4", - "sec1", - "subtle", - "zeroize", -] - -[[package]] -name = "endian-type" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" - -[[package]] -name = "enr" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe81b5c06ecfdbc71dd845216f225f53b62a10cb8a16c946836a3467f701d05b" -dependencies = [ - "base64", - "bytes", - "ed25519-dalek", - "hex", - "k256", - "log", - "rand 0.8.5", - "rlp", - "secp256k1 0.27.0", - "serde", - "sha3", - "zeroize", -] - -[[package]] -name = "enum-as-inner" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "570d109b813e904becc80d8d5da38376818a143348413f7149f1340fe04754d4" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "enum-ordinalize" -version = "3.1.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bf1fa3f06bbff1ea5b1a9c7b14aa992a39657db60a2759457328d7e058f49ee" -dependencies = [ - "num-bigint", - "num-traits", - "proc-macro2", - "quote", - "syn 2.0.52", -] - -[[package]] -name = "enumn" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fd000fd6988e73bbe993ea3db9b1aa64906ab88766d654973924340c8cddb42" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.52", -] - -[[package]] -name = "equivalent" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" - -[[package]] -name = "errno" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "eyre" -version = "0.6.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" -dependencies = [ - "indenter", - "once_cell", -] - -[[package]] -name = "fastrand" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" - -[[package]] -name = "fastrlp" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "139834ddba373bbdd213dffe02c8d110508dcf1726c2be27e8d1f7d7e1856418" -dependencies = [ - "arrayvec", - "auto_impl", - "bytes", -] - -[[package]] -name = "ff" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" -dependencies = [ - "rand_core 0.6.4", - "subtle", -] - -[[package]] -name = "fiat-crypto" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1676f435fc1dadde4d03e43f5d62b259e1ce5f40bd4ffb21db2b42ebe59c1382" - -[[package]] -name = "fixed-hash" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" -dependencies = [ - "byteorder", - "rand 0.8.5", - "rustc-hex", - "static_assertions", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "form_urlencoded" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "funty" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" - -[[package]] -name = "futures" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" - -[[package]] -name = "futures-executor" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-io" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" - -[[package]] -name = "futures-macro" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.52", -] - -[[package]] -name = "futures-sink" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" - -[[package]] -name = "futures-task" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" - -[[package]] -name = "futures-util" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "slab", -] - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", - "zeroize", -] - -[[package]] -name = "getrandom" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.9.0+wasi-snapshot-preview1", -] - -[[package]] -name = "getrandom" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.11.0+wasi-snapshot-preview1", -] - -[[package]] -name = "ghash" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1583cc1656d7839fd3732b80cf4f38850336cdb9b8ded1cd399ca62958de3c99" -dependencies = [ - "opaque-debug", - "polyval", -] - -[[package]] -name = "gimli" -version = "0.28.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" - -[[package]] -name = "glob" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" - -[[package]] -name = "group" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" -dependencies = [ - "ff", - "rand_core 0.6.4", - "subtle", -] - -[[package]] -name = "h2" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http", - "indexmap 2.2.3", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - -[[package]] -name = "hashbrown" -version = "0.14.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" -dependencies = [ - "ahash", - "allocator-api2", - "serde", -] - -[[package]] -name = "hashlink" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" -dependencies = [ - "hashbrown 0.14.3", -] - -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" - -[[package]] -name = "hermit-abi" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "379dada1584ad501b383485dd706b8afb7a70fcbc7f4da7d780638a5a6124a60" - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" -dependencies = [ - "serde", -] - -[[package]] -name = "hex-literal" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" - -[[package]] -name = "hkdf" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" -dependencies = [ - "hmac", -] - -[[package]] -name = "hmac" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" -dependencies = [ - "digest 0.10.7", -] - -[[package]] -name = "http" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "http-body" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" -dependencies = [ - "bytes", - "http", - "pin-project-lite", -] - -[[package]] -name = "httparse" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" - -[[package]] -name = "httpdate" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" - -[[package]] -name = "hyper" -version = "0.14.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" -dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "socket2 0.4.10", - "tokio", - "tower-service", - "tracing", - "want", -] - -[[package]] -name = "hyper-system-resolver" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eea26c5d0b6ab9d72219f65000af310f042a740926f7b2fa3553e774036e2e7" -dependencies = [ - "derive_builder", - "dns-lookup", - "hyper", - "tokio", - "tower-service", - "tracing", -] - -[[package]] -name = "iana-time-zone" -version = "0.1.60" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "wasm-bindgen", - "windows-core", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" -dependencies = [ - "cc", -] - -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - -[[package]] -name = "idna" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" -dependencies = [ - "matches", - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "idna" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -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", - "http", - "hyper", - "log", - "rand 0.8.5", - "tokio", - "url", - "xmltree", -] - -[[package]] -name = "impl-codec" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" -dependencies = [ - "parity-scale-codec", -] - -[[package]] -name = "impl-trait-for-tuples" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "include_dir" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18762faeff7122e89e0857b02f7ce6fcc0d101d5e9ad2ad7846cc01d61b7f19e" -dependencies = [ - "include_dir_macros", -] - -[[package]] -name = "include_dir_macros" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b139284b5cf57ecfa712bcc66950bb635b31aff41c188e8a4cfc758eca374a3f" -dependencies = [ - "proc-macro2", - "quote", -] - -[[package]] -name = "indenter" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" - -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", - "serde", -] - -[[package]] -name = "indexmap" -version = "2.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233cf39063f058ea2caae4091bf4a3ef70a653afbc026f5c4a4135d114e3c177" -dependencies = [ - "equivalent", - "hashbrown 0.14.3", - "serde", -] - -[[package]] -name = "inout" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" -dependencies = [ - "block-padding", - "generic-array", -] - -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "ipnet" -version = "2.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" - -[[package]] -name = "itertools" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" -dependencies = [ - "either", -] - -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" - -[[package]] -name = "jobserver" -version = "0.1.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab46a6e9526ddef3ae7f787c06f0f2600639ba80ea3eade3d8e670a2230f51d6" -dependencies = [ - "libc", -] - -[[package]] -name = "js-sys" -version = "0.3.68" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "406cda4b368d531c842222cf9d2600a9a4acce8d29423695379c6868a143a9ee" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "jsonrpsee-types" -version = "0.20.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5be0be325642e850ed0bdff426674d2e66b2b7117c9be23a7caef68a2902b7d9" -dependencies = [ - "anyhow", - "beef", - "serde", - "serde_json", - "thiserror", - "tracing", -] - -[[package]] -name = "k256" -version = "0.13.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" -dependencies = [ - "cfg-if", - "ecdsa", - "elliptic-curve", - "once_cell", - "sha2", - "signature", -] - -[[package]] -name = "keccak" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -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", -] - -[[package]] -name = "lazycell" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" - -[[package]] -name = "libc" -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 = "f36115160c57e8529781b4183c2bb51fdc1f6d6d1ed345591d84be7703befb3c" -dependencies = [ - "cc", -] - -[[package]] -name = "libloading" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" -dependencies = [ - "cfg-if", - "windows-sys 0.48.0", -] - -[[package]] -name = "libm" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" - -[[package]] -name = "linked-hash-map" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" - -[[package]] -name = "linked_hash_set" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47186c6da4d81ca383c7c47c1bfc80f4b95f4720514d860a5407aaf4233f9588" -dependencies = [ - "linked-hash-map", -] - -[[package]] -name = "linux-raw-sys" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" - -[[package]] -name = "lock_api" -version = "0.4.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" - -[[package]] -name = "lru" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc" -dependencies = [ - "hashbrown 0.14.3", -] - -[[package]] -name = "lz4_flex" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "912b45c753ff5f7f5208307e8ace7d2a2e30d024e26d3509f3dce546c044ce15" - -[[package]] -name = "matchers" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" -dependencies = [ - "regex-automata 0.1.10", -] - -[[package]] -name = "matches" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" - -[[package]] -name = "memchr" -version = "2.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" - -[[package]] -name = "memmap2" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f49388d20533534cd19360ad3d6a7dadc885944aa802ba3995040c5ec11288c6" -dependencies = [ - "libc", -] - -[[package]] -name = "metrics" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fde3af1a009ed76a778cb84fdef9e7dbbdf5775ae3e4cc1f434a6a307f6f76c5" -dependencies = [ - "ahash", - "metrics-macros", - "portable-atomic", -] - -[[package]] -name = "metrics-macros" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b4faf00617defe497754acde3024865bc143d44a86799b24e191ecff91354f" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.52", -] - -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - -[[package]] -name = "miniz_oxide" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" -dependencies = [ - "adler", -] - -[[package]] -name = "mio" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" -dependencies = [ - "libc", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.48.0", -] - -[[package]] -name = "modular-bitfield" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a53d79ba8304ac1c4f9eb3b9d281f21f7be9d4626f72ce7df4ad8fbde4f38a74" -dependencies = [ - "modular-bitfield-impl", - "static_assertions", -] - -[[package]] -name = "modular-bitfield-impl" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a7d5f7076603ebc68de2dc6a650ec331a062a13abaa346975be747bbfa4b789" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "more-asserts" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fafa6961cabd9c63bcd77a45d7e3b7f3b552b70417831fb0f56db717e72407e" - -[[package]] -name = "nibble_vec" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a5d83df9f36fe23f0c3648c6bbb8b0298bb5f1939c8f2704431371f4b84d43" -dependencies = [ - "smallvec", -] - -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - -[[package]] -name = "nu-ansi-term" -version = "0.46.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" -dependencies = [ - "overload", - "winapi", -] - -[[package]] -name = "num" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" -dependencies = [ - "num-bigint", - "num-complex", - "num-integer", - "num-iter", - "num-rational", - "num-traits", -] - -[[package]] -name = "num-bigint" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-complex" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -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.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-iter" -version = "0.1.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" -dependencies = [ - "autocfg", - "num-bigint", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" -dependencies = [ - "autocfg", - "libm", -] - -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "num_enum" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845" -dependencies = [ - "num_enum_derive", -] - -[[package]] -name = "num_enum_derive" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" -dependencies = [ - "proc-macro-crate 3.1.0", - "proc-macro2", - "quote", - "syn 2.0.52", -] - -[[package]] -name = "nybbles" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95f06be0417d97f81fe4e5c86d7d01b392655a9cac9c19a848aa033e18937b23" -dependencies = [ - "alloy-rlp", - "const-hex", - "proptest", - "serde", - "smallvec", -] - -[[package]] -name = "object" -version = "0.32.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" -dependencies = [ - "memchr", -] - -[[package]] -name = "once_cell" -version = "1.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" - -[[package]] -name = "opaque-debug" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" - -[[package]] -name = "overload" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" - -[[package]] -name = "page_size" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30d5b2194ed13191c1999ae0704b7839fb18384fa22e49b57eeaa97d79ce40da" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "parity-scale-codec" -version = "3.6.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "881331e34fa842a2fb61cc2db9643a8fedc615e47cfcc52597d1af0db9a7e8fe" -dependencies = [ - "arrayvec", - "bitvec", - "byte-slice-cast", - "bytes", - "impl-trait-for-tuples", - "parity-scale-codec-derive", - "serde", -] - -[[package]] -name = "parity-scale-codec-derive" -version = "3.6.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be30eaf4b0a9fba5336683b38de57bb86d179a35862ba6bfcf57625d006bde5b" -dependencies = [ - "proc-macro-crate 2.0.0", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "parking_lot" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" -dependencies = [ - "instant", - "lock_api", - "parking_lot_core 0.8.6", -] - -[[package]] -name = "parking_lot" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" -dependencies = [ - "lock_api", - "parking_lot_core 0.9.9", -] - -[[package]] -name = "parking_lot_core" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" -dependencies = [ - "cfg-if", - "instant", - "libc", - "redox_syscall 0.2.16", - "smallvec", - "winapi", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall 0.4.1", - "smallvec", - "windows-targets 0.48.5", -] - -[[package]] -name = "paste" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" - -[[package]] -name = "percent-encoding" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" - -[[package]] -name = "pest" -version = "2.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "219c0dcc30b6a27553f9cc242972b67f75b60eb0db71f0b5462f38b058c41546" -dependencies = [ - "memchr", - "thiserror", - "ucd-trie", -] - -[[package]] -name = "ph" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b7b74d575d7c11fb653fae69688be5206cafc1ead33c01ce61ac7f36eae45b" -dependencies = [ - "binout", - "bitm", - "dyn_size_of", - "rayon", - "wyhash", -] - -[[package]] -name = "pin-project" -version = "1.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0302c4a0442c456bd56f841aee5c3bfd17967563f6fadc9ceb9f9c23cf3807e0" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266c042b60c9c76b8d53061e52b2e0d1116abc57cefc8c5cd671619a56ac3690" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.52", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "pkcs8" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" -dependencies = [ - "der", - "spki", -] - -[[package]] -name = "pkg-config" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" - -[[package]] -name = "polyval" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8419d2b623c7c0896ff2d5d96e2cb4ede590fed28fcc34934f4c33c036e620a1" -dependencies = [ - "cfg-if", - "cpufeatures", - "opaque-debug", - "universal-hash", -] - -[[package]] -name = "portable-atomic" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" - -[[package]] -name = "powerfmt" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" - -[[package]] -name = "ppv-lite86" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" - -[[package]] -name = "primitive-types" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" -dependencies = [ - "fixed-hash", - "impl-codec", - "uint", -] - -[[package]] -name = "proc-macro-crate" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8" -dependencies = [ - "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]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - -[[package]] -name = "proc-macro2" -version = "1.0.78" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "proptest" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31b476131c3c86cb68032fdc5cb6d5a1045e3e42d96b69fa599fd77701e1f5bf" -dependencies = [ - "bit-set", - "bit-vec", - "bitflags 2.4.2", - "lazy_static", - "num-traits", - "rand 0.8.5", - "rand_chacha 0.3.1", - "rand_xorshift", - "regex-syntax 0.8.2", - "rusty-fork", - "tempfile", - "unarray", -] - -[[package]] -name = "public-ip" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b4c40db5262d93298c363a299f8bc1b3a956a78eecddba3bc0e58b76e2f419a" -dependencies = [ - "dns-lookup", - "futures-core", - "futures-util", - "http", - "hyper", - "hyper-system-resolver", - "pin-project-lite", - "thiserror", - "tokio", - "tracing", - "tracing-futures", - "trust-dns-client", - "trust-dns-proto", -] - -[[package]] -name = "quick-error" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" - -[[package]] -name = "quote" -version = "1.0.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "radium" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" - -[[package]] -name = "radix_trie" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c069c179fcdc6a2fe24d8d18305cf085fdbd4f922c041943e203685d6a1c58fd" -dependencies = [ - "endian-type", - "nibble_vec", -] - -[[package]] -name = "rand" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom 0.1.16", - "libc", - "rand_chacha 0.2.2", - "rand_core 0.5.1", - "rand_hc", -] - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" -dependencies = [ - "ppv-lite86", - "rand_core 0.5.1", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom 0.1.16", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom 0.2.12", -] - -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core 0.5.1", -] - -[[package]] -name = "rand_xorshift" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" -dependencies = [ - "rand_core 0.6.4", -] - -[[package]] -name = "rayon" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4963ed1bc86e4f3ee217022bd855b297cef07fb9eac5dfa1f788b220b49b3bd" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" -dependencies = [ - "crossbeam-deque", - "crossbeam-utils", -] - -[[package]] -name = "redox_syscall" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "redox_syscall" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "regex" -version = "1.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata 0.4.5", - "regex-syntax 0.8.2", -] - -[[package]] -name = "regex-automata" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" -dependencies = [ - "regex-syntax 0.6.29", -] - -[[package]] -name = "regex-automata" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax 0.8.2", -] - -[[package]] -name = "regex-syntax" -version = "0.6.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" - -[[package]] -name = "regex-syntax" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" - -[[package]] -name = "reth-blockchain-tree" -version = "0.1.0-alpha.21" -source = "git+https://github.com/paradigmxyz/reth.git?rev=e0c220e#e0c220efef09dd5732e69d1da5c79bc52e0b5424" -dependencies = [ - "aquamarine", - "linked_hash_set", - "lru", - "metrics", - "parking_lot 0.12.1", - "reth-db", - "reth-interfaces", - "reth-metrics", - "reth-primitives", - "reth-provider", - "reth-stages", - "reth-trie", - "tokio", - "tracing", -] - -[[package]] -name = "reth-codecs" -version = "0.1.0-alpha.21" -source = "git+https://github.com/paradigmxyz/reth.git?rev=e0c220e#e0c220efef09dd5732e69d1da5c79bc52e0b5424" -dependencies = [ - "alloy-primitives", - "bytes", - "codecs-derive", -] - -[[package]] -name = "reth-consensus-common" -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", - "reth-provider", -] - -[[package]] -name = "reth-db" -version = "0.1.0-alpha.21" -source = "git+https://github.com/paradigmxyz/reth.git?rev=e0c220e#e0c220efef09dd5732e69d1da5c79bc52e0b5424" -dependencies = [ - "bytes", - "derive_more", - "eyre", - "metrics", - "modular-bitfield", - "once_cell", - "page_size", - "parity-scale-codec", - "parking_lot 0.12.1", - "paste", - "reth-codecs", - "reth-interfaces", - "reth-libmdbx", - "reth-metrics", - "reth-nippy-jar", - "reth-primitives", - "reth-tracing", - "rustc-hash", - "serde", - "strum", - "thiserror", -] - -[[package]] -name = "reth-discv4" -version = "0.1.0-alpha.21" -source = "git+https://github.com/paradigmxyz/reth.git?rev=e0c220e#e0c220efef09dd5732e69d1da5c79bc52e0b5424" -dependencies = [ - "alloy-rlp", - "discv5", - "enr", - "generic-array", - "parking_lot 0.12.1", - "reth-net-common", - "reth-net-nat", - "reth-primitives", - "rlp", - "secp256k1 0.27.0", - "serde", - "thiserror", - "tokio", - "tokio-stream", - "tracing", -] - -[[package]] -name = "reth-ecies" -version = "0.1.0-alpha.21" -source = "git+https://github.com/paradigmxyz/reth.git?rev=e0c220e#e0c220efef09dd5732e69d1da5c79bc52e0b5424" -dependencies = [ - "aes 0.8.4", - "alloy-rlp", - "block-padding", - "byteorder", - "cipher 0.4.4", - "ctr 0.9.2", - "digest 0.10.7", - "educe", - "futures", - "generic-array", - "hmac", - "pin-project", - "rand 0.8.5", - "reth-net-common", - "reth-primitives", - "secp256k1 0.27.0", - "sha2", - "sha3", - "thiserror", - "tokio", - "tokio-stream", - "tokio-util", - "tracing", - "typenum", -] - -[[package]] -name = "reth-eth-wire" -version = "0.1.0-alpha.21" -source = "git+https://github.com/paradigmxyz/reth.git?rev=e0c220e#e0c220efef09dd5732e69d1da5c79bc52e0b5424" -dependencies = [ - "alloy-chains", - "alloy-rlp", - "bytes", - "derive_more", - "futures", - "metrics", - "pin-project", - "reth-codecs", - "reth-discv4", - "reth-ecies", - "reth-metrics", - "reth-primitives", - "serde", - "snap", - "thiserror", - "tokio", - "tokio-stream", - "tokio-util", - "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.21" -source = "git+https://github.com/paradigmxyz/reth.git?rev=e0c220e#e0c220efef09dd5732e69d1da5c79bc52e0b5424" -dependencies = [ - "auto_impl", - "futures", - "reth-eth-wire", - "reth-network-api", - "reth-nippy-jar", - "reth-primitives", - "reth-rpc-types", - "thiserror", - "tokio", - "tracing", -] - -[[package]] -name = "reth-libmdbx" -version = "0.1.0-alpha.21" -source = "git+https://github.com/paradigmxyz/reth.git?rev=e0c220e#e0c220efef09dd5732e69d1da5c79bc52e0b5424" -dependencies = [ - "bitflags 2.4.2", - "byteorder", - "dashmap", - "derive_more", - "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.21" -source = "git+https://github.com/paradigmxyz/reth.git?rev=e0c220e#e0c220efef09dd5732e69d1da5c79bc52e0b5424" -dependencies = [ - "bindgen", - "cc", - "libc", -] - -[[package]] -name = "reth-metrics" -version = "0.1.0-alpha.21" -source = "git+https://github.com/paradigmxyz/reth.git?rev=e0c220e#e0c220efef09dd5732e69d1da5c79bc52e0b5424" -dependencies = [ - "futures", - "metrics", - "reth-metrics-derive", - "tokio", - "tokio-util", -] - -[[package]] -name = "reth-metrics-derive" -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.52", -] - -[[package]] -name = "reth-net-common" -version = "0.1.0-alpha.21" -source = "git+https://github.com/paradigmxyz/reth.git?rev=e0c220e#e0c220efef09dd5732e69d1da5c79bc52e0b5424" -dependencies = [ - "pin-project", - "reth-primitives", - "tokio", -] - -[[package]] -name = "reth-net-nat" -version = "0.1.0-alpha.21" -source = "git+https://github.com/paradigmxyz/reth.git?rev=e0c220e#e0c220efef09dd5732e69d1da5c79bc52e0b5424" -dependencies = [ - "igd-next", - "pin-project-lite", - "public-ip", - "serde_with", - "thiserror", - "tokio", - "tracing", -] - -[[package]] -name = "reth-network-api" -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", - "reth-primitives", - "reth-rpc-types", - "serde", - "thiserror", - "tokio", -] - -[[package]] -name = "reth-nippy-jar" -version = "0.1.0-alpha.21" -source = "git+https://github.com/paradigmxyz/reth.git?rev=e0c220e#e0c220efef09dd5732e69d1da5c79bc52e0b5424" -dependencies = [ - "anyhow", - "bincode", - "cuckoofilter", - "derive_more", - "lz4_flex", - "memmap2", - "ph", - "serde", - "sucds 0.8.1", - "thiserror", - "tracing", - "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.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", - "cfg-if", - "derive_more", - "itertools 0.12.1", - "modular-bitfield", - "num_enum", - "nybbles", - "once_cell", - "rayon", - "reth-codecs", - "reth-ethereum-forks", - "reth-rpc-types", - "revm", - "revm-primitives", - "secp256k1 0.27.0", - "serde", - "serde_json", - "sha2", - "strum", - "sucds 0.6.0", - "tempfile", - "thiserror", - "tracing", - "zstd", -] - -[[package]] -name = "reth-provider" -version = "0.1.0-alpha.21" -source = "git+https://github.com/paradigmxyz/reth.git?rev=e0c220e#e0c220efef09dd5732e69d1da5c79bc52e0b5424" -dependencies = [ - "auto_impl", - "dashmap", - "itertools 0.12.1", - "metrics", - "parking_lot 0.12.1", - "pin-project", - "rayon", - "reth-db", - "reth-interfaces", - "reth-metrics", - "reth-nippy-jar", - "reth-node-api", - "reth-primitives", - "reth-trie", - "revm", - "strum", - "tokio", - "tokio-stream", - "tracing", -] - -[[package]] -name = "reth-revm" -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", - "revm", - "revm-inspectors", - "tracing", -] - -[[package]] -name = "reth-rpc-types" -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.12.1", - "jsonrpsee-types", - "secp256k1 0.27.0", - "serde", - "serde_json", - "serde_with", - "thiserror", - "url", -] - -[[package]] -name = "reth-stages" -version = "0.1.0-alpha.21" -source = "git+https://github.com/paradigmxyz/reth.git?rev=e0c220e#e0c220efef09dd5732e69d1da5c79bc52e0b5424" -dependencies = [ - "aquamarine", - "auto_impl", - "futures-util", - "itertools 0.12.1", - "metrics", - "num-traits", - "pin-project", - "rayon", - "reth-codecs", - "reth-db", - "reth-interfaces", - "reth-metrics", - "reth-primitives", - "reth-provider", - "reth-tokio-util", - "reth-trie", - "revm", - "serde", - "thiserror", - "tokio", - "tokio-stream", - "tracing", -] - -[[package]] -name = "reth-tokio-util" -version = "0.1.0-alpha.21" -source = "git+https://github.com/paradigmxyz/reth.git?rev=e0c220e#e0c220efef09dd5732e69d1da5c79bc52e0b5424" -dependencies = [ - "tokio", - "tokio-stream", -] - -[[package]] -name = "reth-tracing" -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.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", - "tracing", -] - -[[package]] -name = "rethdb-reader" -version = "0.1.0" -dependencies = [ - "alloy-rlp", - "anyhow", - "reth-blockchain-tree", - "reth-db", - "reth-primitives", - "reth-provider", - "reth-revm", - "reth-rpc-types", - "serde", - "serde_json", -] - -[[package]] -name = "revm" -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 = [ - "alloy-primitives", - "alloy-rpc-trace-types", - "alloy-rpc-types", - "alloy-sol-types", - "anstyle", - "colorchoice", - "revm", -] - -[[package]] -name = "revm-interpreter" -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 = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db828d49d329560a70809d9d1fa0c74695edb49f50c5332db3eb24483076deac" -dependencies = [ - "aurora-engine-modexp", - "c-kzg", - "k256", - "once_cell", - "revm-primitives", - "ripemd", - "secp256k1 0.28.2", - "sha2", - "substrate-bn", -] - -[[package]] -name = "revm-primitives" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fecd125aad58e135e2ca5771ed6e4e7b1f05fa3a64e0dfb9cc643b7a800a8435" -dependencies = [ - "alloy-primitives", - "auto_impl", - "bitflags 2.4.2", - "bitvec", - "c-kzg", - "cfg-if", - "derive_more", - "enumn", - "hashbrown 0.14.3", - "hex", - "once_cell", - "serde", -] - -[[package]] -name = "rfc6979" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" -dependencies = [ - "hmac", - "subtle", -] - -[[package]] -name = "ripemd" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" -dependencies = [ - "digest 0.10.7", -] - -[[package]] -name = "rlp" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" -dependencies = [ - "bytes", - "rustc-hex", -] - -[[package]] -name = "rolling-file" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8395b4f860856b740f20a296ea2cd4d823e81a2658cf05ef61be22916026a906" -dependencies = [ - "chrono", -] - -[[package]] -name = "ruint" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49b1d9521f889713d1221270fdd63370feca7e5c71a18745343402fa86e4f04f" -dependencies = [ - "alloy-rlp", - "ark-ff 0.3.0", - "ark-ff 0.4.2", - "bytes", - "fastrlp", - "num-bigint", - "num-traits", - "parity-scale-codec", - "primitive-types", - "proptest", - "rand 0.8.5", - "rlp", - "ruint-macro", - "serde", - "valuable", - "zeroize", -] - -[[package]] -name = "ruint-macro" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f86854cf50259291520509879a5c294c3c9a4c334e9ff65071c51e42ef1e2343" - -[[package]] -name = "rustc-demangle" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" - -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - -[[package]] -name = "rustc-hex" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" - -[[package]] -name = "rustc_version" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" -dependencies = [ - "semver 0.11.0", -] - -[[package]] -name = "rustc_version" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" -dependencies = [ - "semver 1.0.22", -] - -[[package]] -name = "rustix" -version = "0.38.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" -dependencies = [ - "bitflags 2.4.2", - "errno", - "libc", - "linux-raw-sys", - "windows-sys 0.52.0", -] - -[[package]] -name = "rustversion" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" - -[[package]] -name = "rusty-fork" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" -dependencies = [ - "fnv", - "quick-error", - "tempfile", - "wait-timeout", -] - -[[package]] -name = "ryu" -version = "1.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "sec1" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" -dependencies = [ - "base16ct", - "der", - "generic-array", - "pkcs8", - "subtle", - "zeroize", -] - -[[package]] -name = "secp256k1" -version = "0.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25996b82292a7a57ed3508f052cfff8640d38d32018784acd714758b43da9c8f" -dependencies = [ - "rand 0.8.5", - "secp256k1-sys 0.8.1", - "serde", -] - -[[package]] -name = "secp256k1" -version = "0.28.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d24b59d129cdadea20aea4fb2352fa053712e5d713eee47d700cd4b2bc002f10" -dependencies = [ - "secp256k1-sys 0.9.2", -] - -[[package]] -name = "secp256k1-sys" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70a129b9e9efbfb223753b9163c4ab3b13cff7fd9c7f010fbac25ab4099fa07e" -dependencies = [ - "cc", -] - -[[package]] -name = "secp256k1-sys" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d1746aae42c19d583c3c1a8c646bfad910498e2051c551a7f2e3c0c9fbb7eb" -dependencies = [ - "cc", -] - -[[package]] -name = "semver" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" -dependencies = [ - "semver-parser", -] - -[[package]] -name = "semver" -version = "1.0.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" - -[[package]] -name = "semver-parser" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" -dependencies = [ - "pest", -] - -[[package]] -name = "serde" -version = "1.0.197" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_bytes" -version = "0.11.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b8497c313fd43ab992087548117643f6fcd935cbf36f176ffda0aacf9591734" -dependencies = [ - "serde", -] - -[[package]] -name = "serde_derive" -version = "1.0.197" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.52", -] - -[[package]] -name = "serde_json" -version = "1.0.114" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" -dependencies = [ - "indexmap 2.2.3", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "serde_with" -version = "3.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15d167997bd841ec232f5b2b8e0e26606df2e7caa4c31b95ea9ca52b200bd270" -dependencies = [ - "base64", - "chrono", - "hex", - "indexmap 1.9.3", - "indexmap 2.2.3", - "serde", - "serde_derive", - "serde_json", - "serde_with_macros", - "time", -] - -[[package]] -name = "serde_with_macros" -version = "3.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "865f9743393e638991566a8b7a479043c2c8da94a33e0a31f18214c9cae0a64d" -dependencies = [ - "darling 0.20.8", - "proc-macro2", - "quote", - "syn 2.0.52", -] - -[[package]] -name = "sha2" -version = "0.10.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.10.7", -] - -[[package]] -name = "sha3" -version = "0.10.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" -dependencies = [ - "digest 0.10.7", - "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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" -dependencies = [ - "lazy_static", -] - -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - -[[package]] -name = "signal-hook-registry" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" -dependencies = [ - "libc", -] - -[[package]] -name = "signature" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" -dependencies = [ - "digest 0.10.7", - "rand_core 0.6.4", -] - -[[package]] -name = "slab" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] - -[[package]] -name = "smallvec" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" -dependencies = [ - "serde", -] - -[[package]] -name = "snap" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b6b67fb9a61334225b5b790716f609cd58395f895b3fe8b328786812a40bc3b" - -[[package]] -name = "socket2" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "socket2" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" - -[[package]] -name = "spki" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" -dependencies = [ - "base64ct", - "der", -] - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "strsim" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" - -[[package]] -name = "strsim" -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.26.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "723b93e8addf9aa965ebe2d11da6d7540fa2283fcea14b3371ff055f7ba13f5f" -dependencies = [ - "strum_macros", -] - -[[package]] -name = "strum_macros" -version = "0.26.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a3417fc93d76740d974a01654a09777cb500428cc874ca9f45edfe0c4d4cd18" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "rustversion", - "syn 2.0.52", -] - -[[package]] -name = "substrate-bn" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b5bbfa79abbae15dd642ea8176a21a635ff3c00059961d1ea27ad04e5b441c" -dependencies = [ - "byteorder", - "crunchy", - "lazy_static", - "rand 0.8.5", - "rustc-hex", -] - -[[package]] -name = "subtle" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" - -[[package]] -name = "sucds" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64accd20141dfbef67ad83c51d588146cff7810616e1bda35a975be369059533" -dependencies = [ - "anyhow", -] - -[[package]] -name = "sucds" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d53d46182afe6ed822a94c54a532dc0d59691a8f49226bdc4596529ca864cdd6" -dependencies = [ - "anyhow", - "num-traits", -] - -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.52" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn-solidity" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e656cbcef8a77543b5accbd76f60f9e0bc4be364b0aba4263a6f313f8a355511" -dependencies = [ - "paste", - "proc-macro2", - "quote", - "syn 2.0.52", -] - -[[package]] -name = "tap" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" - -[[package]] -name = "tempfile" -version = "3.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" -dependencies = [ - "cfg-if", - "fastrand", - "rustix", - "windows-sys 0.52.0", -] - -[[package]] -name = "thiserror" -version = "1.0.57" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.57" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.52", -] - -[[package]] -name = "thread_local" -version = "1.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" -dependencies = [ - "cfg-if", - "once_cell", -] - -[[package]] -name = "threadpool" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" -dependencies = [ - "num_cpus", -] - -[[package]] -name = "time" -version = "0.3.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" -dependencies = [ - "deranged", - "itoa", - "num-conv", - "powerfmt", - "serde", - "time-core", - "time-macros", -] - -[[package]] -name = "time-core" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" - -[[package]] -name = "time-macros" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774" -dependencies = [ - "num-conv", - "time-core", -] - -[[package]] -name = "tiny-keccak" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" -dependencies = [ - "crunchy", -] - -[[package]] -name = "tinyvec" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - -[[package]] -name = "tokio" -version = "1.36.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" -dependencies = [ - "backtrace", - "bytes", - "libc", - "mio", - "num_cpus", - "parking_lot 0.12.1", - "pin-project-lite", - "signal-hook-registry", - "socket2 0.5.6", - "tokio-macros", - "windows-sys 0.48.0", -] - -[[package]] -name = "tokio-macros" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.52", -] - -[[package]] -name = "tokio-stream" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" -dependencies = [ - "futures-core", - "pin-project-lite", - "tokio", - "tokio-util", -] - -[[package]] -name = "tokio-util" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", - "slab", - "tokio", - "tracing", -] - -[[package]] -name = "toml_datetime" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" - -[[package]] -name = "toml_edit" -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 = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" -dependencies = [ - "indexmap 2.2.3", - "toml_datetime", - "winnow", -] - -[[package]] -name = "tower-service" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" - -[[package]] -name = "tracing" -version = "0.1.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" -dependencies = [ - "log", - "pin-project-lite", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-appender" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3566e8ce28cc0a3fe42519fc80e6b4c943cc4c8cef275620eb8dac2d3d4e06cf" -dependencies = [ - "crossbeam-channel", - "thiserror", - "time", - "tracing-subscriber", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.52", -] - -[[package]] -name = "tracing-core" -version = "0.1.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" -dependencies = [ - "once_cell", - "valuable", -] - -[[package]] -name = "tracing-futures" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" -dependencies = [ - "futures", - "futures-task", - "pin-project", - "tracing", -] - -[[package]] -name = "tracing-journald" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba316a74e8fc3c3896a850dba2375928a9fa171b085ecddfc7c054d39970f3fd" -dependencies = [ - "libc", - "tracing-core", - "tracing-subscriber", -] - -[[package]] -name = "tracing-log" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -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.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -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]] -name = "trust-dns-client" -version = "0.20.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b4ef9b9bde0559b78a4abb00339143750085f05e5a453efb7b8bef1061f09dc" -dependencies = [ - "cfg-if", - "data-encoding", - "futures-channel", - "futures-util", - "lazy_static", - "log", - "radix_trie", - "rand 0.8.5", - "thiserror", - "time", - "tokio", - "trust-dns-proto", -] - -[[package]] -name = "trust-dns-proto" -version = "0.20.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca94d4e9feb6a181c690c4040d7a24ef34018d8313ac5044a61d21222ae24e31" -dependencies = [ - "async-trait", - "cfg-if", - "data-encoding", - "enum-as-inner", - "futures-channel", - "futures-io", - "futures-util", - "idna 0.2.3", - "ipnet", - "lazy_static", - "log", - "rand 0.8.5", - "smallvec", - "thiserror", - "tinyvec", - "tokio", - "url", -] - -[[package]] -name = "try-lock" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" - -[[package]] -name = "typenum" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" - -[[package]] -name = "ucd-trie" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" - -[[package]] -name = "uint" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" -dependencies = [ - "byteorder", - "crunchy", - "hex", - "static_assertions", -] - -[[package]] -name = "unarray" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" - -[[package]] -name = "unicode-bidi" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" - -[[package]] -name = "unicode-ident" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "unicode-normalization" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" -dependencies = [ - "tinyvec", -] - -[[package]] -name = "unicode-segmentation" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" - -[[package]] -name = "universal-hash" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8326b2c654932e3e4f9196e69d08fdf7cfd718e1dc6f66b347e6024a0c961402" -dependencies = [ - "generic-array", - "subtle", -] - -[[package]] -name = "url" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" -dependencies = [ - "form_urlencoded", - "idna 0.5.0", - "percent-encoding", -] - -[[package]] -name = "utf8parse" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" - -[[package]] -name = "valuable" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "wait-timeout" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" -dependencies = [ - "libc", -] - -[[package]] -name = "want" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" -dependencies = [ - "try-lock", -] - -[[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "wasm-bindgen" -version = "0.2.91" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f" -dependencies = [ - "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.91" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b" -dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn 2.0.52", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.91" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.91" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.52", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.91" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838" - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows-core" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" -dependencies = [ - "windows-targets 0.52.4", -] - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "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]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "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]] -name = "windows_aarch64_gnullvm" -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.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" -dependencies = [ - "memchr", -] - -[[package]] -name = "wyhash" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf6e163c25e3fac820b4b453185ea2dea3b6a3e0a721d4d23d75bd33734c295" -dependencies = [ - "rand_core 0.6.4", -] - -[[package]] -name = "wyz" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" -dependencies = [ - "tap", -] - -[[package]] -name = "xml-rs" -version = "0.8.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcb9cbac069e033553e8bb871be2fbdffcab578eb25bd0f7c508cedc6dcd75a" - -[[package]] -name = "xmltree" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7d8a75eaf6557bb84a65ace8609883db44a29951042ada9b393151532e41fcb" -dependencies = [ - "xml-rs", -] - -[[package]] -name = "zerocopy" -version = "0.7.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.7.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.52", -] - -[[package]] -name = "zeroize" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" -dependencies = [ - "zeroize_derive", -] - -[[package]] -name = "zeroize_derive" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.52", -] - -[[package]] -name = "zstd" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a27595e173641171fc74a1232b7b1c7a7cb6e18222c11e9dfb9888fa424c53c" -dependencies = [ - "zstd-safe", -] - -[[package]] -name = "zstd-safe" -version = "6.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee98ffd0b48ee95e6c5168188e44a54550b1564d9d530ee21d5f0eaed1069581" -dependencies = [ - "libc", - "zstd-sys", -] - -[[package]] -name = "zstd-sys" -version = "2.0.9+zstd.1.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e16efa8a874a0481a574084d34cc26fdb3b99627480f785888deb6386506656" -dependencies = [ - "cc", - "pkg-config", -] diff --git a/op-service/rethdb-reader/Cargo.toml b/op-service/rethdb-reader/Cargo.toml deleted file mode 100644 index 16bbc7325b7f4..0000000000000 --- a/op-service/rethdb-reader/Cargo.toml +++ /dev/null @@ -1,26 +0,0 @@ -[package] -name = "rethdb-reader" -description = "A simple library for reading data through Reth's DB abstractions." -version = "0.1.0" -edition = "2021" - -[lib] -name = "rethdbreader" -crate-type = ["cdylib"] - -[dependencies] -# reth -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.197" -serde_json = "1.0.114" -anyhow = "1.0.80" - -[dev-dependencies] -reth-revm = { git = "https://github.com/paradigmxyz/reth.git", rev = "e0c220e" } -alloy-rlp = "0.3.4" diff --git a/op-service/rethdb-reader/Makefile b/op-service/rethdb-reader/Makefile deleted file mode 100644 index 6e9037bdfe5be..0000000000000 --- a/op-service/rethdb-reader/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -.PHONY: testdata -testdata: - mkdir -p testdata - @echo "Fetching block RLP and receipts for block #18,663,292 from ethereum mainnet" - cast rpc debug_getRawBlock 0x11CC77C | jq -r | xxd -r -p > testdata/block.rlp - cast rpc debug_getRawReceipts 0x11CC77C | jq -r > testdata/receipts.json - @echo "Done. Generating testdata DB & testing integrity..." - cargo test diff --git a/op-service/rethdb-reader/README.md b/op-service/rethdb-reader/README.md deleted file mode 100644 index 9f760f9780153..0000000000000 --- a/op-service/rethdb-reader/README.md +++ /dev/null @@ -1,113 +0,0 @@ -# `rethdb-reader` - -A dylib to be accessed via FFI in `op-service`'s `sources` package for reading information -directly from the `reth` database. - -## Developing - -**Building** - -To build the dylib, you must first have the [Rust Toolchain][rust-toolchain] installed. - -```sh -cargo build --release -``` - -**Docs** - -Documentation is available via rustdoc. - -```sh -cargo doc --open -``` - -**Linting** - -```sh -cargo +nightly fmt -- && cargo +nightly clippy --all --all-features -- -D warnings -``` - -**Generating `testdata`** - -The testdata block and `reth` database can be generated by running the `testdata` make directive: - -```sh -ETH_RPC_URL="" make testdata -``` - -**Generating the C header** - -To generate the C header, first install `cbindgen` via `cargo install cbindgen --force`. Then, run the generation script: - -```sh -./headgen.sh -``` - -### C Header - -The C header below is generated by `cbindgen`, and it is the interface that consumers of the dylib use to call its exported -functions. Currently, the only exported functions pertain to reading fully hydrated block receipts from the database. - -```c -#include -#include -#include -#include - -/** - * A [ReceiptsResult] is a wrapper around a JSON string containing serialized [TransactionReceipt]s - * as well as an error status that is compatible with FFI. - * - * # Safety - * - When the `error` field is false, the `data` pointer is guaranteed to be valid. - * - When the `error` field is true, the `data` pointer is guaranteed to be null. - */ -typedef struct ReceiptsResult { - uint32_t *data; - uintptr_t data_len; - bool error; -} ReceiptsResult; - -/** - * A [OpenDBResult] is a wrapper of DB instance [BlockchainProvider] - * as well as an error status that is compatible with FFI. - * - * # Safety - * - When the `error` field is false, the `data` pointer is guaranteed to be valid. - * - When the `error` field is true, the `data` pointer is guaranteed to be null. - */ -typedef struct OpenDBResult { - const void *data; - bool error; -} OpenDBResult; - -/** - * Read the receipts for a blockhash from the RETH database directly. - * - * # Safety - * - All possible nil pointer dereferences are checked, and the function will return a failing - * [ReceiptsResult] if any are found. - */ -struct ReceiptsResult rdb_read_receipts(const uint8_t *block_hash, - uintptr_t block_hash_len, - const void *db_instance); - -/** - * Free a string that was allocated in Rust and passed to C. - * - * # Safety - * - All possible nil pointer dereferences are checked. - */ -void rdb_free_string(char *string); - -/** - * Open a DB instance and return. - * - * # Safety - * - All possible nil pointer dereferences are checked, and the function will return a failing - * [OpenDBResult] if any are found. - */ -struct OpenDBResult open_db_read_only(const char *db_path); -``` - -[rust-toolchain]: https://rustup.rs/ diff --git a/op-service/rethdb-reader/headgen.sh b/op-service/rethdb-reader/headgen.sh deleted file mode 100755 index e7f7daf676d4c..0000000000000 --- a/op-service/rethdb-reader/headgen.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -set -e - -# Generate rdb.h -cbindgen --crate rethdb-reader --output rdb.h -l C - -# Process README.md to replace the content within the specified code block -awk ' - BEGIN { in_code_block=0; } - /^```c/ { in_code_block=1; print; next; } - /^```/ && in_code_block { in_code_block=0; while ((getline line < "rdb.h") > 0) print line; } - !in_code_block { print; } -' README.md > README.tmp && mv README.tmp README.md - -echo "Generated C header successfully" diff --git a/op-service/rethdb-reader/rustfmt.toml b/op-service/rethdb-reader/rustfmt.toml deleted file mode 100644 index 68c3c93033d4f..0000000000000 --- a/op-service/rethdb-reader/rustfmt.toml +++ /dev/null @@ -1,11 +0,0 @@ -reorder_imports = true -imports_granularity = "Crate" -use_small_heuristics = "Max" -comment_width = 100 -wrap_comments = true -binop_separator = "Back" -trailing_comma = "Vertical" -trailing_semicolon = false -use_field_init_shorthand = true -format_code_in_doc_comments = true -doc_comment_code_block_width = 100 diff --git a/op-service/rethdb-reader/src/db.rs b/op-service/rethdb-reader/src/db.rs deleted file mode 100644 index 8d1840fbdea03..0000000000000 --- a/op-service/rethdb-reader/src/db.rs +++ /dev/null @@ -1,59 +0,0 @@ -use anyhow::{anyhow, Result}; -use reth_blockchain_tree::noop::NoopBlockchainTree; -use reth_db::{mdbx::DatabaseArguments, open_db_read_only}; -use reth_primitives::MAINNET; -use reth_provider::{providers::BlockchainProvider, ProviderFactory}; -use std::{ - ffi::{c_char, c_void}, - path::Path, -}; - -/// A [OpenDBResult] is a wrapper of DB instance [BlockchainProvider] -/// as well as an error status that is compatible with FFI. -/// -/// # Safety -/// - When the `error` field is false, the `data` pointer is guaranteed to be valid. -/// - When the `error` field is true, the `data` pointer is guaranteed to be null. -#[repr(C)] -pub struct OpenDBResult { - pub(crate) data: *const c_void, - pub(crate) error: bool, -} - -impl OpenDBResult { - /// Constructs a successful [OpenDBResult] from a DB instance. - pub fn success(data: *const c_void) -> Self { - Self { data, error: false } - } - - /// Constructs a failing [OpenDBResult] with a null pointer to the data. - pub fn fail() -> Self { - Self { data: std::ptr::null_mut(), error: true } - } -} - -/// Open and return a DB instance. -/// -/// # Safety -/// - All possible nil pointer dereferences are checked, and the function will return a failing -/// [OpenDBResult] if any are found. -#[inline(always)] -pub(crate) unsafe fn open_db_read_only_inner(db_path: *const c_char) -> Result { - // Convert the *const c_char to a Rust &str - let db_path_str = { - if db_path.is_null() { - anyhow::bail!("db path pointer is null"); - } - std::ffi::CStr::from_ptr(db_path) - } - .to_str()?; - - 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 - let provider = Box::new(BlockchainProvider::new(factory, NoopBlockchainTree::default())?); - let res = OpenDBResult::success(Box::into_raw(provider) as *const c_void); - Ok(res) -} diff --git a/op-service/rethdb-reader/src/lib.rs b/op-service/rethdb-reader/src/lib.rs deleted file mode 100644 index 4aa7856080817..0000000000000 --- a/op-service/rethdb-reader/src/lib.rs +++ /dev/null @@ -1,47 +0,0 @@ -#![doc = include_str!("../README.md")] - -use db::{open_db_read_only_inner, OpenDBResult}; -use receipts::{read_receipts_inner, ReceiptsResult}; -use std::ffi::c_void; - -use std::os::raw::c_char; - -mod db; -mod receipts; - -/// Read the receipts for a blockhash from the RETH database directly. -/// -/// # Safety -/// - All possible nil pointer dereferences are checked, and the function will return a failing -/// [ReceiptsResult] if any are found. -#[no_mangle] -pub unsafe extern "C" fn rdb_read_receipts( - block_hash: *const u8, - block_hash_len: usize, - db_instance: *const c_void, -) -> ReceiptsResult { - read_receipts_inner(block_hash, block_hash_len, db_instance).unwrap_or(ReceiptsResult::fail()) -} - -/// Free a string that was allocated in Rust and passed to C. -/// -/// # Safety -/// - All possible nil pointer dereferences are checked. -#[no_mangle] -pub unsafe extern "C" fn rdb_free_string(string: *mut c_char) { - // Convert the raw pointer back to a CString and let it go out of scope, - // which will deallocate the memory. - if !string.is_null() { - let _ = std::ffi::CString::from_raw(string); - } -} - -/// Open a DB instance and return. -/// -/// # Safety -/// - All possible nil pointer dereferences are checked, and the function will return a failing -/// [OpenDBResult] if any are found. -#[no_mangle] -pub unsafe extern "C" fn open_db_read_only(db_path: *const c_char) -> OpenDBResult { - open_db_read_only_inner(db_path).unwrap_or(OpenDBResult::fail()) -} diff --git a/op-service/rethdb-reader/src/receipts.rs b/op-service/rethdb-reader/src/receipts.rs deleted file mode 100644 index 0dea66689b5f4..0000000000000 --- a/op-service/rethdb-reader/src/receipts.rs +++ /dev/null @@ -1,334 +0,0 @@ -//! This module contains the logic for reading a block's fully hydrated receipts directly from the -//! [reth] database. - -use anyhow::{anyhow, Result}; -use reth_blockchain_tree::noop::NoopBlockchainTree; -use reth_db::DatabaseEnv; -use reth_primitives::{ - BlockHashOrNumber, Receipt, TransactionKind, TransactionMeta, TransactionSigned, U128, U256, - U64, -}; -use reth_provider::{providers::BlockchainProvider, BlockReader, ReceiptProvider}; -use reth_rpc_types::{Log, TransactionReceipt}; -use std::ffi::c_void; - -/// A [ReceiptsResult] is a wrapper around a JSON string containing serialized [TransactionReceipt]s -/// as well as an error status that is compatible with FFI. -/// -/// # Safety -/// - When the `error` field is false, the `data` pointer is guaranteed to be valid. -/// - When the `error` field is true, the `data` pointer is guaranteed to be null. -#[repr(C)] -pub struct ReceiptsResult { - data: *mut char, - data_len: usize, - error: bool, -} - -impl ReceiptsResult { - /// Constructs a successful [ReceiptsResult] from a JSON string. - pub fn success(data: *mut char, data_len: usize) -> Self { - Self { data, data_len, error: false } - } - - /// Constructs a failing [ReceiptsResult] with a null pointer to the data. - pub fn fail() -> Self { - Self { data: std::ptr::null_mut(), data_len: 0, error: true } - } -} - -/// Read the receipts for a blockhash from the RETH database directly. -/// -/// # Safety -/// - All possible nil pointer dereferences are checked, and the function will return a failing -/// [ReceiptsResult] if any are found. -#[inline(always)] -pub(crate) unsafe fn read_receipts_inner( - block_hash: *const u8, - block_hash_len: usize, - db_instance: *const c_void, -) -> Result { - // Convert the raw pointer and length back to a Rust slice - let block_hash: [u8; 32] = { - if block_hash.is_null() { - anyhow::bail!("block_hash pointer is null"); - } - std::slice::from_raw_parts(block_hash, block_hash_len) - } - .try_into()?; - - // Create a read-only BlockChainProvider - let provider = &*(db_instance as *const BlockchainProvider); - // Fetch the block and the receipts within it - let block = - provider.block_by_hash(block_hash.into())?.ok_or(anyhow!("Failed to fetch block"))?; - let receipts = provider - .receipts_by_block(BlockHashOrNumber::Hash(block_hash.into()))? - .ok_or(anyhow!("Failed to fetch block receipts"))?; - - let block_number = block.number; - let base_fee = block.base_fee_per_gas; - let block_hash = block.hash_slow(); - let receipts = block - .body - .into_iter() - .zip(receipts.clone()) - .enumerate() - .map(|(idx, (tx, receipt))| { - let meta = TransactionMeta { - tx_hash: tx.hash, - index: idx as u64, - block_hash, - block_number, - base_fee, - excess_blob_gas: None, - }; - build_transaction_receipt_with_block_receipts(tx, meta, receipt, &receipts) - }) - .collect::>>() - .ok_or(anyhow!("Failed to build receipts"))?; - - // Convert the receipts to JSON for transport - let mut receipts_json = serde_json::to_string(&receipts)?; - - // Create a ReceiptsResult with a pointer to the json-ified receipts - let res = ReceiptsResult::success(receipts_json.as_mut_ptr() as *mut char, receipts_json.len()); - - // Forget the `receipts_json` string so that its memory isn't freed by the - // borrow checker at the end of this scope - std::mem::forget(receipts_json); // Prevent Rust from freeing the memory - - Ok(res) -} - -/// Builds a hydrated [TransactionReceipt] from information in the passed transaction, -/// receipt, and block receipts. -/// -/// Returns [None] if the transaction's sender could not be recovered from the signature. -#[inline(always)] -fn build_transaction_receipt_with_block_receipts( - tx: TransactionSigned, - meta: TransactionMeta, - receipt: Receipt, - all_receipts: &[Receipt], -) -> Option { - let transaction = tx.clone().into_ecrecovered()?; - - // get the previous transaction cumulative gas used - let gas_used = if meta.index == 0 { - receipt.cumulative_gas_used - } else { - let prev_tx_idx = (meta.index - 1) as usize; - all_receipts - .get(prev_tx_idx) - .map(|prev_receipt| receipt.cumulative_gas_used - prev_receipt.cumulative_gas_used) - .unwrap_or_default() - }; - - let mut res_receipt = TransactionReceipt { - transaction_hash: Some(meta.tx_hash), - transaction_index: U64::from(meta.index), - block_hash: Some(meta.block_hash), - block_number: Some(U256::from(meta.block_number)), - from: transaction.signer(), - to: None, - cumulative_gas_used: U256::from(receipt.cumulative_gas_used), - gas_used: Some(U256::from(gas_used)), - contract_address: None, - logs: Vec::with_capacity(receipt.logs.len()), - effective_gas_price: U128::from(transaction.effective_gas_price(meta.base_fee)), - transaction_type: tx.transaction.tx_type().into(), - // TODO pre-byzantium receipts have a post-transaction state root - state_root: None, - logs_bloom: receipt.bloom_slow(), - status_code: if receipt.success { Some(U64::from(1)) } else { Some(U64::from(0)) }, - - // EIP-4844 fields - blob_gas_price: None, - blob_gas_used: None, - - // Other: - other: Default::default(), - }; - - match tx.transaction.kind() { - TransactionKind::Create => { - res_receipt.contract_address = - Some(transaction.signer().create(tx.transaction.nonce())); - } - TransactionKind::Call(addr) => { - res_receipt.to = Some(*addr); - } - } - - // get number of logs in the block - let mut num_logs = 0; - for prev_receipt in all_receipts.iter().take(meta.index as usize) { - num_logs += prev_receipt.logs.len(); - } - - for (tx_log_idx, log) in receipt.logs.into_iter().enumerate() { - let rpclog = Log { - address: log.address, - topics: log.topics, - data: log.data, - block_hash: Some(meta.block_hash), - block_number: Some(U256::from(meta.block_number)), - transaction_hash: Some(meta.tx_hash), - transaction_index: Some(U256::from(meta.index)), - log_index: Some(U256::from(num_logs + tx_log_idx)), - removed: false, - }; - res_receipt.logs.push(rpclog); - } - - Some(res_receipt) -} - -#[cfg(test)] -mod test { - use super::*; - use alloy_rlp::Decodable; - use reth_db::{database::Database, mdbx::DatabaseArguments}; - use reth_primitives::{ - address, b256, bloom, hex, Address, Block, Bytes, ReceiptWithBloom, Receipts, - SealedBlockWithSenders, MAINNET, U8, - }; - use reth_provider::{BlockWriter, BundleStateWithReceipts, DatabaseProvider}; - use reth_revm::revm::db::BundleState; - use std::{ - ffi::{c_char, CString}, - fs::File, - path::Path, - }; - - #[inline] - fn dummy_block_with_receipts() -> Result<(Block, Vec)> { - // To generate testdata (block 18,663,292 on Ethereum Mainnet): - // 1. BLOCK RLP: `cast rpc debug_getRawBlock 0x11CC77C | jq -r | xxd -r -p > - // testdata/block.rlp` - // 2. RECEIPTS RLP: `cast rpc debug_getRawReceipts 0x11CC77C | jq -r > - // testdata/receipts.json` - let block_rlp = include_bytes!("../testdata/block.rlp"); - let block = Block::decode(&mut block_rlp.as_ref())?; - - let receipt_rlp: Vec> = serde_json::from_str(include_str!( - "../testdata/receipts.json" - )) - .map(|v: Vec| { - v.into_iter().map(|s| hex::decode(s)).collect::>, _>>() - })??; - let receipts = receipt_rlp - .iter() - .map(|r| ReceiptWithBloom::decode(&mut r.as_slice()).map(|r| r.receipt)) - .collect::, _>>()?; - - Ok((block, receipts)) - } - - #[inline] - fn open_receipts_testdata_db() -> Result<()> { - if File::open("testdata/db").is_ok() { - return Ok(()); - } - - // Open a RW handle to the MDBX database - 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 - let (mut block, receipts) = dummy_block_with_receipts()?; - - // Patch: The block's current state root expects the rest of the chain history to be in the - // DB; manually override it. Otherwise, the DatabaseProvider will fail to commit the - // block. - block.header.state_root = reth_primitives::constants::EMPTY_ROOT_HASH; - - // Fetch the block number and tx senders for bundle state creation. - let block_number = block.header.number; - let senders = block - .body - .iter() - .map(|tx| tx.recover_signer()) - .collect::>>() - .ok_or(anyhow!("Failed to recover signers"))?; - - // Commit the bundle state to the database - 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()?; - - Ok(()) - } - - #[test] - fn fetch_receipts() { - open_receipts_testdata_db().unwrap(); - unsafe { - let res = crate::open_db_read_only( - CString::new("testdata/db").unwrap().into_raw() as *const c_char - ); - assert_eq!(res.error, false); - - let mut block_hash = - b256!("6a229123d607c2232a8b0bdd36f90745945d05181018e64e60ff2b93ab6b52e5"); - let receipts_res = - super::read_receipts_inner(block_hash.as_mut_ptr(), 32, res.data).unwrap(); - - let receipts_data = - std::slice::from_raw_parts(receipts_res.data as *const u8, receipts_res.data_len); - let receipt = { - let mut receipts: Vec = - serde_json::from_slice(receipts_data).unwrap(); - receipts.remove(0) - }; - - // Check the first receipt in the block for validity - assert_eq!(receipt.transaction_type, U8::from(2)); - assert_eq!(receipt.status_code, Some(U64::from(1))); - assert_eq!(receipt.cumulative_gas_used, U256::from(115_316)); - assert_eq!(receipt.logs_bloom, bloom!("00200000000000000000000080001000000000000000000000000000000000000000000000000000000000000000100002000100080000000000000000000000000000000000000000000008000000200000000400000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000400000000000001000000000000000100000000080000004000000000000000000000000000000000000002000000000000000000000000000000000000000006000000000000000000000000000000000000001000000000000000000000200000000000000100000000020000000000000000000000000000000010")); - assert_eq!( - receipt.logs[0].address, - address!("c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2") - ); - assert_eq!( - receipt.logs[0].topics[0], - b256!("ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef") - ); - assert_eq!( - receipt.logs[0].topics[1], - b256!("00000000000000000000000000000000003b3cc22af3ae1eac0440bcee416b40") - ); - assert_eq!( - receipt.logs[0].data, - Bytes::from_static( - hex!("00000000000000000000000000000000000000000000000008a30cd230000000") - .as_slice() - ) - ); - assert_eq!(receipt.from, address!("41d3ab85aafed2ef9e644cb7d3bbca2fc4d8cac8")); - assert_eq!(receipt.to, Some(address!("00000000003b3cc22af3ae1eac0440bcee416b40"))); - assert_eq!( - receipt.transaction_hash, - Some(b256!("88b2d153a4e893ba91ac235325c44b1aa0c802fcb42657701e1a73e1c675f7ca")) - ); - - assert_eq!(receipt.block_number, Some(U256::from(18_663_292))); - assert_eq!(receipt.block_hash, Some(block_hash)); - assert_eq!(receipt.transaction_index, U64::from(0)); - - crate::rdb_free_string(receipts_res.data as *mut c_char); - } - } -} diff --git a/op-service/rethdb-reader/testdata/block.rlp b/op-service/rethdb-reader/testdata/block.rlp deleted file mode 100644 index 978ba6be01b47..0000000000000 Binary files a/op-service/rethdb-reader/testdata/block.rlp and /dev/null differ diff --git a/op-service/rethdb-reader/testdata/receipts.json b/op-service/rethdb-reader/testdata/receipts.json deleted file mode 100644 index aef76b0c2eb8c..0000000000000 --- a/op-service/rethdb-reader/testdata/receipts.json +++ /dev/null @@ -1,12 +0,0 @@ -[ - "0xb903c202f903be018301c274b9010000200000000000000000000080001000000000000000000000000000000000000000000000000000000000000000100002000100080000000000000000000000000000000000000000000008000000200000000400000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000400000000000001000000000000000100000000080000004000000000000000000000000000000000000002000000000000000000000000000000000000000006000000000000000000000000000000000000001000000000000000000000200000000000000100000000020000000000000000000000000000000010f902b3f89b94c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa000000000000000000000000000000000003b3cc22af3ae1eac0440bcee416b40a00000000000000000000000005c1694c8168668c11777909c79142dc9d992788fa000000000000000000000000000000000000000000000000008a30cd230000000f89b94d10bc8517059e51b625e1e57a60b348d552f685df863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa00000000000000000000000005c1694c8168668c11777909c79142dc9d992788fa000000000000000000000000000000000003b3cc22af3ae1eac0440bcee416b40a000000000000000000000000000000000000000000000000000007921e915b684f879945c1694c8168668c11777909c79142dc9d992788fe1a01c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1b840000000000000000000000000000000000000000000000001129c9861392306df000000000000000000000000000000000000000000000000000e9d834abd9cdff8fc945c1694c8168668c11777909c79142dc9d992788ff863a0d78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822a000000000000000000000000000000000003b3cc22af3ae1eac0440bcee416b40a000000000000000000000000000000000003b3cc22af3ae1eac0440bcee416b40b88000000000000000000000000000000000000000000000000008a30cd2300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007921e915b684", - "0xb9043e02f9043a0183042135b9010000200000000000000000000080001000100000000000000000000000000000000000000000000000000000000000100002000000080000000000000000010000000000000000010000000008000000200000000400100000000000008000000000000000000000000000000000000000000000000000000000000010000000000000000400000000000001000000000000000101000000080000004000000000000000000000000000000000000002000000000000000000000000000000000000000002000000000000000000000000000000000000001000000000000000000000200000000000008000000000020000000000000000400000000000000010f9032ff87a94c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f842a0e1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109ca00000000000000000000000002ec705d306b51e486b1bc0d6ebee708e0661add1a00000000000000000000000000000000000000000000000000bd0c7ca01c48000f89b94c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa00000000000000000000000002ec705d306b51e486b1bc0d6ebee708e0661add1a00000000000000000000000005c1694c8168668c11777909c79142dc9d992788fa00000000000000000000000000000000000000000000000000bd0c7ca01c48000f89b94d10bc8517059e51b625e1e57a60b348d552f685df863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa00000000000000000000000005c1694c8168668c11777909c79142dc9d992788fa00000000000000000000000001f3c8f19ab956457994de1d50eb0ae7d057f77f8a0000000000000000000000000000000000000000000000000000099e622c10336f879945c1694c8168668c11777909c79142dc9d992788fe1a01c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1b8400000000000000000000000000000000000000000000000011e6d602b3ae786df000000000000000000000000000000000000000000000000000e039d27fc99a9f8fc945c1694c8168668c11777909c79142dc9d992788ff863a0d78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822a00000000000000000000000002ec705d306b51e486b1bc0d6ebee708e0661add1a00000000000000000000000001f3c8f19ab956457994de1d50eb0ae7d057f77f8b8800000000000000000000000000000000000000000000000000bd0c7ca01c4800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000099e622c10336", - "0xb903c202f903be018305b26fb9010000200000000000000000000080001000000000000000000000000000000000000000000000000000000000000000100002000100080000000000000000000000000000000000000000000008000000200000000400000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000400000000000001000000000000000100000000080000004000000000000000000000000000000000000002000000000000000000000000000000000000000006000000000000000000000000000000000000001000000000000000000000200000000000000100000000020000000000000000000000000000000010f902b3f89b94d10bc8517059e51b625e1e57a60b348d552f685df863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa000000000000000000000000000000000003b3cc22af3ae1eac0440bcee416b40a00000000000000000000000005c1694c8168668c11777909c79142dc9d992788fa000000000000000000000000000000000000000000000000000007921e99216a0f89b94c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa00000000000000000000000005c1694c8168668c11777909c79142dc9d992788fa000000000000000000000000000000000003b3cc22af3ae1eac0440bcee416b40a00000000000000000000000000000000000000000000000000953f38350000000f879945c1694c8168668c11777909c79142dc9d992788fe1a01c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1b84000000000000000000000000000000000000000000000000115196ca7eae786df000000000000000000000000000000000000000000000000000e7cbf118eb049f8fc945c1694c8168668c11777909c79142dc9d992788ff863a0d78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822a000000000000000000000000000000000003b3cc22af3ae1eac0440bcee416b40a000000000000000000000000000000000003b3cc22af3ae1eac0440bcee416b40b880000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007921e99216a00000000000000000000000000000000000000000000000000953f383500000000000000000000000000000000000000000000000000000000000000000000000", - "0xb90bdf02f90bdb01830b2215b9010000200000002000000000000080000000000000000000000001010000000004000000000000000000420000000000010002000000080020002000000000200800000000000000080800000008000000200090000000000000080000408040000000000000000000000008084000000000000000000000000010010050000800000800800000000000000000000000000000000000000000080000004000100000020100000000000000100080000004000000000000020000000000000000000000400002000000000000000000000000000000000000001000000000002000400012200000800000020404000000000000020000008000000000000000000010f90ad0f89b941111111254eeb25477b68fb85ed929f73a960582f842a0b9ed0243fdf00f0545c63a0af8850c090d86bb46682baec4bf3c496814fe4f02a000000000000000000000000058c1c6a484ef2d6b0f8d93b2dbeb72f3c3e9ceb5b8402511106c0eade4c289445ac7275a89e6e088cc2cb5e313a42712b2987c2fb8d30000000000000000000000000000000000000000000000000000000000000001f89b94dac17f958d2ee523a2206206994597c13d831ec7f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa000000000000000000000000058c1c6a484ef2d6b0f8d93b2dbeb72f3c3e9ceb5a0000000000000000000000000d1742b3c4fbb096990c8950fa635aec75b30781aa000000000000000000000000000000000000000000000000000000002f0174a58f89b94fe67a4450907459c3e1fff623aa927dd4e28c67af863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa0000000000000000000000000a050f7adc241afa59ad5f343eaf4faf5f30a4cdba0000000000000000000000000d1742b3c4fbb096990c8950fa635aec75b30781aa000000000000000000000000000000000000000000000143c3719a34f04e020edf89b94dac17f958d2ee523a2206206994597c13d831ec7f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa0000000000000000000000000d1742b3c4fbb096990c8950fa635aec75b30781aa000000000000000000000000006da0fd433c1a5d7a4faa01111c044910a184553a000000000000000000000000000000000000000000000000000000000da1b3bf5f89b94dac17f958d2ee523a2206206994597c13d831ec7f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa0000000000000000000000000d1742b3c4fbb096990c8950fa635aec75b30781aa00000000000000000000000000d4a11d5eeaac28ec3f61d100daf4d40471f1852a00000000000000000000000000000000000000000000000000000000215fc0e63f89b94c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa000000000000000000000000006da0fd433c1a5d7a4faa01111c044910a184553a0000000000000000000000000a050f7adc241afa59ad5f343eaf4faf5f30a4cdba00000000000000000000000000000000000000000000000001913572822ee731ff8799406da0fd433c1a5d7a4faa01111c044910a184553e1a01c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1b8400000000000000000000000000000000000000000000000b3986c20be3ddb96f70000000000000000000000000000000000000000000000000000061647f821daf8fc9406da0fd433c1a5d7a4faa01111c044910a184553f863a0d78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822a0000000000000000000000000d1742b3c4fbb096990c8950fa635aec75b30781aa0000000000000000000000000a050f7adc241afa59ad5f343eaf4faf5f30a4cdbb880000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000da1b3bf50000000000000000000000000000000000000000000000001913572822ee731f0000000000000000000000000000000000000000000000000000000000000000f89b94c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa00000000000000000000000000d4a11d5eeaac28ec3f61d100daf4d40471f1852a0000000000000000000000000a050f7adc241afa59ad5f343eaf4faf5f30a4cdba00000000000000000000000000000000000000000000000003d5ec06d1b711bcff879940d4a11d5eeaac28ec3f61d100daf4d40471f1852e1a01c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1b8400000000000000000000000000000000000000000000004724d25b9c0c67a0c7800000000000000000000000000000000000000000000000000002694ca870b04f8fc940d4a11d5eeaac28ec3f61d100daf4d40471f1852f863a0d78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822a0000000000000000000000000d1742b3c4fbb096990c8950fa635aec75b30781aa0000000000000000000000000a050f7adc241afa59ad5f343eaf4faf5f30a4cdbb88000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000215fc0e630000000000000000000000000000000000000000000000003d5ec06d1b711bcf0000000000000000000000000000000000000000000000000000000000000000f9011c94a050f7adc241afa59ad5f343eaf4faf5f30a4cdbf863a0c42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca67a0000000000000000000000000d1742b3c4fbb096990c8950fa635aec75b30781aa0000000000000000000000000d1742b3c4fbb096990c8950fa635aec75b30781ab8a0000000000000000000000000000000000000000000000000567217953e5f8eeeffffffffffffffffffffffffffffffffffffffffffffebc3c8e65cb0fb1fdf13000000000000000000000000000000000000007b89284efd1b25e6f5f0dcbf2e000000000000000000000000000000000000000000000aa86d459fd0c59c2a59000000000000000000000000000000000000000000000000000000000001784ff89b94fe67a4450907459c3e1fff623aa927dd4e28c67af863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa0000000000000000000000000d1742b3c4fbb096990c8950fa635aec75b30781aa0000000000000000000000000a88800cd213da5ae406ce248380802bd53b47647a0000000000000000000000000000000000000000000001375a0d26e739f71f370f89b94fe67a4450907459c3e1fff623aa927dd4e28c67af863a08c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925a0000000000000000000000000a88800cd213da5ae406ce248380802bd53b47647a00000000000000000000000001111111254eeb25477b68fb85ed929f73a960582a0000000000000000000000000000000000000000000001375a0d26e739f71f370f89b94fe67a4450907459c3e1fff623aa927dd4e28c67af863a08c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925a0000000000000000000000000a88800cd213da5ae406ce248380802bd53b47647a00000000000000000000000001111111254eeb25477b68fb85ed929f73a960582a00000000000000000000000000000000000000000000000000000000000000000f89b94fe67a4450907459c3e1fff623aa927dd4e28c67af863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa0000000000000000000000000a88800cd213da5ae406ce248380802bd53b47647a000000000000000000000000058c1c6a484ef2d6b0f8d93b2dbeb72f3c3e9ceb5a0000000000000000000000000000000000000000000001375a0d26e739f71f370", - "0xb905cf02f905cb01830e0902b9010000200000008020000000000280004000000000000000000000000000000000000000200000000000000000200080000002000000080000000000000800000000000000000000000100000008040000200004000000000000000000008000004000000000000000000000000000000400240000000000000004000010000000000000000000000000000001010000000200000001000000080000004000000400002000000000004002020000000000000000000000000000002000000000000000000002000000000000000000000040000000000000001000000000000000000000200000000000000000000000000000000001000400400000000080010000f904c0f87a94c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f842a0e1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109ca0000000000000000000000000db5889e35e379ef0498aae126fc2cce1fbd23216a000000000000000000000000000000000000000000000000001617eb90b26c000f89b94c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa0000000000000000000000000db5889e35e379ef0498aae126fc2cce1fbd23216a0000000000000000000000000e090e0518ea17607a01e9286522655808c3f8919a000000000000000000000000000000000000000000000000001617eb90b26c000f89b94f83e0399fd7ef1c9c1a3dbc0a4d586edc3c8d125f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa0000000000000000000000000e090e0518ea17607a01e9286522655808c3f8919a0000000000000000000000000faa04b4d06297dca749c2ac7783211638de3e491a000000000000000000000000000000000000000000000019d0da576764721e7e7f87994e090e0518ea17607a01e9286522655808c3f8919e1a01c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1b8400000000000000000000000000000000000000000000000001e6d6c84d2f7cd2b00000000000000000000000000000000000000000000220ae8d75c1df124f53df8fc94e090e0518ea17607a01e9286522655808c3f8919f863a0d78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822a0000000000000000000000000c6265979793435b496e28e61af1500c22c3ba277a0000000000000000000000000faa04b4d06297dca749c2ac7783211638de3e491b88000000000000000000000000000000000000000000000000001617eb90b26c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000019d0da576764721e7e7f87994db5889e35e379ef0498aae126fc2cce1fbd23216e1a06cb8c9cbcedb37b7d125170f5d929dbbdb3203c8fd4d60356b496fa31f77fd00b8400000000000000000000000000000000000000000000000000001c4793ec69800000000000000000000000000000000000000000000000000000000000000008ef87994db5889e35e379ef0498aae126fc2cce1fbd23216e1a00c2a2f565c7774c59e49ef6b3c255329f4d254147e06e724d3a8569bb7bd21adb8400000000000000000000000000000000000000000000000000001c4793ec69800000000000000000000000000faa04b4d06297dca749c2ac7783211638de3e491f89994db5889e35e379ef0498aae126fc2cce1fbd23216e1a09f849d23f4955d98202378ea318f2b0c7533695d3c9fb2a3931f0f919fa8c420b86000000000000000000000000000000000000000000000000001617eb90b26c00000000000000000000000000000000000000000000000019d0da576764721e7e700000000000000000000000000000000000000000000019d0da576764721e7e7", - "0xf905cb0183105d5cb90100000000000180a0000004000000004000000000000001000000000000002200000000000000000000080200200000000002000000080020000000000800000000000000000000000900000008040000000000000000400000000000000000004000000000000000000000000000000400240000000000040000000010000804000000000000000000000080010000000000000000000000008000000000000480000000000000004002000000000000000000000000000000000000000000008000000002080000000000000000000000000000000000000000000002000000000000200000000000000000000000000000000000000000000000000000010000f904c0f89b94c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa00000000000000000000000009e31efffe1e016f514f774f43d91a85ebbc11564a0000000000000000000000000db5889e35e379ef0498aae126fc2cce1fbd23216a00000000000000000000000000000000000000000000000000e803e90becaf29bf89b949dd5f5dae94633760b3125a7490ecb4571d09a42f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa000000000000000000000000087033ad96757ecd730aa1652b1a7dabcc5ffb182a00000000000000000000000009e31efffe1e016f514f774f43d91a85ebbc11564a0000000000000000000000000000000000000000000acb37f48fe24c23d1833c6f9011c949e31efffe1e016f514f774f43d91a85ebbc11564f863a0c42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca67a0000000000000000000000000db5889e35e379ef0498aae126fc2cce1fbd23216a0000000000000000000000000db5889e35e379ef0498aae126fc2cce1fbd23216b8a0000000000000000000000000000000000000000000acb37f48fe24c23d1833c6fffffffffffffffffffffffffffffffffffffffffffffffff17fc16f41350d65000000000000000000000000000000000000000000049c65546ad3eed1521a58000000000000000000000000000000000000000000009404a8bb774136003dadfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd14eff87a94c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f842a07fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65a0000000000000000000000000db5889e35e379ef0498aae126fc2cce1fbd23216a00000000000000000000000000000000000000000000000000e803e90becaf29bf87994db5889e35e379ef0498aae126fc2cce1fbd23216e1a06cb8c9cbcedb37b7d125170f5d929dbbdb3203c8fd4d60356b496fa31f77fd00b84000000000000000000000000000000000000000000000000000128fac3e64dad00000000000000000000000000000000000000000000000000000000000000012f87994db5889e35e379ef0498aae126fc2cce1fbd23216e1a00c2a2f565c7774c59e49ef6b3c255329f4d254147e06e724d3a8569bb7bd21adb84000000000000000000000000000000000000000000000000000128fac3e64dad000000000000000000000000087033ad96757ecd730aa1652b1a7dabcc5ffb182f89994db5889e35e379ef0498aae126fc2cce1fbd23216e1a09f849d23f4955d98202378ea318f2b0c7533695d3c9fb2a3931f0f919fa8c420b860000000000000000000000000000000000000000000acb37f48fe24c23d1833c60000000000000000000000000000000000000000000000000e803e90becaf29b0000000000000000000000000000000000000000000000000e803e90becaf29bf85894db5889e35e379ef0498aae126fc2cce1fbd23216e1a0522881958b3c4a6fc0840ad3b7fb947b881edc28c004245a62541647422ade97a00000000000000000000000000000000000000000000000000e803e90becaf29b", - "0xb903e402f903e00183128fdcb9010000000000010000000000000000000000000000000000010000000000040000000000000000000000000008000000000002000000080020000000000000000000000000000000000808000008000000000000000000410000000000000000000000000000000000000000040000000000000000000000040000000010000800000000000000000000200000000000000000000000010000000000000000000000000000000000200000000000010000000000000000000000002000000008000000000002000000000000080000000000000000000000000000000002000000000000200000000000000010000000000000000000000000000000000000000000f902d5f89b94c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa000000000000000000000000088e6a0c2ddd26feeb64f039a2c41296fcb3f5640a00000000000000000000000008e30dead12d19228cf9cdc984f237f0ad00df195a000000000000000000000000000000000000000000000000000b5762b8f483dbff89b94a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa0000000000000000000000000f706190050f8c7d62021d5ba52871640ea9fd3fea000000000000000000000000088e6a0c2ddd26feeb64f039a2c41296fcb3f5640a0000000000000000000000000000000000000000000000000000000000629852ff9011c9488e6a0c2ddd26feeb64f039a2c41296fcb3f5640f863a0c42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca67a00000000000000000000000008e30dead12d19228cf9cdc984f237f0ad00df195a00000000000000000000000008e30dead12d19228cf9cdc984f237f0ad00df195b8a0000000000000000000000000000000000000000000000000000000000629852fffffffffffffffffffffffffffffffffffffffffffffffffff4a89d470b7c24100000000000000000000000000000000000056d8c2fe7c57e75b18c386394ff90000000000000000000000000000000000000000000000016397a5e7cf05707c0000000000000000000000000000000000000000000000000000000000030e04f87a94c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f842a07fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65a00000000000000000000000008e30dead12d19228cf9cdc984f237f0ad00df195a000000000000000000000000000000000000000000000000000b5762b8f483dbf", - "0xb901ab02f901a701831345f7b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000200000000000000000000000004000000000008000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000080000000000000008000000000000000000000000000000000000000000000000100000000000000000000010000000000000000000000001000000000000000000000000000000000000f89df89b9496add417293a49e80f024734e96cfd8b355bcc14f863a08c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925a0000000000000000000000000af56ec1d3a54e9d05fbe2bc158219a810890dc77a0000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba3a0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "0xb9053d02f90539018315a059b9010000210000000000100000100080000000000000000000000080000000000000000000000000000000000000000000000002010000080000000000000000080000000020080000800000000008000000208000000000400000000000000020000000000000000000000000000000000000000000000000040000000010000000000040004000000000000000000000000000000000000000080000004000000000000000000000000000000000000000000400000000080000000000000008000000000002000000000000000000000000000400400000101000000002000202000000200000000000000000000001000000001000000000000000000000000400f9042ef8fd94000000000022d473030f116ddee9f6b43ac78ba3f884a0c6a377bfc4eb120024a8ac08eef205be16b817020812c73223e81d1bdb9708eca0000000000000000000000000af56ec1d3a54e9d05fbe2bc158219a810890dc77a000000000000000000000000096add417293a49e80f024734e96cfd8b355bcc14a00000000000000000000000003fc91a3afd70395cd496c647d5a6cc9d4b2b7fadb860000000000000000000000000ffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000658c27210000000000000000000000000000000000000000000000000000000000000000f89b9496add417293a49e80f024734e96cfd8b355bcc14f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa0000000000000000000000000af56ec1d3a54e9d05fbe2bc158219a810890dc77a00000000000000000000000000bee64a7c035fa2f69b9a6cad5d761de038ecb02a000000000000000000000000000000000000000000000000c83b84b800fe98c96f89b94c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa00000000000000000000000000bee64a7c035fa2f69b9a6cad5d761de038ecb02a00000000000000000000000003fc91a3afd70395cd496c647d5a6cc9d4b2b7fada000000000000000000000000000000000000000000000000001e7841cb75e9302f879940bee64a7c035fa2f69b9a6cad5d761de038ecb02e1a01c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1b840000000000000000000000000000000000000000000004581511bfd43276c16b400000000000000000000000000000000000000000000000a99e131364ae486cff8fc940bee64a7c035fa2f69b9a6cad5d761de038ecb02f863a0d78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822a00000000000000000000000003fc91a3afd70395cd496c647d5a6cc9d4b2b7fada00000000000000000000000003fc91a3afd70395cd496c647d5a6cc9d4b2b7fadb88000000000000000000000000000000000000000000000000c83b84b800fe98c960000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e7841cb75e9302f87a94c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f842a07fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65a00000000000000000000000003fc91a3afd70395cd496c647d5a6cc9d4b2b7fada000000000000000000000000000000000000000000000000001e7841cb75e9302", - "0xb9010d02f90109018315f261b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0" -] diff --git a/op-service/rpc/cli.go b/op-service/rpc/cli.go index 99cb2dd6c9b22..ef957765e19f3 100644 --- a/op-service/rpc/cli.go +++ b/op-service/rpc/cli.go @@ -21,7 +21,7 @@ func CLIFlags(envPrefix string) []cli.Flag { &cli.StringFlag{ Name: ListenAddrFlagName, Usage: "rpc listening address", - Value: "0.0.0.0", // TODO(CLI-4159): Switch to 127.0.0.1 + Value: "0.0.0.0", // TODO: Switch to 127.0.0.1 EnvVars: opservice.PrefixEnvVar(envPrefix, "RPC_ADDR"), }, &cli.IntFlag{ diff --git a/op-service/solabi/util.go b/op-service/solabi/util.go index ce26aaf76c58a..41c01106a323c 100644 --- a/op-service/solabi/util.go +++ b/op-service/solabi/util.go @@ -69,7 +69,7 @@ func ReadUint64(r io.Reader) (uint64, error) { return n, fmt.Errorf("number padding was not empty: %x", readPadding[:]) } if err := binary.Read(r, binary.BigEndian, &n); err != nil { - return 0, fmt.Errorf("expected number length to be 8 bytes") + return 0, errors.New("expected number length to be 8 bytes") } return n, nil } diff --git a/op-service/sources/batching/batching.go b/op-service/sources/batching/batching.go index 0cf88f7027046..50fd76da94523 100644 --- a/op-service/sources/batching/batching.go +++ b/op-service/sources/batching/batching.go @@ -2,6 +2,7 @@ package batching import ( "context" + "errors" "fmt" "io" "sync" @@ -176,7 +177,7 @@ func (ibc *IterativeBatchCall[K, V]) Result() ([]V, error) { ibc.resetLock.RLock() if atomic.LoadUint32(&ibc.completed) < uint32(len(ibc.requestsKeys)) { ibc.resetLock.RUnlock() - return nil, fmt.Errorf("results not available yet, Fetch more first") + return nil, errors.New("results not available yet, Fetch more first") } ibc.resetLock.RUnlock() return ibc.requestsValues, nil diff --git a/op-service/sources/batching/test/abi_stub.go b/op-service/sources/batching/test/abi_stub.go index 12b9aecebf2d0..431c77c8dbd44 100644 --- a/op-service/sources/batching/test/abi_stub.go +++ b/op-service/sources/batching/test/abi_stub.go @@ -35,7 +35,7 @@ func (c *expectedCall) Matches(rpcMethod string, args ...interface{}) error { } callOpts, ok := args[0].(map[string]any) if !ok { - return fmt.Errorf("arg 0 is not a map[string]any") + return errors.New("arg 0 is not a map[string]any") } actualBlockRef := args[1] to, ok := callOpts["to"].(*common.Address) diff --git a/op-service/sources/engine_client.go b/op-service/sources/engine_client.go index 07d7ecb9d2716..79921192f9e75 100644 --- a/op-service/sources/engine_client.go +++ b/op-service/sources/engine_client.go @@ -50,9 +50,10 @@ func NewEngineClient(client client.RPC, log log.Logger, metrics caching.Metrics, // EngineAPIClient is an RPC client for the Engine API functions. type EngineAPIClient struct { - RPC client.RPC - log log.Logger - evp EngineVersionProvider + RPC client.RPC + log log.Logger + evp EngineVersionProvider + timeout time.Duration } type EngineVersionProvider interface { @@ -63,9 +64,19 @@ type EngineVersionProvider interface { func NewEngineAPIClient(rpc client.RPC, l log.Logger, evp EngineVersionProvider) *EngineAPIClient { return &EngineAPIClient{ - RPC: rpc, - log: l, - evp: evp, + RPC: rpc, + log: l, + evp: evp, + timeout: time.Second * 5, + } +} + +func NewEngineAPIClientWithTimeout(rpc client.RPC, l log.Logger, evp EngineVersionProvider, timeout time.Duration) *EngineAPIClient { + return &EngineAPIClient{ + RPC: rpc, + log: l, + evp: evp, + timeout: timeout, } } @@ -84,7 +95,7 @@ func (s *EngineAPIClient) ForkchoiceUpdate(ctx context.Context, fc *eth.Forkchoi 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) + fcCtx, cancel := context.WithTimeout(ctx, s.timeout) defer cancel() var result eth.ForkchoiceUpdatedResult method := s.evp.ForkchoiceUpdatedVersion(attributes) @@ -120,7 +131,7 @@ func (s *EngineAPIClient) NewPayload(ctx context.Context, payload *eth.Execution e := s.log.New("block_hash", payload.BlockHash) e.Trace("sending payload for execution") - execCtx, cancel := context.WithTimeout(ctx, time.Second*5) + execCtx, cancel := context.WithTimeout(ctx, s.timeout) defer cancel() var result eth.PayloadStatusV1 diff --git a/op-service/sources/eth_client.go b/op-service/sources/eth_client.go index 22ace823de29f..2686e964797d9 100644 --- a/op-service/sources/eth_client.go +++ b/op-service/sources/eth_client.go @@ -11,6 +11,7 @@ package sources import ( "context" + "errors" "fmt" "math/big" "time" @@ -62,11 +63,6 @@ type EthClientConfig struct { // till we re-attempt the user-preferred methods. // If this is 0 then the client does not fall back to less optimal but available methods. MethodResetDuration time.Duration - - // [OPTIONAL] The reth DB path to fetch receipts from. - // If it is specified, the rethdb receipts fetcher will be used - // and the RPC configuration parameters don't need to be set. - RethDBPath string } func (c *EthClientConfig) Check() error { @@ -82,15 +78,6 @@ func (c *EthClientConfig) Check() error { if c.PayloadsCacheSize < 0 { return fmt.Errorf("invalid payloads cache size: %d", c.PayloadsCacheSize) } - if c.RethDBPath != "" { - if buildRethdb { - // If the rethdb path is set, we use the rethdb receipts fetcher and skip creating - // an RCP receipts fetcher, so below rpc config parameters don't need to be checked. - return nil - } else { - return fmt.Errorf("rethdb path specified, but built without rethdb support") - } - } if c.MaxConcurrentRequests < 1 { return fmt.Errorf("expected at least 1 concurrent request, but max is %d", c.MaxConcurrentRequests) } @@ -136,9 +123,9 @@ func NewEthClient(client client.RPC, log log.Logger, metrics caching.Metrics, co } client = LimitRPC(client, config.MaxConcurrentRequests) - recProvider := newRecProviderFromConfig(client, log, metrics, config) + recProvider := newRPCRecProviderFromConfig(client, log, metrics, config) if recProvider.isInnerNil() { - return nil, fmt.Errorf("failed to open RethDB") + return nil, errors.New("failed to establish receipts provider") } return &EthClient{ client: client, diff --git a/op-service/sources/l2_client.go b/op-service/sources/l2_client.go index 92244deea0ef2..b21b8a9600efc 100644 --- a/op-service/sources/l2_client.go +++ b/op-service/sources/l2_client.go @@ -103,7 +103,7 @@ func (s *L2Client) L2BlockRefByLabel(ctx context.Context, label eth.BlockLabel) if err != nil { // Both geth and erigon like to serve non-standard errors for the safe and finalized heads, correct that. // This happens when the chain just started and nothing is marked as safe/finalized yet. - if strings.Contains(err.Error(), "block not found") || strings.Contains(err.Error(), "Unknown block") || strings.Contains(err.Error(), "unknown block") { + if strings.Contains(err.Error(), "block not found") || strings.Contains(err.Error(), "Unknown block") || strings.Contains(err.Error(), "unknown block") || strings.Contains(err.Error(), "header not found") { err = ethereum.NotFound } // w%: wrap to preserve ethereum.NotFound case diff --git a/op-service/sources/limit_test.go b/op-service/sources/limit_test.go index ed59e0287ec16..5bea12046779a 100644 --- a/op-service/sources/limit_test.go +++ b/op-service/sources/limit_test.go @@ -2,7 +2,7 @@ package sources import ( "context" - "fmt" + "errors" "net" "sync/atomic" "testing" @@ -97,10 +97,10 @@ func TestLimitClient(t *testing.T) { // None of the clients should return yet } - m.errC <- fmt.Errorf("fake-error") - m.errC <- fmt.Errorf("fake-error") + m.errC <- errors.New("fake-error") + m.errC <- errors.New("fake-error") require.Eventually(t, func() bool { return m.blockedCallers.Load() == 1 }, time.Second, 10*time.Millisecond) - m.errC <- fmt.Errorf("fake-error") + m.errC <- errors.New("fake-error") require.ErrorContains(t, <-errC1, "fake-error") require.ErrorContains(t, <-errC2, "fake-error") diff --git a/op-service/sources/reth_db.go b/op-service/sources/reth_db.go deleted file mode 100644 index aff8d491c0c6d..0000000000000 --- a/op-service/sources/reth_db.go +++ /dev/null @@ -1,125 +0,0 @@ -//go:build rethdb - -package sources - -import ( - "context" - "encoding/json" - "fmt" - "unsafe" - - "github.com/ethereum-optimism/optimism/op-service/client" - "github.com/ethereum-optimism/optimism/op-service/eth" - "github.com/ethereum-optimism/optimism/op-service/sources/caching" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/log" -) - -/* -#cgo LDFLAGS: -L../rethdb-reader/target/release -lrethdbreader -#include -#include -#include -#include - -typedef struct { - char* data; - size_t data_len; - bool error; -} ReceiptsResult; - -typedef struct OpenDBResult { - const void *data; - bool error; -} OpenDBResult; - -extern ReceiptsResult rdb_read_receipts(const uint8_t* block_hash, size_t block_hash_len, const void *db_instance); -extern void rdb_free_string(char* string); -extern OpenDBResult open_db_read_only(const char *db_path); -*/ -import "C" - -// FetchRethReceipts fetches the receipts for the given block hash directly from the Reth Database -// and populates the given results slice pointer with the receipts that were found. -func FetchRethReceipts(db unsafe.Pointer, blockHash *common.Hash) (types.Receipts, error) { - if blockHash == nil { - return nil, fmt.Errorf("Must provide a block hash to fetch receipts for.") - } - - // Convert the block hash to a C byte array and defer its deallocation - cBlockHash := C.CBytes(blockHash[:]) - defer C.free(cBlockHash) - - // Call the C function to fetch the receipts from the Reth Database - receiptsResult := C.rdb_read_receipts((*C.uint8_t)(cBlockHash), C.size_t(len(blockHash)), db) - - if receiptsResult.error { - return nil, fmt.Errorf("Error fetching receipts from Reth Database.") - } - - // Free the memory allocated by the C code - defer C.rdb_free_string(receiptsResult.data) - - // Convert the returned JSON string to Go string and parse it - receiptsJSON := C.GoStringN(receiptsResult.data, C.int(receiptsResult.data_len)) - var receipts types.Receipts - if err := json.Unmarshal([]byte(receiptsJSON), &receipts); err != nil { - return nil, err - } - - return receipts, nil -} - -func OpenDBReadOnly(dbPath string) (db unsafe.Pointer, err error) { - // Convert the db path to a C string and defer its deallocation - cDbPath := C.CString(dbPath) - defer C.free(unsafe.Pointer(cDbPath)) - - // Call the C function to fetch the receipts from the Reth Database - openDBResult := C.open_db_read_only(cDbPath) - - if openDBResult.error { - return nil, fmt.Errorf("failed to open RethDB") - } - - return openDBResult.data, nil -} - -type RethDBReceiptsFetcher struct { - dbInstance unsafe.Pointer -} - -var _ ReceiptsProvider = (*RethDBReceiptsFetcher)(nil) - -// NewRethDBReceiptsFetcher opens a RethDB for reading receipts. It returns nil if it was unable to open the database -func NewRethDBReceiptsFetcher(dbPath string) *RethDBReceiptsFetcher { - db, err := OpenDBReadOnly(dbPath) - if err != nil { - return nil - } - return &RethDBReceiptsFetcher{ - dbInstance: db, - } -} - -func (f *RethDBReceiptsFetcher) FetchReceipts(ctx context.Context, block eth.BlockInfo, txHashes []common.Hash) (types.Receipts, error) { - if f.dbInstance == nil { - return nil, fmt.Errorf("Reth dbInstance is nil") - } - hash := block.Hash() - return FetchRethReceipts(f.dbInstance, &hash) -} - -func NewCachingRethDBReceiptsFetcher(dbPath string, m caching.Metrics, cacheSize int) *CachingReceiptsProvider { - return NewCachingReceiptsProvider(NewRethDBReceiptsFetcher(dbPath), m, cacheSize) -} - -const buildRethdb = true - -func newRecProviderFromConfig(client client.RPC, log log.Logger, metrics caching.Metrics, config *EthClientConfig) *CachingReceiptsProvider { - if dbPath := config.RethDBPath; dbPath != "" { - return NewCachingRethDBReceiptsFetcher(dbPath, metrics, config.ReceiptsCacheSize) - } - return newRPCRecProviderFromConfig(client, log, metrics, config) -} diff --git a/op-service/sources/reth_db_stub.go b/op-service/sources/reth_db_stub.go deleted file mode 100644 index 2ddc9c5451682..0000000000000 --- a/op-service/sources/reth_db_stub.go +++ /dev/null @@ -1,15 +0,0 @@ -//go:build !rethdb - -package sources - -import ( - "github.com/ethereum-optimism/optimism/op-service/client" - "github.com/ethereum-optimism/optimism/op-service/sources/caching" - "github.com/ethereum/go-ethereum/log" -) - -const buildRethdb = false - -func newRecProviderFromConfig(client client.RPC, log log.Logger, metrics caching.Metrics, config *EthClientConfig) *CachingReceiptsProvider { - return newRPCRecProviderFromConfig(client, log, metrics, config) -} diff --git a/op-service/sources/reth_db_test.go b/op-service/sources/reth_db_test.go deleted file mode 100644 index d52042c439f26..0000000000000 --- a/op-service/sources/reth_db_test.go +++ /dev/null @@ -1,45 +0,0 @@ -//go:build rethdb - -package sources - -import ( - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/stretchr/testify/require" -) - -func TestRethDBReceiptsLoad(t *testing.T) { - t.Parallel() - - // ETH Mainnet block #18,663,292 - // - // https://etherscan.io/tx/0x88b2d153a4e893ba91ac235325c44b1aa0c802fcb42657701e1a73e1c675f7ca - // - // NOTE: The block hash differs from the live block due to a state root mismatch. In order to generate - // a testdata database with only this block in it, the state root of the block was modified. - // Old State Root: 0xaf81a692d228d56d35c80d65aeba59636b4671403054f6c57446c0e3e4d951c8 - // New State Root (Empty MPT): 0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421 - blockHash := common.HexToHash("0x6a229123d607c2232a8b0bdd36f90745945d05181018e64e60ff2b93ab6b52e5") - fetcher := NewRethDBReceiptsFetcher("../rethdb-reader/testdata/db") - require.NotNil(t, fetcher.dbInstance) - res, err := FetchRethReceipts(fetcher.dbInstance, &blockHash) - require.NoError(t, err) - - receipt := (*types.Receipt)(res[0]) - 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.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.FromHex("00000000000000000000000000000000000000000000000008a30cd230000000")) - require.Equal(t, receipt.TxHash, common.HexToHash("0x88b2d153a4e893ba91ac235325c44b1aa0c802fcb42657701e1a73e1c675f7ca")) - - require.Equal(t, receipt.BlockHash, blockHash) - require.Equal(t, receipt.BlockNumber, big.NewInt(18_663_292)) - require.Equal(t, receipt.TransactionIndex, uint(0)) -} diff --git a/op-service/sources/supervisor_client.go b/op-service/sources/supervisor_client.go new file mode 100644 index 0000000000000..db40e55ef4724 --- /dev/null +++ b/op-service/sources/supervisor_client.go @@ -0,0 +1,84 @@ +package sources + +import ( + "context" + "fmt" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + + "github.com/ethereum-optimism/optimism/op-service/client" + "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" +) + +type SupervisorClient struct { + client client.RPC +} + +func NewSupervisorClient(client client.RPC) *SupervisorClient { + return &SupervisorClient{ + client: client, + } +} + +func (cl *SupervisorClient) Stop( + ctx context.Context, +) error { + var result error + err := cl.client.CallContext( + ctx, + &result, + "admin_stop") + if err != nil { + return fmt.Errorf("failed to stop Supervisor: %w", err) + } + return result +} + +func (cl *SupervisorClient) Start( + ctx context.Context, +) error { + var result error + err := cl.client.CallContext( + ctx, + &result, + "admin_start") + if err != nil { + return fmt.Errorf("failed to start Supervisor: %w", err) + } + return result +} + +func (cl *SupervisorClient) AddL2RPC( + ctx context.Context, + rpc string, +) error { + var result error + err := cl.client.CallContext( + ctx, + &result, + "admin_addL2RPC", + rpc) + if err != nil { + return fmt.Errorf("failed to Add L2 to Supervisor (rpc: %s): %w", rpc, err) + } + return result +} + +func (cl *SupervisorClient) CheckBlock(ctx context.Context, + chainID types.ChainID, blockHash common.Hash, blockNumber uint64) (types.SafetyLevel, error) { + var result types.SafetyLevel + err := cl.client.CallContext( + ctx, + &result, + "supervisor_checkBlock", + (*hexutil.U256)(&chainID), blockHash, hexutil.Uint64(blockNumber)) + if err != nil { + return types.Unsafe, fmt.Errorf("failed to check Block %s:%d (chain %s): %w", blockHash, blockNumber, chainID, err) + } + return result, nil +} + +func (cl *SupervisorClient) Close() { + cl.client.Close() +} diff --git a/op-service/sources/types.go b/op-service/sources/types.go index afb994bd7cc35..f337beb020587 100644 --- a/op-service/sources/types.go +++ b/op-service/sources/types.go @@ -1,6 +1,7 @@ package sources import ( + "errors" "fmt" "math/big" "strings" @@ -229,7 +230,7 @@ func (block *RPCBlock) verify() error { } if block.WithdrawalsRoot != nil { if block.Withdrawals == nil { - return fmt.Errorf("expected withdrawals") + return errors.New("expected withdrawals") } for i, w := range *block.Withdrawals { if w == nil { diff --git a/op-service/testutils/fake_chain.go b/op-service/testutils/fake_chain.go index 8110e37779f15..eca4de1160b68 100644 --- a/op-service/testutils/fake_chain.go +++ b/op-service/testutils/fake_chain.go @@ -14,9 +14,9 @@ import ( "github.com/ethereum-optimism/optimism/op-service/eth" ) -func FakeGenesis(l1 rune, l2 rune, l1GenesisNumber int) rollup.Genesis { +func FakeGenesis(l1 rune, l2 rune, l1GenesisNumber uint64) rollup.Genesis { return rollup.Genesis{ - L1: fakeID(l1, uint64(l1GenesisNumber)), + L1: fakeID(l1, l1GenesisNumber), L2: fakeID(l2, 0), } } diff --git a/op-service/testutils/kurtosisutil/kurtosis.go b/op-service/testutils/kurtosisutil/kurtosis.go new file mode 100644 index 0000000000000..8be6c9b3f2c70 --- /dev/null +++ b/op-service/testutils/kurtosisutil/kurtosis.go @@ -0,0 +1,12 @@ +package kurtosisutil + +import ( + "os" + "testing" +) + +func Test(t *testing.T) { + if os.Getenv("ENABLE_KURTOSIS") == "" { + t.Skip("skipping Kurtosis test") + } +} diff --git a/op-service/testutils/kurtosisutil/runner.go b/op-service/testutils/kurtosisutil/runner.go new file mode 100644 index 0000000000000..6440cedef681c --- /dev/null +++ b/op-service/testutils/kurtosisutil/runner.go @@ -0,0 +1,64 @@ +package kurtosisutil + +import ( + "context" + "fmt" + "testing" + "time" + + "github.com/ethereum/go-ethereum/log" + "github.com/kurtosis-tech/kurtosis/api/golang/core/lib/enclaves" + "github.com/kurtosis-tech/kurtosis/api/golang/core/lib/starlark_run_config" + "github.com/kurtosis-tech/kurtosis/api/golang/engine/lib/kurtosis_context" + "github.com/stretchr/testify/require" +) + +func StartEnclave(t *testing.T, ctx context.Context, lgr log.Logger, pkg string, params string) *enclaves.EnclaveContext { + kurtosisCtx, err := kurtosis_context.NewKurtosisContextFromLocalEngine() + require.NoError(t, err) + + enclaveID := fmt.Sprintf("kurtosis-%s", t.Name()) + enclaveCtx, err := kurtosisCtx.CreateEnclave(ctx, enclaveID) + require.NoError(t, err) + + t.Cleanup(func() { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + err = kurtosisCtx.DestroyEnclave(ctx, enclaveID) + if err != nil { + lgr.Error("Error destroying enclave", "err", err) + } + }) + + stream, _, err := enclaveCtx.RunStarlarkRemotePackage( + ctx, + pkg, + &starlark_run_config.StarlarkRunConfig{ + SerializedParams: params, + }, + ) + require.NoError(t, err) + + logKurtosisOutput := func(msg string) { + lgr.Info(fmt.Sprintf("[KURTOSIS] %s", msg)) + } + + for responseLine := range stream { + if responseLine.GetProgressInfo() != nil { + stepInfo := responseLine.GetProgressInfo().CurrentStepInfo + logKurtosisOutput(stepInfo[len(stepInfo)-1]) + } else if responseLine.GetInstruction() != nil { + logKurtosisOutput(responseLine.GetInstruction().Description) + } else if responseLine.GetError() != nil { + if responseLine.GetError().GetInterpretationError() != nil { + t.Fatalf("interpretation error: %s", responseLine.GetError().GetInterpretationError().String()) + } else if responseLine.GetError().GetValidationError() != nil { + t.Fatalf("validation error: %s", responseLine.GetError().GetValidationError().String()) + } else if responseLine.GetError().GetExecutionError() != nil { + t.Fatalf("execution error: %s", responseLine.GetError().GetExecutionError().String()) + } + } + } + + return enclaveCtx +} diff --git a/op-service/testutils/metrics.go b/op-service/testutils/metrics.go index 617d2ded3c03a..421d32f2109c5 100644 --- a/op-service/testutils/metrics.go +++ b/op-service/testutils/metrics.go @@ -14,6 +14,7 @@ type TestDerivationMetrics struct { FnRecordL2Ref func(name string, ref eth.L2BlockRef) FnRecordUnsafePayloads func(length uint64, memSize uint64, next eth.BlockID) FnRecordChannelInputBytes func(inputCompressedBytes int) + FnRecordChannelTimedOut func() } func (t *TestDerivationMetrics) CountSequencedTxs(count int) { @@ -59,6 +60,9 @@ func (t *TestDerivationMetrics) RecordHeadChannelOpened() { } func (t *TestDerivationMetrics) RecordChannelTimedOut() { + if t.FnRecordChannelTimedOut != nil { + t.FnRecordChannelTimedOut() + } } func (t *TestDerivationMetrics) RecordFrame() { diff --git a/op-service/testutils/mock_interop_backend.go b/op-service/testutils/mock_interop_backend.go new file mode 100644 index 0000000000000..970627ff750f2 --- /dev/null +++ b/op-service/testutils/mock_interop_backend.go @@ -0,0 +1,28 @@ +package testutils + +import ( + "context" + + "github.com/stretchr/testify/mock" + + "github.com/ethereum/go-ethereum/common" + + "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" +) + +type MockInteropBackend struct { + Mock mock.Mock +} + +func (m *MockInteropBackend) ExpectCheckBlock(chainID types.ChainID, blockNumber uint64, safety types.SafetyLevel, err error) { + m.Mock.On("CheckBlock", chainID, blockNumber).Once().Return(safety, &err) +} + +func (m *MockInteropBackend) CheckBlock(ctx context.Context, chainID types.ChainID, blockHash common.Hash, blockNumber uint64) (types.SafetyLevel, error) { + result := m.Mock.MethodCalled("CheckBlock", chainID, blockNumber) + return result.Get(0).(types.SafetyLevel), *result.Get(1).(*error) +} + +func (m *MockInteropBackend) AssertExpectations(t mock.TestingT) { + m.Mock.AssertExpectations(t) +} diff --git a/op-service/txmgr/cli.go b/op-service/txmgr/cli.go index d073198663325..fe65b6dd126e6 100644 --- a/op-service/txmgr/cli.go +++ b/op-service/txmgr/cli.go @@ -79,7 +79,7 @@ var ( MinBaseFeeGwei: 1.0, ResubmissionTimeout: 48 * time.Second, NetworkTimeout: 10 * time.Second, - TxSendTimeout: 0 * time.Second, + TxSendTimeout: 10 * time.Minute, TxNotInMempoolTimeout: 2 * time.Minute, ReceiptQueryInterval: 12 * time.Second, } diff --git a/op-service/txmgr/mocks/TxManager.go b/op-service/txmgr/mocks/TxManager.go index a6ea6b72a914a..ec805b74d004f 100644 --- a/op-service/txmgr/mocks/TxManager.go +++ b/op-service/txmgr/mocks/TxManager.go @@ -4,6 +4,7 @@ package mocks import ( context "context" + big "math/big" common "github.com/ethereum/go-ethereum/common" @@ -120,6 +121,55 @@ func (_m *TxManager) Send(ctx context.Context, candidate txmgr.TxCandidate) (*ty return r0, r1 } +// SendAsync provides a mock function with given fields: ctx, candidate, ch +func (_m *TxManager) SendAsync(ctx context.Context, candidate txmgr.TxCandidate, ch chan txmgr.SendResponse) { + _m.Called(ctx, candidate, ch) +} + +// SuggestGasPriceCaps provides a mock function with given fields: ctx +func (_m *TxManager) SuggestGasPriceCaps(ctx context.Context) (*big.Int, *big.Int, *big.Int, error) { + ret := _m.Called(ctx) + + var r0 *big.Int + var r1 *big.Int + var r2 *big.Int + var r3 error + if rf, ok := ret.Get(0).(func(context.Context) (*big.Int, *big.Int, *big.Int, error)); ok { + return rf(ctx) + } + if rf, ok := ret.Get(0).(func(context.Context) *big.Int); ok { + r0 = rf(ctx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*big.Int) + } + } + + if rf, ok := ret.Get(1).(func(context.Context) *big.Int); ok { + r1 = rf(ctx) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*big.Int) + } + } + + if rf, ok := ret.Get(2).(func(context.Context) *big.Int); ok { + r2 = rf(ctx) + } else { + if ret.Get(2) != nil { + r2 = ret.Get(2).(*big.Int) + } + } + + if rf, ok := ret.Get(3).(func(context.Context) error); ok { + r3 = rf(ctx) + } else { + r3 = ret.Error(3) + } + + return r0, r1, r2, r3 +} + type mockConstructorTestingTNewTxManager interface { mock.TestingT Cleanup(func()) diff --git a/op-service/txmgr/queue.go b/op-service/txmgr/queue.go index cf83b00d5f8a0..ee7a03ffa9288 100644 --- a/op-service/txmgr/queue.go +++ b/op-service/txmgr/queue.go @@ -44,11 +44,11 @@ func NewQueue[T any](ctx context.Context, txMgr TxManager, maxPending uint64) *Q } // Wait waits for all pending txs to complete (or fail). -func (q *Queue[T]) Wait() { +func (q *Queue[T]) Wait() error { if q.group == nil { - return + return nil } - _ = q.group.Wait() + return q.group.Wait() } // Send will wait until the number of pending txs is below the max pending, diff --git a/op-service/txmgr/queue_test.go b/op-service/txmgr/queue_test.go index 678de8dbb28c3..549142c8592ac 100644 --- a/op-service/txmgr/queue_test.go +++ b/op-service/txmgr/queue_test.go @@ -222,7 +222,7 @@ func TestQueue_Send(t *testing.T) { require.Equal(t, c.queued, queued, msg) } // wait for the queue to drain (all txs complete or failed) - queue.Wait() + _ = queue.Wait() duration := time.Since(start) // expect the execution time within a certain window now := time.Now() diff --git a/op-service/txmgr/send_state.go b/op-service/txmgr/send_state.go index fd64f7dd8396d..38e691fc78f8f 100644 --- a/op-service/txmgr/send_state.go +++ b/op-service/txmgr/send_state.go @@ -37,6 +37,9 @@ type SendState struct { // Whether any attempt to send the tx resulted in ErrAlreadyReserved alreadyReserved bool + // Whether we should bump fees before trying to publish the tx again + bumpFees bool + // Miscellaneous tracking bumpCount int // number of times we have bumped the gas price } @@ -120,6 +123,10 @@ func (s *SendState) CriticalError() error { case s.nonceTooLowCount >= s.safeAbortNonceTooLowCount: // we have exceeded the nonce too low count return core.ErrNonceTooLow + case s.successFullPublishCount == 0 && s.nonceTooLowCount > 0: + // A nonce too low error before successfully publishing any transaction means the tx will + // need a different nonce, which we can force by returning error. + return core.ErrNonceTooLow case s.successFullPublishCount == 0 && s.now().After(s.txInMempoolDeadline): // unable to get the tx into the mempool in the allotted time return ErrMempoolDeadlineExpired diff --git a/op-service/txmgr/send_state_test.go b/op-service/txmgr/send_state_test.go index 20bfe155ed97e..d48db5fd15144 100644 --- a/op-service/txmgr/send_state_test.go +++ b/op-service/txmgr/send_state_test.go @@ -58,11 +58,21 @@ func TestSendStateNoAbortAfterProcessOtherError(t *testing.T) { require.Nil(t, sendState.CriticalError()) } +// TestSendStateAbortSafelyAfterNonceTooLowButNoTxMined asserts that we will abort after the very +// first none-too-low error if a tx hasn't yet been published. +func TestSendStateAbortSafelyAfterNonceTooLowNoTxPublished(t *testing.T) { + sendState := newSendState() + + sendState.ProcessSendError(core.ErrNonceTooLow) + require.ErrorIs(t, sendState.CriticalError(), core.ErrNonceTooLow) +} + // TestSendStateAbortSafelyAfterNonceTooLowButNoTxMined asserts that we will // abort after the safe abort interval has elapsed if we haven't mined a tx. func TestSendStateAbortSafelyAfterNonceTooLowButNoTxMined(t *testing.T) { sendState := newSendState() + sendState.ProcessSendError(nil) sendState.ProcessSendError(core.ErrNonceTooLow) require.Nil(t, sendState.CriticalError()) sendState.ProcessSendError(core.ErrNonceTooLow) @@ -90,6 +100,7 @@ func TestSendStateMiningTxCancelsAbort(t *testing.T) { func TestSendStateReorgingTxResetsAbort(t *testing.T) { sendState := newSendState() + sendState.ProcessSendError(nil) sendState.ProcessSendError(core.ErrNonceTooLow) sendState.ProcessSendError(core.ErrNonceTooLow) sendState.TxMined(testHash) @@ -120,6 +131,7 @@ func TestSendStateNoAbortEvenIfNonceTooLowAfterTxMined(t *testing.T) { func TestSendStateSafeAbortIfNonceTooLowPersistsAfterUnmine(t *testing.T) { sendState := newSendState() + sendState.ProcessSendError(nil) sendState.TxMined(testHash) sendState.TxNotMined(testHash) sendState.ProcessSendError(core.ErrNonceTooLow) diff --git a/op-service/txmgr/txmgr.go b/op-service/txmgr/txmgr.go index 49a76aa7e5bbf..6fa0ea5dc15ad 100644 --- a/op-service/txmgr/txmgr.go +++ b/op-service/txmgr/txmgr.go @@ -46,6 +46,12 @@ var ( ErrClosed = errors.New("transaction manager is closed") ) +type SendResponse struct { + Receipt *types.Receipt + Nonce uint64 + Err error +} + // TxManager is an interface that allows callers to reliably publish txs, // bumping the gas price if needed, and obtain the receipt of the resulting tx. // @@ -53,8 +59,8 @@ var ( type TxManager interface { // Send is used to create & send a transaction. It will handle increasing // the gas price & ensuring that the transaction remains in the transaction pool. - // It can be stopped by cancelling the provided context; however, the transaction - // may be included on L1 even if the context is cancelled. + // It can be stopped by canceling the provided context; however, the transaction + // may be included on L1 even if the context is canceled. // // NOTE: Send can be called concurrently, the nonce will be managed internally. // @@ -63,6 +69,14 @@ type TxManager interface { // mempool and is in need of replacement or cancellation. Send(ctx context.Context, candidate TxCandidate) (*types.Receipt, error) + // SendAsync is used to create & send a transaction asynchronously. It has similar internal + // semantics to Send, however it returns a channel that will receive the result of the + // send operation once it completes. Transactions crafted synchronously - that is, nonce + // management and gas estimation happen prior to the method returning. This allows callers + // that rely on predictable nonces to send multiple transactions in parallel while preserving + // the order of nonce increments. + SendAsync(ctx context.Context, candidate TxCandidate, ch chan SendResponse) + // From returns the sending address associated with the instance of the transaction manager. // It is static for a single instance of a TxManager. From() common.Address @@ -76,6 +90,10 @@ type TxManager interface { // Close the underlying connection Close() IsClosed() bool + + // SuggestGasPriceCaps suggests what the new tip, base fee, and blob base fee should be based on + // the current L1 conditions. `blobBaseFee` will be nil if 4844 is not yet active. + SuggestGasPriceCaps(ctx context.Context) (tipCap *big.Int, baseFee *big.Int, blobBaseFee *big.Int, err error) } // ETHBackend is the set of methods that the transaction manager uses to resubmit gas & determine @@ -96,7 +114,7 @@ type ETHBackend interface { SendTransaction(ctx context.Context, tx *types.Transaction) error // These functions are used to estimate what the base fee & priority fee should be set to. - // TODO(CLI-3318): Maybe need a generic interface to support different RPC providers + // TODO: Maybe need a generic interface to support different RPC providers HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) SuggestGasTipCap(ctx context.Context) (*big.Int, error) // NonceAt returns the account nonce of the given account. @@ -222,24 +240,83 @@ func (m *SimpleTxManager) Send(ctx context.Context, candidate TxCandidate) (*typ if m.closed.Load() { return nil, ErrClosed } + m.metr.RecordPendingTx(m.pending.Add(1)) - defer func() { - m.metr.RecordPendingTx(m.pending.Add(-1)) - }() - receipt, err := m.send(ctx, candidate) + defer m.metr.RecordPendingTx(m.pending.Add(-1)) + + var cancel context.CancelFunc + if m.cfg.TxSendTimeout == 0 { + ctx, cancel = context.WithCancel(ctx) + } else { + ctx, cancel = context.WithTimeout(ctx, m.cfg.TxSendTimeout) + } + defer cancel() + + tx, err := m.prepare(ctx, candidate) if err != nil { m.resetNonce() + return nil, err + } + receipt, err := m.sendTx(ctx, tx) + if err != nil { + m.resetNonce() + return nil, err } return receipt, err } -// send performs the actual transaction creation and sending. -func (m *SimpleTxManager) send(ctx context.Context, candidate TxCandidate) (*types.Receipt, error) { - if m.cfg.TxSendTimeout != 0 { - var cancel context.CancelFunc +func (m *SimpleTxManager) SendAsync(ctx context.Context, candidate TxCandidate, ch chan SendResponse) { + if cap(ch) == 0 { + panic("SendAsync: channel must be buffered") + } + + // refuse new requests if the tx manager is closed + if m.closed.Load() { + ch <- SendResponse{ + Receipt: nil, + Err: ErrClosed, + } + return + } + + m.metr.RecordPendingTx(m.pending.Add(1)) + + var cancel context.CancelFunc + if m.cfg.TxSendTimeout == 0 { + ctx, cancel = context.WithCancel(ctx) + } else { ctx, cancel = context.WithTimeout(ctx, m.cfg.TxSendTimeout) - defer cancel() } + + tx, err := m.prepare(ctx, candidate) + if err != nil { + m.resetNonce() + cancel() + m.metr.RecordPendingTx(m.pending.Add(-1)) + ch <- SendResponse{ + Receipt: nil, + Err: err, + } + return + } + + go func() { + defer m.metr.RecordPendingTx(m.pending.Add(-1)) + defer cancel() + receipt, err := m.sendTx(ctx, tx) + if err != nil { + m.resetNonce() + } + ch <- SendResponse{ + Receipt: receipt, + Nonce: tx.Nonce(), + Err: err, + } + }() +} + +// prepare prepares the transaction for sending. +func (m *SimpleTxManager) prepare(ctx context.Context, candidate TxCandidate) (*types.Transaction, error) { tx, err := retry.Do(ctx, 30, retry.Fixed(2*time.Second), func() (*types.Transaction, error) { if m.closed.Load() { return nil, ErrClosed @@ -253,7 +330,7 @@ func (m *SimpleTxManager) send(ctx context.Context, candidate TxCandidate) (*typ if err != nil { return nil, fmt.Errorf("failed to create the tx: %w", err) } - return m.sendTx(ctx, tx) + return tx, nil } // craftTx creates the signed transaction @@ -303,7 +380,7 @@ func (m *SimpleTxManager) craftTx(ctx context.Context, candidate TxCandidate) (* var txMessage types.TxData if sidecar != nil { if blobBaseFee == nil { - return nil, fmt.Errorf("expected non-nil blobBaseFee") + return nil, errors.New("expected non-nil blobBaseFee") } blobFeeCap := m.calcBlobFeeCap(blobBaseFee) message := &types.BlobTx{ @@ -470,44 +547,33 @@ func (m *SimpleTxManager) sendTx(ctx context.Context, tx *types.Transaction) (*t sendState := NewSendState(m.cfg.SafeAbortNonceTooLowCount, m.cfg.TxNotInMempoolTimeout) receiptChan := make(chan *types.Receipt, 1) - publishAndWait := func(tx *types.Transaction, bumpFees bool) *types.Transaction { - wg.Add(1) - tx, published := m.publishTx(ctx, tx, sendState, bumpFees) - if published { - go func() { - defer wg.Done() - m.waitForTx(ctx, tx, sendState, receiptChan) - }() - } else { - wg.Done() - } - return tx - } - - // Immediately publish a transaction before starting the resubmission loop - tx = publishAndWait(tx, false) - resubmissionTimeout := m.GetBumpFeeRetryTime() ticker := time.NewTicker(resubmissionTimeout) defer ticker.Stop() for { + if !sendState.IsWaitingForConfirmation() { + if m.closed.Load() { + // the tx manager closed and no txs are waiting to be confirmed, give up + m.txLogger(tx, false).Warn("TxManager closed, aborting transaction submission") + return nil, ErrClosed + } + var published bool + if tx, published = m.publishTx(ctx, tx, sendState); published { + wg.Add(1) + go func() { + defer wg.Done() + m.waitForTx(ctx, tx, sendState, receiptChan) + }() + } + } 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 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") - return nil, ErrClosed - } - tx = publishAndWait(tx, true) case <-ctx.Done(): return nil, ctx.Err() @@ -523,34 +589,34 @@ func (m *SimpleTxManager) sendTx(ctx context.Context, tx *types.Transaction) (*t // publishTx publishes the transaction to the transaction pool. If it receives any underpriced errors // it will bump the fees and retry. // Returns the latest fee bumped tx, and a boolean indicating whether the tx was sent or not -func (m *SimpleTxManager) publishTx(ctx context.Context, tx *types.Transaction, sendState *SendState, bumpFeesImmediately bool) (*types.Transaction, bool) { +func (m *SimpleTxManager) publishTx(ctx context.Context, tx *types.Transaction, sendState *SendState) (*types.Transaction, bool) { l := m.txLogger(tx, true) l.Info("Publishing transaction", "tx", tx.Hash()) for { - // if the tx manager closed, give up without bumping fees or retrying - if m.closed.Load() { - l.Warn("TxManager closed, aborting transaction submission") - return tx, false - } - if bumpFeesImmediately { - newTx, err := m.increaseGasPrice(ctx, tx) - if err != nil { - l.Error("unable to increase gas", "err", err) + if sendState.bumpFees { + if newTx, err := m.increaseGasPrice(ctx, tx); err != nil { + l.Warn("unable to increase gas, will try to re-publish the tx", "err", err) m.metr.TxPublished("bump_failed") - return tx, false + // Even if we are unable to bump fees, we must still resubmit the transaction + // because a previously successfully published tx can get dropped from the + // mempool. If we don't try to resubmit it to either force a failure (eg. from + // nonce to low errors) or get it back into the mempool, we can end up waiting on + // it to get mined indefinitely. + } else { + if sendState.IsWaitingForConfirmation() { + // A previously published tx might get mined during the increaseGasPrice call + // above, in which case we can abort trying to replace it with a higher fee tx. + return tx, false + } + sendState.bumpCount++ + tx = newTx + l = m.txLogger(tx, true) + // Disable bumping fees again until the new transaction is successfully published, + // or we immediately get another underpriced error. + sendState.bumpFees = false } - tx = newTx - sendState.bumpCount++ - l = m.txLogger(tx, true) - } - bumpFeesImmediately = true // bump fees next loop - - if sendState.IsWaitingForConfirmation() { - // there is a chance the previous tx goes into "waiting for confirmation" state - // during the increaseGasPrice call; continue waiting rather than resubmit the tx - return tx, false } cCtx, cancel := context.WithTimeout(ctx, m.cfg.NetworkTimeout) @@ -561,6 +627,9 @@ func (m *SimpleTxManager) publishTx(ctx context.Context, tx *types.Transaction, if err == nil { m.metr.TxPublished("") l.Info("Transaction successfully published", "tx", tx.Hash()) + // Tx made it into the mempool, so we'll need a fee bump if we end up trying to replace + // it with another publish attempt. + sendState.bumpFees = true return tx, true } @@ -575,26 +644,33 @@ func (m *SimpleTxManager) publishTx(ctx context.Context, tx *types.Transaction, m.metr.TxPublished("nonce_too_low") case errStringMatch(err, context.Canceled): m.metr.RPCError() - l.Warn("transaction send cancelled", "err", err) - m.metr.TxPublished("context_cancelled") + l.Warn("transaction send canceled", "err", err) + m.metr.TxPublished("context_canceled") case errStringMatch(err, txpool.ErrAlreadyKnown): l.Warn("resubmitted already known transaction", "err", err) m.metr.TxPublished("tx_already_known") case errStringMatch(err, txpool.ErrReplaceUnderpriced): l.Warn("transaction replacement is underpriced", "err", err) m.metr.TxPublished("tx_replacement_underpriced") - continue // retry with fee bump + // retry tx with fee bump, unless we already just tried to bump them + if !sendState.bumpFees { + sendState.bumpFees = true + continue + } case errStringMatch(err, txpool.ErrUnderpriced): l.Warn("transaction is underpriced", "err", err) m.metr.TxPublished("tx_underpriced") - continue // retry with fee bump + // retry tx with fee bump, unless we already just tried to bump them + if !sendState.bumpFees { + sendState.bumpFees = true + continue + } default: m.metr.RPCError() l.Error("unable to publish transaction", "err", err) m.metr.TxPublished("unknown_error") } - // on non-underpriced error return immediately; will retry on next resubmission timeout return tx, false } } @@ -617,7 +693,7 @@ func (m *SimpleTxManager) waitForTx(ctx context.Context, tx *types.Transaction, } } -// waitMined waits for the transaction to be mined or for the context to be cancelled. +// waitMined waits for the transaction to be mined or for the context to be canceled. func (m *SimpleTxManager) waitMined(ctx context.Context, tx *types.Transaction, sendState *SendState) (*types.Receipt, error) { txHash := tx.Hash() queryTicker := time.NewTicker(m.cfg.ReceiptQueryInterval) @@ -785,7 +861,7 @@ func (m *SimpleTxManager) increaseGasPrice(ctx context.Context, tx *types.Transa } // SuggestGasPriceCaps suggests what the new tip, base fee, and blob base fee should be based on -// the current L1 conditions. blobfee will be nil if 4844 is not yet active. +// the current L1 conditions. `blobBaseFee` will be nil if 4844 is not yet active. func (m *SimpleTxManager) SuggestGasPriceCaps(ctx context.Context) (*big.Int, *big.Int, *big.Int, error) { cCtx, cancel := context.WithTimeout(ctx, m.cfg.NetworkTimeout) defer cancel() @@ -911,7 +987,7 @@ func updateFees(oldTip, oldFeeCap, newTip, newBaseFee *big.Int, isBlobTx bool, l return newTip, newFeeCap } else if newTip.Cmp(thresholdTip) >= 0 && newFeeCap.Cmp(thresholdFeeCap) < 0 { // Tip has gone up, but base fee is flat or down. - // TODO(CLI-3714): Do we need to recalculate the FC here? + // TODO: Do we need to recalculate the FC here? lgr.Debug("Using new tip and threshold feecap") return newTip, thresholdFeeCap } else if newTip.Cmp(thresholdTip) < 0 && newFeeCap.Cmp(thresholdFeeCap) >= 0 { @@ -921,7 +997,7 @@ func updateFees(oldTip, oldFeeCap, newTip, newBaseFee *big.Int, isBlobTx bool, l return thresholdTip, calcGasFeeCap(newBaseFee, thresholdTip) } else { - // TODO(CLI-3713): Should we skip the bump in this case? + // TODO: Should we skip the bump in this case? lgr.Debug("Using threshold tip and threshold feecap") return thresholdTip, thresholdFeeCap } @@ -964,19 +1040,19 @@ func errStringMatch(err, target error) bool { func finishBlobTx(message *types.BlobTx, chainID, tip, fee, blobFee, value *big.Int) error { var o bool if message.ChainID, o = uint256.FromBig(chainID); o { - return fmt.Errorf("ChainID overflow") + return errors.New("ChainID overflow") } if message.GasTipCap, o = uint256.FromBig(tip); o { - return fmt.Errorf("GasTipCap overflow") + return errors.New("GasTipCap overflow") } if message.GasFeeCap, o = uint256.FromBig(fee); o { - return fmt.Errorf("GasFeeCap overflow") + return errors.New("GasFeeCap overflow") } if message.BlobFeeCap, o = uint256.FromBig(blobFee); o { - return fmt.Errorf("BlobFeeCap overflow") + return errors.New("BlobFeeCap overflow") } if message.Value, o = uint256.FromBig(value); o { - return fmt.Errorf("Value overflow") + return errors.New("Value overflow") } return nil } diff --git a/op-service/txmgr/txmgr_test.go b/op-service/txmgr/txmgr_test.go index e06ecaf98e4f6..6bafa69464b62 100644 --- a/op-service/txmgr/txmgr_test.go +++ b/op-service/txmgr/txmgr_test.go @@ -338,6 +338,27 @@ func (b *mockBackend) TransactionReceipt(ctx context.Context, txHash common.Hash func (b *mockBackend) Close() { } +type testSendVariantsFn func(ctx context.Context, h *testHarness, tx TxCandidate) (*types.Receipt, error) + +func testSendVariants(t *testing.T, testFn func(t *testing.T, send testSendVariantsFn)) { + t.Parallel() + + t.Run("Send", func(t *testing.T) { + testFn(t, func(ctx context.Context, h *testHarness, tx TxCandidate) (*types.Receipt, error) { + return h.mgr.Send(ctx, tx) + }) + }) + + t.Run("SendAsync", func(t *testing.T) { + testFn(t, func(ctx context.Context, h *testHarness, tx TxCandidate) (*types.Receipt, error) { + ch := make(chan SendResponse, 1) + h.mgr.SendAsync(ctx, tx, ch) + res := <-ch + return res.Receipt, res.Err + }) + }) +} + // TestTxMgrConfirmAtMinGasPrice asserts that Send returns the min gas price tx // if the tx is mined instantly. func TestTxMgrConfirmAtMinGasPrice(t *testing.T) { @@ -389,7 +410,7 @@ func TestTxMgrNeverConfirmCancel(t *testing.T) { } h.backend.setTxSender(sendTx) - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() receipt, err := h.mgr.sendTx(ctx, tx) @@ -397,6 +418,37 @@ func TestTxMgrNeverConfirmCancel(t *testing.T) { require.Nil(t, receipt) } +// TestTxMgrTxSendTimeout tests that the TxSendTimeout is respected when trying to send a +// transaction, even if NetworkTimeout expires first. +func TestTxMgrTxSendTimeout(t *testing.T) { + testSendVariants(t, func(t *testing.T, send testSendVariantsFn) { + conf := configWithNumConfs(1) + conf.TxSendTimeout = 3 * time.Second + conf.NetworkTimeout = 1 * time.Second + + h := newTestHarnessWithConfig(t, conf) + + txCandidate := h.createTxCandidate() + sendCount := 0 + sendTx := func(ctx context.Context, tx *types.Transaction) error { + sendCount++ + <-ctx.Done() + return context.DeadlineExceeded + } + h.backend.setTxSender(sendTx) + + ctx, cancel := context.WithTimeout(context.Background(), time.Hour) + defer cancel() + + receipt, err := send(ctx, h, txCandidate) + require.ErrorIs(t, err, context.DeadlineExceeded) + // Because network timeout is much shorter than send timeout, we should see multiple send attempts + // before the overall send fails. + require.Greater(t, sendCount, 1) + require.Nil(t, receipt) + }) +} + // TestAlreadyReserved tests that AlreadyReserved error results in immediate abort of transaction // sending. func TestAlreadyReserved(t *testing.T) { @@ -617,7 +669,7 @@ func TestTxMgr_EstimateGasFails(t *testing.T) { lastNonce := tx.Nonce() // Mock gas estimation failure. - h.gasPricer.err = fmt.Errorf("execution error") + h.gasPricer.err = errors.New("execution error") _, err = h.mgr.craftTx(context.Background(), candidate) require.ErrorContains(t, err, "failed to estimate gas") @@ -634,7 +686,7 @@ func TestTxMgr_SigningFails(t *testing.T) { cfg := configWithNumConfs(1) cfg.Signer = func(ctx context.Context, from common.Address, tx *types.Transaction) (*types.Transaction, error) { if errorSigning { - return nil, fmt.Errorf("signer error") + return nil, errors.New("signer error") } else { return tx, nil } @@ -664,7 +716,7 @@ func TestTxMgr_SigningFails(t *testing.T) { // TestTxMgrOnlyOnePublicationSucceeds asserts that the tx manager will return a // receipt so long as at least one of the publications is able to succeed with a -// simulated rpc failure. +// simulated failure. func TestTxMgrOnlyOnePublicationSucceeds(t *testing.T) { t.Parallel() @@ -679,7 +731,7 @@ func TestTxMgrOnlyOnePublicationSucceeds(t *testing.T) { sendTx := func(ctx context.Context, tx *types.Transaction) error { // Fail all but the final attempt. if !h.gasPricer.shouldMine(tx.GasFeeCap()) { - return errRpcFailure + return txpool.ErrUnderpriced } txHash := tx.Hash() @@ -699,7 +751,7 @@ func TestTxMgrOnlyOnePublicationSucceeds(t *testing.T) { // TestTxMgrConfirmsMinGasPriceAfterBumping delays the mining of the initial tx // with the minimum gas price, and asserts that its receipt is returned even -// though if the gas price has been bumped in other goroutines. +// if the gas price has been bumped in other goroutines. func TestTxMgrConfirmsMinGasPriceAfterBumping(t *testing.T) { t.Parallel() @@ -731,6 +783,47 @@ func TestTxMgrConfirmsMinGasPriceAfterBumping(t *testing.T) { require.Equal(t, h.gasPricer.expGasFeeCap().Uint64(), receipt.GasUsed) } +// TestTxMgrRetriesUnbumpableTx tests that a tx whose fees cannot be bumped will still be +// re-published in case it had been dropped from the mempool. +func TestTxMgrRetriesUnbumpableTx(t *testing.T) { + t.Parallel() + + cfg := configWithNumConfs(1) + cfg.FeeLimitMultiplier.Store(1) // don't allow fees to be bumped over the suggested values + h := newTestHarnessWithConfig(t, cfg) + + // Make the fees unbumpable by starting with fees that will be WAY over the suggested values + gasTipCap, gasFeeCap, _ := h.gasPricer.feesForEpoch(100) + txToSend := types.NewTx(&types.DynamicFeeTx{ + GasTipCap: gasTipCap, + GasFeeCap: gasFeeCap, + }) + + sameTxPublishAttempts := 0 + sendTx := func(ctx context.Context, tx *types.Transaction) error { + // delay mining so several retries should be triggered + if tx.Hash().Cmp(txToSend.Hash()) == 0 { + sameTxPublishAttempts++ + } + if h.gasPricer.shouldMine(tx.GasFeeCap()) { + // delay mining to give it enough time for ~3 retries + time.AfterFunc(3*time.Second, func() { + txHash := tx.Hash() + h.backend.mine(&txHash, tx.GasFeeCap(), nil) + }) + } + return nil + } + h.backend.setTxSender(sendTx) + + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + receipt, err := h.mgr.sendTx(ctx, txToSend) + require.NoError(t, err) + require.NotNil(t, receipt) + require.Greater(t, sameTxPublishAttempts, 1, "expected the original tx to be retried at least once") +} + // TestTxMgrDoesntAbortNonceTooLowAfterMiningTx func TestTxMgrDoesntAbortNonceTooLowAfterMiningTx(t *testing.T) { t.Parallel() @@ -796,21 +889,21 @@ func TestWaitMinedReturnsReceiptOnFirstSuccess(t *testing.T) { require.Equal(t, receipt.TxHash, txHash) } -// TestWaitMinedCanBeCanceled ensures that waitMined exits of the passed context +// TestWaitMinedCanBeCanceled ensures that waitMined exits if the passed context // is canceled before a receipt is found. func TestWaitMinedCanBeCanceled(t *testing.T) { t.Parallel() h := newTestHarness(t) - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) defer cancel() // Create an unimined tx. tx := types.NewTx(&types.LegacyTx{}) receipt, err := h.mgr.waitMined(ctx, tx, NewSendState(10, time.Hour)) - require.Equal(t, err, context.DeadlineExceeded) + require.ErrorIs(t, err, context.DeadlineExceeded) require.Nil(t, receipt) } @@ -831,7 +924,7 @@ func TestWaitMinedMultipleConfs(t *testing.T) { h.backend.mine(&txHash, new(big.Int), nil) receipt, err := h.mgr.waitMined(ctx, tx, NewSendState(10, time.Hour)) - require.Equal(t, err, context.DeadlineExceeded) + require.ErrorIs(t, err, context.DeadlineExceeded) require.Nil(t, receipt) ctx, cancel = context.WithTimeout(context.Background(), time.Second) @@ -1254,40 +1347,42 @@ func TestErrStringMatch(t *testing.T) { } func TestNonceReset(t *testing.T) { - conf := configWithNumConfs(1) - conf.SafeAbortNonceTooLowCount = 1 - h := newTestHarnessWithConfig(t, conf) - - index := -1 - var nonces []uint64 - sendTx := func(ctx context.Context, tx *types.Transaction) error { - index++ - nonces = append(nonces, tx.Nonce()) - // fail every 3rd tx - if index%3 == 0 { - return core.ErrNonceTooLow + testSendVariants(t, func(t *testing.T, send testSendVariantsFn) { + conf := configWithNumConfs(1) + conf.SafeAbortNonceTooLowCount = 1 + h := newTestHarnessWithConfig(t, conf) + + index := -1 + var nonces []uint64 + sendTx := func(ctx context.Context, tx *types.Transaction) error { + index++ + nonces = append(nonces, tx.Nonce()) + // fail every 3rd tx + if index%3 == 0 { + return core.ErrNonceTooLow + } + txHash := tx.Hash() + h.backend.mine(&txHash, tx.GasFeeCap(), nil) + return nil } - txHash := tx.Hash() - h.backend.mine(&txHash, tx.GasFeeCap(), nil) - return nil - } - h.backend.setTxSender(sendTx) + h.backend.setTxSender(sendTx) - ctx := context.Background() - for i := 0; i < 8; i++ { - _, err := h.mgr.Send(ctx, TxCandidate{ - To: &common.Address{}, - }) - // expect every 3rd tx to fail - if i%3 == 0 { - require.Error(t, err) - } else { - require.NoError(t, err) + ctx := context.Background() + for i := 0; i < 8; i++ { + _, err := send(ctx, h, TxCandidate{ + To: &common.Address{}, + }) + // expect every 3rd tx to fail + if i%3 == 0 { + require.Error(t, err) + } else { + require.NoError(t, err) + } } - } - // internal nonce tracking should be reset to startingNonce value every 3rd tx - require.Equal(t, []uint64{1, 1, 2, 3, 1, 2, 3, 1}, nonces) + // internal nonce tracking should be reset to startingNonce value every 3rd tx + require.Equal(t, []uint64{1, 1, 2, 3, 1, 2, 3, 1}, nonces) + }) } func TestMinFees(t *testing.T) { @@ -1359,115 +1454,118 @@ func TestMinFees(t *testing.T) { // TestClose ensures that the tx manager will refuse new work and cancel any in progress func TestClose(t *testing.T) { - conf := configWithNumConfs(1) - conf.SafeAbortNonceTooLowCount = 100 - h := newTestHarnessWithConfig(t, conf) - - sendingSignal := make(chan struct{}) - - // Ensure the manager is not closed - require.False(t, h.mgr.closed.Load()) - - // sendTx will fail until it is called a retry-number of times - called := 0 - const retries = 4 - sendTx := func(ctx context.Context, tx *types.Transaction) (err error) { - called += 1 - // sendingSignal is used when the tx begins to be sent - if called == 1 { - sendingSignal <- struct{}{} - } - if called%retries == 0 { - txHash := tx.Hash() - h.backend.mine(&txHash, tx.GasFeeCap(), big.NewInt(1)) - } else { - time.Sleep(10 * time.Millisecond) - err = core.ErrNonceTooLow + testSendVariants(t, func(t *testing.T, send testSendVariantsFn) { + conf := configWithNumConfs(1) + h := newTestHarnessWithConfig(t, conf) + + sendingSignal := make(chan struct{}) + + // Ensure the manager is not closed + require.False(t, h.mgr.closed.Load()) + + // sendTx will fail until it is called a retry-number of times + called := 0 + const retries = 4 + sendTx := func(ctx context.Context, tx *types.Transaction) (err error) { + called += 1 + // sendingSignal is used when the tx begins to be sent + if called == 1 { + sendingSignal <- struct{}{} + } + if called%retries == 0 { + txHash := tx.Hash() + h.backend.mine(&txHash, tx.GasFeeCap(), big.NewInt(1)) + } else { + time.Sleep(10 * time.Millisecond) + err = errRpcFailure + } + return } - return - } - h.backend.setTxSender(sendTx) - - // on the first call, we don't use the sending signal but we still need to drain it - go func() { - <-sendingSignal - }() - // demonstrate that a tx is sent, even when it must retry repeatedly - ctx := context.Background() - _, err := h.mgr.Send(ctx, TxCandidate{ - To: &common.Address{}, - }) - require.NoError(t, err) - require.Equal(t, retries, called) - called = 0 - // Ensure the manager is *still* not closed - require.False(t, h.mgr.closed.Load()) - - // on the second call, we close the manager while the tx is in progress by consuming the sending signal - go func() { - <-sendingSignal - h.mgr.Close() - }() - // demonstrate that a tx will cancel if it is in progress when the manager is closed - _, err = h.mgr.Send(ctx, TxCandidate{ - To: &common.Address{}, - }) - require.ErrorIs(t, ErrClosed, err) - // confirm that the tx was canceled before it retried to completion - require.Less(t, called, retries) - require.True(t, h.mgr.closed.Load()) - called = 0 - - // demonstrate that new calls to Send will also fail when the manager is closed - // there should be no need to capture the sending signal here because the manager is already closed and will return immediately - _, err = h.mgr.Send(ctx, TxCandidate{ - To: &common.Address{}, + h.backend.setTxSender(sendTx) + + // on the first call, we don't use the sending signal but we still need to drain it + go func() { + <-sendingSignal + }() + // demonstrate that a tx is sent, even when it must retry repeatedly + ctx := context.Background() + _, err := send(ctx, h, TxCandidate{ + To: &common.Address{}, + }) + require.NoError(t, err) + require.Equal(t, retries, called) + called = 0 + // Ensure the manager is *still* not closed + require.False(t, h.mgr.closed.Load()) + + // on the second call, we close the manager while the tx is in progress by consuming the sending signal + go func() { + <-sendingSignal + h.mgr.Close() + }() + // demonstrate that a tx will cancel if it is in progress when the manager is closed + _, err = send(ctx, h, TxCandidate{ + To: &common.Address{}, + }) + require.ErrorIs(t, err, ErrClosed) + // confirm that the tx was canceled before it retried to completion + require.Less(t, called, retries) + require.True(t, h.mgr.closed.Load()) + called = 0 + + // demonstrate that new calls to Send will also fail when the manager is closed + // there should be no need to capture the sending signal here because the manager is already closed and will return immediately + _, err = send(ctx, h, TxCandidate{ + To: &common.Address{}, + }) + require.ErrorIs(t, err, ErrClosed) + // confirm that the tx was canceled before it ever made it to the backend + require.Equal(t, 0, called) }) - require.ErrorIs(t, ErrClosed, err) - // confirm that the tx was canceled before it ever made it to the backend - require.Equal(t, 0, called) } // TestCloseWaitingForConfirmation ensures that the tx manager will wait for confirmation of a tx in flight, even when closed func TestCloseWaitingForConfirmation(t *testing.T) { - // two confirmations required so that we can mine and not yet be fully confirmed - conf := configWithNumConfs(2) - h := newTestHarnessWithConfig(t, conf) - - // sendDone is a signal that the tx has been sent from the sendTx function - sendDone := make(chan struct{}) - // closeDone is a signal that the txmanager has closed - closeDone := make(chan struct{}) - - sendTx := func(ctx context.Context, tx *types.Transaction) error { - txHash := tx.Hash() - h.backend.mine(&txHash, tx.GasFeeCap(), big.NewInt(1)) - close(sendDone) - return nil - } - h.backend.setTxSender(sendTx) + testSendVariants(t, func(t *testing.T, send testSendVariantsFn) { + // two confirmations required so that we can mine and not yet be fully confirmed + conf := configWithNumConfs(2) + h := newTestHarnessWithConfig(t, conf) - // this goroutine will close the manager when the tx sending is complete - // the transaction is not yet confirmed, so the manager will wait for confirmation - go func() { - <-sendDone - h.mgr.Close() - close(closeDone) - }() - - // this goroutine will complete confirmation of the tx when the manager is closed - // by forcing this to happen after close, we are able to observe a closing manager waiting for confirmation - go func() { - <-closeDone - h.backend.mine(nil, nil, big.NewInt(1)) - }() + // sendDone is a signal that the tx has been sent from the sendTx function + sendDone := make(chan struct{}) + // closeDone is a signal that the txmanager has closed + closeDone := make(chan struct{}) - ctx := context.Background() - _, err := h.mgr.Send(ctx, TxCandidate{ - To: &common.Address{}, + sendTx := func(ctx context.Context, tx *types.Transaction) error { + txHash := tx.Hash() + h.backend.mine(&txHash, tx.GasFeeCap(), big.NewInt(1)) + close(sendDone) + return nil + } + h.backend.setTxSender(sendTx) + + // this goroutine will close the manager when the tx sending is complete + // the transaction is not yet confirmed, so the manager will wait for confirmation + go func() { + <-sendDone + h.mgr.Close() + close(closeDone) + }() + + // this goroutine will complete confirmation of the tx when the manager is closed + // by forcing this to happen after close, we are able to observe a closing manager waiting for confirmation + go func() { + <-closeDone + h.backend.mine(nil, nil, big.NewInt(1)) + }() + + ctx := context.Background() + _, err := send(ctx, h, TxCandidate{ + To: &common.Address{}, + }) + require.True(t, h.mgr.closed.Load()) + require.NoError(t, err) }) - require.True(t, h.mgr.closed.Load()) - require.NoError(t, err) } func TestMakeSidecar(t *testing.T) { @@ -1490,3 +1588,12 @@ func TestMakeSidecar(t *testing.T) { require.Equal(t, hashes[i], eth.KZGToVersionedHash(commit)) } } + +func TestSendAsyncUnbufferedChan(t *testing.T) { + conf := configWithNumConfs(2) + h := newTestHarnessWithConfig(t, conf) + + require.Panics(t, func() { + h.mgr.SendAsync(context.Background(), TxCandidate{}, make(chan SendResponse)) + }) +} diff --git a/op-service/util.go b/op-service/util.go index 0a51147fd7d89..5c42d3de5ddeb 100644 --- a/op-service/util.go +++ b/op-service/util.go @@ -4,14 +4,16 @@ import ( "context" "errors" "fmt" + "math/big" "os" - "os/signal" "path/filepath" "reflect" + "strconv" "strings" - "syscall" "time" + "github.com/ethereum-optimism/optimism/op-service/ctxinterrupt" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" "github.com/urfave/cli/v2" @@ -86,37 +88,27 @@ func ParseAddress(address string) (common.Address, error) { return common.Address{}, fmt.Errorf("invalid address: %v", address) } -// CloseAction runs the function in the background, until it finishes or until it is closed by the user with an interrupt. -func CloseAction(fn func(ctx context.Context, shutdown <-chan struct{}) error) error { - stopped := make(chan error, 1) - shutdown := make(chan struct{}, 1) - - ctx, cancel := context.WithCancel(context.Background()) +// CloseAction runs the function in the background, until it finishes or until it is closed by the +// user with an interrupt. +func CloseAction(ctx context.Context, fn func(ctx context.Context) error) error { + ctx, stop := ctxinterrupt.WithSignalWaiter(ctx) + defer stop() + finished := make(chan error, 1) go func() { - stopped <- fn(ctx, shutdown) + finished <- fn(ctx) }() - doneCh := make(chan os.Signal, 1) - signal.Notify(doneCh, []os.Signal{ - os.Interrupt, - os.Kill, - syscall.SIGTERM, - syscall.SIGQUIT, - }...) - select { - case <-doneCh: - cancel() - shutdown <- struct{}{} - + case <-ctx.Done(): + // Stop catching interrupts. + stop() select { - case err := <-stopped: + case err := <-finished: return err case <-time.After(time.Second * 10): return errors.New("command action is unresponsive for more than 10 seconds... shutting down") } - case err := <-stopped: - cancel() + case err := <-finished: return err } } @@ -140,5 +132,34 @@ func FindMonorepoRoot(startDir string) (string, error) { } dir = parentDir } - return "", fmt.Errorf("monorepo root not found") + return "", errors.New("monorepo root not found") +} + +// Parse256BitChainID parses a 256-bit chain ID from a string. Chain IDs +// can be defined as either an integer or a hex string. If the string +// starts with "0x", it is treated as a hex string, otherwise it is +// treated as an integer string. +func Parse256BitChainID(in string) (common.Hash, error) { + var chainIDBig *big.Int + if strings.HasPrefix(in, "0x") { + in = strings.TrimPrefix(in, "0x") + var ok bool + chainIDBig, ok = new(big.Int).SetString(in, 16) + if !ok { + return common.Hash{}, fmt.Errorf("failed to parse chain ID %s", in) + } + } else { + inUint, err := strconv.ParseUint(in, 10, 64) + if err != nil { + return common.Hash{}, fmt.Errorf("failed to parse chain ID %s: %w", in, err) + } + + chainIDBig = new(big.Int).SetUint64(inUint) + } + + if chainIDBig.BitLen() > 256 { + return common.Hash{}, fmt.Errorf("chain ID %s is too large", in) + } + + return common.BigToHash(chainIDBig), nil } diff --git a/op-service/util_test.go b/op-service/util_test.go index 12d28f3b34144..940bb7001fc88 100644 --- a/op-service/util_test.go +++ b/op-service/util_test.go @@ -3,6 +3,8 @@ package op_service import ( "testing" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" "github.com/urfave/cli/v2" ) @@ -30,3 +32,57 @@ func TestValidateEnvVars(t *testing.T) { invalids := validateEnvVars("OP_BATCHER", provided, defined) require.ElementsMatch(t, invalids, []string{"OP_BATCHER_FAKE=false"}) } + +func TestParse256BitChainID(t *testing.T) { + tests := []struct { + name string + input string + expected common.Hash + err bool + }{ + { + name: "valid int", + input: "12345", + expected: common.Hash{30: 0x30, 31: 0x39}, + err: false, + }, + { + name: "invalid hash", + input: common.Hash{0x00: 0xff}.String(), + expected: common.Hash{0x00: 0xff}, + err: false, + }, + { + name: "hash overflow", + input: "0xff0000000000000000000000000000000000000000000000000000000000000000", + err: true, + }, + { + name: "number overflow", + // (2^256 - 1) + 1 + input: "115792089237316195423570985008687907853269984665640564039457584007913129639936", + err: true, + }, + { + name: "invalid hex", + input: "0xnope", + err: true, + }, + { + name: "invalid number", + input: "nope", + err: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + res, err := Parse256BitChainID(tt.input) + if tt.err { + require.Error(t, err) + } else { + require.NoError(t, err) + require.Equal(t, tt.expected, res) + } + }) + } +} diff --git a/op-supervisor/cmd/main.go b/op-supervisor/cmd/main.go index 01444e01b9257..8e306bf9009de 100644 --- a/op-supervisor/cmd/main.go +++ b/op-supervisor/cmd/main.go @@ -11,9 +11,9 @@ import ( opservice "github.com/ethereum-optimism/optimism/op-service" "github.com/ethereum-optimism/optimism/op-service/cliapp" + "github.com/ethereum-optimism/optimism/op-service/ctxinterrupt" oplog "github.com/ethereum-optimism/optimism/op-service/log" "github.com/ethereum-optimism/optimism/op-service/metrics/doc" - "github.com/ethereum-optimism/optimism/op-service/opio" "github.com/ethereum-optimism/optimism/op-supervisor/flags" "github.com/ethereum-optimism/optimism/op-supervisor/metrics" "github.com/ethereum-optimism/optimism/op-supervisor/supervisor" @@ -26,7 +26,7 @@ var ( ) func main() { - ctx := opio.WithInterruptBlocker(context.Background()) + ctx := ctxinterrupt.WithSignalWaiterMain(context.Background()) err := run(ctx, os.Args, fromConfig) if err != nil { log.Crit("Application failed", "message", err) diff --git a/op-supervisor/supervisor/backend/backend.go b/op-supervisor/supervisor/backend/backend.go index 9270300e53852..54b2f2eae20a0 100644 --- a/op-supervisor/supervisor/backend/backend.go +++ b/op-supervisor/supervisor/backend/backend.go @@ -9,27 +9,32 @@ import ( "sync/atomic" "time" + "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-service/client" "github.com/ethereum-optimism/optimism/op-service/dial" + "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-supervisor/config" "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/db" "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/db/heads" "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/db/logs" "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/source" - backendTypes "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/types" "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/frontend" "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/log" ) type SupervisorBackend struct { started atomic.Bool logger log.Logger + m Metrics + dataDir string - chainMonitors []*source.ChainMonitor + chainMonitors map[types.ChainID]*source.ChainMonitor db *db.ChainsDB + + maintenanceCancel context.CancelFunc } var _ frontend.Backend = (*SupervisorBackend)(nil) @@ -37,53 +42,79 @@ var _ frontend.Backend = (*SupervisorBackend)(nil) var _ io.Closer = (*SupervisorBackend)(nil) func NewSupervisorBackend(ctx context.Context, logger log.Logger, m Metrics, cfg *config.Config) (*SupervisorBackend, error) { + // attempt to prepare the data directory if err := prepDataDir(cfg.Datadir); err != nil { return nil, err } + + // create the head tracker headTracker, err := heads.NewHeadTracker(filepath.Join(cfg.Datadir, "heads.json")) if err != nil { return nil, fmt.Errorf("failed to load existing heads: %w", err) } - logDBs := make(map[types.ChainID]db.LogStorage) - chainRPCs := make(map[types.ChainID]string) - chainClients := make(map[types.ChainID]client.RPC) + + // create the chains db + db := db.NewChainsDB(map[types.ChainID]db.LogStorage{}, headTracker, logger) + + // create an empty map of chain monitors + chainMonitors := make(map[types.ChainID]*source.ChainMonitor, len(cfg.L2RPCs)) + + // create the supervisor backend + super := &SupervisorBackend{ + logger: logger, + m: m, + dataDir: cfg.Datadir, + chainMonitors: chainMonitors, + db: db, + } + + // from the RPC strings, have the supervisor backend create a chain monitor + // don't start the monitor yet, as we will start all monitors at once when Start is called for _, rpc := range cfg.L2RPCs { - rpcClient, chainID, err := createRpcClient(ctx, logger, rpc) - if err != nil { - return nil, err - } - cm := newChainMetrics(chainID, m) - path, err := prepLogDBPath(chainID, cfg.Datadir) + err := super.addFromRPC(ctx, logger, rpc, false) if err != nil { - return nil, fmt.Errorf("failed to create datadir for chain %v: %w", chainID, err) + return nil, fmt.Errorf("failed to add chain monitor for rpc %v: %w", rpc, err) } - logDB, err := logs.NewFromFile(logger, cm, path) - if err != nil { - return nil, fmt.Errorf("failed to create logdb for chain %v at %v: %w", chainID, path, err) - } - logDBs[chainID] = logDB - chainRPCs[chainID] = rpc - chainClients[chainID] = rpcClient - } - chainsDB := db.NewChainsDB(logDBs, headTracker) - if err := chainsDB.Resume(); err != nil { - return nil, fmt.Errorf("failed to resume chains db: %w", err) } + return super, nil +} - chainMonitors := make([]*source.ChainMonitor, 0, len(cfg.L2RPCs)) - for chainID, rpc := range chainRPCs { - cm := newChainMetrics(chainID, m) - monitor, err := source.NewChainMonitor(ctx, logger, cm, chainID, rpc, chainClients[chainID], chainsDB) - if err != nil { - return nil, fmt.Errorf("failed to create monitor for rpc %v: %w", rpc, err) +// addFromRPC adds a chain monitor to the supervisor backend from an rpc endpoint +// it does not expect to be called after the backend has been started +// it will start the monitor if shouldStart is true +func (su *SupervisorBackend) addFromRPC(ctx context.Context, logger log.Logger, rpc string, shouldStart bool) error { + // create the rpc client, which yields the chain id + rpcClient, chainID, err := createRpcClient(ctx, logger, rpc) + if err != nil { + return err + } + su.logger.Info("adding from rpc connection", "rpc", rpc, "chainID", chainID) + // create metrics and a logdb for the chain + cm := newChainMetrics(chainID, su.m) + path, err := prepLogDBPath(chainID, su.dataDir) + if err != nil { + return fmt.Errorf("failed to create datadir for chain %v: %w", chainID, err) + } + logDB, err := logs.NewFromFile(logger, cm, path, true) + if err != nil { + return fmt.Errorf("failed to create logdb for chain %v at %v: %w", chainID, path, err) + } + if su.chainMonitors[chainID] != nil { + return fmt.Errorf("chain monitor for chain %v already exists", chainID) + } + monitor, err := source.NewChainMonitor(ctx, logger, cm, chainID, rpc, rpcClient, su.db) + if err != nil { + return fmt.Errorf("failed to create monitor for rpc %v: %w", rpc, err) + } + // start the monitor if requested + if shouldStart { + if err := monitor.Start(); err != nil { + return fmt.Errorf("failed to start monitor for rpc %v: %w", rpc, err) } - chainMonitors = append(chainMonitors, monitor) } - return &SupervisorBackend{ - logger: logger, - chainMonitors: chainMonitors, - db: chainsDB, - }, nil + su.chainMonitors[chainID] = monitor + su.db.AddLogDB(chainID, logDB) + return nil } func createRpcClient(ctx context.Context, logger log.Logger, rpc string) (client.RPC, types.ChainID, error) { @@ -99,9 +130,15 @@ func createRpcClient(ctx context.Context, logger log.Logger, rpc string) (client } func (su *SupervisorBackend) Start(ctx context.Context) error { + // ensure we only start once if !su.started.CompareAndSwap(false, true) { return errors.New("already started") } + // initiate "ResumeFromLastSealedBlock" on the chains db, + // which rewinds the database to the last block that is guaranteed to have been fully recorded + if err := su.db.ResumeFromLastSealedBlock(); err != nil { + return fmt.Errorf("failed to resume chains db: %w", err) + } // start chain monitors for _, monitor := range su.chainMonitors { if err := monitor.Start(); err != nil { @@ -109,20 +146,28 @@ func (su *SupervisorBackend) Start(ctx context.Context) error { } } // start db maintenance loop - su.db.StartCrossHeadMaintenance(ctx) + maintenanceCtx, cancel := context.WithCancel(context.Background()) + su.db.StartCrossHeadMaintenance(maintenanceCtx) + su.maintenanceCancel = cancel return nil } +var errAlreadyStopped = errors.New("already stopped") + func (su *SupervisorBackend) Stop(ctx context.Context) error { if !su.started.CompareAndSwap(true, false) { - return errors.New("already stopped") + return errAlreadyStopped } + // signal the maintenance loop to stop + su.maintenanceCancel() + // collect errors from stopping chain monitors var errs error for _, monitor := range su.chainMonitors { if err := monitor.Stop(); err != nil { errs = errors.Join(errs, fmt.Errorf("failed to stop chain monitor: %w", err)) } } + // close the database if err := su.db.Close(); err != nil { errs = errors.Join(errs, fmt.Errorf("failed to close database: %w", err)) } @@ -134,17 +179,27 @@ func (su *SupervisorBackend) Close() error { return nil } +// AddL2RPC adds a new L2 chain to the supervisor backend +// it stops and restarts the backend to add the new chain +func (su *SupervisorBackend) AddL2RPC(ctx context.Context, rpc string) error { + // start the monitor immediately, as the backend is assumed to already be running + return su.addFromRPC(ctx, su.logger, rpc, true) +} + func (su *SupervisorBackend) CheckMessage(identifier types.Identifier, payloadHash common.Hash) (types.SafetyLevel, error) { chainID := identifier.ChainID blockNum := identifier.BlockNumber logIdx := identifier.LogIndex - ok, i, err := su.db.Check(chainID, blockNum, uint32(logIdx), backendTypes.TruncateHash(payloadHash)) - if err != nil { - return types.Invalid, fmt.Errorf("failed to check log: %w", err) + i, err := su.db.Check(chainID, blockNum, uint32(logIdx), payloadHash) + if errors.Is(err, logs.ErrFuture) { + return types.Unsafe, nil } - if !ok { + if errors.Is(err, logs.ErrConflict) { return types.Invalid, nil } + if err != nil { + return types.Invalid, fmt.Errorf("failed to check log: %w", err) + } safest := types.CrossUnsafe // at this point we have the log entry, and we can check if it is safe by various criteria for _, checker := range []db.SafetyChecker{ @@ -181,13 +236,19 @@ func (su *SupervisorBackend) CheckMessages( // The block is considered safe if all logs in the block are safe // this is decided by finding the last log in the block and func (su *SupervisorBackend) CheckBlock(chainID *hexutil.U256, blockHash common.Hash, blockNumber hexutil.Uint64) (types.SafetyLevel, error) { - // TODO(#11612): this function ignores blockHash and assumes that the block in the db is the one we are looking for - // In order to check block hash, the database must *always* insert a block hash checkpoint, which is not currently done safest := types.CrossUnsafe // find the last log index in the block - i, err := su.db.LastLogInBlock(types.ChainID(*chainID), uint64(blockNumber)) + id := eth.BlockID{Hash: blockHash, Number: uint64(blockNumber)} + i, err := su.db.FindSealedBlock(types.ChainID(*chainID), id) + if errors.Is(err, logs.ErrFuture) { + return types.Unsafe, nil + } + if errors.Is(err, logs.ErrConflict) { + return types.Invalid, nil + } if err != nil { - return types.Invalid, fmt.Errorf("failed to scan block: %w", err) + su.logger.Error("failed to scan block", "err", err) + return "", err } // at this point we have the extent of the block, and we can check if it is safe by various criteria for _, checker := range []db.SafetyChecker{ diff --git a/op-supervisor/supervisor/backend/db/db.go b/op-supervisor/supervisor/backend/db/db.go index c5948dde0b0cb..184be4df76c18 100644 --- a/op-supervisor/supervisor/backend/db/db.go +++ b/op-supervisor/supervisor/backend/db/db.go @@ -7,13 +7,14 @@ import ( "io" "time" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/db/entrydb" "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/db/heads" "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/db/logs" - backendTypes "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/types" "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" - "github.com/ethereum/go-ethereum/log" ) var ( @@ -22,16 +23,32 @@ var ( type LogStorage interface { io.Closer - AddLog(logHash backendTypes.TruncatedHash, block eth.BlockID, timestamp uint64, logIdx uint32, execMsg *backendTypes.ExecutingMessage) error + + AddLog(logHash common.Hash, parentBlock eth.BlockID, + logIdx uint32, execMsg *types.ExecutingMessage) error + + SealBlock(parentHash common.Hash, block eth.BlockID, timestamp uint64) error + Rewind(newHeadBlockNum uint64) error - LatestBlockNum() uint64 - ClosestBlockInfo(blockNum uint64) (uint64, backendTypes.TruncatedHash, error) - ClosestBlockIterator(blockNum uint64) (logs.Iterator, error) - Contains(blockNum uint64, logIdx uint32, loghash backendTypes.TruncatedHash) (bool, entrydb.EntryIdx, error) - LastCheckpointBehind(entrydb.EntryIdx) (logs.Iterator, error) - NextExecutingMessage(logs.Iterator) (backendTypes.ExecutingMessage, error) + + LatestSealedBlockNum() (n uint64, ok bool) + + // FindSealedBlock finds the requested block, to check if it exists, + // returning the next index after it where things continue from. + // returns ErrFuture if the block is too new to be able to tell + // returns ErrDifferent if the known block does not match + FindSealedBlock(block eth.BlockID) (nextEntry entrydb.EntryIdx, err error) + + IteratorStartingAt(i entrydb.EntryIdx) (logs.Iterator, error) + + // returns ErrConflict if the log does not match the canonical chain. + // returns ErrFuture if the log is out of reach. + // returns nil if the log is known and matches the canonical chain. + Contains(blockNum uint64, logIdx uint32, logHash common.Hash) (nextIndex entrydb.EntryIdx, err error) } +var _ LogStorage = (*logs.DB)(nil) + type HeadsStorage interface { Current() *heads.Heads Apply(op heads.Operation) error @@ -40,24 +57,42 @@ type HeadsStorage interface { // ChainsDB is a database that stores logs and heads for multiple chains. // it implements the ChainsStorage interface. type ChainsDB struct { - logDBs map[types.ChainID]LogStorage - heads HeadsStorage + logDBs map[types.ChainID]LogStorage + heads HeadsStorage + maintenanceReady chan struct{} + logger log.Logger } -func NewChainsDB(logDBs map[types.ChainID]LogStorage, heads HeadsStorage) *ChainsDB { +func NewChainsDB(logDBs map[types.ChainID]LogStorage, heads HeadsStorage, l log.Logger) *ChainsDB { return &ChainsDB{ - logDBs: logDBs, - heads: heads, + logDBs: logDBs, + heads: heads, + logger: l, + maintenanceReady: make(chan struct{}, 1), } } -// Resume prepares the chains db to resume recording events after a restart. -// It rewinds the database to the last block that is guaranteed to have been fully recorded to the database +func (db *ChainsDB) AddLogDB(chain types.ChainID, logDB LogStorage) { + if db.logDBs[chain] != nil { + log.Warn("overwriting existing logDB for chain", "chain", chain) + } + db.logDBs[chain] = logDB +} + +// ResumeFromLastSealedBlock prepares the chains db to resume recording events after a restart. +// It rewinds the database to the last block that is guaranteed to have been fully recorded to the database, // to ensure it can resume recording from the first log of the next block. -func (db *ChainsDB) Resume() error { +func (db *ChainsDB) ResumeFromLastSealedBlock() error { for chain, logStore := range db.logDBs { - if err := Resume(logStore); err != nil { - return fmt.Errorf("failed to resume chain %v: %w", chain, err) + headNum, ok := logStore.LatestSealedBlockNum() + if ok { + // db must be empty, nothing to rewind to + db.logger.Info("Resuming, but found no DB contents", "chain", chain) + continue + } + db.logger.Info("Resuming, starting from last sealed block", "head", headNum) + if err := logStore.Rewind(headNum); err != nil { + return fmt.Errorf("failed to rewind chain %s to sealed block %d", chain, headNum) } } return nil @@ -67,25 +102,21 @@ func (db *ChainsDB) Resume() error { // for now it does not prevent multiple instances of this process from running func (db *ChainsDB) StartCrossHeadMaintenance(ctx context.Context) { go func() { - // create three safety checkers, one for each safety level - unsafeChecker := NewSafetyChecker(Unsafe, db) - safeChecker := NewSafetyChecker(Safe, db) - finalizedChecker := NewSafetyChecker(Finalized, db) - // run the maintenance loop every 10 seconds for now - ticker := time.NewTicker(time.Second * 10) + db.logger.Info("cross-head maintenance loop started") + // run the maintenance loop every 1 seconds for now + ticker := time.NewTicker(time.Second * 1) for { select { case <-ctx.Done(): + db.logger.Warn("context cancelled, stopping maintenance loop") return case <-ticker.C: - for _, checker := range []SafetyChecker{ - unsafeChecker, - safeChecker, - finalizedChecker} { - if err := db.UpdateCrossHeads(checker); err != nil { - log.Error("failed to update cross-heads", "err", err, "safety", checker.Name()) - // we should consider exiting if an error is encountered, as the path forward is unclear - } + db.logger.Debug("regular maintenance requested") + db.RequestMaintenance() + case <-db.maintenanceReady: + db.logger.Debug("running maintenance") + if err := db.updateAllHeads(); err != nil { + db.logger.Error("failed to update cross-heads", "err", err) } } } @@ -93,51 +124,78 @@ func (db *ChainsDB) StartCrossHeadMaintenance(ctx context.Context) { } // Check calls the underlying logDB to determine if the given log entry is safe with respect to the checker's criteria. -func (db *ChainsDB) Check(chain types.ChainID, blockNum uint64, logIdx uint32, logHash backendTypes.TruncatedHash) (bool, entrydb.EntryIdx, error) { +func (db *ChainsDB) Check(chain types.ChainID, blockNum uint64, logIdx uint32, logHash common.Hash) (entrydb.EntryIdx, error) { logDB, ok := db.logDBs[chain] if !ok { - return false, 0, fmt.Errorf("%w: %v", ErrUnknownChain, chain) + return 0, fmt.Errorf("%w: %v", ErrUnknownChain, chain) } return logDB.Contains(blockNum, logIdx, logHash) } -// UpdateCrossSafeHeads updates the cross-heads of all chains -// this is an example of how to use the SafetyChecker to update the cross-heads -func (db *ChainsDB) UpdateCrossSafeHeads() error { - checker := NewSafetyChecker(Safe, db) - return db.UpdateCrossHeads(checker) +// RequestMaintenance requests that the maintenance loop update the cross-heads +// it does not block if maintenance is already scheduled +func (db *ChainsDB) RequestMaintenance() { + select { + case db.maintenanceReady <- struct{}{}: + return + default: + return + } +} + +// updateAllHeads updates the cross-heads of all safety levels +// it is called by the maintenance loop +func (db *ChainsDB) updateAllHeads() error { + // create three safety checkers, one for each safety level + unsafeChecker := NewSafetyChecker(Unsafe, db) + safeChecker := NewSafetyChecker(Safe, db) + finalizedChecker := NewSafetyChecker(Finalized, db) + for _, checker := range []SafetyChecker{ + unsafeChecker, + safeChecker, + finalizedChecker} { + if err := db.UpdateCrossHeads(checker); err != nil { + return fmt.Errorf("failed to update cross-heads for safety level %v: %w", checker.Name(), err) + } + } + return nil } // UpdateCrossHeadsForChain updates the cross-head for a single chain. // the provided checker controls which heads are considered. -// TODO: we should invert control and have the underlying logDB call their own update -// for now, monolithic control is fine. There may be a stronger reason to refactor if the API needs it. func (db *ChainsDB) UpdateCrossHeadsForChain(chainID types.ChainID, checker SafetyChecker) error { // start with the xsafe head of the chain xHead := checker.CrossHeadForChain(chainID) // advance as far as the local head localHead := checker.LocalHeadForChain(chainID) // get an iterator for the last checkpoint behind the x-head - i, err := db.logDBs[chainID].LastCheckpointBehind(xHead) + iter, err := db.logDBs[chainID].IteratorStartingAt(xHead) if err != nil { return fmt.Errorf("failed to rewind cross-safe head for chain %v: %w", chainID, err) } + // track if we updated the cross-head + updated := false // advance the logDB through all executing messages we can // this loop will break: // - when we reach the local head // - when we reach a message that is not safe // - if an error occurs for { - exec, err := db.logDBs[chainID].NextExecutingMessage(i) - if err == io.EOF { + if err := iter.NextExecMsg(); err == io.EOF { break } else if err != nil { return fmt.Errorf("failed to read next executing message for chain %v: %w", chainID, err) } - // if we are now beyond the local head, stop - if i.Index() > localHead { + // if we would exceed the local head, then abort + if iter.NextIndex() > localHead { + xHead = localHead // clip to local head + updated = localHead != xHead break } + exec := iter.ExecMessage() + if exec == nil { + panic("expected executing message after traversing to one without error") + } // use the checker to determine if this message is safe safe := checker.Check( types.ChainIDFromUInt64(uint64(exec.Chain)), @@ -148,14 +206,23 @@ func (db *ChainsDB) UpdateCrossHeadsForChain(chainID types.ChainID, checker Safe break } // if all is well, prepare the x-head update to this point - xHead = i.Index() + xHead = iter.NextIndex() + updated = true } - // have the checker create an update to the x-head in question, and apply that update err = db.heads.Apply(checker.Update(chainID, xHead)) if err != nil { return fmt.Errorf("failed to update cross-head for chain %v: %w", chainID, err) } + // if any chain was updated, we can trigger a maintenance request + // this allows for the maintenance loop to handle cascading updates + // instead of waiting for the next scheduled update + if updated { + db.logger.Info("Promoting cross-head", "head", xHead, "safety-level", checker.SafetyLevel()) + db.RequestMaintenance() + } else { + db.logger.Info("No cross-head update", "head", xHead, "safety-level", checker.SafetyLevel()) + } return nil } @@ -163,71 +230,48 @@ func (db *ChainsDB) UpdateCrossHeadsForChain(chainID types.ChainID, checker Safe // based on the provided SafetyChecker. The SafetyChecker is used to determine // the safety of each log entry in the database, and the cross-head associated with it. func (db *ChainsDB) UpdateCrossHeads(checker SafetyChecker) error { - currentHeads := db.heads.Current() - for chainID := range currentHeads.Chains { - if err := db.UpdateCrossHeadsForChain(chainID, checker); err != nil { + for chainID := range db.logDBs { + err := db.UpdateCrossHeadsForChain(chainID, checker) + if err != nil { return err } } return nil } -// LastLogInBlock scans through the logs of the given chain starting from the given block number, -// and returns the index of the last log entry in that block. -func (db *ChainsDB) LastLogInBlock(chain types.ChainID, blockNum uint64) (entrydb.EntryIdx, error) { +func (db *ChainsDB) FindSealedBlock(chain types.ChainID, block eth.BlockID) (nextEntry entrydb.EntryIdx, err error) { logDB, ok := db.logDBs[chain] if !ok { return 0, fmt.Errorf("%w: %v", ErrUnknownChain, chain) } - iter, err := logDB.ClosestBlockIterator(blockNum) - if err != nil { - return 0, fmt.Errorf("failed to get block iterator for chain %v: %w", chain, err) - } - ret := entrydb.EntryIdx(0) - // scan through using the iterator until the block number exceeds the target - for { - bn, index, _, err := iter.NextLog() - // if we have reached the end of the database, stop - if err == io.EOF { - break - } - // all other errors are fatal - if err != nil { - return 0, fmt.Errorf("failed to read next log entry for chain %v: %w", chain, err) - } - // if we are now beyond the target block, stop withour updating the return value - if bn > blockNum { - break - } - // only update the return value if the block number is the same - // it is possible the iterator started before the target block, or that the target block is not in the db - if bn == blockNum { - ret = entrydb.EntryIdx(index) - } - } - // if we never found the block, return an error - if ret == 0 { - return 0, fmt.Errorf("block %v not found in chain %v", blockNum, chain) - } - return ret, nil + return logDB.FindSealedBlock(block) } -// LatestBlockNum returns the latest block number that has been recorded to the logs db +// LatestBlockNum returns the latest fully-sealed block number that has been recorded to the logs db // for the given chain. It does not contain safety guarantees. -func (db *ChainsDB) LatestBlockNum(chain types.ChainID) uint64 { +// The block number might not be available (empty database, or non-existent chain). +func (db *ChainsDB) LatestBlockNum(chain types.ChainID) (num uint64, ok bool) { + logDB, knownChain := db.logDBs[chain] + if !knownChain { + return 0, false + } + return logDB.LatestSealedBlockNum() +} + +func (db *ChainsDB) SealBlock(chain types.ChainID, parentHash common.Hash, block eth.BlockID, timestamp uint64) error { logDB, ok := db.logDBs[chain] if !ok { - return 0 + return fmt.Errorf("%w: %v", ErrUnknownChain, chain) } - return logDB.LatestBlockNum() + return logDB.SealBlock(parentHash, block, timestamp) } -func (db *ChainsDB) AddLog(chain types.ChainID, logHash backendTypes.TruncatedHash, block eth.BlockID, timestamp uint64, logIdx uint32, execMsg *backendTypes.ExecutingMessage) error { +func (db *ChainsDB) AddLog(chain types.ChainID, logHash common.Hash, parentBlock eth.BlockID, logIdx uint32, execMsg *types.ExecutingMessage) error { logDB, ok := db.logDBs[chain] if !ok { return fmt.Errorf("%w: %v", ErrUnknownChain, chain) } - return logDB.AddLog(logHash, block, timestamp, logIdx, execMsg) + return logDB.AddLog(logHash, parentBlock, logIdx, execMsg) } func (db *ChainsDB) Rewind(chain types.ChainID, headBlockNum uint64) error { diff --git a/op-supervisor/supervisor/backend/db/db_test.go b/op-supervisor/supervisor/backend/db/db_test.go index 4f74fe473d723..e1da3c177b108 100644 --- a/op-supervisor/supervisor/backend/db/db_test.go +++ b/op-supervisor/supervisor/backend/db/db_test.go @@ -1,23 +1,28 @@ package db import ( - "fmt" + "errors" "io" + "math/rand" // nosemgrep "testing" + "github.com/stretchr/testify/require" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum-optimism/optimism/op-service/eth" + "github.com/ethereum-optimism/optimism/op-service/testlog" "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/db/entrydb" "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/db/heads" "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/db/logs" - backendTypes "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/types" "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" - "github.com/stretchr/testify/require" ) func TestChainsDB_AddLog(t *testing.T) { t.Run("UnknownChain", func(t *testing.T) { - db := NewChainsDB(nil, &stubHeadStorage{}) - err := db.AddLog(types.ChainIDFromUInt64(2), backendTypes.TruncatedHash{}, eth.BlockID{}, 1234, 33, nil) + db := NewChainsDB(nil, &stubHeadStorage{}, testlog.Logger(t, log.LevelDebug)) + err := db.AddLog(types.ChainIDFromUInt64(2), common.Hash{}, eth.BlockID{}, 33, nil) require.ErrorIs(t, err, ErrUnknownChain) }) @@ -26,16 +31,20 @@ func TestChainsDB_AddLog(t *testing.T) { logDB := &stubLogDB{} db := NewChainsDB(map[types.ChainID]LogStorage{ chainID: logDB, - }, &stubHeadStorage{}) - err := db.AddLog(chainID, backendTypes.TruncatedHash{}, eth.BlockID{}, 1234, 33, nil) + }, &stubHeadStorage{}, testlog.Logger(t, log.LevelDebug)) + bl10 := eth.BlockID{Hash: common.Hash{0x10}, Number: 10} + err := db.SealBlock(chainID, common.Hash{0x9}, bl10, 1234) + require.NoError(t, err, err) + err = db.AddLog(chainID, common.Hash{}, bl10, 0, nil) require.NoError(t, err, err) require.Equal(t, 1, logDB.addLogCalls) + require.Equal(t, 1, logDB.sealBlockCalls) }) } func TestChainsDB_Rewind(t *testing.T) { t.Run("UnknownChain", func(t *testing.T) { - db := NewChainsDB(nil, &stubHeadStorage{}) + db := NewChainsDB(nil, &stubHeadStorage{}, testlog.Logger(t, log.LevelDebug)) err := db.Rewind(types.ChainIDFromUInt64(2), 42) require.ErrorIs(t, err, ErrUnknownChain) }) @@ -45,145 +54,34 @@ func TestChainsDB_Rewind(t *testing.T) { logDB := &stubLogDB{} db := NewChainsDB(map[types.ChainID]LogStorage{ chainID: logDB, - }, &stubHeadStorage{}) + }, &stubHeadStorage{}, + testlog.Logger(t, log.LevelDebug)) err := db.Rewind(chainID, 23) require.NoError(t, err, err) require.EqualValues(t, 23, logDB.headBlockNum) }) } -func TestChainsDB_LastLogInBlock(t *testing.T) { - // using a chainID of 1 for simplicity - chainID := types.ChainIDFromUInt64(1) - // get default stubbed components - logDB, _, h := setupStubbedForUpdateHeads(chainID) - logDB.nextLogs = []nextLogResponse{ - {10, 1, backendTypes.TruncatedHash{}, nil}, - {10, 2, backendTypes.TruncatedHash{}, nil}, - {10, 3, backendTypes.TruncatedHash{}, nil}, - {10, 4, backendTypes.TruncatedHash{}, nil}, - {11, 5, backendTypes.TruncatedHash{}, nil}, - } - - // The ChainsDB is real, but uses only stubbed components - db := NewChainsDB( - map[types.ChainID]LogStorage{ - chainID: logDB}, - &stubHeadStorage{h}) - - // LastLogInBlock is expected to: - // 1. get a block iterator for block 10 (stubbed) - // 2. scan through the iterator until the block number exceeds the target (10) - // 3. return the index of the last log in the block (4) - index, err := db.LastLogInBlock(chainID, 10) - require.NoError(t, err) - require.Equal(t, entrydb.EntryIdx(4), index) -} - -func TestChainsDB_LastLogInBlockEOF(t *testing.T) { - // using a chainID of 1 for simplicity - chainID := types.ChainIDFromUInt64(1) - // get default stubbed components - logDB, _, h := setupStubbedForUpdateHeads(chainID) - logDB.nextLogs = []nextLogResponse{ - {10, 5, backendTypes.TruncatedHash{}, nil}, - {10, 6, backendTypes.TruncatedHash{}, nil}, - {10, 7, backendTypes.TruncatedHash{}, nil}, - {10, 8, backendTypes.TruncatedHash{}, nil}, - {10, 9, backendTypes.TruncatedHash{}, nil}, - {10, 10, backendTypes.TruncatedHash{}, nil}, - } - - // The ChainsDB is real, but uses only stubbed components - db := NewChainsDB( - map[types.ChainID]LogStorage{ - chainID: logDB}, - &stubHeadStorage{h}) - - // LastLogInBlock is expected to: - // 1. get a block iterator for block 10 (stubbed) - // 2. scan through the iterator and never find the target block - // return an error - index, err := db.LastLogInBlock(chainID, 10) - require.NoError(t, err) - require.Equal(t, entrydb.EntryIdx(10), index) -} - -func TestChainsDB_LastLogInBlockNotFound(t *testing.T) { - // using a chainID of 1 for simplicity - chainID := types.ChainIDFromUInt64(1) - // get default stubbed components - logDB, _, h := setupStubbedForUpdateHeads(chainID) - logDB.nextLogs = []nextLogResponse{ - {100, 5, backendTypes.TruncatedHash{}, nil}, - {100, 6, backendTypes.TruncatedHash{}, nil}, - {100, 7, backendTypes.TruncatedHash{}, nil}, - {101, 8, backendTypes.TruncatedHash{}, nil}, - {101, 9, backendTypes.TruncatedHash{}, nil}, - {101, 10, backendTypes.TruncatedHash{}, nil}, - } - - // The ChainsDB is real, but uses only stubbed components - db := NewChainsDB( - map[types.ChainID]LogStorage{ - chainID: logDB}, - &stubHeadStorage{h}) - - // LastLogInBlock is expected to: - // 1. get a block iterator for block 10 (stubbed) - // 2. scan through the iterator and never find the target block - // return an error - _, err := db.LastLogInBlock(chainID, 10) - require.ErrorContains(t, err, "block 10 not found") -} - -func TestChainsDB_LastLogInBlockError(t *testing.T) { - // using a chainID of 1 for simplicity - chainID := types.ChainIDFromUInt64(1) - // get default stubbed components - logDB, _, h := setupStubbedForUpdateHeads(chainID) - logDB.nextLogs = []nextLogResponse{ - {10, 1, backendTypes.TruncatedHash{}, nil}, - {10, 2, backendTypes.TruncatedHash{}, nil}, - {10, 3, backendTypes.TruncatedHash{}, nil}, - {0, 0, backendTypes.TruncatedHash{}, fmt.Errorf("some error")}, - {11, 5, backendTypes.TruncatedHash{}, nil}, - } - - // The ChainsDB is real, but uses only stubbed components - db := NewChainsDB( - map[types.ChainID]LogStorage{ - chainID: logDB}, - &stubHeadStorage{h}) - - // LastLogInBlock is expected to: - // 1. get a block iterator for block 10 (stubbed) - // 2. scan through the iterator and encounter an error - // return an error - _, err := db.LastLogInBlock(chainID, 10) - require.ErrorContains(t, err, "some error") -} - func TestChainsDB_UpdateCrossHeads(t *testing.T) { // using a chainID of 1 for simplicity chainID := types.ChainIDFromUInt64(1) // get default stubbed components logDB, checker, h := setupStubbedForUpdateHeads(chainID) + checker.numSafe = 1 + xSafe := checker.crossHeadForChain + // The ChainsDB is real, but uses only stubbed components db := NewChainsDB( map[types.ChainID]LogStorage{ chainID: logDB}, - &stubHeadStorage{h}) + &stubHeadStorage{h}, + testlog.Logger(t, log.LevelDebug)) - // Update cross-heads is expected to: - // 1. get a last checkpoint iterator from the logDB (stubbed to be at 15) - // 2. progress the iterator to the next log (16) because the first safety check will pass - // 3. fail the second safety check - // 4. update the cross-heads to the last successful safety check (16) err := db.UpdateCrossHeads(checker) require.NoError(t, err) - require.Equal(t, entrydb.EntryIdx(16), checker.updated) + // found a safe executing message, and no new initiating messages + require.Equal(t, xSafe+1, checker.updated) } func TestChainsDB_UpdateCrossHeadsBeyondLocal(t *testing.T) { @@ -191,14 +89,17 @@ func TestChainsDB_UpdateCrossHeadsBeyondLocal(t *testing.T) { chainID := types.ChainIDFromUInt64(1) // get default stubbed components logDB, checker, h := setupStubbedForUpdateHeads(chainID) - // set the safety checker to pass 99 times, effeciively allowing all messages to be safe + // set the safety checker to pass 99 times, effectively allowing all messages to be safe checker.numSafe = 99 + startLocalSafe := checker.localHeadForChain + // The ChainsDB is real, but uses only stubbed components db := NewChainsDB( map[types.ChainID]LogStorage{ chainID: logDB}, - &stubHeadStorage{h}) + &stubHeadStorage{h}, + testlog.Logger(t, log.LevelDebug)) // Update cross-heads is expected to: // 1. get a last checkpoint iterator from the logDB (stubbed to be at 15) @@ -206,7 +107,7 @@ func TestChainsDB_UpdateCrossHeadsBeyondLocal(t *testing.T) { // 3. exceed the local head, and update the cross-head to the local head (40) err := db.UpdateCrossHeads(checker) require.NoError(t, err) - require.Equal(t, entrydb.EntryIdx(40), checker.updated) + require.Equal(t, startLocalSafe, checker.updated) } func TestChainsDB_UpdateCrossHeadsEOF(t *testing.T) { @@ -215,24 +116,25 @@ func TestChainsDB_UpdateCrossHeadsEOF(t *testing.T) { // get default stubbed components logDB, checker, h := setupStubbedForUpdateHeads(chainID) // set the log DB to return an EOF error when trying to get the next executing message - // after processing 10 messages as safe (with more messages available to be safe) - logDB.errOverload = io.EOF - logDB.errAfter = 10 + // after processing 10 message (with more messages available to be safe) + logDB.nextLogs = logDB.nextLogs[:checker.crossHeadForChain+11] + // This is a legacy test, the local head is further than the DB content... + checker.numSafe = 99 // The ChainsDB is real, but uses only stubbed components db := NewChainsDB( map[types.ChainID]LogStorage{ chainID: logDB}, - &stubHeadStorage{h}) + &stubHeadStorage{h}, + testlog.Logger(t, log.LevelDebug)) // Update cross-heads is expected to: - // 1. get a last checkpoint iterator from the logDB (stubbed to be at 15) - // 2. after processing 10 messages as safe, fail to find any executing messages (EOF) - // 3. update to the last successful safety check (25) without returning an error + // - process 10 logs as safe, 5 of which execute something + // - update cross-safe to what was there err := db.UpdateCrossHeads(checker) require.NoError(t, err) - require.Equal(t, entrydb.EntryIdx(25), checker.updated) + require.Equal(t, checker.crossHeadForChain+11, checker.updated) } func TestChainsDB_UpdateCrossHeadsError(t *testing.T) { @@ -242,15 +144,26 @@ func TestChainsDB_UpdateCrossHeadsError(t *testing.T) { logDB, checker, h := setupStubbedForUpdateHeads(chainID) // set the log DB to return an error when trying to get the next executing message // after processing 3 messages as safe (with more messages available to be safe) - logDB.errOverload = fmt.Errorf("some error") - logDB.errAfter = 3 + + executed := 0 + for i, e := range logDB.nextLogs { + if executed == 3 { + logDB.nextLogs[i].err = errors.New("some error") + } + if entrydb.EntryIdx(i) > checker.crossHeadForChain && e.execIdx >= 0 { + executed++ + } + } + + // everything is safe until error checker.numSafe = 99 // The ChainsDB is real, but uses only stubbed components db := NewChainsDB( map[types.ChainID]LogStorage{ chainID: logDB}, - &stubHeadStorage{h}) + &stubHeadStorage{h}, + testlog.Logger(t, log.LevelDebug)) // Update cross-heads is expected to: // 1. get a last checkpoint iterator from the logDB (stubbed to be at 10) @@ -268,8 +181,6 @@ func TestChainsDB_UpdateCrossHeadsError(t *testing.T) { // this isn't an issue for now, as all tests can modify the stubbed components directly after calling this function. // but readability and maintainability would be improved by making this function more configurable. func setupStubbedForUpdateHeads(chainID types.ChainID) (*stubLogDB, *stubChecker, *heads.Heads) { - // the checkpoint starts somewhere behind the last known cross-safe head - checkpoint := entrydb.EntryIdx(15) // the last known cross-safe head is at 20 cross := entrydb.EntryIdx(20) // the local head (the limit of the update) is at 40 @@ -278,23 +189,43 @@ func setupStubbedForUpdateHeads(chainID types.ChainID) (*stubLogDB, *stubChecker numExecutingMessages := 30 // number of safety checks that will pass before returning false numSafe := 1 - // number of calls to nextExecutingMessage before potentially returning an error - errAfter := 4 // set up stubbed logDB logDB := &stubLogDB{} - // the log DB will start the iterator at the checkpoint index - logDB.lastCheckpointBehind = &stubIterator{checkpoint, 0, nil} - // rig the log DB to return an error after a certain number of calls to NextExecutingMessage - logDB.errAfter = errAfter + // set up stubbed executing messages that the ChainsDB can pass to the checker - logDB.executingMessages = []*backendTypes.ExecutingMessage{} + logDB.executingMessages = []*types.ExecutingMessage{} for i := 0; i < numExecutingMessages; i++ { // executing messages are packed in groups of 3, with block numbers increasing by 1 - logDB.executingMessages = append(logDB.executingMessages, &backendTypes.ExecutingMessage{ + logDB.executingMessages = append(logDB.executingMessages, &types.ExecutingMessage{ BlockNum: uint64(100 + int(i/3)), LogIdx: uint32(i), - Hash: backendTypes.TruncatedHash{}, + Hash: common.Hash{}, + }) + } + + rng := rand.New(rand.NewSource(123)) + blockNum := uint64(100) + logIndex := uint32(0) + executedCount := 0 + for i := entrydb.EntryIdx(0); i <= local; i++ { + var logHash common.Hash + rng.Read(logHash[:]) + + execIndex := -1 + // All the even messages have an executing message + if i%2 == 0 { + execIndex = rng.Intn(len(logDB.executingMessages)) + executedCount += 1 + } + var msgErr error + + logDB.nextLogs = append(logDB.nextLogs, nextLogResponse{ + blockNum: blockNum, + logIdx: logIndex, + evtHash: logHash, + err: msgErr, + execIdx: execIndex, }) } @@ -334,7 +265,7 @@ func (s *stubChecker) CrossHeadForChain(chainID types.ChainID) entrydb.EntryIdx } // stubbed Check returns true for the first numSafe calls, and false thereafter -func (s *stubChecker) Check(chain types.ChainID, blockNum uint64, logIdx uint32, logHash backendTypes.TruncatedHash) bool { +func (s *stubChecker) Check(chain types.ChainID, blockNum uint64, logIdx uint32, logHash common.Hash) bool { if s.checkCalls >= s.numSafe { return false } @@ -370,89 +301,138 @@ func (s *stubHeadStorage) Current() *heads.Heads { type nextLogResponse struct { blockNum uint64 - logIdx uint32 - evtHash backendTypes.TruncatedHash - err error + + logIdx uint32 + + evtHash common.Hash + + err error + + // -1 if not executing + execIdx int } + type stubIterator struct { - index entrydb.EntryIdx - nextLogIndex int - nextLogs []nextLogResponse + index entrydb.EntryIdx + + db *stubLogDB } -func (s *stubIterator) NextLog() (uint64, uint32, backendTypes.TruncatedHash, error) { - if s.nextLogIndex >= len(s.nextLogs) { - return 0, 0, backendTypes.TruncatedHash{}, io.EOF - } - r := s.nextLogs[s.nextLogIndex] - s.nextLogIndex++ - return r.blockNum, r.logIdx, r.evtHash, r.err +func (s *stubIterator) End() error { + return nil // only used for DB-loading. The stub is already loaded } -func (s *stubIterator) Index() entrydb.EntryIdx { - return s.index +func (s *stubIterator) NextInitMsg() error { + s.index += 1 + if s.index >= entrydb.EntryIdx(len(s.db.nextLogs)) { + return io.EOF + } + e := s.db.nextLogs[s.index] + return e.err +} + +func (s *stubIterator) NextExecMsg() error { + for { + s.index += 1 + if s.index >= entrydb.EntryIdx(len(s.db.nextLogs)) { + return io.EOF + } + e := s.db.nextLogs[s.index] + if e.err != nil { + return e.err + } + if e.execIdx >= 0 { + return nil + } + } } -func (s *stubIterator) ExecMessage() (backendTypes.ExecutingMessage, error) { - panic("not implemented") + +func (s *stubIterator) NextBlock() error { + panic("not yet supported") } -type stubLogDB struct { - addLogCalls int - headBlockNum uint64 - emIndex int - executingMessages []*backendTypes.ExecutingMessage - nextLogs []nextLogResponse - lastCheckpointBehind *stubIterator - errOverload error - errAfter int - containsResponse containsResponse +func (s *stubIterator) NextIndex() entrydb.EntryIdx { + return s.index + 1 } -// stubbed LastCheckpointBehind returns a stubbed iterator which was passed in to the struct -func (s *stubLogDB) LastCheckpointBehind(entrydb.EntryIdx) (logs.Iterator, error) { - return s.lastCheckpointBehind, nil +func (s *stubIterator) SealedBlock() (hash common.Hash, num uint64, ok bool) { + panic("not yet supported") } -func (s *stubLogDB) ClosestBlockIterator(blockNum uint64) (logs.Iterator, error) { - return &stubIterator{ - index: entrydb.EntryIdx(99), - nextLogs: s.nextLogs, - }, nil +func (s *stubIterator) InitMessage() (hash common.Hash, logIndex uint32, ok bool) { + if s.index < 0 { + return common.Hash{}, 0, false + } + if s.index >= entrydb.EntryIdx(len(s.db.nextLogs)) { + return common.Hash{}, 0, false + } + e := s.db.nextLogs[s.index] + return e.evtHash, e.logIdx, true } -func (s *stubLogDB) NextExecutingMessage(i logs.Iterator) (backendTypes.ExecutingMessage, error) { - // if error overload is set, return it to simulate a failure condition - if s.errOverload != nil && s.emIndex >= s.errAfter { - return backendTypes.ExecutingMessage{}, s.errOverload +func (s *stubIterator) ExecMessage() *types.ExecutingMessage { + if s.index < 0 { + return nil } - // increment the iterator to mark advancement - i.(*stubIterator).index += 1 - // return the next executing message - m := *s.executingMessages[s.emIndex] - // and increment to the next message for the next call - s.emIndex++ - return m, nil + if s.index >= entrydb.EntryIdx(len(s.db.nextLogs)) { + return nil + } + e := s.db.nextLogs[s.index] + if e.execIdx < 0 { + return nil + } + return s.db.executingMessages[e.execIdx] } -func (s *stubLogDB) ClosestBlockInfo(_ uint64) (uint64, backendTypes.TruncatedHash, error) { - panic("not implemented") +var _ logs.Iterator = (*stubIterator)(nil) + +type stubLogDB struct { + addLogCalls int + sealBlockCalls int + headBlockNum uint64 + + executingMessages []*types.ExecutingMessage + nextLogs []nextLogResponse + + containsResponse containsResponse } -func (s *stubLogDB) AddLog(logHash backendTypes.TruncatedHash, block eth.BlockID, timestamp uint64, logIdx uint32, execMsg *backendTypes.ExecutingMessage) error { +func (s *stubLogDB) AddLog(logHash common.Hash, parentBlock eth.BlockID, logIdx uint32, execMsg *types.ExecutingMessage) error { s.addLogCalls++ return nil } +func (s *stubLogDB) SealBlock(parentHash common.Hash, block eth.BlockID, timestamp uint64) error { + s.sealBlockCalls++ + return nil +} + +func (s *stubLogDB) LatestSealedBlockNum() (n uint64, ok bool) { + return s.headBlockNum, true +} + +func (s *stubLogDB) FindSealedBlock(block eth.BlockID) (nextEntry entrydb.EntryIdx, err error) { + panic("not implemented") +} + +func (s *stubLogDB) IteratorStartingAt(i entrydb.EntryIdx) (logs.Iterator, error) { + return &stubIterator{ + index: i - 1, + db: s, + }, nil +} + +var _ LogStorage = (*stubLogDB)(nil) + type containsResponse struct { - contains bool - index entrydb.EntryIdx - err error + index entrydb.EntryIdx + err error } // stubbed Contains records the arguments passed to it // it returns the response set in the struct, or an empty response -func (s *stubLogDB) Contains(blockNum uint64, logIdx uint32, loghash backendTypes.TruncatedHash) (bool, entrydb.EntryIdx, error) { - return s.containsResponse.contains, s.containsResponse.index, s.containsResponse.err +func (s *stubLogDB) Contains(blockNum uint64, logIdx uint32, logHash common.Hash) (nextIndex entrydb.EntryIdx, err error) { + return s.containsResponse.index, s.containsResponse.err } func (s *stubLogDB) Rewind(newHeadBlockNum uint64) error { diff --git a/op-supervisor/supervisor/backend/db/entrydb/entry_db.go b/op-supervisor/supervisor/backend/db/entrydb/entry_db.go index 9d0ffc729efde..a260d143ddb59 100644 --- a/op-supervisor/supervisor/backend/db/entrydb/entry_db.go +++ b/op-supervisor/supervisor/backend/db/entrydb/entry_db.go @@ -10,13 +10,72 @@ import ( ) const ( - EntrySize = 24 + EntrySize = 34 ) type EntryIdx int64 type Entry [EntrySize]byte +func (entry Entry) Type() EntryType { + return EntryType(entry[0]) +} + +type EntryTypeFlag uint8 + +const ( + FlagSearchCheckpoint EntryTypeFlag = 1 << TypeSearchCheckpoint + FlagCanonicalHash EntryTypeFlag = 1 << TypeCanonicalHash + FlagInitiatingEvent EntryTypeFlag = 1 << TypeInitiatingEvent + FlagExecutingLink EntryTypeFlag = 1 << TypeExecutingLink + FlagExecutingCheck EntryTypeFlag = 1 << TypeExecutingCheck + FlagPadding EntryTypeFlag = 1 << TypePadding + // for additional padding + FlagPadding2 EntryTypeFlag = FlagPadding << 1 +) + +func (ex EntryTypeFlag) Any(v EntryTypeFlag) bool { + return ex&v != 0 +} + +func (ex *EntryTypeFlag) Add(v EntryTypeFlag) { + *ex = *ex | v +} + +func (ex *EntryTypeFlag) Remove(v EntryTypeFlag) { + *ex = *ex &^ v +} + +type EntryType uint8 + +const ( + TypeSearchCheckpoint EntryType = iota + TypeCanonicalHash + TypeInitiatingEvent + TypeExecutingLink + TypeExecutingCheck + TypePadding +) + +func (d EntryType) String() string { + switch d { + case TypeSearchCheckpoint: + return "searchCheckpoint" + case TypeCanonicalHash: + return "canonicalHash" + case TypeInitiatingEvent: + return "initiatingEvent" + case TypeExecutingLink: + return "executingLink" + case TypeExecutingCheck: + return "executingCheck" + case TypePadding: + return "padding" + default: + return fmt.Sprintf("unknown-%d", uint8(d)) + } +} + // dataAccess defines a minimal API required to manipulate the actual stored data. // It is a subset of the os.File API but could (theoretically) be satisfied by an in-memory implementation for testing. type dataAccess interface { @@ -54,7 +113,7 @@ func NewEntryDB(logger log.Logger, path string) (*EntryDB, error) { lastEntryIdx: EntryIdx(size - 1), } if size*EntrySize != info.Size() { - logger.Warn("File size is nut a multiple of entry size. Truncating to last complete entry", "fileSize", size, "entrySize", EntrySize) + logger.Warn("File size is not a multiple of entry size. Truncating to last complete entry", "fileSize", size, "entrySize", EntrySize) if err := db.recover(); err != nil { return nil, fmt.Errorf("failed to recover database at %v: %w", path, err) } diff --git a/op-supervisor/supervisor/backend/db/heads/heads.go b/op-supervisor/supervisor/backend/db/heads/heads.go index 65d1cb42abccf..7504806c04352 100644 --- a/op-supervisor/supervisor/backend/db/heads/heads.go +++ b/op-supervisor/supervisor/backend/db/heads/heads.go @@ -7,6 +7,7 @@ import ( "os" "sync" + "github.com/ethereum-optimism/optimism/op-service/ioutil" "github.com/ethereum-optimism/optimism/op-service/jsonutil" ) @@ -58,7 +59,7 @@ func (t *HeadTracker) Current() *Heads { } func (t *HeadTracker) write(heads *Heads) error { - if err := jsonutil.WriteJSON(t.path, heads, 0o644); err != nil { + if err := jsonutil.WriteJSON(heads, ioutil.ToAtomicFile(t.path, 0o644)); err != nil { return fmt.Errorf("failed to write new heads: %w", err) } return nil diff --git a/op-supervisor/supervisor/backend/db/init.go b/op-supervisor/supervisor/backend/db/init.go deleted file mode 100644 index fe6b51e5c21fe..0000000000000 --- a/op-supervisor/supervisor/backend/db/init.go +++ /dev/null @@ -1,34 +0,0 @@ -package db - -import ( - "errors" - "fmt" - "io" - "math" -) - -// Resume prepares the given LogStore to resume recording events. -// It returns the block number of the last block that is guaranteed to have been fully recorded to the database -// and rewinds the database to ensure it can resume recording from the first log of the next block. -func Resume(logDB LogStorage) error { - // Get the last checkpoint that was written then Rewind the db - // to the block prior to that block and start from there. - // Guarantees we will always roll back at least one block - // so we know we're always starting from a fully written block. - checkPointBlock, _, err := logDB.ClosestBlockInfo(math.MaxUint64) - if errors.Is(err, io.EOF) { - // No blocks recorded in the database, start from genesis - return nil - } else if err != nil { - return fmt.Errorf("failed to get block from checkpoint: %w", err) - } - if checkPointBlock == 0 { - return nil - } - block := checkPointBlock - 1 - err = logDB.Rewind(block) - if err != nil { - return fmt.Errorf("failed to rewind the database: %w", err) - } - return nil -} diff --git a/op-supervisor/supervisor/backend/db/init_test.go b/op-supervisor/supervisor/backend/db/init_test.go deleted file mode 100644 index 5ff44c524e5b5..0000000000000 --- a/op-supervisor/supervisor/backend/db/init_test.go +++ /dev/null @@ -1,91 +0,0 @@ -package db - -import ( - "fmt" - "io" - "testing" - - "github.com/ethereum-optimism/optimism/op-service/eth" - "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/db/entrydb" - "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/db/logs" - "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/types" - "github.com/stretchr/testify/require" -) - -func TestRecover(t *testing.T) { - tests := []struct { - name string - stubDB *stubLogStore - expectRewoundTo uint64 - }{ - { - name: "emptydb", - stubDB: &stubLogStore{closestBlockErr: fmt.Errorf("no entries: %w", io.EOF)}, - expectRewoundTo: 0, - }, - { - name: "genesis", - stubDB: &stubLogStore{}, - expectRewoundTo: 0, - }, - { - name: "with_blocks", - stubDB: &stubLogStore{closestBlockNumber: 15}, - expectRewoundTo: 14, - }, - } - for _, test := range tests { - test := test - t.Run(test.name, func(t *testing.T) { - err := Resume(test.stubDB) - require.NoError(t, err) - require.Equal(t, test.expectRewoundTo, test.stubDB.rewoundTo) - }) - } -} - -type stubLogStore struct { - closestBlockNumber uint64 - closestBlockErr error - rewoundTo uint64 -} - -func (s *stubLogStore) Contains(blockNum uint64, logIdx uint32, loghash types.TruncatedHash) (bool, entrydb.EntryIdx, error) { - panic("not supported") -} - -func (s *stubLogStore) ClosestBlockIterator(blockNum uint64) (logs.Iterator, error) { - panic("not supported") -} - -func (s *stubLogStore) LastCheckpointBehind(entrydb.EntryIdx) (logs.Iterator, error) { - panic("not supported") -} - -func (s *stubLogStore) ClosestBlockInfo(blockNum uint64) (uint64, types.TruncatedHash, error) { - if s.closestBlockErr != nil { - return 0, types.TruncatedHash{}, s.closestBlockErr - } - return s.closestBlockNumber, types.TruncatedHash{}, nil -} - -func (s *stubLogStore) NextExecutingMessage(logs.Iterator) (types.ExecutingMessage, error) { - panic("not supported") -} - -func (s *stubLogStore) Rewind(headBlockNum uint64) error { - s.rewoundTo = headBlockNum - return nil -} - -func (s *stubLogStore) AddLog(logHash types.TruncatedHash, block eth.BlockID, timestamp uint64, logIdx uint32, execMsg *types.ExecutingMessage) error { - panic("not supported") -} - -func (s *stubLogStore) LatestBlockNum() uint64 { - panic("not supported") -} - -func (s *stubLogStore) Close() error { - return nil -} diff --git a/op-supervisor/supervisor/backend/db/logs/db.go b/op-supervisor/supervisor/backend/db/logs/db.go index 0f757f5254cd0..996a5c68d712c 100644 --- a/op-supervisor/supervisor/backend/db/logs/db.go +++ b/op-supervisor/supervisor/backend/db/logs/db.go @@ -4,34 +4,35 @@ import ( "errors" "fmt" "io" - "math" "sync" - "github.com/ethereum-optimism/optimism/op-service/eth" - "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/db/entrydb" - "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/types" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/log" -) - -const ( - searchCheckpointFrequency = 256 - eventFlagIncrementLogIdx = byte(1) - eventFlagHasExecutingMessage = byte(1) << 1 + "github.com/ethereum-optimism/optimism/op-service/eth" + "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/db/entrydb" + "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" ) const ( - typeSearchCheckpoint byte = iota - typeCanonicalHash - typeInitiatingEvent - typeExecutingLink - typeExecutingCheck + searchCheckpointFrequency = 256 + eventFlagHasExecutingMessage = byte(1) ) var ( - ErrLogOutOfOrder = errors.New("log out of order") + // ErrLogOutOfOrder happens when you try to add a log to the DB, + // but it does not actually fit onto the latest data (by being too old or new). + ErrLogOutOfOrder = errors.New("log out of order") + // ErrDataCorruption happens when the underlying DB has some I/O issue ErrDataCorruption = errors.New("data corruption") - ErrNotFound = errors.New("not found") + // ErrSkipped happens when we try to retrieve data that is not available (pruned) + // It may also happen if we erroneously skip data, that was not considered a conflict, if the DB is corrupted. + ErrSkipped = errors.New("skipped data") + // ErrFuture happens when data is just not yet available + ErrFuture = errors.New("future data") + // ErrConflict happens when we know for sure that there is different canonical data + ErrConflict = errors.New("conflicting data") ) type Metrics interface { @@ -39,11 +40,6 @@ type Metrics interface { RecordDBSearchEntriesRead(count int64) } -type logContext struct { - blockNum uint64 - logIdx uint32 -} - type EntryStore interface { Size() int64 LastEntryIdx() entrydb.EntryIdx @@ -60,28 +56,6 @@ type EntryStore interface { // Use a fixed 24 bytes per entry. // // Data is an append-only log, that can be binary searched for any necessary event data. -// -// Rules: -// if entry_index % 256 == 0: must be type 0. For easy binary search. -// type 1 always adjacent to type 0 -// type 2 "diff" values are offsets from type 0 values (always within 256 entries range) -// type 3 always after type 2 -// type 4 always after type 3 -// -// Types ( = 1 byte): -// type 0: "search checkpoint" = 20 bytes -// type 1: "canonical hash" = 21 bytes -// type 2: "initiating event" = 23 bytes -// type 3: "executing link" = 24 bytes -// type 4: "executing check" = 21 bytes -// other types: future compat. E.g. for linking to L1, registering block-headers as a kind of initiating-event, tracking safe-head progression, etc. -// -// Right-pad each entry that is not 24 bytes. -// -// event-flags: each bit represents a boolean value, currently only two are defined -// * event-flags & 0x01 - true if the log index should increment. Should only be false when the event is immediately after a search checkpoint and canonical hash -// * event-flags & 0x02 - true if the initiating event has an executing link that should follow. Allows detecting when the executing link failed to write. -// event-hash: H(origin, timestamp, payloadhash); enough to check identifier matches & payload matches. type DB struct { log log.Logger m Metrics @@ -91,21 +65,21 @@ type DB struct { lastEntryContext logContext } -func NewFromFile(logger log.Logger, m Metrics, path string) (*DB, error) { +func NewFromFile(logger log.Logger, m Metrics, path string, trimToLastSealed bool) (*DB, error) { store, err := entrydb.NewEntryDB(logger, path) if err != nil { return nil, fmt.Errorf("failed to open DB: %w", err) } - return NewFromEntryStore(logger, m, store) + return NewFromEntryStore(logger, m, store, trimToLastSealed) } -func NewFromEntryStore(logger log.Logger, m Metrics, store EntryStore) (*DB, error) { +func NewFromEntryStore(logger log.Logger, m Metrics, store EntryStore, trimToLastSealed bool) (*DB, error) { db := &DB{ log: logger, m: m, store: store, } - if err := db.init(); err != nil { + if err := db.init(trimToLastSealed); err != nil { return nil, fmt.Errorf("failed to init database: %w", err) } return db, nil @@ -115,59 +89,57 @@ func (db *DB) lastEntryIdx() entrydb.EntryIdx { return db.store.LastEntryIdx() } -func (db *DB) init() error { +func (db *DB) init(trimToLastSealed bool) error { defer db.updateEntryCountMetric() // Always update the entry count metric after init completes - if err := db.trimInvalidTrailingEntries(); err != nil { - return fmt.Errorf("failed to trim invalid trailing entries: %w", err) + if trimToLastSealed { + if err := db.trimToLastSealed(); err != nil { + return fmt.Errorf("failed to trim invalid trailing entries: %w", err) + } } if db.lastEntryIdx() < 0 { - // Database is empty so no context to load + // Database is empty. + // Make a state that is ready to apply the genesis block on top of as first entry. + // This will infer into a checkpoint (half of the block seal here) + // and is then followed up with canonical-hash entry of genesis. + db.lastEntryContext = logContext{ + nextEntryIndex: 0, + blockHash: common.Hash{}, + blockNum: 0, + timestamp: 0, + logsSince: 0, + logHash: common.Hash{}, + execMsg: nil, + out: nil, + } return nil } - + // start at the last checkpoint, + // and then apply any remaining changes on top, to hydrate the state. lastCheckpoint := (db.lastEntryIdx() / searchCheckpointFrequency) * searchCheckpointFrequency - i, err := db.newIterator(lastCheckpoint) - if err != nil { - return fmt.Errorf("failed to create iterator at last search checkpoint: %w", err) - } - // Read all entries until the end of the file - for { - _, _, _, err := i.NextLog() - if errors.Is(err, io.EOF) { - break - } else if err != nil { - return fmt.Errorf("failed to init from existing entries: %w", err) - } + i := db.newIterator(lastCheckpoint) + i.current.need.Add(entrydb.FlagCanonicalHash) + if err := i.End(); err != nil { + return fmt.Errorf("failed to init from remaining trailing data: %w", err) } db.lastEntryContext = i.current return nil } -func (db *DB) trimInvalidTrailingEntries() error { +func (db *DB) trimToLastSealed() error { i := db.lastEntryIdx() for ; i >= 0; i-- { entry, err := db.store.Read(i) if err != nil { return fmt.Errorf("failed to read %v to check for trailing entries: %w", i, err) } - if entry[0] == typeExecutingCheck { - // executing check is a valid final entry + if entry.Type() == entrydb.TypeCanonicalHash { + // only an executing hash, indicating a sealed block, is a valid point for restart break } - if entry[0] == typeInitiatingEvent { - evt, err := newInitiatingEventFromEntry(entry) - if err != nil { - // Entry is invalid, keep walking backwards - continue - } - if !evt.hasExecMsg { - // init event with no exec msg is a valid final entry - break - } - } } if i < db.lastEntryIdx() { db.log.Warn("Truncating unexpected trailing entries", "prev", db.lastEntryIdx(), "new", i) + // trim such that the last entry is the canonical-hash we identified return db.store.Truncate(i) } return nil @@ -177,383 +149,352 @@ func (db *DB) updateEntryCountMetric() { db.m.RecordDBEntryCount(db.store.Size()) } -func (db *DB) LatestBlockNum() uint64 { - return db.lastEntryContext.blockNum +func (db *DB) IteratorStartingAt(i entrydb.EntryIdx) (Iterator, error) { + db.rwLock.RLock() + defer db.rwLock.RUnlock() + if i > db.lastEntryContext.nextEntryIndex { + return nil, ErrFuture + } + // TODO(#12031): Workaround while we not have IteratorStartingAt(heads.HeadPointer): + // scroll back from the index, to find block info. + idx := i + for ; idx >= 0; i-- { + entry, err := db.store.Read(idx) + if err != nil { + if errors.Is(err, io.EOF) { + continue // traverse to when we did have blocks + } + return nil, err + } + if entry.Type() == entrydb.TypeSearchCheckpoint { + break + } + if idx == 0 { + return nil, fmt.Errorf("empty DB, no block entry, cannot start at %d", i) + } + } + iter := db.newIterator(idx) + for iter.NextIndex() < i { + if _, err := iter.next(); err != nil { + return nil, errors.New("failed to process back up to the head pointer") + } + } + return iter, nil } -// ClosestBlockInfo returns the block number and hash of the highest recorded block at or before blockNum. -// Since block data is only recorded in search checkpoints, this may return an earlier block even if log data is -// recorded for the requested block. -func (db *DB) ClosestBlockInfo(blockNum uint64) (uint64, types.TruncatedHash, error) { +// FindSealedBlock finds the requested block, to check if it exists, +// returning the next index after it where things continue from. +// returns ErrFuture if the block is too new to be able to tell +// returns ErrDifferent if the known block does not match +func (db *DB) FindSealedBlock(block eth.BlockID) (nextEntry entrydb.EntryIdx, err error) { db.rwLock.RLock() defer db.rwLock.RUnlock() - checkpointIdx, err := db.searchCheckpoint(blockNum, math.MaxUint32) - if err != nil { - return 0, types.TruncatedHash{}, fmt.Errorf("no checkpoint at or before block %v found: %w", blockNum, err) + iter, err := db.newIteratorAt(block.Number, 0) + if errors.Is(err, ErrFuture) { + return 0, fmt.Errorf("block %d is not known yet: %w", block.Number, ErrFuture) + } else if err != nil { + return 0, fmt.Errorf("failed to find sealed block %d: %w", block.Number, err) } - checkpoint, err := db.readSearchCheckpoint(checkpointIdx) - if err != nil { - return 0, types.TruncatedHash{}, fmt.Errorf("failed to reach checkpoint: %w", err) + h, _, ok := iter.SealedBlock() + if !ok { + panic("expected block") } - entry, err := db.readCanonicalHash(checkpointIdx + 1) - if err != nil { - return 0, types.TruncatedHash{}, fmt.Errorf("failed to read canonical hash: %w", err) + if block.Hash != h { + return 0, fmt.Errorf("queried %s but got %s at number %d: %w", block.Hash, h, block.Number, ErrConflict) } - return checkpoint.blockNum, entry.hash, nil + return iter.NextIndex(), nil } -// ClosestBlockIterator returns an iterator for the block closest to the specified blockNum. -// The iterator will start at the search checkpoint for the block, or the first checkpoint before it. -func (db *DB) ClosestBlockIterator(blockNum uint64) (Iterator, error) { +// LatestSealedBlockNum returns the block number of the block that was last sealed, +// or ok=false if there is no sealed block (i.e. empty DB) +func (db *DB) LatestSealedBlockNum() (n uint64, ok bool) { db.rwLock.RLock() defer db.rwLock.RUnlock() - checkpointIdx, err := db.searchCheckpoint(blockNum, math.MaxUint32) - if err != nil { - return nil, fmt.Errorf("no checkpoint at or before block %v found: %w", blockNum, err) + if db.lastEntryContext.nextEntryIndex == 0 { + return 0, false // empty DB, time to add the first seal + } + if !db.lastEntryContext.hasCompleteBlock() { + db.log.Debug("New block is already in progress", "num", db.lastEntryContext.blockNum) } - return db.newIterator(checkpointIdx) + return db.lastEntryContext.blockNum, true } -// Get returns the truncated hash of the log at the specified blockNum and logIdx, -// or an error if the log is not found. -func (db *DB) Get(blockNum uint64, logiIdx uint32) (types.TruncatedHash, error) { +// Get returns the hash of the log at the specified blockNum (of the sealed block) +// and logIdx (of the log after the block), or an error if the log is not found. +func (db *DB) Get(blockNum uint64, logIdx uint32) (common.Hash, error) { db.rwLock.RLock() defer db.rwLock.RUnlock() - hash, _, err := db.findLogInfo(blockNum, logiIdx) + hash, _, err := db.findLogInfo(blockNum, logIdx) return hash, err } -// Contains return true iff the specified logHash is recorded in the specified blockNum and logIdx. -// If the log is found, the entry index of the log is returned, too. +// Contains returns no error iff the specified logHash is recorded in the specified blockNum and logIdx. +// If the log is out of reach, then ErrFuture is returned. +// If the log is determined to conflict with the canonical chain, then ErrConflict is returned. // logIdx is the index of the log in the array of all logs in the block. // This can be used to check the validity of cross-chain interop events. -func (db *DB) Contains(blockNum uint64, logIdx uint32, logHash types.TruncatedHash) (bool, entrydb.EntryIdx, error) { +func (db *DB) Contains(blockNum uint64, logIdx uint32, logHash common.Hash) (entrydb.EntryIdx, error) { db.rwLock.RLock() defer db.rwLock.RUnlock() db.log.Trace("Checking for log", "blockNum", blockNum, "logIdx", logIdx, "hash", logHash) evtHash, iter, err := db.findLogInfo(blockNum, logIdx) - if errors.Is(err, ErrNotFound) { - // Did not find a log at blockNum and logIdx - return false, 0, nil - } else if err != nil { - return false, 0, err + if err != nil { + return 0, err // may be ErrConflict if the block does not have as many logs } db.log.Trace("Found initiatingEvent", "blockNum", blockNum, "logIdx", logIdx, "hash", evtHash) // Found the requested block and log index, check if the hash matches - if evtHash == logHash { - return true, iter.Index(), nil + if evtHash != logHash { + return 0, fmt.Errorf("payload hash mismatch: expected %s, got %s", logHash, evtHash) } - return false, 0, nil + return iter.NextIndex(), nil } -// Executes checks if the log identified by the specific block number and log index, has an ExecutingMessage associated -// with it that needs to be checked as part of interop validation. -// logIdx is the index of the log in the array of all logs in the block. -// Returns the ExecutingMessage if it exists, or ExecutingMessage{} if the log is found but has no ExecutingMessage. -// Returns ErrNotFound if the specified log does not exist in the database. -func (db *DB) Executes(blockNum uint64, logIdx uint32) (types.ExecutingMessage, error) { - db.rwLock.RLock() - defer db.rwLock.RUnlock() - _, iter, err := db.findLogInfo(blockNum, logIdx) - if err != nil { - return types.ExecutingMessage{}, err +func (db *DB) findLogInfo(blockNum uint64, logIdx uint32) (common.Hash, Iterator, error) { + if blockNum == 0 { + return common.Hash{}, nil, ErrConflict // no logs in block 0 } - execMsg, err := iter.ExecMessage() - if err != nil { - return types.ExecutingMessage{}, fmt.Errorf("failed to read executing message: %w", err) - } - return execMsg, nil + // blockNum-1, such that we find a log that came after the parent num-1 was sealed. + // logIdx, such that all entries before logIdx can be skipped, but logIdx itself is still readable. + iter, err := db.newIteratorAt(blockNum-1, logIdx) + if errors.Is(err, ErrFuture) { + db.log.Trace("Could not find log yet", "blockNum", blockNum, "logIdx", logIdx) + return common.Hash{}, nil, err + } else if err != nil { + db.log.Error("Failed searching for log", "blockNum", blockNum, "logIdx", logIdx) + return common.Hash{}, nil, err + } + if err := iter.NextInitMsg(); err != nil { + return common.Hash{}, nil, fmt.Errorf("failed to read initiating message %d, on top of block %d: %w", logIdx, blockNum, err) + } + if _, x, ok := iter.SealedBlock(); !ok { + panic("expected block") + } else if x < blockNum-1 { + panic(fmt.Errorf("bug in newIteratorAt, expected to have found parent block %d but got %d", blockNum-1, x)) + } else if x > blockNum-1 { + return common.Hash{}, nil, fmt.Errorf("log does not exist, found next block already: %w", ErrConflict) + } + logHash, x, ok := iter.InitMessage() + if !ok { + panic("expected init message") + } else if x != logIdx { + panic(fmt.Errorf("bug in newIteratorAt, expected to have found log %d but got %d", logIdx, x)) + } + return logHash, iter, nil } -func (db *DB) findLogInfo(blockNum uint64, logIdx uint32) (types.TruncatedHash, Iterator, error) { - entryIdx, err := db.searchCheckpoint(blockNum, logIdx) +// newIteratorAt returns an iterator ready after the given sealed block number, +// and positioned such that the next log-read on the iterator return the log with logIndex, if any. +// It may return an ErrNotFound if the block number is unknown, +// or if there are just not that many seen log events after the block as requested. +func (db *DB) newIteratorAt(blockNum uint64, logIndex uint32) (*iterator, error) { + // find a checkpoint before or exactly when blockNum was sealed, + // and have processed up to but not including [logIndex] number of logs (i.e. all prior logs, if any). + searchCheckpointIndex, err := db.searchCheckpoint(blockNum, logIndex) if errors.Is(err, io.EOF) { // Did not find a checkpoint to start reading from so the log cannot be present. - return types.TruncatedHash{}, nil, ErrNotFound + return nil, ErrFuture } else if err != nil { - return types.TruncatedHash{}, nil, err + return nil, err } - - i, err := db.newIterator(entryIdx) + // The iterator did not consume the checkpoint yet, it's positioned right at it. + // So we can call NextBlock() and get the checkpoint itself as first entry. + iter := db.newIterator(searchCheckpointIndex) if err != nil { - return types.TruncatedHash{}, nil, fmt.Errorf("failed to create iterator: %w", err) + return nil, err } - db.log.Trace("Starting search", "entry", entryIdx, "blockNum", i.current.blockNum, "logIdx", i.current.logIdx) + iter.current.need.Add(entrydb.FlagCanonicalHash) defer func() { - db.m.RecordDBSearchEntriesRead(i.entriesRead) + db.m.RecordDBSearchEntriesRead(iter.entriesRead) }() + // First walk up to the block that we are sealed up to (incl.) for { - evtBlockNum, evtLogIdx, evtHash, err := i.NextLog() - if errors.Is(err, io.EOF) { - // Reached end of log without finding the event - return types.TruncatedHash{}, nil, ErrNotFound + if _, n, _ := iter.SealedBlock(); n == blockNum { // we may already have it exactly + break + } + if err := iter.NextBlock(); errors.Is(err, ErrFuture) { + db.log.Trace("ran out of data, could not find block", "nextIndex", iter.NextIndex(), "target", blockNum) + return nil, ErrFuture } else if err != nil { - return types.TruncatedHash{}, nil, fmt.Errorf("failed to read next log: %w", err) + db.log.Error("failed to read next block", "nextIndex", iter.NextIndex(), "target", blockNum, "err", err) + return nil, err } - if evtBlockNum == blockNum && evtLogIdx == logIdx { - db.log.Trace("Found initiatingEvent", "blockNum", evtBlockNum, "logIdx", evtLogIdx, "hash", evtHash) - return evtHash, i, nil + h, num, ok := iter.SealedBlock() + if !ok { + panic("expected sealed block") } - if evtBlockNum > blockNum || (evtBlockNum == blockNum && evtLogIdx > logIdx) { - // Progressed past the requested log without finding it. - return types.TruncatedHash{}, nil, ErrNotFound + db.log.Trace("found sealed block", "num", num, "hash", h) + if num < blockNum { + continue } - } -} - -func (db *DB) newIterator(startCheckpointEntry entrydb.EntryIdx) (*iterator, error) { - checkpoint, err := db.readSearchCheckpoint(startCheckpointEntry) - if err != nil { - return nil, fmt.Errorf("failed to read search checkpoint entry %v: %w", startCheckpointEntry, err) - } - startIdx := startCheckpointEntry + 2 - firstEntry, err := db.store.Read(startIdx) - if errors.Is(err, io.EOF) { - // There should always be an entry after a checkpoint and canonical hash so an EOF here is data corruption - return nil, fmt.Errorf("%w: no entry after checkpoint and canonical hash at %v", ErrDataCorruption, startCheckpointEntry) - } else if err != nil { - return nil, fmt.Errorf("failed to read first entry to iterate %v: %w", startCheckpointEntry+2, err) - } - startLogCtx := logContext{ - blockNum: checkpoint.blockNum, - logIdx: checkpoint.logIdx, - } - // Handle starting from a checkpoint after initiating-event but before its executing-link or executing-check - if firstEntry[0] == typeExecutingLink || firstEntry[0] == typeExecutingCheck { - if firstEntry[0] == typeExecutingLink { - // The start checkpoint was between the initiating event and the executing link - // Step back to read the initiating event. The checkpoint block data will be for the initiating event - startIdx = startCheckpointEntry - 1 - } else { - // The start checkpoint was between the executing link and the executing check - // Step back to read the initiating event. The checkpoint block data will be for the initiating event - startIdx = startCheckpointEntry - 2 + if num != blockNum { // block does not contain + return nil, fmt.Errorf("looking for %d, but already at %d: %w", blockNum, num, ErrConflict) } - initEntry, err := db.store.Read(startIdx) - if err != nil { - return nil, fmt.Errorf("failed to read prior initiating event: %w", err) + break + } + // Now walk up to the number of seen logs that we want to have processed. + // E.g. logIndex == 2, need to have processed index 0 and 1, + // so two logs before quiting (and not 3 to then quit after). + for iter.current.logsSince < logIndex { + if err := iter.NextInitMsg(); err == io.EOF { + return nil, ErrFuture + } else if err != nil { + return nil, err } - initEvt, err := newInitiatingEventFromEntry(initEntry) - if err != nil { - return nil, fmt.Errorf("invalid initiating event at idx %v: %w", startIdx, err) + _, num, ok := iter.SealedBlock() + if !ok { + panic("expected sealed block") + } + if num > blockNum { + // we overshot, the block did not contain as many seen log events as requested + return nil, ErrConflict + } + _, idx, ok := iter.InitMessage() + if !ok { + panic("expected initializing message") + } + if idx+1 < logIndex { + continue + } + if idx+1 == logIndex { + break // the NextInitMsg call will position the iterator at the re } - startLogCtx = initEvt.preContext(startLogCtx) + return nil, fmt.Errorf("unexpected log-skip at block %d log %d", blockNum, idx) } - i := &iterator{ + return iter, nil +} + +// newIterator creates an iterator at the given index. +// None of the iterator attributes will be ready for reads, +// but the entry at the given index will be first read when using the iterator. +func (db *DB) newIterator(index entrydb.EntryIdx) *iterator { + return &iterator{ db: db, - // +2 to skip the initial search checkpoint and the canonical hash event after it - nextEntryIdx: startIdx, - current: startLogCtx, + current: logContext{ + nextEntryIndex: index, + }, } - return i, nil } -// searchCheckpoint performs a binary search of the searchCheckpoint entries to find the closest one at or before -// the requested log. -// Returns the index of the searchCheckpoint to begin reading from or an error -func (db *DB) searchCheckpoint(blockNum uint64, logIdx uint32) (entrydb.EntryIdx, error) { +// searchCheckpoint performs a binary search of the searchCheckpoint entries +// to find the closest one with an equal or lower block number and equal or lower amount of seen logs. +// Returns the index of the searchCheckpoint to begin reading from or an error. +func (db *DB) searchCheckpoint(sealedBlockNum uint64, logsSince uint32) (entrydb.EntryIdx, error) { + if db.lastEntryContext.nextEntryIndex == 0 { + return 0, ErrFuture // empty DB, everything is in the future + } n := (db.lastEntryIdx() / searchCheckpointFrequency) + 1 - // Define x[-1] < target and x[n] >= target. - // Invariant: x[i-1] < target, x[j] >= target. + // Define: x is the array of known checkpoints + // Invariant: x[i] <= target, x[j] > target. i, j := entrydb.EntryIdx(0), n - for i < j { - h := entrydb.EntryIdx(uint64(i+j) >> 1) // avoid overflow when computing h + for i+1 < j { // i is inclusive, j is exclusive. + // Get the checkpoint exactly in-between, + // bias towards a higher value if an even number of checkpoints. + // E.g. i=3 and j=4 would not run, since i + 1 < j + // E.g. i=3 and j=5 leaves checkpoints 3, 4, and we pick 4 as pivot + // E.g. i=3 and j=6 leaves checkpoints 3, 4, 5, and we pick 4 as pivot + // + // The following holds: i ≤ h < j + h := entrydb.EntryIdx((uint64(i) + uint64(j)) >> 1) checkpoint, err := db.readSearchCheckpoint(h * searchCheckpointFrequency) if err != nil { return 0, fmt.Errorf("failed to read entry %v: %w", h, err) } - // i ≤ h < j - if checkpoint.blockNum < blockNum || (checkpoint.blockNum == blockNum && checkpoint.logIdx < logIdx) { - i = h + 1 // preserves x[i-1] < target + if checkpoint.blockNum < sealedBlockNum || + (checkpoint.blockNum == sealedBlockNum && checkpoint.logsSince < logsSince) { + i = h } else { - j = h // preserves x[j] >= target + j = h } } - if i < n { - checkpoint, err := db.readSearchCheckpoint(i * searchCheckpointFrequency) - if err != nil { - return 0, fmt.Errorf("failed to read entry %v: %w", i, err) - } - if checkpoint.blockNum == blockNum && checkpoint.logIdx == logIdx { - // Found entry at requested block number and log index - return i * searchCheckpointFrequency, nil - } + if i+1 != j { + panic("expected to have 1 checkpoint left") + } + result := i * searchCheckpointFrequency + checkpoint, err := db.readSearchCheckpoint(result) + if err != nil { + return 0, fmt.Errorf("failed to read final search checkpoint result: %w", err) } - if i == 0 { - // There are no checkpoints before the requested blocks - return 0, io.EOF + if checkpoint.blockNum > sealedBlockNum || + (checkpoint.blockNum == sealedBlockNum && checkpoint.logsSince > logsSince) { + return 0, fmt.Errorf("missing data, earliest search checkpoint is %d with %d logs, cannot find something before or at %d with %d logs: %w", + checkpoint.blockNum, checkpoint.logsSince, sealedBlockNum, logsSince, ErrSkipped) } - // Not found, need to start reading from the entry prior - return (i - 1) * searchCheckpointFrequency, nil + return result, nil } -func (db *DB) AddLog(logHash types.TruncatedHash, block eth.BlockID, timestamp uint64, logIdx uint32, execMsg *types.ExecutingMessage) error { - db.rwLock.Lock() - defer db.rwLock.Unlock() - postState := logContext{ - blockNum: block.Number, - logIdx: logIdx, - } - if block.Number == 0 { - return fmt.Errorf("%w: should not have logs in block 0", ErrLogOutOfOrder) - } - if db.lastEntryContext.blockNum > block.Number { - return fmt.Errorf("%w: adding block %v, head block: %v", ErrLogOutOfOrder, block.Number, db.lastEntryContext.blockNum) - } - if db.lastEntryContext.blockNum == block.Number && db.lastEntryContext.logIdx+1 != logIdx { - return fmt.Errorf("%w: adding log %v in block %v, but currently at log %v", ErrLogOutOfOrder, logIdx, block.Number, db.lastEntryContext.logIdx) - } - if db.lastEntryContext.blockNum < block.Number && logIdx != 0 { - return fmt.Errorf("%w: adding log %v as first log in block %v", ErrLogOutOfOrder, logIdx, block.Number) +// debug util to log the last 10 entries of the chain +func (db *DB) debugTip() { + for x := 0; x < 10; x++ { + index := db.lastEntryIdx() - entrydb.EntryIdx(x) + if index < 0 { + continue + } + e, err := db.store.Read(index) + if err == nil { + db.log.Debug("tip", "index", index, "type", e.Type()) + } } - var entriesToAdd []entrydb.Entry - newContext := db.lastEntryContext - lastEntryIdx := db.lastEntryIdx() +} - addEntry := func(entry entrydb.Entry) { - entriesToAdd = append(entriesToAdd, entry) - lastEntryIdx++ +func (db *DB) flush() error { + for i, e := range db.lastEntryContext.out { + db.log.Trace("appending entry", "type", e.Type(), "entry", hexutil.Bytes(e[:]), + "next", int(db.lastEntryContext.nextEntryIndex)-len(db.lastEntryContext.out)+i) } - maybeAddCheckpoint := func() { - if (lastEntryIdx+1)%searchCheckpointFrequency == 0 { - addEntry(newSearchCheckpoint(block.Number, logIdx, timestamp).encode()) - addEntry(newCanonicalHash(types.TruncateHash(block.Hash)).encode()) - newContext = postState - } + if err := db.store.Append(db.lastEntryContext.out...); err != nil { + return fmt.Errorf("failed to append entries: %w", err) } - maybeAddCheckpoint() + db.lastEntryContext.out = db.lastEntryContext.out[:0] + db.updateEntryCountMetric() + return nil +} - evt, err := newInitiatingEvent(newContext, postState.blockNum, postState.logIdx, logHash, execMsg != nil) - if err != nil { - return fmt.Errorf("failed to create initiating event: %w", err) +func (db *DB) SealBlock(parentHash common.Hash, block eth.BlockID, timestamp uint64) error { + db.rwLock.Lock() + defer db.rwLock.Unlock() + + if err := db.lastEntryContext.SealBlock(parentHash, block, timestamp); err != nil { + return fmt.Errorf("failed to seal block: %w", err) } - addEntry(evt.encode()) + db.log.Trace("Sealed block", "parent", parentHash, "block", block, "timestamp", timestamp) + return db.flush() +} - if execMsg != nil { - maybeAddCheckpoint() - link, err := newExecutingLink(*execMsg) - if err != nil { - return fmt.Errorf("failed to create executing link: %w", err) - } - addEntry(link.encode()) +func (db *DB) AddLog(logHash common.Hash, parentBlock eth.BlockID, logIdx uint32, execMsg *types.ExecutingMessage) error { + db.rwLock.Lock() + defer db.rwLock.Unlock() - maybeAddCheckpoint() - addEntry(newExecutingCheck(execMsg.Hash).encode()) + if err := db.lastEntryContext.ApplyLog(parentBlock, logIdx, logHash, execMsg); err != nil { + return fmt.Errorf("failed to apply log: %w", err) } - if err := db.store.Append(entriesToAdd...); err != nil { - return fmt.Errorf("failed to append entries: %w", err) - } - db.lastEntryContext = postState - db.updateEntryCountMetric() - return nil + db.log.Trace("Applied log", "parentBlock", parentBlock, "logIndex", logIdx, "logHash", logHash, "executing", execMsg != nil) + return db.flush() } // Rewind the database to remove any blocks after headBlockNum // The block at headBlockNum itself is not removed. -func (db *DB) Rewind(headBlockNum uint64) error { +func (db *DB) Rewind(newHeadBlockNum uint64) error { db.rwLock.Lock() defer db.rwLock.Unlock() - if headBlockNum >= db.lastEntryContext.blockNum { - // Nothing to do - return nil - } - // Find the last checkpoint before the block to remove - idx, err := db.searchCheckpoint(headBlockNum+1, 0) - if errors.Is(err, io.EOF) { - // Requested a block prior to the first checkpoint - // Delete everything without scanning forward - idx = -1 - } else if err != nil { - return fmt.Errorf("failed to find checkpoint prior to block %v: %w", headBlockNum, err) - } else { - // Scan forward from the checkpoint to find the first entry about a block after headBlockNum - i, err := db.newIterator(idx) - if err != nil { - return fmt.Errorf("failed to create iterator when searching for rewind point: %w", err) - } - // If we don't find any useful logs after the checkpoint, we should delete the checkpoint itself - // So move our delete marker back to include it as a starting point - idx-- - for { - blockNum, _, _, err := i.NextLog() - if errors.Is(err, io.EOF) { - // Reached end of file, we need to keep everything - return nil - } else if err != nil { - return fmt.Errorf("failed to find rewind point: %w", err) - } - if blockNum > headBlockNum { - // Found the first entry we don't need, so stop searching and delete everything after idx - break - } - // Otherwise we need all of the entries the iterator just read - idx = i.nextEntryIdx - 1 - } + // Even if the last fully-processed block matches headBlockNum, + // we might still have trailing log events to get rid of. + iter, err := db.newIteratorAt(newHeadBlockNum, 0) + if err != nil { + return err } - // Truncate to contain idx+1 entries, since indices are 0 based, this deletes everything after idx - if err := db.store.Truncate(idx); err != nil { - return fmt.Errorf("failed to truncate to block %v: %w", headBlockNum, err) + // Truncate to contain idx+1 entries, since indices are 0 based, + // this deletes everything after idx + if err := db.store.Truncate(iter.NextIndex()); err != nil { + return fmt.Errorf("failed to truncate to block %v: %w", newHeadBlockNum, err) } // Use db.init() to find the log context for the new latest log entry - if err := db.init(); err != nil { + if err := db.init(true); err != nil { return fmt.Errorf("failed to find new last entry context: %w", err) } return nil } -// NextExecutingMessage returns the next executing message in the log database. -// it skips over any non-executing messages, and will return an error if encountered. -// the iterator is modified in the process. -func (db *DB) NextExecutingMessage(iter Iterator) (types.ExecutingMessage, error) { - db.rwLock.RLock() - defer db.rwLock.RUnlock() - // this for-loop will break: - // - when the iterator reaches the end of the log - // - when the iterator reaches an executing message - // - if an error occurs - for { - _, _, _, err := iter.NextLog() - if err != nil { - return types.ExecutingMessage{}, err - } - // if the log is not an executing message, both exec and err are empty - exec, err := iter.ExecMessage() - if err != nil { - return types.ExecutingMessage{}, fmt.Errorf("failed to get executing message: %w", err) - } - if exec != (types.ExecutingMessage{}) { - return exec, nil - } - } -} - -// LastCheckpointBehind returns an iterator for the last checkpoint behind the specified entry index. -// If the entry index is a search checkpoint, the iterator will start at that checkpoint. -// After searching back long enough (the searchCheckpointFrequency), an error is returned, -// as checkpoints are expected to be found within the frequency. -func (db *DB) LastCheckpointBehind(entryIdx entrydb.EntryIdx) (Iterator, error) { - for attempts := 0; attempts < searchCheckpointFrequency; attempts++ { - // attempt to read the index entry as a search checkpoint - _, err := db.readSearchCheckpoint(entryIdx) - if err == nil { - return db.newIterator(entryIdx) - } - // ErrDataCorruption is the return value if the entry is not a search checkpoint - // if it's not that type of error, we should return it instead of continuing - if !errors.Is(err, ErrDataCorruption) { - return nil, err - } - // don't attempt to read behind the start of the data - if entryIdx == 0 { - break - } - // reverse if we haven't found it yet - entryIdx -= 1 - } - return nil, fmt.Errorf("failed to find a search checkpoint in the last %v entries", searchCheckpointFrequency) -} - func (db *DB) readSearchCheckpoint(entryIdx entrydb.EntryIdx) (searchCheckpoint, error) { data, err := db.store.Read(entryIdx) if err != nil { @@ -562,14 +503,6 @@ func (db *DB) readSearchCheckpoint(entryIdx entrydb.EntryIdx) (searchCheckpoint, return newSearchCheckpointFromEntry(data) } -func (db *DB) readCanonicalHash(entryIdx entrydb.EntryIdx) (canonicalHash, error) { - data, err := db.store.Read(entryIdx) - if err != nil { - return canonicalHash{}, fmt.Errorf("failed to read entry %v: %w", entryIdx, err) - } - return newCanonicalHashFromEntry(data) -} - func (db *DB) Close() error { return db.store.Close() } diff --git a/op-supervisor/supervisor/backend/db/logs/db_invariants_test.go b/op-supervisor/supervisor/backend/db/logs/db_invariants_test.go index e0837e8c57bf4..04c004f3d0966 100644 --- a/op-supervisor/supervisor/backend/db/logs/db_invariants_test.go +++ b/op-supervisor/supervisor/backend/db/logs/db_invariants_test.go @@ -38,16 +38,13 @@ func checkDBInvariants(t *testing.T, dbPath string, m *stubMetrics) { } entryInvariants := []entryInvariant{ - invariantSearchCheckpointOnlyAtFrequency, invariantSearchCheckpointAtEverySearchCheckpointFrequency, - invariantCanonicalHashAfterEverySearchCheckpoint, + invariantCanonicalHashOrCheckpointAfterEverySearchCheckpoint, invariantSearchCheckpointBeforeEveryCanonicalHash, - invariantIncrementLogIdxIfNotImmediatelyAfterCanonicalHash, invariantExecLinkAfterInitEventWithFlagSet, invariantExecLinkOnlyAfterInitiatingEventWithFlagSet, invariantExecCheckAfterExecLink, invariantExecCheckOnlyAfterExecLink, - invariantValidLastEntry, } for i, entry := range entries { for _, invariant := range entryInvariants { @@ -83,81 +80,47 @@ func invariantFileSizeMatchesEntryCountMetric(stat os.FileInfo, m *stubMetrics) return nil } -func invariantSearchCheckpointOnlyAtFrequency(entryIdx int, entry entrydb.Entry, entries []entrydb.Entry, m *stubMetrics) error { - if entry[0] != typeSearchCheckpoint { - return nil - } - if entryIdx%searchCheckpointFrequency != 0 { - return fmt.Errorf("should only have search checkpoints every %v entries but found at entry %v", searchCheckpointFrequency, entryIdx) - } - return nil -} - func invariantSearchCheckpointAtEverySearchCheckpointFrequency(entryIdx int, entry entrydb.Entry, entries []entrydb.Entry, m *stubMetrics) error { - if entryIdx%searchCheckpointFrequency == 0 && entry[0] != typeSearchCheckpoint { + if entryIdx%searchCheckpointFrequency == 0 && entry.Type() != entrydb.TypeSearchCheckpoint { return fmt.Errorf("should have search checkpoints every %v entries but entry %v was %x", searchCheckpointFrequency, entryIdx, entry) } return nil } -func invariantCanonicalHashAfterEverySearchCheckpoint(entryIdx int, entry entrydb.Entry, entries []entrydb.Entry, m *stubMetrics) error { - if entry[0] != typeSearchCheckpoint { +func invariantCanonicalHashOrCheckpointAfterEverySearchCheckpoint(entryIdx int, entry entrydb.Entry, entries []entrydb.Entry, m *stubMetrics) error { + if entry.Type() != entrydb.TypeSearchCheckpoint { return nil } if entryIdx+1 >= len(entries) { - return fmt.Errorf("expected canonical hash after search checkpoint at entry %v but no further entries found", entryIdx) + return fmt.Errorf("expected canonical hash or checkpoint after search checkpoint at entry %v but no further entries found", entryIdx) } nextEntry := entries[entryIdx+1] - if nextEntry[0] != typeCanonicalHash { - return fmt.Errorf("expected canonical hash after search checkpoint at entry %v but got %x", entryIdx, nextEntry) + if nextEntry.Type() != entrydb.TypeCanonicalHash && nextEntry.Type() != entrydb.TypeSearchCheckpoint { + return fmt.Errorf("expected canonical hash or checkpoint after search checkpoint at entry %v but got %x", entryIdx, nextEntry) } return nil } // invariantSearchCheckpointBeforeEveryCanonicalHash ensures we don't have extra canonical-hash entries func invariantSearchCheckpointBeforeEveryCanonicalHash(entryIdx int, entry entrydb.Entry, entries []entrydb.Entry, m *stubMetrics) error { - if entry[0] != typeCanonicalHash { + if entry.Type() != entrydb.TypeCanonicalHash { return nil } if entryIdx == 0 { return fmt.Errorf("expected search checkpoint before canonical hash at entry %v but no previous entries present", entryIdx) } prevEntry := entries[entryIdx-1] - if prevEntry[0] != typeSearchCheckpoint { + if prevEntry.Type() != entrydb.TypeSearchCheckpoint { return fmt.Errorf("expected search checkpoint before canonical hash at entry %v but got %x", entryIdx, prevEntry) } return nil } -func invariantIncrementLogIdxIfNotImmediatelyAfterCanonicalHash(entryIdx int, entry entrydb.Entry, entries []entrydb.Entry, m *stubMetrics) error { - if entry[0] != typeInitiatingEvent { - return nil - } - if entryIdx == 0 { - return fmt.Errorf("found initiating event at index %v before any search checkpoint", entryIdx) - } - blockDiff := entry[1] - flags := entry[2] - incrementsLogIdx := flags&eventFlagIncrementLogIdx != 0 - prevEntry := entries[entryIdx-1] - prevEntryIsCanonicalHash := prevEntry[0] == typeCanonicalHash - if incrementsLogIdx && prevEntryIsCanonicalHash { - return fmt.Errorf("initiating event at index %v increments logIdx despite being immediately after canonical hash (prev entry %x)", entryIdx, prevEntry) - } - if incrementsLogIdx && blockDiff > 0 { - return fmt.Errorf("initiating event at index %v increments logIdx despite starting a new block", entryIdx) - } - if !incrementsLogIdx && !prevEntryIsCanonicalHash && blockDiff == 0 { - return fmt.Errorf("initiating event at index %v does not increment logIdx when block unchanged and not after canonical hash (prev entry %x)", entryIdx, prevEntry) - } - return nil -} - func invariantExecLinkAfterInitEventWithFlagSet(entryIdx int, entry entrydb.Entry, entries []entrydb.Entry, m *stubMetrics) error { - if entry[0] != typeInitiatingEvent { + if entry.Type() != entrydb.TypeInitiatingEvent { return nil } - hasExecMessage := entry[2]&eventFlagHasExecutingMessage != 0 + hasExecMessage := entry[1]&eventFlagHasExecutingMessage != 0 if !hasExecMessage { return nil } @@ -168,14 +131,14 @@ func invariantExecLinkAfterInitEventWithFlagSet(entryIdx int, entry entrydb.Entr if len(entries) <= linkIdx { return fmt.Errorf("expected executing link after initiating event with exec msg flag set at entry %v but there were no more events", entryIdx) } - if entries[linkIdx][0] != typeExecutingLink { + if entries[linkIdx].Type() != entrydb.TypeExecutingLink { return fmt.Errorf("expected executing link at idx %v after initiating event with exec msg flag set at entry %v but got type %v", linkIdx, entryIdx, entries[linkIdx][0]) } return nil } func invariantExecLinkOnlyAfterInitiatingEventWithFlagSet(entryIdx int, entry entrydb.Entry, entries []entrydb.Entry, m *stubMetrics) error { - if entry[0] != typeExecutingLink { + if entry.Type() != entrydb.TypeExecutingLink { return nil } if entryIdx == 0 { @@ -189,10 +152,10 @@ func invariantExecLinkOnlyAfterInitiatingEventWithFlagSet(entryIdx int, entry en return fmt.Errorf("found executing link without a preceding initiating event at entry %v", entryIdx) } initEntry := entries[initIdx] - if initEntry[0] != typeInitiatingEvent { + if initEntry.Type() != entrydb.TypeInitiatingEvent { return fmt.Errorf("expected initiating event at entry %v prior to executing link at %v but got %x", initIdx, entryIdx, initEntry[0]) } - flags := initEntry[2] + flags := initEntry[1] if flags&eventFlagHasExecutingMessage == 0 { return fmt.Errorf("initiating event at %v prior to executing link at %v does not have flag set to indicate needing a executing event: %x", initIdx, entryIdx, initEntry) } @@ -200,7 +163,7 @@ func invariantExecLinkOnlyAfterInitiatingEventWithFlagSet(entryIdx int, entry en } func invariantExecCheckAfterExecLink(entryIdx int, entry entrydb.Entry, entries []entrydb.Entry, m *stubMetrics) error { - if entry[0] != typeExecutingLink { + if entry.Type() != entrydb.TypeExecutingLink { return nil } checkIdx := entryIdx + 1 @@ -211,14 +174,14 @@ func invariantExecCheckAfterExecLink(entryIdx int, entry entrydb.Entry, entries return fmt.Errorf("expected executing link at %v to be followed by executing check at %v but ran out of entries", entryIdx, checkIdx) } checkEntry := entries[checkIdx] - if checkEntry[0] != typeExecutingCheck { + if checkEntry.Type() != entrydb.TypeExecutingCheck { return fmt.Errorf("expected executing link at %v to be followed by executing check at %v but got type %v", entryIdx, checkIdx, checkEntry[0]) } return nil } func invariantExecCheckOnlyAfterExecLink(entryIdx int, entry entrydb.Entry, entries []entrydb.Entry, m *stubMetrics) error { - if entry[0] != typeExecutingCheck { + if entry.Type() != entrydb.TypeExecutingCheck { return nil } if entryIdx == 0 { @@ -232,29 +195,8 @@ func invariantExecCheckOnlyAfterExecLink(entryIdx int, entry entrydb.Entry, entr return fmt.Errorf("found executing link without a preceding initiating event at entry %v", entryIdx) } linkEntry := entries[linkIdx] - if linkEntry[0] != typeExecutingLink { + if linkEntry.Type() != entrydb.TypeExecutingLink { return fmt.Errorf("expected executing link at entry %v prior to executing check at %v but got %x", linkIdx, entryIdx, linkEntry[0]) } return nil } - -// invariantValidLastEntry checks that the last entry is either a executing check or initiating event with no exec message -func invariantValidLastEntry(entryIdx int, entry entrydb.Entry, entries []entrydb.Entry, m *stubMetrics) error { - if entryIdx+1 < len(entries) { - return nil - } - if entry[0] == typeExecutingCheck { - return nil - } - if entry[0] != typeInitiatingEvent { - return fmt.Errorf("invalid final event type: %v", entry[0]) - } - evt, err := newInitiatingEventFromEntry(entry) - if err != nil { - return fmt.Errorf("final event was invalid: %w", err) - } - if evt.hasExecMsg { - return errors.New("ends with init event that should have exec msg but no exec msg follows") - } - return nil -} diff --git a/op-supervisor/supervisor/backend/db/logs/db_test.go b/op-supervisor/supervisor/backend/db/logs/db_test.go index 91caa2fe3e5da..31067b05808d5 100644 --- a/op-supervisor/supervisor/backend/db/logs/db_test.go +++ b/op-supervisor/supervisor/backend/db/logs/db_test.go @@ -1,44 +1,47 @@ package logs import ( - "bytes" - "fmt" + "encoding/binary" "io" "io/fs" "os" "path/filepath" "testing" + "github.com/stretchr/testify/require" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/testlog" "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/db/entrydb" - "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/types" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/log" - "github.com/stretchr/testify/require" + "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" ) -func createTruncatedHash(i int) types.TruncatedHash { - return types.TruncateHash(createHash(i)) -} - func createHash(i int) common.Hash { - data := bytes.Repeat([]byte{byte(i)}, common.HashLength) - return common.BytesToHash(data) + if i == -1 { // parent-hash of genesis is zero + return common.Hash{} + } + var data [9]byte + data[0] = 0xff + binary.BigEndian.PutUint64(data[1:], uint64(i)) + return crypto.Keccak256Hash(data[:]) } func TestErrorOpeningDatabase(t *testing.T) { dir := t.TempDir() - _, err := NewFromFile(testlog.Logger(t, log.LvlInfo), &stubMetrics{}, filepath.Join(dir, "missing-dir", "file.db")) + _, err := NewFromFile(testlog.Logger(t, log.LvlInfo), &stubMetrics{}, filepath.Join(dir, "missing-dir", "file.db"), false) require.ErrorIs(t, err, os.ErrNotExist) } func runDBTest(t *testing.T, setup func(t *testing.T, db *DB, m *stubMetrics), assert func(t *testing.T, db *DB, m *stubMetrics)) { createDb := func(t *testing.T, dir string) (*DB, *stubMetrics, string) { - logger := testlog.Logger(t, log.LvlInfo) + logger := testlog.Logger(t, log.LvlTrace) path := filepath.Join(dir, "test.db") m := &stubMetrics{} - db, err := NewFromFile(logger, m, path) + db, err := NewFromFile(logger, m, path, false) require.NoError(t, err, "Failed to create database") t.Cleanup(func() { err := db.Close() @@ -73,122 +76,243 @@ func TestEmptyDbDoesNotFindEntry(t *testing.T) { runDBTest(t, func(t *testing.T, db *DB, m *stubMetrics) {}, func(t *testing.T, db *DB, m *stubMetrics) { - requireNotContains(t, db, 0, 0, createHash(1)) - requireNotContains(t, db, 0, 0, common.Hash{}) + requireFuture(t, db, 1, 0, createHash(1)) + requireFuture(t, db, 1, 0, common.Hash{}) }) } +func TestLatestSealedBlockNum(t *testing.T) { + t.Run("Empty case", func(t *testing.T) { + runDBTest(t, + func(t *testing.T, db *DB, m *stubMetrics) {}, + func(t *testing.T, db *DB, m *stubMetrics) { + n, ok := db.LatestSealedBlockNum() + require.False(t, ok, "empty db expected") + require.Zero(t, n) + idx, err := db.searchCheckpoint(0, 0) + require.ErrorIs(t, err, ErrFuture, "no checkpoint in empty db") + require.Zero(t, idx) + }) + }) + t.Run("Zero case", func(t *testing.T) { + genesis := eth.BlockID{Hash: createHash(0), Number: 0} + runDBTest(t, + func(t *testing.T, db *DB, m *stubMetrics) { + require.NoError(t, db.SealBlock(common.Hash{}, genesis, 5000), "seal genesis") + }, + func(t *testing.T, db *DB, m *stubMetrics) { + n, ok := db.LatestSealedBlockNum() + require.True(t, ok, "genesis block expected") + require.Equal(t, genesis.Number, n) + idx, err := db.searchCheckpoint(0, 0) + require.NoError(t, err) + require.Zero(t, idx, "genesis block as checkpoint 0") + }) + }) + t.Run("Later genesis case", func(t *testing.T) { + genesis := eth.BlockID{Hash: createHash(10), Number: 10} + runDBTest(t, + func(t *testing.T, db *DB, m *stubMetrics) { + require.NoError(t, db.SealBlock(common.Hash{}, genesis, 5000), "seal genesis") + }, + func(t *testing.T, db *DB, m *stubMetrics) { + n, ok := db.LatestSealedBlockNum() + require.True(t, ok, "genesis block expected") + require.Equal(t, genesis.Number, n) + idx, err := db.searchCheckpoint(genesis.Number, 0) + require.NoError(t, err) + require.Zero(t, idx, "anchor block as checkpoint 0") + _, err = db.searchCheckpoint(0, 0) + require.ErrorIs(t, err, ErrSkipped, "no checkpoint before genesis") + }) + }) + t.Run("Block 1 case", func(t *testing.T) { + genesis := eth.BlockID{Hash: createHash(0), Number: 0} + block1 := eth.BlockID{Hash: createHash(1), Number: 1} + runDBTest(t, + func(t *testing.T, db *DB, m *stubMetrics) { + require.NoError(t, db.SealBlock(common.Hash{}, genesis, 5000), "seal genesis") + require.NoError(t, db.SealBlock(genesis.Hash, block1, 5001), "seal block 1") + }, + func(t *testing.T, db *DB, m *stubMetrics) { + n, ok := db.LatestSealedBlockNum() + require.True(t, ok, "block 1 expected") + require.Equal(t, block1.Number, n) + idx, err := db.searchCheckpoint(block1.Number, 0) + require.NoError(t, err) + require.Equal(t, entrydb.EntryIdx(0), idx, "checkpoint 0 still for block 1") + }) + }) + t.Run("Using checkpoint case", func(t *testing.T) { + genesis := eth.BlockID{Hash: createHash(0), Number: 0} + runDBTest(t, + func(t *testing.T, db *DB, m *stubMetrics) { + require.NoError(t, db.SealBlock(common.Hash{}, genesis, 5000), "seal genesis") + for i := 1; i <= 260; i++ { + id := eth.BlockID{Hash: createHash(i), Number: uint64(i)} + require.NoError(t, db.SealBlock(createHash(i-1), id, 5001), "seal block %d", i) + } + }, + func(t *testing.T, db *DB, m *stubMetrics) { + n, ok := db.LatestSealedBlockNum() + require.True(t, ok, "latest block expected") + expected := uint64(260) + require.Equal(t, expected, n) + idx, err := db.searchCheckpoint(expected, 0) + require.NoError(t, err) + // It costs 2 entries per block, so if we add more than 1 checkpoint worth of blocks, + // then we get to checkpoint 2 + require.Equal(t, entrydb.EntryIdx(searchCheckpointFrequency*2), idx, "checkpoint 1 reached") + }) + }) +} + func TestAddLog(t *testing.T) { t.Run("BlockZero", func(t *testing.T) { // There are no logs in the genesis block so recording an entry for block 0 should be rejected. runDBTest(t, func(t *testing.T, db *DB, m *stubMetrics) {}, func(t *testing.T, db *DB, m *stubMetrics) { - err := db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(15), Number: 0}, 5000, 0, nil) + genesis := eth.BlockID{Hash: createHash(15), Number: 0} + err := db.AddLog(createHash(1), genesis, 0, nil) require.ErrorIs(t, err, ErrLogOutOfOrder) }) }) - t.Run("FirstEntry", func(t *testing.T) { + t.Run("FirstEntries", func(t *testing.T) { runDBTest(t, func(t *testing.T, db *DB, m *stubMetrics) { - err := db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(15), Number: 15}, 5000, 0, nil) - require.NoError(t, err) + genesis := eth.BlockID{Hash: createHash(15), Number: 15} + require.NoError(t, db.SealBlock(common.Hash{}, genesis, 5000), "seal genesis") + err := db.AddLog(createHash(1), genesis, 0, nil) + require.NoError(t, err, "first log after genesis") + require.NoError(t, db.SealBlock(genesis.Hash, eth.BlockID{Hash: createHash(16), Number: 16}, 5001)) }, func(t *testing.T, db *DB, m *stubMetrics) { - requireContains(t, db, 15, 0, createHash(1)) + requireContains(t, db, 16, 0, createHash(1)) }) }) t.Run("MultipleEntriesFromSameBlock", func(t *testing.T) { runDBTest(t, func(t *testing.T, db *DB, m *stubMetrics) { - err := db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(15), Number: 15}, 5000, 0, nil) + // create 15 empty blocks + for i := 0; i <= 15; i++ { + bl := eth.BlockID{Hash: createHash(i), Number: uint64(i)} + require.NoError(t, db.SealBlock(createHash(i-1), bl, 5000+uint64(i)), "seal blocks") + } + // Now apply 3 logs on top of that, contents for block 16 + bl15 := eth.BlockID{Hash: createHash(15), Number: 15} + err := db.AddLog(createHash(1), bl15, 0, nil) + require.NoError(t, err) + err = db.AddLog(createHash(2), bl15, 1, nil) require.NoError(t, err) - err = db.AddLog(createTruncatedHash(2), eth.BlockID{Hash: createHash(15), Number: 15}, 5000, 1, nil) + err = db.AddLog(createHash(3), bl15, 2, nil) require.NoError(t, err) - err = db.AddLog(createTruncatedHash(3), eth.BlockID{Hash: createHash(15), Number: 15}, 5000, 2, nil) + // Now seal block 16 + bl16 := eth.BlockID{Hash: createHash(16), Number: 16} + err = db.SealBlock(bl15.Hash, bl16, 5016) require.NoError(t, err) }, func(t *testing.T, db *DB, m *stubMetrics) { - require.EqualValues(t, 5, m.entryCount, "should not output new searchCheckpoint for every log") - requireContains(t, db, 15, 0, createHash(1)) - requireContains(t, db, 15, 1, createHash(2)) - requireContains(t, db, 15, 2, createHash(3)) + require.EqualValues(t, 16*2+3+2, m.entryCount, "empty blocks have logs") + requireContains(t, db, 16, 0, createHash(1)) + requireContains(t, db, 16, 1, createHash(2)) + requireContains(t, db, 16, 2, createHash(3)) }) }) t.Run("MultipleEntriesFromMultipleBlocks", func(t *testing.T) { runDBTest(t, func(t *testing.T, db *DB, m *stubMetrics) { - err := db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(15), Number: 15}, 5000, 0, nil) + bl14 := eth.BlockID{Hash: createHash(14), Number: 14} + err := db.SealBlock(createHash(13), bl14, 5000) require.NoError(t, err) - err = db.AddLog(createTruncatedHash(2), eth.BlockID{Hash: createHash(15), Number: 15}, 5000, 1, nil) + bl15 := eth.BlockID{Hash: createHash(15), Number: 15} + err = db.SealBlock(createHash(14), bl15, 5001) require.NoError(t, err) - err = db.AddLog(createTruncatedHash(3), eth.BlockID{Hash: createHash(16), Number: 16}, 5002, 0, nil) + err = db.AddLog(createHash(1), bl15, 0, nil) require.NoError(t, err) - err = db.AddLog(createTruncatedHash(4), eth.BlockID{Hash: createHash(16), Number: 16}, 5002, 1, nil) + err = db.AddLog(createHash(2), bl15, 1, nil) + require.NoError(t, err) + bl16 := eth.BlockID{Hash: createHash(16), Number: 16} + err = db.SealBlock(bl15.Hash, bl16, 5003) + require.NoError(t, err) + err = db.AddLog(createHash(3), bl16, 0, nil) + require.NoError(t, err) + err = db.AddLog(createHash(4), bl16, 1, nil) + require.NoError(t, err) + bl17 := eth.BlockID{Hash: createHash(17), Number: 17} + err = db.SealBlock(bl16.Hash, bl17, 5003) require.NoError(t, err) }, func(t *testing.T, db *DB, m *stubMetrics) { - require.EqualValues(t, 6, m.entryCount, "should not output new searchCheckpoint for every block") - requireContains(t, db, 15, 0, createHash(1)) - requireContains(t, db, 15, 1, createHash(2)) - requireContains(t, db, 16, 0, createHash(3)) - requireContains(t, db, 16, 1, createHash(4)) + require.EqualValues(t, 2+2+1+1+2+1+1+2, m.entryCount, "should not output new searchCheckpoint for every block") + requireContains(t, db, 16, 0, createHash(1)) + requireContains(t, db, 16, 1, createHash(2)) + requireContains(t, db, 17, 0, createHash(3)) + requireContains(t, db, 17, 1, createHash(4)) }) }) t.Run("ErrorWhenBeforeCurrentBlock", func(t *testing.T) { runDBTest(t, func(t *testing.T, db *DB, m *stubMetrics) { - err := db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(15), Number: 15}, 5000, 0, nil) + bl15 := eth.BlockID{Hash: createHash(15), Number: 15} + err := db.SealBlock(common.Hash{}, bl15, 5001) require.NoError(t, err) }, func(t *testing.T, db *DB, m *stubMetrics) { - err := db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(14), Number: 14}, 4998, 0, nil) - require.ErrorIs(t, err, ErrLogOutOfOrder) + bl14 := eth.BlockID{Hash: createHash(14), Number: 14} + err := db.SealBlock(createHash(13), bl14, 5000) + require.ErrorIs(t, err, ErrConflict) }) }) t.Run("ErrorWhenBeforeCurrentBlockButAfterLastCheckpoint", func(t *testing.T) { runDBTest(t, func(t *testing.T, db *DB, m *stubMetrics) { - err := db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(13), Number: 13}, 5000, 0, nil) + err := db.lastEntryContext.forceBlock(eth.BlockID{Hash: createHash(13), Number: 13}, 5000) + require.NoError(t, err) + err = db.SealBlock(createHash(13), eth.BlockID{Hash: createHash(14), Number: 14}, 5001) require.NoError(t, err) - err = db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(15), Number: 15}, 5000, 0, nil) + err = db.SealBlock(createHash(14), eth.BlockID{Hash: createHash(15), Number: 15}, 5002) require.NoError(t, err) }, func(t *testing.T, db *DB, m *stubMetrics) { - err := db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(14), Number: 14}, 4998, 0, nil) - require.ErrorIs(t, err, ErrLogOutOfOrder) + onto := eth.BlockID{Hash: createHash(14), Number: 14} + err := db.AddLog(createHash(1), onto, 0, nil) + require.ErrorIs(t, err, ErrLogOutOfOrder, "cannot build logs on 14 when 15 is already sealed") }) }) t.Run("ErrorWhenBeforeCurrentLogEvent", func(t *testing.T) { runDBTest(t, func(t *testing.T, db *DB, m *stubMetrics) { - require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(15), Number: 15}, 5000, 0, nil)) - require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(15), Number: 15}, 5000, 1, nil)) + bl15 := eth.BlockID{Hash: createHash(15), Number: 15} + err := db.lastEntryContext.forceBlock(bl15, 5000) + require.NoError(t, err) + require.NoError(t, db.AddLog(createHash(1), bl15, 0, nil)) + require.NoError(t, db.AddLog(createHash(1), bl15, 1, nil)) }, func(t *testing.T, db *DB, m *stubMetrics) { - err := db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(14), Number: 15}, 4998, 0, nil) - require.ErrorIs(t, err, ErrLogOutOfOrder) + bl15 := eth.BlockID{Hash: createHash(15), Number: 15} + err := db.AddLog(createHash(1), bl15, 0, nil) + require.ErrorIs(t, err, ErrLogOutOfOrder, "already at log index 2") }) }) - t.Run("ErrorWhenBeforeCurrentLogEventButAfterLastCheckpoint", func(t *testing.T) { + t.Run("ErrorWhenBeforeBlockSeal", func(t *testing.T) { runDBTest(t, func(t *testing.T, db *DB, m *stubMetrics) { - err := db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(15), Number: 15}, 5000, 0, nil) - require.NoError(t, err) - err = db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(15), Number: 15}, 5000, 1, nil) - require.NoError(t, err) - err = db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(15), Number: 15}, 5000, 2, nil) + bl15 := eth.BlockID{Hash: createHash(15), Number: 15} + err := db.lastEntryContext.forceBlock(bl15, 5000) require.NoError(t, err) + require.NoError(t, db.AddLog(createHash(1), bl15, 0, nil)) + require.NoError(t, db.AddLog(createHash(1), bl15, 1, nil)) }, func(t *testing.T, db *DB, m *stubMetrics) { - err := db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(14), Number: 15}, 4998, 1, nil) + err := db.AddLog(createHash(1), eth.BlockID{Hash: createHash(16), Number: 16}, 0, nil) require.ErrorIs(t, err, ErrLogOutOfOrder) }) }) @@ -196,24 +320,31 @@ func TestAddLog(t *testing.T) { t.Run("ErrorWhenAtCurrentLogEvent", func(t *testing.T) { runDBTest(t, func(t *testing.T, db *DB, m *stubMetrics) { - require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(15), Number: 15}, 5000, 0, nil)) - require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(15), Number: 15}, 5000, 1, nil)) + bl15 := eth.BlockID{Hash: createHash(15), Number: 15} + err := db.lastEntryContext.forceBlock(bl15, 5000) + require.NoError(t, err) + require.NoError(t, db.AddLog(createHash(1), bl15, 0, nil)) + require.NoError(t, db.AddLog(createHash(1), bl15, 1, nil)) }, func(t *testing.T, db *DB, m *stubMetrics) { - err := db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(15), Number: 15}, 4998, 1, nil) - require.ErrorIs(t, err, ErrLogOutOfOrder) + bl15 := eth.BlockID{Hash: createHash(15), Number: 15} + err := db.AddLog(createHash(1), bl15, 1, nil) + require.ErrorIs(t, err, ErrLogOutOfOrder, "already at log index 2") }) }) t.Run("ErrorWhenAtCurrentLogEventButAfterLastCheckpoint", func(t *testing.T) { runDBTest(t, func(t *testing.T, db *DB, m *stubMetrics) { - require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(15), Number: 15}, 5000, 0, nil)) - require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(15), Number: 15}, 5000, 1, nil)) - require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(15), Number: 15}, 5000, 2, nil)) + bl15 := eth.BlockID{Hash: createHash(15), Number: 15} + err := db.lastEntryContext.forceBlock(bl15, 5000) + require.NoError(t, err) + require.NoError(t, db.AddLog(createHash(1), bl15, 0, nil)) + require.NoError(t, db.AddLog(createHash(1), bl15, 1, nil)) }, func(t *testing.T, db *DB, m *stubMetrics) { - err := db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(14), Number: 15}, 4998, 2, nil) + bl15 := eth.BlockID{Hash: createHash(16), Number: 16} + err := db.AddLog(createHash(1), bl15, 2, nil) require.ErrorIs(t, err, ErrLogOutOfOrder) }) }) @@ -221,19 +352,27 @@ func TestAddLog(t *testing.T) { t.Run("ErrorWhenSkippingLogEvent", func(t *testing.T) { runDBTest(t, func(t *testing.T, db *DB, m *stubMetrics) { - err := db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(15), Number: 15}, 5000, 0, nil) + bl15 := eth.BlockID{Hash: createHash(15), Number: 15} + err := db.lastEntryContext.forceBlock(bl15, 5000) require.NoError(t, err) + require.NoError(t, db.AddLog(createHash(1), bl15, 0, nil)) }, func(t *testing.T, db *DB, m *stubMetrics) { - err := db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(15), Number: 15}, 4998, 2, nil) + bl15 := eth.BlockID{Hash: createHash(15), Number: 15} + err := db.AddLog(createHash(1), bl15, 2, nil) require.ErrorIs(t, err, ErrLogOutOfOrder) }) }) t.Run("ErrorWhenFirstLogIsNotLogIdxZero", func(t *testing.T) { - runDBTest(t, func(t *testing.T, db *DB, m *stubMetrics) {}, + runDBTest(t, func(t *testing.T, db *DB, m *stubMetrics) { + bl15 := eth.BlockID{Hash: createHash(15), Number: 15} + err := db.lastEntryContext.forceBlock(bl15, 5000) + require.NoError(t, err) + }, func(t *testing.T, db *DB, m *stubMetrics) { - err := db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(15), Number: 15}, 4998, 5, nil) + bl15 := eth.BlockID{Hash: createHash(15), Number: 15} + err := db.AddLog(createHash(1), bl15, 5, nil) require.ErrorIs(t, err, ErrLogOutOfOrder) }) }) @@ -241,54 +380,102 @@ func TestAddLog(t *testing.T) { t.Run("ErrorWhenFirstLogOfNewBlockIsNotLogIdxZero", func(t *testing.T) { runDBTest(t, func(t *testing.T, db *DB, m *stubMetrics) { - require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(14), Number: 14}, 4996, 0, nil)) + bl15 := eth.BlockID{Hash: createHash(15), Number: 15} + err := db.lastEntryContext.forceBlock(bl15, 5000) + require.NoError(t, err) + err = db.AddLog(createHash(1), bl15, 0, nil) + require.NoError(t, err) }, func(t *testing.T, db *DB, m *stubMetrics) { - err := db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(15), Number: 15}, 4998, 1, nil) + bl15 := eth.BlockID{Hash: createHash(15), Number: 15} + err := db.AddLog(createHash(1), bl15, 1, nil) + require.NoError(t, err) + bl16 := eth.BlockID{Hash: createHash(16), Number: 16} + err = db.SealBlock(bl15.Hash, bl16, 5001) + require.NoError(t, err) + err = db.AddLog(createHash(1), bl16, 1, nil) require.ErrorIs(t, err, ErrLogOutOfOrder) }) }) t.Run("MultipleSearchCheckpoints", func(t *testing.T) { + block0 := eth.BlockID{Hash: createHash(10), Number: 10} block1 := eth.BlockID{Hash: createHash(11), Number: 11} block2 := eth.BlockID{Hash: createHash(12), Number: 12} - block3 := eth.BlockID{Hash: createHash(15), Number: 15} - block4 := eth.BlockID{Hash: createHash(16), Number: 16} - // First checkpoint is at entry idx 0 - // Block 1 logs don't reach the second checkpoint + block3 := eth.BlockID{Hash: createHash(13), Number: 13} + block4 := eth.BlockID{Hash: createHash(14), Number: 14} + // Ignoring seal-checkpoints in checkpoint counting comments here; + // First search-checkpoint is at entry idx 0 + // Block 1 logs don't reach the second search-checkpoint block1LogCount := searchCheckpointFrequency - 10 - // Block 2 logs extend to just after the third checkpoint - block2LogCount := searchCheckpointFrequency + 20 - // Block 3 logs extend to immediately before the fourth checkpoint - block3LogCount := searchCheckpointFrequency - 16 + // Block 2 logs extend to just after the third search-checkpoint + block2LogCount := searchCheckpointFrequency + 16 + // Block 3 logs extend to immediately before the fourth search-checkpoint + block3LogCount := searchCheckpointFrequency - 19 block4LogCount := 2 runDBTest(t, func(t *testing.T, db *DB, m *stubMetrics) { - for i := 0; i < block1LogCount; i++ { - err := db.AddLog(createTruncatedHash(i), block1, 3000, uint32(i), nil) - require.NoErrorf(t, err, "failed to add log %v of block 1", i) + // force in block 0 + require.NoError(t, db.lastEntryContext.forceBlock(block0, 3000)) + expectedIndex := entrydb.EntryIdx(2) + t.Logf("block 0 complete, at entry %d", db.lastEntryContext.NextIndex()) + require.Equal(t, expectedIndex, db.lastEntryContext.NextIndex()) + { // create block 1 + for i := 0; i < block1LogCount; i++ { + err := db.AddLog(createHash(i), block0, uint32(i), nil) + require.NoError(t, err) + } + err := db.SealBlock(block0.Hash, block1, 3001) // second seal-checkpoint + require.NoError(t, err) } - for i := 0; i < block2LogCount; i++ { - err := db.AddLog(createTruncatedHash(i), block2, 3002, uint32(i), nil) - require.NoErrorf(t, err, "failed to add log %v of block 2", i) + expectedIndex += entrydb.EntryIdx(block1LogCount) + 2 + t.Logf("block 1 complete, at entry %d", db.lastEntryContext.NextIndex()) + require.Equal(t, expectedIndex, db.lastEntryContext.NextIndex(), "added logs and a seal checkpoint") + { // create block 2 + for i := 0; i < block2LogCount; i++ { + // two of these imply a search checkpoint, the second and third search-checkpoint + err := db.AddLog(createHash(i), block1, uint32(i), nil) + require.NoError(t, err) + } + err := db.SealBlock(block1.Hash, block2, 3002) // third seal-checkpoint + require.NoError(t, err) } - for i := 0; i < block3LogCount; i++ { - err := db.AddLog(createTruncatedHash(i), block3, 3004, uint32(i), nil) - require.NoErrorf(t, err, "failed to add log %v of block 3", i) + expectedIndex += entrydb.EntryIdx(block2LogCount) + 2 + 2 + 2 + t.Logf("block 2 complete, at entry %d", db.lastEntryContext.NextIndex()) + require.Equal(t, expectedIndex, db.lastEntryContext.NextIndex(), "added logs, two search checkpoints, and a seal checkpoint") + { // create block 3 + for i := 0; i < block3LogCount; i++ { + err := db.AddLog(createHash(i), block2, uint32(i), nil) + require.NoError(t, err) + } + err := db.SealBlock(block2.Hash, block3, 3003) + require.NoError(t, err) } - // Verify that we're right before the fourth checkpoint will be written. + expectedIndex += entrydb.EntryIdx(block3LogCount) + 2 + t.Logf("block 3 complete, at entry %d", db.lastEntryContext.NextIndex()) + require.Equal(t, expectedIndex, db.lastEntryContext.NextIndex(), "added logs, and a seal checkpoint") + + // Verify that we're right before the fourth search-checkpoint will be written. // entryCount is the number of entries, so given 0 based indexing is the index of the next entry // the first checkpoint is at entry 0, the second at entry searchCheckpointFrequency etc - // so the fourth is at entry 3*searchCheckpointFrequency - require.EqualValues(t, 3*searchCheckpointFrequency, m.entryCount) - for i := 0; i < block4LogCount; i++ { - err := db.AddLog(createTruncatedHash(i), block4, 3006, uint32(i), nil) - require.NoErrorf(t, err, "failed to add log %v of block 4", i) + // so the fourth is at entry 3*searchCheckpointFrequency. + require.EqualValues(t, 3*searchCheckpointFrequency-1, m.entryCount) + { // create block 4 + for i := 0; i < block4LogCount; i++ { + // includes a fourth search checkpoint + err := db.AddLog(createHash(i), block3, uint32(i), nil) + require.NoError(t, err) + } + err := db.SealBlock(block3.Hash, block4, 3003) // fourth seal checkpoint + require.NoError(t, err) } + expectedIndex += entrydb.EntryIdx(block4LogCount) + 2 + 2 + require.Equal(t, expectedIndex, db.lastEntryContext.NextIndex(), "added logs, a search checkpoint, and a seal checkpoint") + t.Logf("block 4 complete, at entry %d", db.lastEntryContext.NextIndex()) }, func(t *testing.T, db *DB, m *stubMetrics) { - // Check that we wrote additional search checkpoints - expectedCheckpointCount := 4 + // Check that we wrote additional search checkpoints and seal checkpoints + expectedCheckpointCount := 4 + 4 expectedEntryCount := block1LogCount + block2LogCount + block3LogCount + block4LogCount + (2 * expectedCheckpointCount) require.EqualValues(t, expectedEntryCount, m.entryCount) // Check we can find all the logs. @@ -317,73 +504,98 @@ func TestAddDependentLog(t *testing.T) { BlockNum: 42894, LogIdx: 42, Timestamp: 8742482, - Hash: types.TruncateHash(createHash(8844)), + Hash: createHash(8844), } t.Run("FirstEntry", func(t *testing.T) { runDBTest(t, func(t *testing.T, db *DB, m *stubMetrics) { - err := db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(15), Number: 15}, 5000, 0, &execMsg) - require.NoError(t, err) - }, - func(t *testing.T, db *DB, m *stubMetrics) { - requireContains(t, db, 15, 0, createHash(1), execMsg) - }) - }) - - t.Run("CheckpointBetweenInitEventAndExecLink", func(t *testing.T) { - runDBTest(t, - func(t *testing.T, db *DB, m *stubMetrics) { - for i := uint32(0); m.entryCount < searchCheckpointFrequency-1; i++ { - require.NoError(t, db.AddLog(createTruncatedHash(9), eth.BlockID{Hash: createHash(9), Number: 1}, 500, i, nil)) - } - err := db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(15), Number: 15}, 5000, 0, &execMsg) + bl15 := eth.BlockID{Hash: createHash(15), Number: 15} + require.NoError(t, db.lastEntryContext.forceBlock(bl15, 5000)) + err := db.AddLog(createHash(1), bl15, 0, &execMsg) require.NoError(t, err) }, func(t *testing.T, db *DB, m *stubMetrics) { - requireContains(t, db, 15, 0, createHash(1), execMsg) + requireContains(t, db, 16, 0, createHash(1), execMsg) }) }) - t.Run("CheckpointBetweenInitEventAndExecLinkNotIncrementingBlock", func(t *testing.T) { + t.Run("BlockSealSearchCheckpointOverlap", func(t *testing.T) { runDBTest(t, func(t *testing.T, db *DB, m *stubMetrics) { - + bl15 := eth.BlockID{Hash: createHash(15), Number: 15} + require.NoError(t, db.lastEntryContext.forceBlock(bl15, 5000)) for i := uint32(0); m.entryCount < searchCheckpointFrequency-1; i++ { - require.NoError(t, db.AddLog(createTruncatedHash(9), eth.BlockID{Hash: createHash(9), Number: 1}, 500, i, nil)) + require.NoError(t, db.AddLog(createHash(9), bl15, i, nil)) } - err := db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(15), Number: 1}, 5000, 253, &execMsg) + bl16 := eth.BlockID{Hash: createHash(16), Number: 16} + require.NoError(t, db.SealBlock(bl15.Hash, bl16, 5001)) + // added 3 entries: seal-checkpoint, then a search-checkpoint, then the canonical hash + require.Equal(t, m.entryCount, int64(searchCheckpointFrequency+2)) + err := db.AddLog(createHash(1), bl16, 0, &execMsg) require.NoError(t, err) }, func(t *testing.T, db *DB, m *stubMetrics) { - requireContains(t, db, 1, 253, createHash(1), execMsg) + requireContains(t, db, 16, 0, createHash(9)) + requireContains(t, db, 17, 0, createHash(1), execMsg) }) }) - t.Run("CheckpointBetweenExecLinkAndExecCheck", func(t *testing.T) { + t.Run("AvoidCheckpointOverlapWithExecutingCheck", func(t *testing.T) { runDBTest(t, func(t *testing.T, db *DB, m *stubMetrics) { - for i := uint32(0); m.entryCount < searchCheckpointFrequency-2; i++ { - require.NoError(t, db.AddLog(createTruncatedHash(9), eth.BlockID{Hash: createHash(9), Number: 1}, 500, i, nil)) + bl15 := eth.BlockID{Hash: createHash(15), Number: 15} + require.NoError(t, db.lastEntryContext.forceBlock(bl15, 5000)) + // we add 256 - 2 (start) - 2 (init msg, exec link) = 252 entries + for i := uint32(0); i < 252; i++ { + require.NoError(t, db.AddLog(createHash(9), bl15, i, nil)) } - err := db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(15), Number: 15}, 5000, 0, &execMsg) + // add an executing message + err := db.AddLog(createHash(1), bl15, 252, &execMsg) require.NoError(t, err) + // 0,1: start + // 2..252+2: initiating logs without exec message + // 254 = inferred padding - 3 entries for exec msg would overlap with checkpoint + // 255 = inferred padding + // 256 = search checkpoint - what would be the exec check without padding + // 257 = canonical hash + // 258 = initiating message + // 259 = executing message link + // 260 = executing message check + require.Equal(t, int64(261), m.entryCount) + db.debugTip() }, func(t *testing.T, db *DB, m *stubMetrics) { - requireContains(t, db, 15, 0, createHash(1), execMsg) + requireContains(t, db, 16, 251, createHash(9)) + requireContains(t, db, 16, 252, createHash(1), execMsg) }) }) - t.Run("CheckpointBetweenExecLinkAndExecCheckNotIncrementingBlock", func(t *testing.T) { + t.Run("AvoidCheckpointOverlapWithExecutingLink", func(t *testing.T) { runDBTest(t, func(t *testing.T, db *DB, m *stubMetrics) { - for i := uint32(0); m.entryCount < searchCheckpointFrequency-2; i++ { - require.NoError(t, db.AddLog(createTruncatedHash(9), eth.BlockID{Hash: createHash(9), Number: 1}, 500, i, nil)) + bl15 := eth.BlockID{Hash: createHash(15), Number: 15} + require.NoError(t, db.lastEntryContext.forceBlock(bl15, 5000)) + // we add 256 - 2 (start) - 1 (init msg) = 253 entries + for i := uint32(0); i < 253; i++ { + require.NoError(t, db.AddLog(createHash(9), bl15, i, nil)) } - err := db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(15), Number: 1}, 5000, 252, &execMsg) + // add an executing message + err := db.AddLog(createHash(1), bl15, 253, &execMsg) require.NoError(t, err) + // 0,1: start + // 2..253+2: initiating logs without exec message + // 255 = inferred padding - 3 entries for exec msg would overlap with checkpoint + // 256 = search checkpoint - what would be the exec link without padding + // 257 = canonical hash + // 258 = initiating message + // 259 = executing message link + // 260 = executing message check + db.debugTip() + require.Equal(t, int64(261), m.entryCount) }, func(t *testing.T, db *DB, m *stubMetrics) { - requireContains(t, db, 1, 252, createHash(1), execMsg) + requireContains(t, db, 16, 252, createHash(9)) + requireContains(t, db, 16, 253, createHash(1), execMsg) }) }) } @@ -391,35 +603,36 @@ func TestAddDependentLog(t *testing.T) { func TestContains(t *testing.T) { runDBTest(t, func(t *testing.T, db *DB, m *stubMetrics) { - require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(50), Number: 50}, 500, 0, nil)) - require.NoError(t, db.AddLog(createTruncatedHash(3), eth.BlockID{Hash: createHash(50), Number: 50}, 500, 1, nil)) - require.NoError(t, db.AddLog(createTruncatedHash(2), eth.BlockID{Hash: createHash(50), Number: 50}, 500, 2, nil)) - require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(52), Number: 52}, 500, 0, nil)) - require.NoError(t, db.AddLog(createTruncatedHash(3), eth.BlockID{Hash: createHash(52), Number: 52}, 500, 1, nil)) + bl50 := eth.BlockID{Hash: createHash(50), Number: 50} + require.NoError(t, db.lastEntryContext.forceBlock(bl50, 5000)) + require.NoError(t, db.AddLog(createHash(1), bl50, 0, nil)) + require.NoError(t, db.AddLog(createHash(3), bl50, 1, nil)) + require.NoError(t, db.AddLog(createHash(2), bl50, 2, nil)) + bl51 := eth.BlockID{Hash: createHash(51), Number: 51} + require.NoError(t, db.SealBlock(bl50.Hash, bl51, 5001)) + bl52 := eth.BlockID{Hash: createHash(52), Number: 52} + require.NoError(t, db.SealBlock(bl51.Hash, bl52, 5001)) + require.NoError(t, db.AddLog(createHash(1), bl52, 0, nil)) + require.NoError(t, db.AddLog(createHash(3), bl52, 1, nil)) }, func(t *testing.T, db *DB, m *stubMetrics) { // Should find added logs - requireContains(t, db, 50, 0, createHash(1)) - requireContains(t, db, 50, 1, createHash(3)) - requireContains(t, db, 50, 2, createHash(2)) - requireContains(t, db, 52, 0, createHash(1)) - requireContains(t, db, 52, 1, createHash(3)) - - // Should not find log when block number too low - requireNotContains(t, db, 49, 0, createHash(1)) - - // Should not find log when block number too high - requireNotContains(t, db, 51, 0, createHash(1)) - - // Should not find log when requested log after end of database - requireNotContains(t, db, 52, 2, createHash(3)) - requireNotContains(t, db, 53, 0, createHash(3)) - - // Should not find log when log index too high - requireNotContains(t, db, 50, 3, createHash(2)) - - // Should not find log when hash doesn't match log at block number and index - requireWrongHash(t, db, 50, 0, createHash(5), types.ExecutingMessage{}) + requireContains(t, db, 51, 0, createHash(1)) + requireContains(t, db, 51, 1, createHash(3)) + requireContains(t, db, 51, 2, createHash(2)) + requireContains(t, db, 53, 0, createHash(1)) + requireContains(t, db, 53, 1, createHash(3)) + + // 52 was sealed as empty + requireConflicts(t, db, 52, 0, createHash(1)) + + // 53 only contained 2 logs, not 3, and is not sealed yet + requireFuture(t, db, 53, 2, createHash(3)) + // 54 doesn't exist yet + requireFuture(t, db, 54, 0, createHash(3)) + + // 51 only contained 3 logs, not 4 + requireConflicts(t, db, 51, 3, createHash(2)) }) } @@ -429,72 +642,81 @@ func TestExecutes(t *testing.T) { BlockNum: 22, LogIdx: 99, Timestamp: 948294, - Hash: createTruncatedHash(332299), + Hash: createHash(332299), } execMsg2 := types.ExecutingMessage{ Chain: 44, BlockNum: 55, LogIdx: 66, Timestamp: 77777, - Hash: createTruncatedHash(445566), + Hash: createHash(445566), } execMsg3 := types.ExecutingMessage{ Chain: 77, BlockNum: 88, LogIdx: 89, Timestamp: 6578567, - Hash: createTruncatedHash(778889), + Hash: createHash(778889), } runDBTest(t, func(t *testing.T, db *DB, m *stubMetrics) { - require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(50), Number: 50}, 500, 0, nil)) - require.NoError(t, db.AddLog(createTruncatedHash(3), eth.BlockID{Hash: createHash(50), Number: 50}, 500, 1, &execMsg1)) - require.NoError(t, db.AddLog(createTruncatedHash(2), eth.BlockID{Hash: createHash(50), Number: 50}, 500, 2, nil)) - require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(52), Number: 52}, 500, 0, &execMsg2)) - require.NoError(t, db.AddLog(createTruncatedHash(3), eth.BlockID{Hash: createHash(52), Number: 52}, 500, 1, &execMsg3)) + bl50 := eth.BlockID{Hash: createHash(50), Number: 50} + require.NoError(t, db.lastEntryContext.forceBlock(bl50, 500)) + require.NoError(t, db.AddLog(createHash(1), bl50, 0, nil)) + require.NoError(t, db.AddLog(createHash(3), bl50, 1, &execMsg1)) + require.NoError(t, db.AddLog(createHash(2), bl50, 2, nil)) + bl51 := eth.BlockID{Hash: createHash(51), Number: 51} + require.NoError(t, db.SealBlock(bl50.Hash, bl51, 5001)) + bl52 := eth.BlockID{Hash: createHash(52), Number: 52} + require.NoError(t, db.SealBlock(bl51.Hash, bl52, 5001)) + require.NoError(t, db.AddLog(createHash(1), bl52, 0, &execMsg2)) + require.NoError(t, db.AddLog(createHash(3), bl52, 1, &execMsg3)) }, func(t *testing.T, db *DB, m *stubMetrics) { // Should find added logs - requireExecutingMessage(t, db, 50, 0, types.ExecutingMessage{}) - requireExecutingMessage(t, db, 50, 1, execMsg1) - requireExecutingMessage(t, db, 50, 2, types.ExecutingMessage{}) - requireExecutingMessage(t, db, 52, 0, execMsg2) - requireExecutingMessage(t, db, 52, 1, execMsg3) - - // Should not find log when block number too low - requireNotContains(t, db, 49, 0, createHash(1)) - - // Should not find log when block number too high - requireNotContains(t, db, 51, 0, createHash(1)) - - // Should not find log when requested log after end of database - requireNotContains(t, db, 52, 2, createHash(3)) - requireNotContains(t, db, 53, 0, createHash(3)) - - // Should not find log when log index too high - requireNotContains(t, db, 50, 3, createHash(2)) + requireExecutingMessage(t, db, 51, 0, types.ExecutingMessage{}) + requireExecutingMessage(t, db, 51, 1, execMsg1) + requireExecutingMessage(t, db, 51, 2, types.ExecutingMessage{}) + requireExecutingMessage(t, db, 53, 0, execMsg2) + requireExecutingMessage(t, db, 53, 1, execMsg3) + + // 52 was sealed without logs + requireConflicts(t, db, 52, 0, createHash(1)) + + // 53 only contained 2 logs, not 3, and is not sealed yet + requireFuture(t, db, 53, 2, createHash(3)) + // 54 doesn't exist yet + requireFuture(t, db, 54, 0, createHash(3)) + + // 51 only contained 3 logs, not 4 + requireConflicts(t, db, 51, 3, createHash(2)) }) } func TestGetBlockInfo(t *testing.T) { - t.Run("ReturnsEOFWhenEmpty", func(t *testing.T) { + t.Run("ReturnsErrFutureWhenEmpty", func(t *testing.T) { runDBTest(t, func(t *testing.T, db *DB, m *stubMetrics) {}, func(t *testing.T, db *DB, m *stubMetrics) { - _, _, err := db.ClosestBlockInfo(10) - require.ErrorIs(t, err, io.EOF) + bl10 := eth.BlockID{Hash: createHash(10), Number: 10} + _, err := db.FindSealedBlock(bl10) + require.ErrorIs(t, err, ErrFuture) }) }) - t.Run("ReturnsEOFWhenRequestedBlockBeforeFirstSearchCheckpoint", func(t *testing.T) { + t.Run("ReturnsErrFutureWhenRequestedBlockBeforeFirstSearchCheckpoint", func(t *testing.T) { runDBTest(t, func(t *testing.T, db *DB, m *stubMetrics) { - err := db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(11), Number: 11}, 500, 0, nil) + bl11 := eth.BlockID{Hash: createHash(11), Number: 11} + require.NoError(t, db.lastEntryContext.forceBlock(bl11, 500)) + err := db.AddLog(createHash(1), bl11, 0, nil) require.NoError(t, err) }, func(t *testing.T, db *DB, m *stubMetrics) { - _, _, err := db.ClosestBlockInfo(10) - require.ErrorIs(t, err, io.EOF) + // if the DB starts at 11, then shouldn't find 10 + bl10 := eth.BlockID{Hash: createHash(10), Number: 10} + _, err := db.FindSealedBlock(bl10) + require.ErrorIs(t, err, ErrSkipped) }) }) @@ -502,56 +724,24 @@ func TestGetBlockInfo(t *testing.T) { block := eth.BlockID{Hash: createHash(11), Number: 11} runDBTest(t, func(t *testing.T, db *DB, m *stubMetrics) { - err := db.AddLog(createTruncatedHash(1), block, 500, 0, nil) - require.NoError(t, err) - }, - func(t *testing.T, db *DB, m *stubMetrics) { - requireClosestBlockInfo(t, db, 11, block.Number, block.Hash) - requireClosestBlockInfo(t, db, 12, block.Number, block.Hash) - requireClosestBlockInfo(t, db, 200, block.Number, block.Hash) - }) - }) - - t.Run("ReturnClosestCheckpointBlockInfo", func(t *testing.T) { - runDBTest(t, - func(t *testing.T, db *DB, m *stubMetrics) { - for i := 1; i < searchCheckpointFrequency+3; i++ { - block := eth.BlockID{Hash: createHash(i), Number: uint64(i)} - err := db.AddLog(createTruncatedHash(i), block, uint64(i)*2, 0, nil) - require.NoError(t, err) - } + require.NoError(t, db.SealBlock(common.Hash{}, block, 500)) }, func(t *testing.T, db *DB, m *stubMetrics) { - // Expect block from the first checkpoint - requireClosestBlockInfo(t, db, 1, 1, createHash(1)) - requireClosestBlockInfo(t, db, 10, 1, createHash(1)) - requireClosestBlockInfo(t, db, searchCheckpointFrequency-3, 1, createHash(1)) - - // Expect block from the second checkpoint - // 2 entries used for initial checkpoint but we start at block 1 - secondCheckpointBlockNum := searchCheckpointFrequency - 1 - requireClosestBlockInfo(t, db, uint64(secondCheckpointBlockNum), uint64(secondCheckpointBlockNum), createHash(secondCheckpointBlockNum)) - requireClosestBlockInfo(t, db, uint64(secondCheckpointBlockNum)+1, uint64(secondCheckpointBlockNum), createHash(secondCheckpointBlockNum)) - requireClosestBlockInfo(t, db, uint64(secondCheckpointBlockNum)+2, uint64(secondCheckpointBlockNum), createHash(secondCheckpointBlockNum)) + index, err := db.FindSealedBlock(block) + require.NoError(t, err) + require.Equal(t, entrydb.EntryIdx(2), index, + "expecting to continue after search checkpoint that declared the block") }) }) } -func requireClosestBlockInfo(t *testing.T, db *DB, searchFor uint64, expectedBlockNum uint64, expectedHash common.Hash) { - blockNum, hash, err := db.ClosestBlockInfo(searchFor) - require.NoError(t, err) - require.Equal(t, expectedBlockNum, blockNum) - require.Equal(t, types.TruncateHash(expectedHash), hash) -} - func requireContains(t *testing.T, db *DB, blockNum uint64, logIdx uint32, logHash common.Hash, execMsg ...types.ExecutingMessage) { require.LessOrEqual(t, len(execMsg), 1, "cannot have multiple executing messages for a single log") m, ok := db.m.(*stubMetrics) require.True(t, ok, "Did not get the expected metrics type") - result, _, err := db.Contains(blockNum, logIdx, types.TruncateHash(logHash)) + _, err := db.Contains(blockNum, logIdx, logHash) require.NoErrorf(t, err, "Error searching for log %v in block %v", logIdx, blockNum) - require.Truef(t, result, "Did not find log %v in block %v with hash %v", logIdx, blockNum, logHash) - require.LessOrEqual(t, m.entriesReadForSearch, int64(searchCheckpointFrequency), "Should not need to read more than between two checkpoints") + require.LessOrEqual(t, m.entriesReadForSearch, int64(searchCheckpointFrequency*2), "Should not need to read more than between two checkpoints") require.NotZero(t, m.entriesReadForSearch, "Must read at least some entries to find the log") var expectedExecMsg types.ExecutingMessage @@ -561,318 +751,354 @@ func requireContains(t *testing.T, db *DB, blockNum uint64, logIdx uint32, logHa requireExecutingMessage(t, db, blockNum, logIdx, expectedExecMsg) } -func requireNotContains(t *testing.T, db *DB, blockNum uint64, logIdx uint32, logHash common.Hash) { +func requireConflicts(t *testing.T, db *DB, blockNum uint64, logIdx uint32, logHash common.Hash) { m, ok := db.m.(*stubMetrics) require.True(t, ok, "Did not get the expected metrics type") - result, _, err := db.Contains(blockNum, logIdx, types.TruncateHash(logHash)) - require.NoErrorf(t, err, "Error searching for log %v in block %v", logIdx, blockNum) - require.Falsef(t, result, "Found unexpected log %v in block %v with hash %v", logIdx, blockNum, logHash) - require.LessOrEqual(t, m.entriesReadForSearch, int64(searchCheckpointFrequency), "Should not need to read more than between two checkpoints") - - _, err = db.Executes(blockNum, logIdx) - require.ErrorIs(t, err, ErrNotFound, "Found unexpected log when getting executing message") - require.LessOrEqual(t, m.entriesReadForSearch, int64(searchCheckpointFrequency), "Should not need to read more than between two checkpoints") + _, err := db.Contains(blockNum, logIdx, logHash) + require.ErrorIs(t, err, ErrConflict, "canonical chain must not include this log") + require.LessOrEqual(t, m.entriesReadForSearch, int64(searchCheckpointFrequency*2), "Should not need to read more than between two checkpoints") } -func requireExecutingMessage(t *testing.T, db *DB, blockNum uint64, logIdx uint32, execMsg types.ExecutingMessage) { +func requireFuture(t *testing.T, db *DB, blockNum uint64, logIdx uint32, logHash common.Hash) { m, ok := db.m.(*stubMetrics) require.True(t, ok, "Did not get the expected metrics type") - actualExecMsg, err := db.Executes(blockNum, logIdx) - require.NoError(t, err, "Error when searching for executing message") - require.Equal(t, execMsg, actualExecMsg, "Should return matching executing message") - require.LessOrEqual(t, m.entriesReadForSearch, int64(searchCheckpointFrequency), "Should not need to read more than between two checkpoints") - require.NotZero(t, m.entriesReadForSearch, "Must read at least some entries to find the log") + _, err := db.Contains(blockNum, logIdx, logHash) + require.ErrorIs(t, err, ErrFuture, "canonical chain does not yet include this log") + require.LessOrEqual(t, m.entriesReadForSearch, int64(searchCheckpointFrequency*2), "Should not need to read more than between two checkpoints") } -func requireWrongHash(t *testing.T, db *DB, blockNum uint64, logIdx uint32, logHash common.Hash, _ types.ExecutingMessage) { +func requireExecutingMessage(t *testing.T, db *DB, blockNum uint64, logIdx uint32, execMsg types.ExecutingMessage) { m, ok := db.m.(*stubMetrics) require.True(t, ok, "Did not get the expected metrics type") - result, _, err := db.Contains(blockNum, logIdx, types.TruncateHash(logHash)) - require.NoErrorf(t, err, "Error searching for log %v in block %v", logIdx, blockNum) - require.Falsef(t, result, "Found unexpected log %v in block %v with hash %v", logIdx, blockNum, logHash) - - _, err = db.Executes(blockNum, logIdx) + _, iter, err := db.findLogInfo(blockNum, logIdx) require.NoError(t, err, "Error when searching for executing message") - require.LessOrEqual(t, m.entriesReadForSearch, int64(searchCheckpointFrequency), "Should not need to read more than between two checkpoints") + actualExecMsg := iter.ExecMessage() // non-nil if not just an initiating message, but also an executing message + if execMsg == (types.ExecutingMessage{}) { + require.Nil(t, actualExecMsg) + } else { + require.NotNil(t, actualExecMsg) + require.Equal(t, execMsg, *actualExecMsg, "Should return matching executing message") + } + require.LessOrEqual(t, m.entriesReadForSearch, int64(searchCheckpointFrequency*2), "Should not need to read more than between two checkpoints") + require.NotZero(t, m.entriesReadForSearch, "Must read at least some entries to find the log") } func TestRecoverOnCreate(t *testing.T) { createDb := func(t *testing.T, store *stubEntryStore) (*DB, *stubMetrics, error) { logger := testlog.Logger(t, log.LvlInfo) m := &stubMetrics{} - db, err := NewFromEntryStore(logger, m, store) + db, err := NewFromEntryStore(logger, m, store, true) return db, m, err } - validInitEvent, err := newInitiatingEvent(logContext{blockNum: 1, logIdx: 0}, 1, 0, createTruncatedHash(1), false) - require.NoError(t, err) - validEventSequence := []entrydb.Entry{ - newSearchCheckpoint(1, 0, 100).encode(), - newCanonicalHash(createTruncatedHash(344)).encode(), - validInitEvent.encode(), + storeWithEvents := func(evts ...entrydb.Entry) *stubEntryStore { + store := &stubEntryStore{} + store.entries = append(store.entries, evts...) + return store } - var emptyEventSequence []entrydb.Entry - - for _, prefixEvents := range [][]entrydb.Entry{emptyEventSequence, validEventSequence} { - prefixEvents := prefixEvents - storeWithEvents := func(evts ...entrydb.Entry) *stubEntryStore { - store := &stubEntryStore{} - store.entries = append(store.entries, prefixEvents...) - store.entries = append(store.entries, evts...) - return store + t.Run("NoTruncateWhenLastEntryIsLogWithNoExecMessageSealed", func(t *testing.T) { + store := storeWithEvents( + // seal 0, 1, 2, 3 + newSearchCheckpoint(0, 0, 100).encode(), + newCanonicalHash(createHash(300)).encode(), + newSearchCheckpoint(1, 0, 101).encode(), + newCanonicalHash(createHash(301)).encode(), + newSearchCheckpoint(2, 0, 102).encode(), + newCanonicalHash(createHash(302)).encode(), + newSearchCheckpoint(3, 0, 103).encode(), + newCanonicalHash(createHash(303)).encode(), + // open and seal 4 + newInitiatingEvent(createHash(1), false).encode(), + newSearchCheckpoint(4, 0, 104).encode(), + newCanonicalHash(createHash(304)).encode(), + ) + db, m, err := createDb(t, store) + require.NoError(t, err) + require.EqualValues(t, int64(4*2+3), m.entryCount) + requireContains(t, db, 4, 0, createHash(1)) + }) + + t.Run("NoTruncateWhenLastEntryIsExecutingCheckSealed", func(t *testing.T) { + execMsg := types.ExecutingMessage{ + Chain: 4, + BlockNum: 10, + LogIdx: 4, + Timestamp: 1288, + Hash: createHash(4), } - t.Run(fmt.Sprintf("PrefixEvents-%v", len(prefixEvents)), func(t *testing.T) { - t.Run("NoTruncateWhenLastEntryIsLogWithNoExecMessage", func(t *testing.T) { - initEvent, err := newInitiatingEvent(logContext{blockNum: 3, logIdx: 0}, 3, 0, createTruncatedHash(1), false) - require.NoError(t, err) - store := storeWithEvents( - newSearchCheckpoint(3, 0, 100).encode(), - newCanonicalHash(createTruncatedHash(344)).encode(), - initEvent.encode(), - ) - db, m, err := createDb(t, store) - require.NoError(t, err) - require.EqualValues(t, len(prefixEvents)+3, m.entryCount) - requireContains(t, db, 3, 0, createHash(1)) - }) - - t.Run("NoTruncateWhenLastEntryIsExecutingCheck", func(t *testing.T) { - initEvent, err := newInitiatingEvent(logContext{blockNum: 3, logIdx: 0}, 3, 0, createTruncatedHash(1), true) - execMsg := types.ExecutingMessage{ - Chain: 4, - BlockNum: 10, - LogIdx: 4, - Timestamp: 1288, - Hash: createTruncatedHash(4), - } - require.NoError(t, err) - linkEvt, err := newExecutingLink(execMsg) - require.NoError(t, err) - store := storeWithEvents( - newSearchCheckpoint(3, 0, 100).encode(), - newCanonicalHash(createTruncatedHash(344)).encode(), - initEvent.encode(), - linkEvt.encode(), - newExecutingCheck(execMsg.Hash).encode(), - ) - db, m, err := createDb(t, store) - require.NoError(t, err) - require.EqualValues(t, len(prefixEvents)+5, m.entryCount) - requireContains(t, db, 3, 0, createHash(1), execMsg) - }) + linkEvt, err := newExecutingLink(execMsg) + require.NoError(t, err) + store := storeWithEvents( + newSearchCheckpoint(0, 0, 100).encode(), + newCanonicalHash(createHash(300)).encode(), + newSearchCheckpoint(1, 0, 101).encode(), + newCanonicalHash(createHash(301)).encode(), + newSearchCheckpoint(2, 0, 102).encode(), + newCanonicalHash(createHash(302)).encode(), + newInitiatingEvent(createHash(1111), true).encode(), + linkEvt.encode(), + newExecutingCheck(execMsg.Hash).encode(), + newSearchCheckpoint(3, 0, 103).encode(), + newCanonicalHash(createHash(303)).encode(), + ) + db, m, err := createDb(t, store) + require.NoError(t, err) + require.EqualValues(t, int64(3*2+5), m.entryCount) + requireContains(t, db, 3, 0, createHash(1111), execMsg) + }) - t.Run("TruncateWhenLastEntrySearchCheckpoint", func(t *testing.T) { - store := storeWithEvents(newSearchCheckpoint(3, 0, 100).encode()) - _, m, err := createDb(t, store) - require.NoError(t, err) - require.EqualValues(t, len(prefixEvents), m.entryCount) - }) + t.Run("TruncateWhenLastEntrySearchCheckpoint", func(t *testing.T) { + // A checkpoint, without a canonical blockhash, is useless, and thus truncated. + store := storeWithEvents( + newSearchCheckpoint(0, 0, 100).encode()) + _, m, err := createDb(t, store) + require.NoError(t, err) + require.EqualValues(t, int64(0), m.entryCount) + }) - t.Run("TruncateWhenLastEntryCanonicalHash", func(t *testing.T) { - store := storeWithEvents( - newSearchCheckpoint(3, 0, 100).encode(), - newCanonicalHash(createTruncatedHash(344)).encode(), - ) - _, m, err := createDb(t, store) - require.NoError(t, err) - require.EqualValues(t, len(prefixEvents), m.entryCount) - }) + t.Run("NoTruncateWhenLastEntryCanonicalHash", func(t *testing.T) { + // A completed seal is fine to have as last entry. + store := storeWithEvents( + newSearchCheckpoint(0, 0, 100).encode(), + newCanonicalHash(createHash(344)).encode(), + ) + _, m, err := createDb(t, store) + require.NoError(t, err) + require.EqualValues(t, int64(2), m.entryCount) + }) - t.Run("TruncateWhenLastEntryInitEventWithExecMsg", func(t *testing.T) { - initEvent, err := newInitiatingEvent(logContext{blockNum: 3, logIdx: 0}, 3, 0, createTruncatedHash(1), true) - require.NoError(t, err) - store := storeWithEvents( - newSearchCheckpoint(3, 0, 100).encode(), - newCanonicalHash(createTruncatedHash(344)).encode(), - initEvent.encode(), - ) - _, m, err := createDb(t, store) - require.NoError(t, err) - require.EqualValues(t, len(prefixEvents), m.entryCount) - }) + t.Run("TruncateWhenLastEntryInitEventWithExecMsg", func(t *testing.T) { + // An initiating event that claims an executing message, + // without said executing message, is dropped. + store := storeWithEvents( + newSearchCheckpoint(0, 0, 100).encode(), + newCanonicalHash(createHash(344)).encode(), + // both pruned because we go back to a seal + newInitiatingEvent(createHash(0), false).encode(), + newInitiatingEvent(createHash(1), true).encode(), + ) + _, m, err := createDb(t, store) + require.NoError(t, err) + require.EqualValues(t, int64(2), m.entryCount) + }) - t.Run("TruncateWhenLastEntryInitEventWithExecLink", func(t *testing.T) { - initEvent, err := newInitiatingEvent(logContext{blockNum: 3, logIdx: 0}, 3, 0, createTruncatedHash(1), true) - require.NoError(t, err) - execMsg := types.ExecutingMessage{ - Chain: 4, - BlockNum: 10, - LogIdx: 4, - Timestamp: 1288, - Hash: createTruncatedHash(4), - } - require.NoError(t, err) - linkEvt, err := newExecutingLink(execMsg) - require.NoError(t, err) - store := storeWithEvents( - newSearchCheckpoint(3, 0, 100).encode(), - newCanonicalHash(createTruncatedHash(344)).encode(), - initEvent.encode(), - linkEvt.encode(), - ) - _, m, err := createDb(t, store) - require.NoError(t, err) - require.EqualValues(t, len(prefixEvents), m.entryCount) - }) - }) - } + t.Run("NoTruncateWhenLastEntrySealed", func(t *testing.T) { + // An initiating event that claims an executing message, + // without said executing message, is dropped. + store := storeWithEvents( + newSearchCheckpoint(0, 0, 100).encode(), + newCanonicalHash(createHash(300)).encode(), + // pruned because we go back to a seal + newInitiatingEvent(createHash(0), false).encode(), + newSearchCheckpoint(1, 0, 100).encode(), + newCanonicalHash(createHash(301)).encode(), + ) + _, m, err := createDb(t, store) + require.NoError(t, err) + require.EqualValues(t, int64(5), m.entryCount) + }) + + t.Run("TruncateWhenLastEntryInitEventWithExecLink", func(t *testing.T) { + execMsg := types.ExecutingMessage{ + Chain: 4, + BlockNum: 10, + LogIdx: 4, + Timestamp: 1288, + Hash: createHash(4), + } + linkEvt, err := newExecutingLink(execMsg) + require.NoError(t, err) + store := storeWithEvents( + newSearchCheckpoint(3, 0, 100).encode(), + newCanonicalHash(createHash(344)).encode(), + newInitiatingEvent(createHash(1), true).encode(), + linkEvt.encode(), + ) + _, m, err := createDb(t, store) + require.NoError(t, err) + require.EqualValues(t, int64(2), m.entryCount) + }) } func TestRewind(t *testing.T) { t.Run("WhenEmpty", func(t *testing.T) { runDBTest(t, func(t *testing.T, db *DB, m *stubMetrics) {}, func(t *testing.T, db *DB, m *stubMetrics) { - require.NoError(t, db.Rewind(100)) - require.NoError(t, db.Rewind(0)) + require.ErrorIs(t, db.Rewind(100), ErrFuture) + // Genesis is a block to, not present in an empty DB + require.ErrorIs(t, db.Rewind(0), ErrFuture) }) }) t.Run("AfterLastBlock", func(t *testing.T) { runDBTest(t, func(t *testing.T, db *DB, m *stubMetrics) { - require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(50), Number: 50}, 500, 0, nil)) - require.NoError(t, db.AddLog(createTruncatedHash(2), eth.BlockID{Hash: createHash(50), Number: 50}, 500, 1, nil)) - require.NoError(t, db.AddLog(createTruncatedHash(3), eth.BlockID{Hash: createHash(51), Number: 51}, 502, 0, nil)) - require.NoError(t, db.AddLog(createTruncatedHash(4), eth.BlockID{Hash: createHash(74), Number: 74}, 700, 0, nil)) - require.NoError(t, db.Rewind(75)) + bl50 := eth.BlockID{Hash: createHash(50), Number: 50} + require.NoError(t, db.SealBlock(createHash(49), bl50, 500)) + require.NoError(t, db.AddLog(createHash(1), bl50, 0, nil)) + require.NoError(t, db.AddLog(createHash(2), bl50, 1, nil)) + bl51 := eth.BlockID{Hash: createHash(51), Number: 51} + require.NoError(t, db.SealBlock(bl50.Hash, bl51, 502)) + require.NoError(t, db.AddLog(createHash(3), bl51, 0, nil)) + bl52 := eth.BlockID{Hash: createHash(52), Number: 52} + require.NoError(t, db.SealBlock(bl51.Hash, bl52, 504)) + require.NoError(t, db.AddLog(createHash(4), bl52, 0, nil)) + // cannot rewind to a block that is not sealed yet + require.ErrorIs(t, db.Rewind(53), ErrFuture) }, func(t *testing.T, db *DB, m *stubMetrics) { - requireContains(t, db, 50, 0, createHash(1)) - requireContains(t, db, 50, 1, createHash(2)) - requireContains(t, db, 51, 0, createHash(3)) - requireContains(t, db, 74, 0, createHash(4)) + requireContains(t, db, 51, 0, createHash(1)) + requireContains(t, db, 51, 1, createHash(2)) + requireContains(t, db, 52, 0, createHash(3)) + // Still have the pending log of unsealed block if the rewind to unknown sealed block fails + requireContains(t, db, 53, 0, createHash(4)) }) }) t.Run("BeforeFirstBlock", func(t *testing.T) { runDBTest(t, func(t *testing.T, db *DB, m *stubMetrics) { - require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(50), Number: 50}, 500, 0, nil)) - require.NoError(t, db.AddLog(createTruncatedHash(2), eth.BlockID{Hash: createHash(50), Number: 50}, 500, 1, nil)) - require.NoError(t, db.Rewind(25)) + bl50 := eth.BlockID{Hash: createHash(50), Number: 50} + require.NoError(t, db.SealBlock(createHash(49), bl50, 500)) + require.NoError(t, db.AddLog(createHash(1), bl50, 0, nil)) + require.NoError(t, db.AddLog(createHash(2), bl50, 1, nil)) + // cannot go back to an unknown block + require.ErrorIs(t, db.Rewind(25), ErrSkipped) }, func(t *testing.T, db *DB, m *stubMetrics) { - requireNotContains(t, db, 50, 0, createHash(1)) - requireNotContains(t, db, 50, 0, createHash(1)) - require.Zero(t, m.entryCount) + requireContains(t, db, 51, 0, createHash(1)) + requireContains(t, db, 51, 0, createHash(1)) }) }) t.Run("AtFirstBlock", func(t *testing.T) { runDBTest(t, func(t *testing.T, db *DB, m *stubMetrics) { - require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(50), Number: 50}, 500, 0, nil)) - require.NoError(t, db.AddLog(createTruncatedHash(2), eth.BlockID{Hash: createHash(50), Number: 50}, 500, 1, nil)) - require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(51), Number: 51}, 502, 0, nil)) - require.NoError(t, db.AddLog(createTruncatedHash(2), eth.BlockID{Hash: createHash(51), Number: 51}, 502, 1, nil)) - require.NoError(t, db.Rewind(50)) + bl50 := eth.BlockID{Hash: createHash(50), Number: 50} + require.NoError(t, db.SealBlock(createHash(49), bl50, 500)) + require.NoError(t, db.AddLog(createHash(1), bl50, 0, nil)) + require.NoError(t, db.AddLog(createHash(2), bl50, 1, nil)) + bl51 := eth.BlockID{Hash: createHash(51), Number: 51} + require.NoError(t, db.SealBlock(bl50.Hash, bl51, 502)) + require.NoError(t, db.AddLog(createHash(1), bl51, 0, nil)) + require.NoError(t, db.AddLog(createHash(2), bl51, 1, nil)) + bl52 := eth.BlockID{Hash: createHash(52), Number: 52} + require.NoError(t, db.SealBlock(bl51.Hash, bl52, 504)) + require.NoError(t, db.Rewind(51)) }, func(t *testing.T, db *DB, m *stubMetrics) { - requireContains(t, db, 50, 0, createHash(1)) - requireContains(t, db, 50, 1, createHash(2)) - requireNotContains(t, db, 51, 0, createHash(1)) - requireNotContains(t, db, 51, 1, createHash(2)) + requireContains(t, db, 51, 0, createHash(1)) + requireContains(t, db, 51, 1, createHash(2)) + requireFuture(t, db, 52, 0, createHash(1)) + requireFuture(t, db, 52, 1, createHash(2)) }) }) - t.Run("AtSecondCheckpoint", func(t *testing.T) { + t.Run("AfterSecondCheckpoint", func(t *testing.T) { runDBTest(t, func(t *testing.T, db *DB, m *stubMetrics) { + bl50 := eth.BlockID{Hash: createHash(50), Number: 50} + require.NoError(t, db.SealBlock(createHash(49), bl50, 500)) for i := uint32(0); m.entryCount < searchCheckpointFrequency; i++ { - require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(50), Number: 50}, 500, i, nil)) + require.NoError(t, db.AddLog(createHash(1), bl50, i, nil)) } - require.EqualValues(t, searchCheckpointFrequency, m.entryCount) - require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(51), Number: 51}, 502, 0, nil)) - require.EqualValues(t, searchCheckpointFrequency+3, m.entryCount, "Should have inserted new checkpoint and extra log") - require.NoError(t, db.AddLog(createTruncatedHash(2), eth.BlockID{Hash: createHash(51), Number: 51}, 502, 1, nil)) - require.NoError(t, db.Rewind(50)) + // The checkpoint is added automatically, + // it will be there as soon as it reaches 255 with log events. + // Thus add 2 for the checkpoint. + require.EqualValues(t, searchCheckpointFrequency+2, m.entryCount) + bl51 := eth.BlockID{Hash: createHash(51), Number: 51} + require.NoError(t, db.SealBlock(bl50.Hash, bl51, 502)) + require.NoError(t, db.AddLog(createHash(1), bl51, 0, nil)) + require.EqualValues(t, searchCheckpointFrequency+2+3, m.entryCount, "Should have inserted new checkpoint and extra log") + require.NoError(t, db.AddLog(createHash(2), bl51, 1, nil)) + bl52 := eth.BlockID{Hash: createHash(52), Number: 52} + require.NoError(t, db.SealBlock(bl51.Hash, bl52, 504)) + require.NoError(t, db.Rewind(51)) }, func(t *testing.T, db *DB, m *stubMetrics) { - require.EqualValues(t, searchCheckpointFrequency, m.entryCount, "Should have deleted second checkpoint") - requireContains(t, db, 50, 0, createHash(1)) - requireContains(t, db, 50, 1, createHash(1)) - requireNotContains(t, db, 51, 0, createHash(1)) - requireNotContains(t, db, 51, 1, createHash(2)) + require.EqualValues(t, searchCheckpointFrequency+2+2, m.entryCount, "Should have deleted second checkpoint") + requireContains(t, db, 51, 0, createHash(1)) + requireContains(t, db, 51, 1, createHash(1)) + requireFuture(t, db, 52, 0, createHash(1)) + requireFuture(t, db, 52, 1, createHash(2)) }) }) - t.Run("BetweenLogEntries", func(t *testing.T) { + t.Run("BetweenBlockEntries", func(t *testing.T) { runDBTest(t, func(t *testing.T, db *DB, m *stubMetrics) { - require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(50), Number: 50}, 500, 0, nil)) - require.NoError(t, db.AddLog(createTruncatedHash(2), eth.BlockID{Hash: createHash(50), Number: 50}, 500, 1, nil)) - require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(60), Number: 60}, 502, 0, nil)) - require.NoError(t, db.AddLog(createTruncatedHash(2), eth.BlockID{Hash: createHash(60), Number: 60}, 502, 1, nil)) - require.NoError(t, db.Rewind(55)) - }, - func(t *testing.T, db *DB, m *stubMetrics) { - requireContains(t, db, 50, 0, createHash(1)) - requireContains(t, db, 50, 1, createHash(2)) - requireNotContains(t, db, 60, 0, createHash(1)) - requireNotContains(t, db, 60, 1, createHash(2)) - }) - }) - - t.Run("AtExistingLogEntry", func(t *testing.T) { - runDBTest(t, - func(t *testing.T, db *DB, m *stubMetrics) { - require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(59), Number: 59}, 500, 0, nil)) - require.NoError(t, db.AddLog(createTruncatedHash(2), eth.BlockID{Hash: createHash(59), Number: 59}, 500, 1, nil)) - require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(60), Number: 60}, 502, 0, nil)) - require.NoError(t, db.AddLog(createTruncatedHash(2), eth.BlockID{Hash: createHash(60), Number: 60}, 502, 1, nil)) - require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(61), Number: 61}, 502, 0, nil)) - require.NoError(t, db.AddLog(createTruncatedHash(2), eth.BlockID{Hash: createHash(61), Number: 61}, 502, 1, nil)) - require.NoError(t, db.Rewind(60)) + // create many blocks, and all the odd blocks get 2 logs + for i := uint32(0); i < 30; i++ { + bl := eth.BlockID{Hash: createHash(int(i)), Number: uint64(i)} + require.NoError(t, db.SealBlock(createHash(int(i)-1), bl, 500+uint64(i))) + if i%2 == 0 { + require.NoError(t, db.AddLog(createHash(1), bl, 0, nil)) + require.NoError(t, db.AddLog(createHash(2), bl, 1, nil)) + } + } + require.NoError(t, db.Rewind(15)) }, func(t *testing.T, db *DB, m *stubMetrics) { - requireContains(t, db, 59, 0, createHash(1)) - requireContains(t, db, 59, 1, createHash(2)) - requireContains(t, db, 60, 0, createHash(1)) - requireContains(t, db, 60, 1, createHash(2)) - requireNotContains(t, db, 61, 0, createHash(1)) - requireNotContains(t, db, 61, 1, createHash(2)) + requireContains(t, db, 15, 0, createHash(1)) + requireContains(t, db, 15, 1, createHash(2)) + requireFuture(t, db, 16, 0, createHash(1)) + requireFuture(t, db, 16, 1, createHash(2)) }) }) t.Run("AtLastEntry", func(t *testing.T) { runDBTest(t, func(t *testing.T, db *DB, m *stubMetrics) { - require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(50), Number: 50}, 500, 0, nil)) - require.NoError(t, db.AddLog(createTruncatedHash(2), eth.BlockID{Hash: createHash(50), Number: 50}, 500, 1, nil)) - require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(60), Number: 60}, 502, 0, nil)) - require.NoError(t, db.AddLog(createTruncatedHash(2), eth.BlockID{Hash: createHash(60), Number: 60}, 502, 1, nil)) - require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(70), Number: 70}, 502, 0, nil)) - require.NoError(t, db.AddLog(createTruncatedHash(2), eth.BlockID{Hash: createHash(70), Number: 70}, 502, 1, nil)) - require.NoError(t, db.Rewind(70)) + // create many blocks, and all the even blocks get 2 logs + for i := uint32(0); i <= 30; i++ { + bl := eth.BlockID{Hash: createHash(int(i)), Number: uint64(i)} + require.NoError(t, db.SealBlock(createHash(int(i)-1), bl, 500+uint64(i))) + if i%2 == 1 { + require.NoError(t, db.AddLog(createHash(1), bl, 0, nil)) + require.NoError(t, db.AddLog(createHash(2), bl, 1, nil)) + } + } + // We ended at 30, and sealed it, nothing left to prune + require.NoError(t, db.Rewind(30)) }, func(t *testing.T, db *DB, m *stubMetrics) { - requireContains(t, db, 50, 0, createHash(1)) - requireContains(t, db, 50, 1, createHash(2)) - requireContains(t, db, 60, 0, createHash(1)) - requireContains(t, db, 60, 1, createHash(2)) - requireContains(t, db, 70, 0, createHash(1)) - requireContains(t, db, 70, 1, createHash(2)) + requireContains(t, db, 20, 0, createHash(1)) + requireContains(t, db, 20, 1, createHash(2)) + // built on top of 29, these are in sealed block 30, still around + requireContains(t, db, 30, 0, createHash(1)) + requireContains(t, db, 30, 1, createHash(2)) }) }) - t.Run("ReaddDeletedBlocks", func(t *testing.T) { + t.Run("ReadDeletedBlocks", func(t *testing.T) { runDBTest(t, func(t *testing.T, db *DB, m *stubMetrics) { - require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(59), Number: 59}, 500, 0, nil)) - require.NoError(t, db.AddLog(createTruncatedHash(2), eth.BlockID{Hash: createHash(59), Number: 59}, 500, 1, nil)) - require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(60), Number: 60}, 502, 0, nil)) - require.NoError(t, db.AddLog(createTruncatedHash(2), eth.BlockID{Hash: createHash(60), Number: 60}, 502, 1, nil)) - require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(61), Number: 61}, 502, 0, nil)) - require.NoError(t, db.AddLog(createTruncatedHash(2), eth.BlockID{Hash: createHash(61), Number: 61}, 502, 1, nil)) - require.NoError(t, db.Rewind(60)) + // create many blocks, and all the odd blocks get 2 logs + for i := uint32(0); i < 30; i++ { + bl := eth.BlockID{Hash: createHash(int(i)), Number: uint64(i)} + require.NoError(t, db.SealBlock(createHash(int(i)-1), bl, 500+uint64(i))) + if i%2 == 0 { + require.NoError(t, db.AddLog(createHash(1), bl, 0, nil)) + require.NoError(t, db.AddLog(createHash(2), bl, 1, nil)) + } + } + require.NoError(t, db.Rewind(16)) }, func(t *testing.T, db *DB, m *stubMetrics) { - err := db.AddLog(createTruncatedHash(2), eth.BlockID{Hash: createHash(59), Number: 59}, 500, 1, nil) - require.ErrorIs(t, err, ErrLogOutOfOrder, "Cannot add block before rewound head") - err = db.AddLog(createTruncatedHash(2), eth.BlockID{Hash: createHash(60), Number: 60}, 502, 1, nil) - require.ErrorIs(t, err, ErrLogOutOfOrder, "Cannot add block that was rewound to") - err = db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(60), Number: 61}, 502, 0, nil) - require.NoError(t, err, "Can re-add deleted block") + bl29 := eth.BlockID{Hash: createHash(29), Number: 29} + // 29 was deleted + err := db.AddLog(createHash(2), bl29, 1, nil) + require.ErrorIs(t, err, ErrLogOutOfOrder, "Cannot add log on removed block") + // 15 is older, we have up to 16 + bl15 := eth.BlockID{Hash: createHash(15), Number: 15} + // try to add a third log to 15 + err = db.AddLog(createHash(10), bl15, 2, nil) + require.ErrorIs(t, err, ErrLogOutOfOrder) + bl16 := eth.BlockID{Hash: createHash(16), Number: 16} + // try to add a log to 17, on top of 16 + err = db.AddLog(createHash(42), bl16, 0, nil) + require.NoError(t, err) + requireContains(t, db, 17, 0, createHash(42)) }) }) } diff --git a/op-supervisor/supervisor/backend/db/logs/entries.go b/op-supervisor/supervisor/backend/db/logs/entries.go index 8816474cdd2fe..431adc99f465d 100644 --- a/op-supervisor/supervisor/backend/db/logs/entries.go +++ b/op-supervisor/supervisor/backend/db/logs/entries.go @@ -3,161 +3,111 @@ package logs import ( "encoding/binary" "fmt" - "math" + + "github.com/ethereum/go-ethereum/common" "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/db/entrydb" - "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/types" + "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" ) +// searchCheckpoint is both a checkpoint for searching, as well as a checkpoint for sealing blocks. type searchCheckpoint struct { - blockNum uint64 - logIdx uint32 + blockNum uint64 + // seen logs *after* the seal of the mentioned block, i.e. not part of this block, but building on top of it. + // There is at least one checkpoint per L2 block with logsSince == 0, i.e. the exact block boundary. + logsSince uint32 timestamp uint64 } -func newSearchCheckpoint(blockNum uint64, logIdx uint32, timestamp uint64) searchCheckpoint { +func newSearchCheckpoint(blockNum uint64, logsSince uint32, timestamp uint64) searchCheckpoint { return searchCheckpoint{ blockNum: blockNum, - logIdx: logIdx, + logsSince: logsSince, timestamp: timestamp, } } func newSearchCheckpointFromEntry(data entrydb.Entry) (searchCheckpoint, error) { - if data[0] != typeSearchCheckpoint { - return searchCheckpoint{}, fmt.Errorf("%w: attempting to decode search checkpoint but was type %v", ErrDataCorruption, data[0]) + if data.Type() != entrydb.TypeSearchCheckpoint { + return searchCheckpoint{}, fmt.Errorf("%w: attempting to decode search checkpoint but was type %s", ErrDataCorruption, data.Type()) } return searchCheckpoint{ blockNum: binary.LittleEndian.Uint64(data[1:9]), - logIdx: binary.LittleEndian.Uint32(data[9:13]), + logsSince: binary.LittleEndian.Uint32(data[9:13]), timestamp: binary.LittleEndian.Uint64(data[13:21]), }, nil } -// encode creates a search checkpoint entry -// type 0: "search checkpoint" = 20 bytes +// encode creates a checkpoint entry +// type 0: "search checkpoint" = 21 bytes func (s searchCheckpoint) encode() entrydb.Entry { var data entrydb.Entry - data[0] = typeSearchCheckpoint + data[0] = uint8(entrydb.TypeSearchCheckpoint) binary.LittleEndian.PutUint64(data[1:9], s.blockNum) - binary.LittleEndian.PutUint32(data[9:13], s.logIdx) + binary.LittleEndian.PutUint32(data[9:13], s.logsSince) binary.LittleEndian.PutUint64(data[13:21], s.timestamp) return data } type canonicalHash struct { - hash types.TruncatedHash + hash common.Hash } -func newCanonicalHash(hash types.TruncatedHash) canonicalHash { +func newCanonicalHash(hash common.Hash) canonicalHash { return canonicalHash{hash: hash} } func newCanonicalHashFromEntry(data entrydb.Entry) (canonicalHash, error) { - if data[0] != typeCanonicalHash { - return canonicalHash{}, fmt.Errorf("%w: attempting to decode canonical hash but was type %v", ErrDataCorruption, data[0]) + if data.Type() != entrydb.TypeCanonicalHash { + return canonicalHash{}, fmt.Errorf("%w: attempting to decode canonical hash but was type %s", ErrDataCorruption, data.Type()) } - var truncated types.TruncatedHash - copy(truncated[:], data[1:21]) - return newCanonicalHash(truncated), nil + return newCanonicalHash(common.Hash(data[1:33])), nil } func (c canonicalHash) encode() entrydb.Entry { var entry entrydb.Entry - entry[0] = typeCanonicalHash - copy(entry[1:21], c.hash[:]) + entry[0] = uint8(entrydb.TypeCanonicalHash) + copy(entry[1:33], c.hash[:]) return entry } type initiatingEvent struct { - blockDiff uint8 - incrementLogIdx bool - hasExecMsg bool - logHash types.TruncatedHash + hasExecMsg bool + logHash common.Hash } func newInitiatingEventFromEntry(data entrydb.Entry) (initiatingEvent, error) { - if data[0] != typeInitiatingEvent { - return initiatingEvent{}, fmt.Errorf("%w: attempting to decode initiating event but was type %v", ErrDataCorruption, data[0]) + if data.Type() != entrydb.TypeInitiatingEvent { + return initiatingEvent{}, fmt.Errorf("%w: attempting to decode initiating event but was type %s", ErrDataCorruption, data.Type()) } - blockNumDiff := data[1] - flags := data[2] + flags := data[1] return initiatingEvent{ - blockDiff: blockNumDiff, - incrementLogIdx: flags&eventFlagIncrementLogIdx != 0, - hasExecMsg: flags&eventFlagHasExecutingMessage != 0, - logHash: types.TruncatedHash(data[3:23]), + hasExecMsg: flags&eventFlagHasExecutingMessage != 0, + logHash: common.Hash(data[2:34]), }, nil } -func newInitiatingEvent(pre logContext, blockNum uint64, logIdx uint32, logHash types.TruncatedHash, hasExecMsg bool) (initiatingEvent, error) { - blockDiff := blockNum - pre.blockNum - if blockDiff > math.MaxUint8 { - // TODO(optimism#11091): Need to find a way to support this. - return initiatingEvent{}, fmt.Errorf("too many block skipped between %v and %v", pre.blockNum, blockNum) - } - - currLogIdx := pre.logIdx - if blockDiff > 0 { - currLogIdx = 0 - } - logDiff := logIdx - currLogIdx - if logDiff > 1 { - return initiatingEvent{}, fmt.Errorf("skipped logs between %v and %v", currLogIdx, logIdx) - } - +func newInitiatingEvent(logHash common.Hash, hasExecMsg bool) initiatingEvent { return initiatingEvent{ - blockDiff: uint8(blockDiff), - incrementLogIdx: logDiff > 0, - hasExecMsg: hasExecMsg, - logHash: logHash, - }, nil + hasExecMsg: hasExecMsg, + logHash: logHash, + } } // encode creates an initiating event entry -// type 2: "initiating event" = 23 bytes +// type 2: "initiating event" = 22 bytes func (i initiatingEvent) encode() entrydb.Entry { var data entrydb.Entry - data[0] = typeInitiatingEvent - data[1] = i.blockDiff + data[0] = uint8(entrydb.TypeInitiatingEvent) flags := byte(0) - if i.incrementLogIdx { - // Set flag to indicate log idx needs to be incremented (ie we're not directly after a checkpoint) - flags = flags | eventFlagIncrementLogIdx - } if i.hasExecMsg { flags = flags | eventFlagHasExecutingMessage } - data[2] = flags - copy(data[3:23], i.logHash[:]) + data[1] = flags + copy(data[2:34], i.logHash[:]) return data } -func (i initiatingEvent) postContext(pre logContext) logContext { - post := logContext{ - blockNum: pre.blockNum + uint64(i.blockDiff), - logIdx: pre.logIdx, - } - if i.blockDiff > 0 { - post.logIdx = 0 - } - if i.incrementLogIdx { - post.logIdx++ - } - return post -} - -// preContext is the reverse of postContext and calculates the logContext required as input to get the specified post -// context after applying this init event. -func (i initiatingEvent) preContext(post logContext) logContext { - pre := post - pre.blockNum = post.blockNum - uint64(i.blockDiff) - if i.incrementLogIdx { - pre.logIdx-- - } - return pre -} - type executingLink struct { chain uint32 blockNum uint64 @@ -178,8 +128,8 @@ func newExecutingLink(msg types.ExecutingMessage) (executingLink, error) { } func newExecutingLinkFromEntry(data entrydb.Entry) (executingLink, error) { - if data[0] != typeExecutingLink { - return executingLink{}, fmt.Errorf("%w: attempting to decode executing link but was type %v", ErrDataCorruption, data[0]) + if data.Type() != entrydb.TypeExecutingLink { + return executingLink{}, fmt.Errorf("%w: attempting to decode executing link but was type %s", ErrDataCorruption, data.Type()) } timestamp := binary.LittleEndian.Uint64(data[16:24]) return executingLink{ @@ -194,7 +144,7 @@ func newExecutingLinkFromEntry(data entrydb.Entry) (executingLink, error) { // type 3: "executing link" = 24 bytes func (e executingLink) encode() entrydb.Entry { var entry entrydb.Entry - entry[0] = typeExecutingLink + entry[0] = uint8(entrydb.TypeExecutingLink) binary.LittleEndian.PutUint32(entry[1:5], e.chain) binary.LittleEndian.PutUint64(entry[5:13], e.blockNum) @@ -207,45 +157,35 @@ func (e executingLink) encode() entrydb.Entry { } type executingCheck struct { - hash types.TruncatedHash + hash common.Hash } -func newExecutingCheck(hash types.TruncatedHash) executingCheck { +func newExecutingCheck(hash common.Hash) executingCheck { return executingCheck{hash: hash} } -func newExecutingCheckFromEntry(entry entrydb.Entry) (executingCheck, error) { - if entry[0] != typeExecutingCheck { - return executingCheck{}, fmt.Errorf("%w: attempting to decode executing check but was type %v", ErrDataCorruption, entry[0]) +func newExecutingCheckFromEntry(data entrydb.Entry) (executingCheck, error) { + if data.Type() != entrydb.TypeExecutingCheck { + return executingCheck{}, fmt.Errorf("%w: attempting to decode executing check but was type %s", ErrDataCorruption, data.Type()) } - var hash types.TruncatedHash - copy(hash[:], entry[1:21]) - return newExecutingCheck(hash), nil + return newExecutingCheck(common.Hash(data[1:33])), nil } // encode creates an executing check entry -// type 4: "executing check" = 21 bytes +// type 4: "executing check" = 33 bytes func (e executingCheck) encode() entrydb.Entry { var entry entrydb.Entry - entry[0] = typeExecutingCheck - copy(entry[1:21], e.hash[:]) + entry[0] = uint8(entrydb.TypeExecutingCheck) + copy(entry[1:33], e.hash[:]) return entry } -func newExecutingMessageFromEntries(linkEntry entrydb.Entry, checkEntry entrydb.Entry) (types.ExecutingMessage, error) { - link, err := newExecutingLinkFromEntry(linkEntry) - if err != nil { - return types.ExecutingMessage{}, fmt.Errorf("invalid executing link: %w", err) - } - check, err := newExecutingCheckFromEntry(checkEntry) - if err != nil { - return types.ExecutingMessage{}, fmt.Errorf("invalid executing check: %w", err) - } - return types.ExecutingMessage{ - Chain: link.chain, - BlockNum: link.blockNum, - LogIdx: link.logIdx, - Timestamp: link.timestamp, - Hash: check.hash, - }, nil +type paddingEntry struct{} + +// encoding of the padding entry +// type 5: "padding" = 34 bytes +func (e paddingEntry) encode() entrydb.Entry { + var entry entrydb.Entry + entry[0] = uint8(entrydb.TypePadding) + return entry } diff --git a/op-supervisor/supervisor/backend/db/logs/iterator.go b/op-supervisor/supervisor/backend/db/logs/iterator.go index 7312966b24554..4b3bd1b65908d 100644 --- a/op-supervisor/supervisor/backend/db/logs/iterator.go +++ b/op-supervisor/supervisor/backend/db/logs/iterator.go @@ -5,110 +5,140 @@ import ( "fmt" "io" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/db/entrydb" - "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/types" + "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" ) +type IteratorState interface { + NextIndex() entrydb.EntryIdx + SealedBlock() (hash common.Hash, num uint64, ok bool) + InitMessage() (hash common.Hash, logIndex uint32, ok bool) + ExecMessage() *types.ExecutingMessage +} + type Iterator interface { - NextLog() (blockNum uint64, logIdx uint32, evtHash types.TruncatedHash, outErr error) - Index() entrydb.EntryIdx - ExecMessage() (types.ExecutingMessage, error) + End() error + NextInitMsg() error + NextExecMsg() error + NextBlock() error + IteratorState } type iterator struct { - db *DB - nextEntryIdx entrydb.EntryIdx - - current logContext - hasExecMsg bool - + db *DB + current logContext entriesRead int64 } -// NextLog returns the next log in the iterator. -// It scans forward until it finds an initiating event, returning the block number, log index, and event hash. -func (i *iterator) NextLog() (blockNum uint64, logIdx uint32, evtHash types.TruncatedHash, outErr error) { - for i.nextEntryIdx <= i.db.lastEntryIdx() { - entryIdx := i.nextEntryIdx - entry, err := i.db.store.Read(entryIdx) +// End traverses the iterator to the end of the DB. +// It does not return io.EOF or ErrFuture. +func (i *iterator) End() error { + for { + _, err := i.next() + if errors.Is(err, ErrFuture) { + return nil + } else if err != nil { + return err + } + } +} + +// NextInitMsg returns the next initiating message in the iterator. +// It scans forward until it finds and fully reads an initiating event, skipping any blocks. +func (i *iterator) NextInitMsg() error { + seenLog := false + for { + typ, err := i.next() if err != nil { - outErr = fmt.Errorf("failed to read entry %v: %w", i, err) - return + return err } - i.nextEntryIdx++ - i.entriesRead++ - i.hasExecMsg = false - switch entry[0] { - case typeSearchCheckpoint: - current, err := newSearchCheckpointFromEntry(entry) - if err != nil { - outErr = fmt.Errorf("failed to parse search checkpoint at idx %v: %w", entryIdx, err) - return - } - i.current.blockNum = current.blockNum - i.current.logIdx = current.logIdx - case typeInitiatingEvent: - evt, err := newInitiatingEventFromEntry(entry) - if err != nil { - outErr = fmt.Errorf("failed to parse initiating event at idx %v: %w", entryIdx, err) - return - } - i.current = evt.postContext(i.current) - blockNum = i.current.blockNum - logIdx = i.current.logIdx - evtHash = evt.logHash - i.hasExecMsg = evt.hasExecMsg - return - case typeCanonicalHash: // Skip - case typeExecutingCheck: // Skip - case typeExecutingLink: // Skip - default: - outErr = fmt.Errorf("unknown entry type at idx %v %v", entryIdx, entry[0]) - return + if typ == entrydb.TypeInitiatingEvent { + seenLog = true + } + if !i.current.hasCompleteBlock() { + continue // must know the block we're building on top of + } + if i.current.hasIncompleteLog() { + continue // didn't finish processing the log yet + } + if seenLog { + return nil } } - outErr = io.EOF - return } -func (i *iterator) Index() entrydb.EntryIdx { - return i.nextEntryIdx - 1 +// NextExecMsg returns the next executing message in the iterator. +// It scans forward until it finds and fully reads an initiating event, skipping any blocks. +// This does not stay at the executing message of the current initiating message, if there is any. +func (i *iterator) NextExecMsg() error { + for { + err := i.NextInitMsg() + if err != nil { + return err + } + if i.current.execMsg != nil { + return nil // found a new executing message! + } + } } -func (i *iterator) ExecMessage() (types.ExecutingMessage, error) { - if !i.hasExecMsg { - return types.ExecutingMessage{}, nil - } - // Look ahead to find the exec message info - logEntryIdx := i.nextEntryIdx - 1 - execMsg, err := i.readExecMessage(logEntryIdx) - if err != nil { - return types.ExecutingMessage{}, fmt.Errorf("failed to read exec message for initiating event at %v: %w", logEntryIdx, err) +// NextBlock returns the next block in the iterator. +// It scans forward until it finds and fully reads a block, skipping any events. +func (i *iterator) NextBlock() error { + seenBlock := false + for { + typ, err := i.next() + if err != nil { + return err + } + if typ == entrydb.TypeSearchCheckpoint { + seenBlock = true + } + if !i.current.hasCompleteBlock() { + continue // need the full block content + } + if seenBlock { + return nil + } } - return execMsg, nil } -func (i *iterator) readExecMessage(initEntryIdx entrydb.EntryIdx) (types.ExecutingMessage, error) { - linkIdx := initEntryIdx + 1 - if linkIdx%searchCheckpointFrequency == 0 { - linkIdx += 2 // skip the search checkpoint and canonical hash entries +// Read and apply the next entry. +func (i *iterator) next() (entrydb.EntryType, error) { + index := i.current.nextEntryIndex + entry, err := i.db.store.Read(index) + if err != nil { + if errors.Is(err, io.EOF) { + return 0, ErrFuture + } + return 0, fmt.Errorf("failed to read entry %d: %w", index, err) } - linkEntry, err := i.db.store.Read(linkIdx) - if errors.Is(err, io.EOF) { - return types.ExecutingMessage{}, fmt.Errorf("%w: missing expected executing link event at idx %v", ErrDataCorruption, linkIdx) - } else if err != nil { - return types.ExecutingMessage{}, fmt.Errorf("failed to read executing link event at idx %v: %w", linkIdx, err) + if err := i.current.ApplyEntry(entry); err != nil { + return entry.Type(), fmt.Errorf("failed to apply entry %d to iterator state: %w", index, err) } - checkIdx := linkIdx + 1 - if checkIdx%searchCheckpointFrequency == 0 { - checkIdx += 2 // skip the search checkpoint and canonical hash entries - } - checkEntry, err := i.db.store.Read(checkIdx) - if errors.Is(err, io.EOF) { - return types.ExecutingMessage{}, fmt.Errorf("%w: missing expected executing check event at idx %v", ErrDataCorruption, checkIdx) - } else if err != nil { - return types.ExecutingMessage{}, fmt.Errorf("failed to read executing check event at idx %v: %w", checkIdx, err) - } - return newExecutingMessageFromEntries(linkEntry, checkEntry) + i.entriesRead++ + return entry.Type(), nil +} + +func (i *iterator) NextIndex() entrydb.EntryIdx { + return i.current.NextIndex() +} + +// SealedBlock returns the sealed block that we are appending logs after, if any is available. +// I.e. the block is the parent block of the block containing the logs that are currently appending to it. +func (i *iterator) SealedBlock() (hash common.Hash, num uint64, ok bool) { + return i.current.SealedBlock() +} + +// InitMessage returns the current initiating message, if any is available. +func (i *iterator) InitMessage() (hash common.Hash, logIndex uint32, ok bool) { + return i.current.InitMessage() +} + +// ExecMessage returns the current executing message, if any is available. +func (i *iterator) ExecMessage() *types.ExecutingMessage { + return i.current.ExecMessage() } diff --git a/op-supervisor/supervisor/backend/db/logs/state.go b/op-supervisor/supervisor/backend/db/logs/state.go new file mode 100644 index 0000000000000..bb00762acc2e4 --- /dev/null +++ b/op-supervisor/supervisor/backend/db/logs/state.go @@ -0,0 +1,407 @@ +package logs + +import ( + "errors" + "fmt" + "io" + + "github.com/ethereum/go-ethereum/common" + + "github.com/ethereum-optimism/optimism/op-service/eth" + "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/db/entrydb" + "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" +) + +// logContext is a buffer on top of the DB, +// where blocks and logs can be applied to. +// +// Rules: +// +// if entry_index % 256 == 0: must be type 0. For easy binary search. +// else if end_of_block: also type 0. +// else: +// after type 0: type 1 +// after type 1: type 2 iff any event and space, otherwise type 0 +// after type 2: type 3 iff executing, otherwise type 2 or 0 +// after type 3: type 4 +// after type 4: type 2 iff any event and space, otherwise type 0 +// after type 5: any +// +// Type 0 can repeat: seal the block, then start a search checkpoint, then a single canonical hash. +// Type 0 may also be used as padding: type 2 only starts when it will not be interrupted by a search checkpoint. +// +// Types ( = 1 byte): +// type 0: "checkpoint" = 21 bytes +// type 1: "canonical hash" = 33 bytes +// type 2: "initiating event" = 34 bytes +// type 3: "executing link" = 24 bytes +// type 4: "executing check" = 33 bytes +// type 5: "padding" = 34 bytes +// other types: future compat. E.g. for linking to L1, registering block-headers as a kind of initiating-event, tracking safe-head progression, etc. +// +// Right-pad each entry that is not 34 bytes. +// +// We insert a checkpoint for every search interval and block sealing event, +// and these may overlap as the same thing. +// Such seal has logsSince == 0, i.e. wrapping up the last block and starting a fresh list of logs. +// +// event-flags: each bit represents a boolean value, currently only two are defined +// * event-flags & 0x01 - true if the initiating event has an executing link that should follow. Allows detecting when the executing link failed to write. +// event-hash: H(origin, timestamp, payloadhash); enough to check identifier matches & payload matches. +type logContext struct { + // next entry index, including the contents of `out` + nextEntryIndex entrydb.EntryIdx + + // blockHash of the last sealed block. + // A block is not considered sealed until we know its block hash. + // While we process logs we keep the parent-block of said logs around as sealed block. + blockHash common.Hash + // blockNum of the last sealed block + blockNum uint64 + // timestamp of the last sealed block + timestamp uint64 + + // number of logs since the last sealed block + logsSince uint32 + + // payload-hash of the log-event that was last processed. (may not be fully processed, see doneLog) + logHash common.Hash + + // executing message that might exist for the current log event. + // Might be incomplete; if !logDone while we already processed the initiating event, + // then we know an executing message is still coming. + execMsg *types.ExecutingMessage + + need entrydb.EntryTypeFlag + + // buffer of entries not yet in the DB. + // This is generated as objects are applied. + // E.g. you can build multiple hypothetical blocks with log events on top of the state, + // before flushing the entries to a DB. + // However, no entries can be read from the DB while objects are being applied. + out []entrydb.Entry +} + +type EntryObj interface { + encode() entrydb.Entry +} + +func (l *logContext) NextIndex() entrydb.EntryIdx { + return l.nextEntryIndex +} + +// SealedBlock returns the block that we are building on top of, and if it is sealed. +func (l *logContext) SealedBlock() (hash common.Hash, num uint64, ok bool) { + if !l.hasCompleteBlock() { + return common.Hash{}, 0, false + } + return l.blockHash, l.blockNum, true +} + +func (l *logContext) hasCompleteBlock() bool { + return !l.need.Any(entrydb.FlagCanonicalHash) +} + +func (l *logContext) hasIncompleteLog() bool { + return l.need.Any(entrydb.FlagInitiatingEvent | entrydb.FlagExecutingLink | entrydb.FlagExecutingCheck) +} + +func (l *logContext) hasReadableLog() bool { + return l.logsSince > 0 && !l.hasIncompleteLog() +} + +// InitMessage returns the current initiating message, if any is available. +func (l *logContext) InitMessage() (hash common.Hash, logIndex uint32, ok bool) { + if !l.hasReadableLog() { + return common.Hash{}, 0, false + } + return l.logHash, l.logsSince - 1, true +} + +// ExecMessage returns the current executing message, if any is available. +func (l *logContext) ExecMessage() *types.ExecutingMessage { + if l.hasCompleteBlock() && l.hasReadableLog() && l.execMsg != nil { + return l.execMsg + } + return nil +} + +// ApplyEntry applies an entry on top of the current state. +func (l *logContext) ApplyEntry(entry entrydb.Entry) error { + // Wrap processEntry to add common useful error message info + err := l.processEntry(entry) + if err != nil { + return fmt.Errorf("failed to process type %s entry at idx %d (%x): %w", entry.Type().String(), l.nextEntryIndex, entry[:], err) + } + return nil +} + +// processEntry decodes and applies an entry to the state. +// Entries may not be applied if we are in the process of generating entries from objects. +// These outputs need to be flushed before inputs can be accepted. +func (l *logContext) processEntry(entry entrydb.Entry) error { + if len(l.out) != 0 { + panic("can only apply without appending if the state is still empty") + } + switch entry.Type() { + case entrydb.TypeSearchCheckpoint: + current, err := newSearchCheckpointFromEntry(entry) + if err != nil { + return err + } + l.blockNum = current.blockNum + l.blockHash = common.Hash{} + l.logsSince = current.logsSince // TODO this is bumping the logsSince? + l.timestamp = current.timestamp + l.need.Add(entrydb.FlagCanonicalHash) + // Log data after the block we are sealing remains to be seen + if l.logsSince == 0 { + l.logHash = common.Hash{} + l.execMsg = nil + } + case entrydb.TypeCanonicalHash: + if !l.need.Any(entrydb.FlagCanonicalHash) { + return errors.New("not ready for canonical hash entry, already sealed the last block") + } + canonHash, err := newCanonicalHashFromEntry(entry) + if err != nil { + return err + } + l.blockHash = canonHash.hash + l.need.Remove(entrydb.FlagCanonicalHash) + case entrydb.TypeInitiatingEvent: + if !l.hasCompleteBlock() { + return errors.New("did not complete block seal, cannot add log") + } + if l.hasIncompleteLog() { + return errors.New("cannot process log before last log completes") + } + evt, err := newInitiatingEventFromEntry(entry) + if err != nil { + return err + } + l.execMsg = nil // clear the old state + l.logHash = evt.logHash + if evt.hasExecMsg { + l.need.Add(entrydb.FlagExecutingLink | entrydb.FlagExecutingCheck) + } else { + l.logsSince += 1 + } + l.need.Remove(entrydb.FlagInitiatingEvent) + case entrydb.TypeExecutingLink: + if !l.need.Any(entrydb.FlagExecutingLink) { + return errors.New("unexpected executing-link") + } + link, err := newExecutingLinkFromEntry(entry) + if err != nil { + return err + } + l.execMsg = &types.ExecutingMessage{ + Chain: link.chain, + BlockNum: link.blockNum, + LogIdx: link.logIdx, + Timestamp: link.timestamp, + Hash: common.Hash{}, // not known yet + } + l.need.Remove(entrydb.FlagExecutingLink) + l.need.Add(entrydb.FlagExecutingCheck) + case entrydb.TypeExecutingCheck: + if l.need.Any(entrydb.FlagExecutingLink) { + return errors.New("need executing link to be applied before the check part") + } + if !l.need.Any(entrydb.FlagExecutingCheck) { + return errors.New("unexpected executing check") + } + link, err := newExecutingCheckFromEntry(entry) + if err != nil { + return err + } + l.execMsg.Hash = link.hash + l.need.Remove(entrydb.FlagExecutingCheck) + l.logsSince += 1 + case entrydb.TypePadding: + if l.need.Any(entrydb.FlagPadding) { + l.need.Remove(entrydb.FlagPadding) + } else { + l.need.Remove(entrydb.FlagPadding2) + } + default: + return fmt.Errorf("unknown entry type: %s", entry.Type()) + } + l.nextEntryIndex += 1 + return nil +} + +// appendEntry add the entry to the output-buffer, +// and registers it as last processed entry type, and increments the next entry-index. +func (l *logContext) appendEntry(obj EntryObj) { + entry := obj.encode() + l.out = append(l.out, entry) + l.nextEntryIndex += 1 +} + +// infer advances the logContext in cases where multiple entries are to be appended implicitly +// depending on the last type of entry, a new entry is appended, +// or when the searchCheckpoint should be inserted. +// This can be done repeatedly until there is no more implied data to extend. +func (l *logContext) infer() error { + // We force-insert a checkpoint whenever we hit the known fixed interval. + if l.nextEntryIndex%searchCheckpointFrequency == 0 { + l.need.Add(entrydb.FlagSearchCheckpoint) + } + if l.need.Any(entrydb.FlagSearchCheckpoint) { + l.appendEntry(newSearchCheckpoint(l.blockNum, l.logsSince, l.timestamp)) + l.need.Add(entrydb.FlagCanonicalHash) // always follow with a canonical hash + l.need.Remove(entrydb.FlagSearchCheckpoint) + return nil + } + if l.need.Any(entrydb.FlagCanonicalHash) { + l.appendEntry(newCanonicalHash(l.blockHash)) + l.need.Remove(entrydb.FlagCanonicalHash) + return nil + } + if l.need.Any(entrydb.FlagPadding) { + l.appendEntry(paddingEntry{}) + l.need.Remove(entrydb.FlagPadding) + return nil + } + if l.need.Any(entrydb.FlagPadding2) { + l.appendEntry(paddingEntry{}) + l.need.Remove(entrydb.FlagPadding2) + return nil + } + if l.need.Any(entrydb.FlagInitiatingEvent) { + // If we are running out of space for log-event data, + // write some checkpoints as padding, to pass the checkpoint. + if l.execMsg != nil { // takes 3 total. Need to avoid the checkpoint. + switch l.nextEntryIndex % searchCheckpointFrequency { + case searchCheckpointFrequency - 1: + l.need.Add(entrydb.FlagPadding) + return nil + case searchCheckpointFrequency - 2: + l.need.Add(entrydb.FlagPadding | entrydb.FlagPadding2) + return nil + } + } + evt := newInitiatingEvent(l.logHash, l.execMsg != nil) + l.appendEntry(evt) + l.need.Remove(entrydb.FlagInitiatingEvent) + if l.execMsg == nil { + l.logsSince += 1 + } + return nil + } + if l.need.Any(entrydb.FlagExecutingLink) { + link, err := newExecutingLink(*l.execMsg) + if err != nil { + return fmt.Errorf("failed to create executing link: %w", err) + } + l.appendEntry(link) + l.need.Remove(entrydb.FlagExecutingLink) + return nil + } + if l.need.Any(entrydb.FlagExecutingCheck) { + l.appendEntry(newExecutingCheck(l.execMsg.Hash)) + l.need.Remove(entrydb.FlagExecutingCheck) + l.logsSince += 1 + return nil + } + return io.EOF +} + +// inferFull advances the queued entries held by the log context repeatedly +// until no more implied entries can be added +func (l *logContext) inferFull() error { + for i := 0; i < 10; i++ { + err := l.infer() + if err == nil { + continue + } + if err == io.EOF { // wrapped io.EOF does not count. + return nil + } else { + return err + } + } + panic("hit sanity limit") +} + +// forceBlock force-overwrites the state, to match the given sealed block as starting point (excl) +func (l *logContext) forceBlock(upd eth.BlockID, timestamp uint64) error { + if l.nextEntryIndex != 0 { + return errors.New("can only bootstrap on top of an empty state") + } + l.blockHash = upd.Hash + l.blockNum = upd.Number + l.timestamp = timestamp + l.logsSince = 0 + l.execMsg = nil + l.logHash = common.Hash{} + l.need = 0 + l.out = nil + return l.inferFull() // apply to the state as much as possible +} + +// SealBlock applies a block header on top of the current state. +// This seals the state; no further logs of this block may be added with ApplyLog. +func (l *logContext) SealBlock(parent common.Hash, upd eth.BlockID, timestamp uint64) error { + // If we don't have any entries yet, allow any block to start things off + if l.nextEntryIndex != 0 { + if err := l.inferFull(); err != nil { // ensure we can start applying + return err + } + if l.blockHash != parent { + return fmt.Errorf("%w: cannot apply block %s (parent %s) on top of %s", ErrConflict, upd, parent, l.blockHash) + } + if l.blockHash != (common.Hash{}) && l.blockNum+1 != upd.Number { + return fmt.Errorf("%w: cannot apply block %d on top of %d", ErrConflict, upd.Number, l.blockNum) + } + if l.timestamp > timestamp { + return fmt.Errorf("%w: block timestamp %d must be equal or larger than current timestamp %d", ErrConflict, timestamp, l.timestamp) + } + } + l.blockHash = upd.Hash + l.blockNum = upd.Number + l.timestamp = timestamp + l.logsSince = 0 + l.execMsg = nil + l.logHash = common.Hash{} + l.need.Add(entrydb.FlagSearchCheckpoint) + return l.inferFull() // apply to the state as much as possible +} + +// ApplyLog applies a log on top of the current state. +// The parent-block that the log comes after must be applied with ApplyBlock first. +func (l *logContext) ApplyLog(parentBlock eth.BlockID, logIdx uint32, logHash common.Hash, execMsg *types.ExecutingMessage) error { + if parentBlock == (eth.BlockID{}) { + return fmt.Errorf("genesis does not have logs: %w", ErrLogOutOfOrder) + } + if err := l.inferFull(); err != nil { // ensure we can start applying + return err + } + if !l.hasCompleteBlock() { + if l.blockNum == 0 { + return fmt.Errorf("%w: should not have logs in block 0", ErrLogOutOfOrder) + } else { + return errors.New("cannot append log before last known block is sealed") + } + } + // check parent block + if l.blockHash != parentBlock.Hash { + return fmt.Errorf("%w: log builds on top of block %s, but have block %s", ErrLogOutOfOrder, parentBlock, l.blockHash) + } + if l.blockNum != parentBlock.Number { + return fmt.Errorf("%w: log builds on top of block %d, but have block %d", ErrLogOutOfOrder, parentBlock.Number, l.blockNum) + } + // check if log fits on top. The length so far == the index of the next log. + if logIdx != l.logsSince { + return fmt.Errorf("%w: expected event index %d, cannot append %d", ErrLogOutOfOrder, l.logsSince, logIdx) + } + l.logHash = logHash + l.execMsg = execMsg + l.need.Add(entrydb.FlagInitiatingEvent) + if execMsg != nil { + l.need.Add(entrydb.FlagExecutingLink | entrydb.FlagExecutingCheck) + } + return l.inferFull() // apply to the state as much as possible +} diff --git a/op-supervisor/supervisor/backend/db/safety_checkers.go b/op-supervisor/supervisor/backend/db/safety_checkers.go index 3c92c1e808dfe..916f26f6dead3 100644 --- a/op-supervisor/supervisor/backend/db/safety_checkers.go +++ b/op-supervisor/supervisor/backend/db/safety_checkers.go @@ -1,9 +1,13 @@ package db import ( + "errors" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/db/entrydb" "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/db/heads" - backendTypes "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/types" + "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/db/logs" "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" ) @@ -18,7 +22,7 @@ const ( type SafetyChecker interface { LocalHeadForChain(chainID types.ChainID) entrydb.EntryIdx CrossHeadForChain(chainID types.ChainID) entrydb.EntryIdx - Check(chain types.ChainID, blockNum uint64, logIdx uint32, logHash backendTypes.TruncatedHash) bool + Check(chain types.ChainID, blockNum uint64, logIdx uint32, logHash common.Hash) bool Update(chain types.ChainID, index entrydb.EntryIdx) heads.OperationFn Name() string SafetyLevel() types.SafetyLevel @@ -126,28 +130,34 @@ func check( chain types.ChainID, blockNum uint64, logIdx uint32, - logHash backendTypes.TruncatedHash) bool { + logHash common.Hash) bool { // for the Check to be valid, the log must: // exist at the blockNum and logIdx // have a hash that matches the provided hash (implicit in the Contains call), and // be less than or equal to the local head for the chain - exists, index, err := chainsDB.logDBs[chain].Contains(blockNum, logIdx, logHash) + index, err := chainsDB.logDBs[chain].Contains(blockNum, logIdx, logHash) if err != nil { + if errors.Is(err, logs.ErrFuture) { + return false // TODO(#12031) + } + if errors.Is(err, logs.ErrConflict) { + return false // TODO(#12031) + } return false } - return exists && index <= localHead + return index <= localHead } // Check checks if the log entry is safe, provided a local head for the chain // it passes on the local head this checker is concerned with, along with its view of the database -func (c *unsafeChecker) Check(chain types.ChainID, blockNum uint64, logIdx uint32, logHash backendTypes.TruncatedHash) bool { +func (c *unsafeChecker) Check(chain types.ChainID, blockNum uint64, logIdx uint32, logHash common.Hash) bool { return check(c.chainsDB, c.LocalHeadForChain(chain), chain, blockNum, logIdx, logHash) } -func (c *safeChecker) Check(chain types.ChainID, blockNum uint64, logIdx uint32, logHash backendTypes.TruncatedHash) bool { +func (c *safeChecker) Check(chain types.ChainID, blockNum uint64, logIdx uint32, logHash common.Hash) bool { return check(c.chainsDB, c.LocalHeadForChain(chain), chain, blockNum, logIdx, logHash) } -func (c *finalizedChecker) Check(chain types.ChainID, blockNum uint64, logIdx uint32, logHash backendTypes.TruncatedHash) bool { +func (c *finalizedChecker) Check(chain types.ChainID, blockNum uint64, logIdx uint32, logHash common.Hash) bool { return check(c.chainsDB, c.LocalHeadForChain(chain), chain, blockNum, logIdx, logHash) } diff --git a/op-supervisor/supervisor/backend/db/safety_checkers_test.go b/op-supervisor/supervisor/backend/db/safety_checkers_test.go index d2303d7ec3e57..c8fb4e34a757a 100644 --- a/op-supervisor/supervisor/backend/db/safety_checkers_test.go +++ b/op-supervisor/supervisor/backend/db/safety_checkers_test.go @@ -1,14 +1,19 @@ package db import ( - "fmt" + "errors" "testing" + "github.com/stretchr/testify/require" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/log" + + "github.com/ethereum-optimism/optimism/op-service/testlog" "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/db/entrydb" "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/db/heads" - backendTypes "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/types" + "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/db/logs" "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" - "github.com/stretchr/testify/require" ) // TestHeadsForChain tests the heads for a chain, @@ -25,7 +30,7 @@ func TestHeadsForChain(t *testing.T) { CrossFinalized: entrydb.EntryIdx(6), } h.Put(types.ChainIDFromUInt64(1), chainHeads) - chainsDB := NewChainsDB(nil, &stubHeadStorage{h}) + chainsDB := NewChainsDB(nil, &stubHeadStorage{h}, testlog.Logger(t, log.LevelDebug)) tcases := []struct { name string chainID types.ChainID @@ -92,7 +97,7 @@ func TestCheck(t *testing.T) { types.ChainIDFromUInt64(1): logDB, } - chainsDB := NewChainsDB(logsStore, &stubHeadStorage{h}) + chainsDB := NewChainsDB(logsStore, &stubHeadStorage{h}, testlog.Logger(t, log.LevelDebug)) tcases := []struct { name string @@ -100,7 +105,7 @@ func TestCheck(t *testing.T) { chainID types.ChainID blockNum uint64 logIdx uint32 - loghash backendTypes.TruncatedHash + loghash common.Hash containsResponse containsResponse expected bool }{ @@ -112,8 +117,8 @@ func TestCheck(t *testing.T) { types.ChainIDFromUInt64(1), 1, 1, - backendTypes.TruncatedHash{1, 2, 3}, - containsResponse{true, entrydb.EntryIdx(6), nil}, + common.Hash{1, 2, 3}, + containsResponse{entrydb.EntryIdx(6), nil}, true, }, { @@ -123,8 +128,8 @@ func TestCheck(t *testing.T) { types.ChainIDFromUInt64(1), 1, 1, - backendTypes.TruncatedHash{1, 2, 3}, - containsResponse{true, entrydb.EntryIdx(3), nil}, + common.Hash{1, 2, 3}, + containsResponse{entrydb.EntryIdx(3), nil}, true, }, { @@ -134,8 +139,8 @@ func TestCheck(t *testing.T) { types.ChainIDFromUInt64(1), 1, 1, - backendTypes.TruncatedHash{1, 2, 3}, - containsResponse{true, entrydb.EntryIdx(1), nil}, + common.Hash{1, 2, 3}, + containsResponse{entrydb.EntryIdx(1), nil}, true, }, { @@ -145,8 +150,8 @@ func TestCheck(t *testing.T) { types.ChainIDFromUInt64(1), 1, 1, - backendTypes.TruncatedHash{1, 2, 3}, - containsResponse{false, entrydb.EntryIdx(1), nil}, + common.Hash{1, 2, 3}, + containsResponse{entrydb.EntryIdx(1), logs.ErrConflict}, false, }, { @@ -156,8 +161,8 @@ func TestCheck(t *testing.T) { types.ChainIDFromUInt64(1), 1, 1, - backendTypes.TruncatedHash{1, 2, 3}, - containsResponse{true, entrydb.EntryIdx(100), nil}, + common.Hash{1, 2, 3}, + containsResponse{entrydb.EntryIdx(100), nil}, false, }, { @@ -167,8 +172,8 @@ func TestCheck(t *testing.T) { types.ChainIDFromUInt64(1), 1, 1, - backendTypes.TruncatedHash{1, 2, 3}, - containsResponse{true, entrydb.EntryIdx(5), nil}, + common.Hash{1, 2, 3}, + containsResponse{entrydb.EntryIdx(5), nil}, false, }, { @@ -178,8 +183,8 @@ func TestCheck(t *testing.T) { types.ChainIDFromUInt64(1), 1, 1, - backendTypes.TruncatedHash{1, 2, 3}, - containsResponse{true, entrydb.EntryIdx(3), nil}, + common.Hash{1, 2, 3}, + containsResponse{entrydb.EntryIdx(3), nil}, false, }, { @@ -189,8 +194,8 @@ func TestCheck(t *testing.T) { types.ChainIDFromUInt64(1), 1, 1, - backendTypes.TruncatedHash{1, 2, 3}, - containsResponse{false, entrydb.EntryIdx(0), fmt.Errorf("error")}, + common.Hash{1, 2, 3}, + containsResponse{entrydb.EntryIdx(0), errors.New("error")}, false, }, } diff --git a/op-supervisor/supervisor/backend/mock.go b/op-supervisor/supervisor/backend/mock.go index 71c77b2355257..e62c7b950b7c8 100644 --- a/op-supervisor/supervisor/backend/mock.go +++ b/op-supervisor/supervisor/backend/mock.go @@ -39,6 +39,10 @@ func (m *MockBackend) Stop(ctx context.Context) error { return nil } +func (m *MockBackend) AddL2RPC(ctx context.Context, rpc string) error { + return nil +} + func (m *MockBackend) CheckMessage(identifier types.Identifier, payloadHash common.Hash) (types.SafetyLevel, error) { return types.CrossUnsafe, nil } diff --git a/op-supervisor/supervisor/backend/source/chain.go b/op-supervisor/supervisor/backend/source/chain.go index f7fd31b202dc9..c8fef89f8b832 100644 --- a/op-supervisor/supervisor/backend/source/chain.go +++ b/op-supervisor/supervisor/backend/source/chain.go @@ -26,7 +26,7 @@ type Metrics interface { type Storage interface { LogStorage DatabaseRewinder - LatestBlockNum(chainID types.ChainID) uint64 + LatestBlockNum(chainID types.ChainID) (num uint64, ok bool) } // ChainMonitor monitors a source L2 chain, retrieving the data required to populate the database and perform @@ -43,8 +43,13 @@ func NewChainMonitor(ctx context.Context, logger log.Logger, m Metrics, chainID return nil, err } + latest, ok := store.LatestBlockNum(chainID) + if !ok { + logger.Warn("") + } + startingHead := eth.L1BlockRef{ - Number: store.LatestBlockNum(chainID), + Number: latest, } processLogs := newLogProcessor(chainID, store) diff --git a/op-supervisor/supervisor/backend/source/chain_processor.go b/op-supervisor/supervisor/backend/source/chain_processor.go index b2f60af904bf4..0a42da1556a06 100644 --- a/op-supervisor/supervisor/backend/source/chain_processor.go +++ b/op-supervisor/supervisor/backend/source/chain_processor.go @@ -49,10 +49,13 @@ func NewChainProcessor(log log.Logger, client BlockByNumberSource, chain types.C } func (s *ChainProcessor) OnNewHead(ctx context.Context, head eth.L1BlockRef) { + s.log.Debug("Processing chain", "chain", s.chain, "head", head, "last", s.lastBlock) if head.Number <= s.lastBlock.Number { + s.log.Info("head is not newer than last processed block", "head", head, "lastBlock", s.lastBlock) return } for s.lastBlock.Number+1 < head.Number { + s.log.Debug("Filling in skipped block", "chain", s.chain, "lastBlock", s.lastBlock, "head", head) blockNum := s.lastBlock.Number + 1 nextBlock, err := s.client.L1BlockRefByNumber(ctx, blockNum) if err != nil { diff --git a/op-supervisor/supervisor/backend/source/contracts/l2inbox.go b/op-supervisor/supervisor/backend/source/contracts/l2inbox.go index b490b612e6c68..741c6ae3d8659 100644 --- a/op-supervisor/supervisor/backend/source/contracts/l2inbox.go +++ b/op-supervisor/supervisor/backend/source/contracts/l2inbox.go @@ -10,7 +10,6 @@ import ( "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum-optimism/optimism/op-service/solabi" "github.com/ethereum-optimism/optimism/op-service/sources/batching" - backendTypes "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/types" "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" "github.com/ethereum-optimism/optimism/packages/contracts-bedrock/snapshots" "github.com/ethereum/go-ethereum/common" @@ -48,20 +47,20 @@ func NewCrossL2Inbox() *CrossL2Inbox { } } -func (i *CrossL2Inbox) DecodeExecutingMessageLog(l *ethTypes.Log) (backendTypes.ExecutingMessage, error) { +func (i *CrossL2Inbox) DecodeExecutingMessageLog(l *ethTypes.Log) (types.ExecutingMessage, error) { if l.Address != i.contract.Addr() { - return backendTypes.ExecutingMessage{}, fmt.Errorf("%w: log not from CrossL2Inbox", ErrEventNotFound) + return types.ExecutingMessage{}, fmt.Errorf("%w: log not from CrossL2Inbox", ErrEventNotFound) } // use DecodeEvent to check the name of the event // but the actual decoding is done manually to extract the contract identifier name, _, err := i.contract.DecodeEvent(l) if errors.Is(err, batching.ErrUnknownEvent) { - return backendTypes.ExecutingMessage{}, fmt.Errorf("%w: %v", ErrEventNotFound, err.Error()) + return types.ExecutingMessage{}, fmt.Errorf("%w: %v", ErrEventNotFound, err.Error()) } else if err != nil { - return backendTypes.ExecutingMessage{}, fmt.Errorf("failed to decode event: %w", err) + return types.ExecutingMessage{}, fmt.Errorf("failed to decode event: %w", err) } if name != eventExecutingMessage { - return backendTypes.ExecutingMessage{}, fmt.Errorf("%w: event %v not an ExecutingMessage event", ErrEventNotFound, name) + return types.ExecutingMessage{}, fmt.Errorf("%w: event %v not an ExecutingMessage event", ErrEventNotFound, name) } // the second topic is the hash of the payload (the first is the event ID) msgHash := l.Topics[1] @@ -69,14 +68,14 @@ func (i *CrossL2Inbox) DecodeExecutingMessageLog(l *ethTypes.Log) (backendTypes. identifierBytes := bytes.NewReader(l.Data[32:]) identifier, err := identifierFromBytes(identifierBytes) if err != nil { - return backendTypes.ExecutingMessage{}, fmt.Errorf("failed to read contract identifier: %w", err) + return types.ExecutingMessage{}, fmt.Errorf("failed to read contract identifier: %w", err) } chainID, err := types.ChainIDFromBig(identifier.ChainId).ToUInt32() if err != nil { - return backendTypes.ExecutingMessage{}, fmt.Errorf("failed to convert chain ID %v to uint32: %w", identifier.ChainId, err) + return types.ExecutingMessage{}, fmt.Errorf("failed to convert chain ID %v to uint32: %w", identifier.ChainId, err) } hash := payloadHashToLogHash(msgHash, identifier.Origin) - return backendTypes.ExecutingMessage{ + return types.ExecutingMessage{ Chain: chainID, Hash: hash, BlockNum: identifier.BlockNumber.Uint64(), @@ -126,9 +125,9 @@ func identifierFromBytes(identifierBytes io.Reader) (contractIdentifier, error) // to the log the referenced initiating message. // TODO: this function is duplicated between contracts and backend/source/log_processor.go // to avoid a circular dependency. It should be reorganized to avoid this duplication. -func payloadHashToLogHash(payloadHash common.Hash, addr common.Address) backendTypes.TruncatedHash { +func payloadHashToLogHash(payloadHash common.Hash, addr common.Address) common.Hash { msg := make([]byte, 0, 2*common.HashLength) msg = append(msg, addr.Bytes()...) msg = append(msg, payloadHash.Bytes()...) - return backendTypes.TruncateHash(crypto.Keccak256Hash(msg)) + return crypto.Keccak256Hash(msg) } diff --git a/op-supervisor/supervisor/backend/source/contracts/l2inbox_test.go b/op-supervisor/supervisor/backend/source/contracts/l2inbox_test.go index b343519a48fc9..302b188e5cdf7 100644 --- a/op-supervisor/supervisor/backend/source/contracts/l2inbox_test.go +++ b/op-supervisor/supervisor/backend/source/contracts/l2inbox_test.go @@ -7,7 +7,7 @@ import ( "github.com/ethereum-optimism/optimism/op-service/predeploys" "github.com/ethereum-optimism/optimism/op-service/sources/batching" - backendTypes "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/types" + "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" "github.com/ethereum-optimism/optimism/packages/contracts-bedrock/snapshots" "github.com/ethereum/go-ethereum/common" ethTypes "github.com/ethereum/go-ethereum/core/types" @@ -19,7 +19,7 @@ func TestDecodeExecutingMessageEvent(t *testing.T) { inbox := NewCrossL2Inbox() payload := bytes.Repeat([]byte{0xaa, 0xbb}, 50) payloadHash := crypto.Keccak256Hash(payload) - expected := backendTypes.ExecutingMessage{ + expected := types.ExecutingMessage{ Chain: 42424, BlockNum: 12345, LogIdx: 98, diff --git a/op-supervisor/supervisor/backend/source/log_processor.go b/op-supervisor/supervisor/backend/source/log_processor.go index 3fd96476d41f4..1c20f8c4530a1 100644 --- a/op-supervisor/supervisor/backend/source/log_processor.go +++ b/op-supervisor/supervisor/backend/source/log_processor.go @@ -5,30 +5,31 @@ import ( "errors" "fmt" - "github.com/ethereum-optimism/optimism/op-service/eth" - "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/source/contracts" - backendTypes "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/types" - supTypes "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" "github.com/ethereum/go-ethereum/common" ethTypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" + + "github.com/ethereum-optimism/optimism/op-service/eth" + "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/source/contracts" + "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" ) type LogStorage interface { - AddLog(chain supTypes.ChainID, logHash backendTypes.TruncatedHash, block eth.BlockID, timestamp uint64, logIdx uint32, execMsg *backendTypes.ExecutingMessage) error + SealBlock(chain types.ChainID, parentHash common.Hash, block eth.BlockID, timestamp uint64) error + AddLog(chain types.ChainID, logHash common.Hash, parentBlock eth.BlockID, logIdx uint32, execMsg *types.ExecutingMessage) error } type EventDecoder interface { - DecodeExecutingMessageLog(log *ethTypes.Log) (backendTypes.ExecutingMessage, error) + DecodeExecutingMessageLog(log *ethTypes.Log) (types.ExecutingMessage, error) } type logProcessor struct { - chain supTypes.ChainID + chain types.ChainID logStore LogStorage eventDecoder EventDecoder } -func newLogProcessor(chain supTypes.ChainID, logStore LogStorage) *logProcessor { +func newLogProcessor(chain types.ChainID, logStore LogStorage) *logProcessor { return &logProcessor{ chain: chain, logStore: logStore, @@ -43,7 +44,7 @@ func (p *logProcessor) ProcessLogs(_ context.Context, block eth.L1BlockRef, rcpt for _, l := range rcpt.Logs { // log hash represents the hash of *this* log as a potentially initiating message logHash := logToLogHash(l) - var execMsg *backendTypes.ExecutingMessage + var execMsg *types.ExecutingMessage msg, err := p.eventDecoder.DecodeExecutingMessageLog(l) if err != nil && !errors.Is(err, contracts.ErrEventNotFound) { return fmt.Errorf("failed to decode executing message log: %w", err) @@ -53,13 +54,15 @@ func (p *logProcessor) ProcessLogs(_ context.Context, block eth.L1BlockRef, rcpt } // executing messages have multiple entries in the database // they should start with the initiating message and then include the execution - fmt.Println("p.chain", p.chain) - err = p.logStore.AddLog(p.chain, logHash, block.ID(), block.Time, uint32(l.Index), execMsg) + err = p.logStore.AddLog(p.chain, logHash, block.ParentID(), uint32(l.Index), execMsg) if err != nil { return fmt.Errorf("failed to add log %d from block %v: %w", l.Index, block.ID(), err) } } } + if err := p.logStore.SealBlock(p.chain, block.ParentHash, block.ID(), block.Time); err != nil { + return fmt.Errorf("failed to seal block %s: %w", block.ID(), err) + } return nil } @@ -68,7 +71,7 @@ func (p *logProcessor) ProcessLogs(_ context.Context, block eth.L1BlockRef, rcpt // which is then hashed again. This is the hash that is stored in the log storage. // The address is hashed into the payload hash to save space in the log storage, // and because they represent paired data. -func logToLogHash(l *ethTypes.Log) backendTypes.TruncatedHash { +func logToLogHash(l *ethTypes.Log) common.Hash { payloadHash := crypto.Keccak256(logToMessagePayload(l)) return payloadHashToLogHash(common.Hash(payloadHash), l.Address) } @@ -90,9 +93,9 @@ func logToMessagePayload(l *ethTypes.Log) []byte { // which is then hashed. This is the hash that is stored in the log storage. // The logHash can then be used to traverse from the executing message // to the log the referenced initiating message. -func payloadHashToLogHash(payloadHash common.Hash, addr common.Address) backendTypes.TruncatedHash { +func payloadHashToLogHash(payloadHash common.Hash, addr common.Address) common.Hash { msg := make([]byte, 0, 2*common.HashLength) msg = append(msg, addr.Bytes()...) msg = append(msg, payloadHash.Bytes()...) - return backendTypes.TruncateHash(crypto.Keccak256Hash(msg)) + return crypto.Keccak256Hash(msg) } diff --git a/op-supervisor/supervisor/backend/source/log_processor_test.go b/op-supervisor/supervisor/backend/source/log_processor_test.go index 5c65973ab4e49..bd7aa7abc3d10 100644 --- a/op-supervisor/supervisor/backend/source/log_processor_test.go +++ b/op-supervisor/supervisor/backend/source/log_processor_test.go @@ -7,18 +7,22 @@ import ( "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/predeploys" - backendTypes "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/types" - supTypes "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" + "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" "github.com/ethereum/go-ethereum/common" ethTypes "github.com/ethereum/go-ethereum/core/types" "github.com/stretchr/testify/require" ) -var logProcessorChainID = supTypes.ChainIDFromUInt64(4) +var logProcessorChainID = types.ChainIDFromUInt64(4) func TestLogProcessor(t *testing.T) { ctx := context.Background() - block1 := eth.L1BlockRef{Number: 100, Hash: common.Hash{0x11}, Time: 1111} + block1 := eth.L1BlockRef{ + ParentHash: common.Hash{0x42}, + Number: 100, + Hash: common.Hash{0x11}, + Time: 1111, + } t.Run("NoOutputWhenLogsAreEmpty", func(t *testing.T) { store := &stubLogStorage{} processor := newLogProcessor(logProcessorChainID, store) @@ -59,30 +63,36 @@ func TestLogProcessor(t *testing.T) { err := processor.ProcessLogs(ctx, block1, rcpts) require.NoError(t, err) - expected := []storedLog{ + expectedLogs := []storedLog{ { - block: block1.ID(), - timestamp: block1.Time, - logIdx: 0, - logHash: logToLogHash(rcpts[0].Logs[0]), - execMsg: nil, + parent: block1.ParentID(), + logIdx: 0, + logHash: logToLogHash(rcpts[0].Logs[0]), + execMsg: nil, }, { - block: block1.ID(), - timestamp: block1.Time, - logIdx: 0, - logHash: logToLogHash(rcpts[0].Logs[1]), - execMsg: nil, + parent: block1.ParentID(), + logIdx: 0, + logHash: logToLogHash(rcpts[0].Logs[1]), + execMsg: nil, }, { + parent: block1.ParentID(), + logIdx: 0, + logHash: logToLogHash(rcpts[1].Logs[0]), + execMsg: nil, + }, + } + require.Equal(t, expectedLogs, store.logs) + + expectedBlocks := []storedSeal{ + { + parent: block1.ParentHash, block: block1.ID(), timestamp: block1.Time, - logIdx: 0, - logHash: logToLogHash(rcpts[1].Logs[0]), - execMsg: nil, }, } - require.Equal(t, expected, store.logs) + require.Equal(t, expectedBlocks, store.seals) }) t.Run("IncludeExecutingMessage", func(t *testing.T) { @@ -97,16 +107,16 @@ func TestLogProcessor(t *testing.T) { }, }, } - execMsg := backendTypes.ExecutingMessage{ + execMsg := types.ExecutingMessage{ Chain: 4, BlockNum: 6, LogIdx: 8, Timestamp: 10, - Hash: backendTypes.TruncatedHash{0xaa}, + Hash: common.Hash{0xaa}, } store := &stubLogStorage{} - processor := newLogProcessor(supTypes.ChainID{4}, store) - processor.eventDecoder = EventDecoderFn(func(l *ethTypes.Log) (backendTypes.ExecutingMessage, error) { + processor := newLogProcessor(types.ChainID{4}, store) + processor.eventDecoder = EventDecoderFn(func(l *ethTypes.Log) (types.ExecutingMessage, error) { require.Equal(t, rcpts[0].Logs[0], l) return execMsg, nil }) @@ -115,14 +125,22 @@ func TestLogProcessor(t *testing.T) { require.NoError(t, err) expected := []storedLog{ { + parent: block1.ParentID(), + logIdx: 0, + logHash: logToLogHash(rcpts[0].Logs[0]), + execMsg: &execMsg, + }, + } + require.Equal(t, expected, store.logs) + + expectedBlocks := []storedSeal{ + { + parent: block1.ParentHash, block: block1.ID(), timestamp: block1.Time, - logIdx: 0, - logHash: logToLogHash(rcpts[0].Logs[0]), - execMsg: &execMsg, }, } - require.Equal(t, expected, store.logs) + require.Equal(t, expectedBlocks, store.seals) }) } @@ -163,7 +181,7 @@ func TestToLogHash(t *testing.T) { refHash := logToLogHash(mkLog()) // The log hash is stored in the database so test that it matches the actual value. // If this changes, compatibility with existing databases may be affected - expectedRefHash := backendTypes.TruncateHash(common.HexToHash("0x4e1dc08fddeb273275f787762cdfe945cf47bb4e80a1fabbc7a825801e81b73f")) + expectedRefHash := common.HexToHash("0x4e1dc08fddeb273275f787762cdfe945cf47bb4e80a1fabbc7a825801e81b73f") require.Equal(t, expectedRefHash, refHash, "reference hash changed, check that database compatibility is not broken") // Check that the hash is changed when any data it should include changes @@ -183,33 +201,50 @@ func TestToLogHash(t *testing.T) { } type stubLogStorage struct { - logs []storedLog + logs []storedLog + seals []storedSeal } -func (s *stubLogStorage) AddLog(chainID supTypes.ChainID, logHash backendTypes.TruncatedHash, block eth.BlockID, timestamp uint64, logIdx uint32, execMsg *backendTypes.ExecutingMessage) error { +func (s *stubLogStorage) SealBlock(chainID types.ChainID, parentHash common.Hash, block eth.BlockID, timestamp uint64) error { if logProcessorChainID != chainID { return fmt.Errorf("chain id mismatch, expected %v but got %v", logProcessorChainID, chainID) } - s.logs = append(s.logs, storedLog{ + s.seals = append(s.seals, storedSeal{ + parent: parentHash, block: block, timestamp: timestamp, - logIdx: logIdx, - logHash: logHash, - execMsg: execMsg, }) return nil } -type storedLog struct { +func (s *stubLogStorage) AddLog(chainID types.ChainID, logHash common.Hash, parentBlock eth.BlockID, logIdx uint32, execMsg *types.ExecutingMessage) error { + if logProcessorChainID != chainID { + return fmt.Errorf("chain id mismatch, expected %v but got %v", logProcessorChainID, chainID) + } + s.logs = append(s.logs, storedLog{ + parent: parentBlock, + logIdx: logIdx, + logHash: logHash, + execMsg: execMsg, + }) + return nil +} + +type storedSeal struct { + parent common.Hash block eth.BlockID timestamp uint64 - logIdx uint32 - logHash backendTypes.TruncatedHash - execMsg *backendTypes.ExecutingMessage } -type EventDecoderFn func(*ethTypes.Log) (backendTypes.ExecutingMessage, error) +type storedLog struct { + parent eth.BlockID + logIdx uint32 + logHash common.Hash + execMsg *types.ExecutingMessage +} + +type EventDecoderFn func(*ethTypes.Log) (types.ExecutingMessage, error) -func (f EventDecoderFn) DecodeExecutingMessageLog(log *ethTypes.Log) (backendTypes.ExecutingMessage, error) { +func (f EventDecoderFn) DecodeExecutingMessageLog(log *ethTypes.Log) (types.ExecutingMessage, error) { return f(log) } diff --git a/op-supervisor/supervisor/backend/types/types.go b/op-supervisor/supervisor/backend/types/types.go deleted file mode 100644 index cf28120a34ee8..0000000000000 --- a/op-supervisor/supervisor/backend/types/types.go +++ /dev/null @@ -1,27 +0,0 @@ -package types - -import ( - "encoding/hex" - - "github.com/ethereum/go-ethereum/common" -) - -type TruncatedHash [20]byte - -func TruncateHash(hash common.Hash) TruncatedHash { - var truncated TruncatedHash - copy(truncated[:], hash[0:20]) - return truncated -} - -func (h TruncatedHash) String() string { - return hex.EncodeToString(h[:]) -} - -type ExecutingMessage struct { - Chain uint32 - BlockNum uint64 - LogIdx uint32 - Timestamp uint64 - Hash TruncatedHash -} diff --git a/op-supervisor/supervisor/frontend/frontend.go b/op-supervisor/supervisor/frontend/frontend.go index 421b231e128ea..41fb84e511cd2 100644 --- a/op-supervisor/supervisor/frontend/frontend.go +++ b/op-supervisor/supervisor/frontend/frontend.go @@ -12,6 +12,7 @@ import ( type AdminBackend interface { Start(ctx context.Context) error Stop(ctx context.Context) error + AddL2RPC(ctx context.Context, rpc string) error } type QueryBackend interface { @@ -61,3 +62,8 @@ func (a *AdminFrontend) Start(ctx context.Context) error { func (a *AdminFrontend) Stop(ctx context.Context) error { return a.Supervisor.Stop(ctx) } + +// AddL2RPC adds a new L2 chain to the supervisor backend +func (a *AdminFrontend) AddL2RPC(ctx context.Context, rpc string) error { + return a.Supervisor.AddL2RPC(ctx, rpc) +} diff --git a/op-supervisor/supervisor/service.go b/op-supervisor/supervisor/service.go index aecd90ad2fbad..47fcb3e9ec23e 100644 --- a/op-supervisor/supervisor/service.go +++ b/op-supervisor/supervisor/service.go @@ -164,6 +164,7 @@ func (su *SupervisorService) Start(ctx context.Context) error { } su.metrics.RecordUp() + su.log.Info("JSON-RPC Server started", "endpoint", su.rpcServer.Endpoint()) return nil } @@ -171,7 +172,7 @@ func (su *SupervisorService) Stop(ctx context.Context) error { if !su.closing.CompareAndSwap(false, true) { return nil // already closing } - + su.log.Info("Stopping JSON-RPC server") var result error if su.rpcServer != nil { if err := su.rpcServer.Stop(); err != nil { @@ -193,9 +194,16 @@ func (su *SupervisorService) Stop(ctx context.Context) error { result = errors.Join(result, fmt.Errorf("failed to stop metrics server: %w", err)) } } + su.log.Info("JSON-RPC server stopped") return result } func (su *SupervisorService) Stopped() bool { return su.closing.Load() } + +func (su *SupervisorService) RPC() string { + // the RPC endpoint is assumed to be HTTP + // TODO(#11032): make this flexible for ws if the server supports it + return "http://" + su.rpcServer.Endpoint() +} diff --git a/op-supervisor/supervisor/types/types.go b/op-supervisor/supervisor/types/types.go index 54b1a8a0c92c0..b035e26abcefd 100644 --- a/op-supervisor/supervisor/types/types.go +++ b/op-supervisor/supervisor/types/types.go @@ -13,6 +13,14 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" ) +type ExecutingMessage struct { + Chain uint32 // same as ChainID for now, but will be indirect, i.e. translated to full ID, later + BlockNum uint64 + LogIdx uint32 + Timestamp uint64 + Hash common.Hash +} + type Message struct { Identifier Identifier `json:"identifier"` PayloadHash common.Hash `json:"payloadHash"` diff --git a/op-wheel/commands.go b/op-wheel/commands.go index 5a643b7ec12db..521578a34cb6b 100644 --- a/op-wheel/commands.go +++ b/op-wheel/commands.go @@ -504,7 +504,7 @@ var ( metricsCfg := opmetrics.ReadCLIConfig(ctx) - return opservice.CloseAction(func(ctx context.Context, shutdown <-chan struct{}) error { + return opservice.CloseAction(ctx.Context, func(ctx context.Context) error { registry := opmetrics.NewRegistry() metrics := engine.NewMetrics("wheel", registry) if metricsCfg.Enabled { @@ -519,7 +519,7 @@ var ( } }() } - return engine.Auto(ctx, metrics, client, l, shutdown, settings) + return engine.Auto(ctx, metrics, client, l, settings) }) }), } diff --git a/op-wheel/engine/engine.go b/op-wheel/engine/engine.go index 8518a48031b0f..8a00e212b3cab 100644 --- a/op-wheel/engine/engine.go +++ b/op-wheel/engine/engine.go @@ -189,7 +189,13 @@ func newPayloadAttributes(evp sources.EngineVersionProvider, timestamp uint64, p return pa } -func Auto(ctx context.Context, metrics Metricer, client *sources.EngineAPIClient, log log.Logger, shutdown <-chan struct{}, settings *BlockBuildingSettings) error { +func Auto( + ctx context.Context, + metrics Metricer, + client *sources.EngineAPIClient, + log log.Logger, + settings *BlockBuildingSettings, +) error { ticker := time.NewTicker(time.Millisecond * 100) defer ticker.Stop() @@ -197,9 +203,6 @@ func Auto(ctx context.Context, metrics Metricer, client *sources.EngineAPIClient var buildErr error for { select { - case <-shutdown: - log.Info("shutting down") - return nil case <-ctx.Done(): log.Info("context closed", "err", ctx.Err()) return ctx.Err() diff --git a/ops/docker/Dockerfile.packages b/ops/docker/Dockerfile.packages index 598f40b3e3bb5..dbd496afc8af3 100644 --- a/ops/docker/Dockerfile.packages +++ b/ops/docker/Dockerfile.packages @@ -1,11 +1,12 @@ +# We need to specify the platforms below, otherwise platforms other than +# linux/amd64 will be forced to rebuild the contracts every time this +# image is used. + # This Dockerfile builds all the dependencies needed by the smart-contracts, excluding Go and Python. -FROM us-docker.pkg.dev/oplabs-tools-artifacts/images/ci-builder:latest as foundry +FROM --platform=linux/amd64 us-docker.pkg.dev/oplabs-tools-artifacts/images/ci-builder:latest as foundry -# Historically the contracts-bedrock was on the node image based on Debian 11 (bullseye), -# for Node / PNPM compatibility reasons. -# We no longer use Node JS, but continue to use the same Debian version for compatibility. -FROM debian:bullseye-slim as base +FROM --platform=linux/amd64 debian:bookworm-20240812-slim as base # Base: install deps RUN apt-get update && apt-get install -y \ @@ -17,13 +18,7 @@ RUN apt-get update && apt-get install -y \ bash \ --no-install-recommends -COPY /ops/docker/oplabs.crt /usr/local/share/ca-certificates/oplabs.crt -RUN chmod 644 /usr/local/share/ca-certificates/oplabs.crt \ - && update-ca-certificates - -# Note: "just" is only available on Debian 13. Instead, pull it from the foundry image. COPY --from=foundry /usr/local/bin/just /usr/local/bin/just - COPY --from=foundry /usr/local/bin/forge /usr/local/bin/forge COPY --from=foundry /usr/local/bin/cast /usr/local/bin/cast @@ -31,22 +26,48 @@ WORKDIR /opt/optimism COPY ./versions.json ./versions.json COPY ./packages ./packages - COPY .git/ ./.git COPY .gitmodules ./.gitmodules -RUN git submodule update --init --recursive + +RUN git submodule update --init --recursive \ + && cd packages/contracts-bedrock \ + && just build \ + && echo $(git rev-parse HEAD) > .gitcommit + +FROM --platform=linux/amd64 debian:bookworm-20240812-slim as contracts-bedrock + +RUN apt-get update && apt-get install -y \ + curl \ + jq \ + ca-certificates \ + git \ + make \ + bash \ + --no-install-recommends + +COPY /ops/docker/oplabs.crt /usr/local/share/ca-certificates/oplabs.crt + +RUN chmod 644 /usr/local/share/ca-certificates/oplabs.crt \ + && update-ca-certificates + +COPY --from=foundry /usr/local/bin/just /usr/local/bin/just +COPY --from=foundry /usr/local/bin/forge /usr/local/bin/forge +COPY --from=foundry /usr/local/bin/cast /usr/local/bin/cast +COPY --from=foundry /usr/local/bin/svm /usr/local/bin/svm + +RUN svm install 0.8.25 && \ + svm install 0.8.15 && \ + svm install 0.8.19 && \ + svm install 0.8.26 # Not to be confused with OP, this is a OnePassword CLI tool. COPY --from=1password/op:2 /usr/local/bin/op /usr/local/bin/op -# prebuild the smart-contracts for the convenience of the user -RUN cd packages/contracts-bedrock && just build +RUN mkdir -p /opt/optimism/packages/contracts-bedrock -FROM base as contracts-bedrock -WORKDIR /opt/optimism/packages/contracts-bedrock +COPY --from=base /opt/optimism/packages/contracts-bedrock /opt/optimism/packages/contracts-bedrock +COPY --from=base /opt/optimism/versions.json /opt/optimism/versions.json -# Set "just" as entrypoint, so the default args (the Dockerfile CMD) -# are passed in to it. This was previously "pnpm run" + "deploy". -ENTRYPOINT ["just"] +WORKDIR /opt/optimism/packages/contracts-bedrock -CMD ["deploy"] +CMD ["echo", "Override this command to use this image."] diff --git a/ops/docker/deployment-utils/Dockerfile b/ops/docker/deployment-utils/Dockerfile new file mode 100644 index 0000000000000..c0f82e5a3405d --- /dev/null +++ b/ops/docker/deployment-utils/Dockerfile @@ -0,0 +1,35 @@ +FROM golang:1.23.1-bookworm AS go-base + +RUN go install github.com/tomwright/dasel/v2/cmd/dasel@master + +FROM debian:12.7-slim AS base + +SHELL ["/bin/bash", "-c"] + +ENV PATH=/root/.cargo/bin:/root/.foundry/bin:$PATH +ENV DEBIAN_FRONTEND=noninteractive +ENV SHELL=/bin/bash + +RUN apt-get update && apt-get install -y curl git jq build-essential + +RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > rustup.sh && \ + chmod +x ./rustup.sh && \ + sh rustup.sh -y + +RUN source $HOME/.profile && rustup update nightly +RUN curl -L https://foundry.paradigm.xyz | bash +RUN foundryup + +FROM debian:12.7-slim + +ENV PATH=/root/.cargo/bin:/root/.foundry/bin:$PATH +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update && apt-get install -y bash curl jq + +SHELL ["/bin/bash", "-c"] + +COPY --from=base /root/.foundry/bin/forge /usr/local/bin/forge +COPY --from=base /root/.foundry/bin/cast /usr/local/bin/cast +COPY --from=base /root/.foundry/bin/anvil /usr/local/bin/anvil +COPY --from=go-base /go/bin/dasel /usr/local/bin/dasel \ No newline at end of file diff --git a/ops/docker/deployment-utils/README.md b/ops/docker/deployment-utils/README.md new file mode 100644 index 0000000000000..450af3423b11d --- /dev/null +++ b/ops/docker/deployment-utils/README.md @@ -0,0 +1,16 @@ +# deployment-utils + +This image provides a minimal set of Foundry and Bash tools for use with builder images like Kurtosis. It contains the +following packages: + +- The Foundry suite (`forge`, `cast`, `anvil`) +- [`Dasel`](https://github.com/TomWright/dasel), for TOML/YAML manipulation. +- `jq` for JSON manipulation. +- `curl`, for when you need to cURLs. +- A default `bash` shell. + +## Image Size + +According to `dive`, this image is 255MB in size including the base Debian image. Most of the additional size comes from +the tools themselves. I'd like to keep it this way. This image should not contain toolchains, libraries, etc. - it is +designed to run prebuilt software and manipulate configuration files. Use the CI builder for everything else. \ No newline at end of file diff --git a/ops/docker/op-stack-go/Dockerfile b/ops/docker/op-stack-go/Dockerfile index 18163a86c3ccb..35f14d19a4391 100644 --- a/ops/docker/op-stack-go/Dockerfile +++ b/ops/docker/op-stack-go/Dockerfile @@ -46,8 +46,15 @@ ARG TARGETARCH # Build the Go services, utilizing caches and share the many common packages. # The "id" defaults to the value of "target", the cache will thus be reused during this build. # "sharing" defaults to "shared", the cache will thus be available to other concurrent docker builds. + +# For now fetch the v1 cannon binary from the op-challenger image +#FROM --platform=$BUILDPLATFORM us-docker.pkg.dev/oplabs-tools-artifacts/images/op-challenger:v1.1.0 AS cannon-builder-0 + FROM --platform=$BUILDPLATFORM builder AS cannon-builder ARG CANNON_VERSION=v0.0.0 +# uncomment these lines once there's a new Cannon version available +#COPY --from=cannon-builder-0 /usr/local/bin/cannon ./cannon/multicannon/embeds/cannon-0 +#COPY --from=cannon-builder-0 /usr/local/bin/cannon ./cannon/multicannon/embeds/cannon-1 RUN --mount=type=cache,target=/go/pkg/mod --mount=type=cache,target=/root/.cache/go-build cd cannon && make cannon \ GOOS=$TARGETOS GOARCH=$TARGETARCH GITCOMMIT=$GIT_COMMIT GITDATE=$GIT_DATE VERSION="$CANNON_VERSION" @@ -101,8 +108,14 @@ ARG OP_SUPERVISOR_VERSION=v0.0.0 RUN --mount=type=cache,target=/go/pkg/mod --mount=type=cache,target=/root/.cache/go-build cd op-supervisor && make op-supervisor \ GOOS=$TARGETOS GOARCH=$TARGETARCH GITCOMMIT=$GIT_COMMIT GITDATE=$GIT_DATE VERSION="$OP_SUPERVISOR_VERSION" +FROM --platform=$BUILDPLATFORM builder AS op-deployer-builder +ARG OP_NODE_VERSION=v0.0.0 +RUN --mount=type=cache,target=/go/pkg/mod --mount=type=cache,target=/root/.cache/go-build cd op-chain-ops && make op-deployer \ + GOOS=$TARGETOS GOARCH=$TARGETARCH GITCOMMIT=$GIT_COMMIT GITDATE=$GIT_DATE VERSION="$OP_DEPLOYER_VERSION" + FROM --platform=$TARGETPLATFORM $TARGET_BASE_IMAGE AS cannon-target COPY --from=cannon-builder /app/cannon/bin/cannon /usr/local/bin/ +COPY --from=cannon-builder /app/cannon/multicannon/embeds/* /usr/local/bin/ CMD ["cannon"] FROM --platform=$TARGETPLATFORM $TARGET_BASE_IMAGE AS op-program-target @@ -150,3 +163,7 @@ CMD ["da-server"] FROM --platform=$TARGETPLATFORM $TARGET_BASE_IMAGE AS op-supervisor-target COPY --from=op-supervisor-builder /app/op-supervisor/bin/op-supervisor /usr/local/bin/ CMD ["op-supervisor"] + +FROM --platform=$TARGETPLATFORM $TARGET_BASE_IMAGE AS op-deployer-target +COPY --from=op-deployer-builder /app/op-chain-ops/bin/op-deployer /usr/local/bin/ +CMD ["op-deployer"] diff --git a/ops/docker/proofs-tools/Dockerfile b/ops/docker/proofs-tools/Dockerfile new file mode 100644 index 0000000000000..61f39c8af7057 --- /dev/null +++ b/ops/docker/proofs-tools/Dockerfile @@ -0,0 +1,26 @@ +ARG GIT_COMMIT +ARG GIT_DATE + +ARG CHALLENGER_VERSION +ARG KONA_VERSION +ARG ASTERISC_VERSION + +FROM --platform=$BUILDPLATFORM us-docker.pkg.dev/oplabs-tools-artifacts/images/op-challenger:$CHALLENGER_VERSION AS challenger +FROM --platform=$BUILDPLATFORM ghcr.io/anton-rs/kona/kona-fpp-asterisc:$KONA_VERSION AS kona +FROM --platform=$BUILDPLATFORM ghcr.io/ethereum-optimism/asterisc/asterisc:$ASTERISC_VERSION AS asterisc + +FROM --platform=$BUILDPLATFORM ubuntu:22.04 AS proofs-tools +RUN apt-get update && apt-get install -y --no-install-recommends musl openssl ca-certificates +COPY --from=challenger /usr/local/bin/op-challenger /usr/local/bin/ +COPY --from=challenger /usr/local/bin/cannon /usr/local/bin/ +ENV OP_CHALLENGER_CANNON_BIN /usr/local/bin/cannon +COPY --from=challenger /usr/local/bin/op-program /usr/local/bin/ +ENV OP_CHALLENGER_CANNON_SERVER=/usr/local/bin/op-program + +COPY --from=kona /kona-host /usr/local/bin/ +ENV OP_CHALLENGER_ASTERISC_KONA_SERVER=/usr/local/bin/kona-host + +COPY --from=asterisc /usr/local/bin/asterisc /usr/local/bin/ +ENV OP_CHALLENGER_ASTERISC_BIN=/usr/local/bin/asterisc + +CMD /usr/local/bin/op-challenger diff --git a/ops/docker/proofs-tools/README.md b/ops/docker/proofs-tools/README.md new file mode 100644 index 0000000000000..faa47f8d4ad33 --- /dev/null +++ b/ops/docker/proofs-tools/README.md @@ -0,0 +1,8 @@ +## Proofs Tools + +The proofs-tools docker image provides a collection of useful fault proofs related tools in a single docker image. +In particular it provides op-challenger with cannon, asterisc, op-program and kona-host ready to participate in +cannon, asterisc or asterisc-kona game types. + +The version of each tool used in the image is specified +in [docker-bake.hcl](https://github.com/ethereum-optimism/optimism/blob/develop/docker-bake.hcl). diff --git a/ops/scripts/ci-docker-tag-op-stack-release.sh b/ops/scripts/ci-docker-tag-op-stack-release.sh index 49904d7cce9af..45dd920949946 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(-rust)?|da-server|ufm-[a-z0-9\-]*|op-[a-z0-9\-]*)' || true) +IMAGE_NAME=$(echo "$GIT_TAG" | grep -Eow '^(ci-builder(-rust)?|da-server|proofs-tools|cannon|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/todo-checker.sh b/ops/scripts/todo-checker.sh index d90d97fc47c9d..6b144ec200cfd 100755 --- a/ops/scripts/todo-checker.sh +++ b/ops/scripts/todo-checker.sh @@ -5,6 +5,7 @@ set -uo pipefail # Flags FAIL_INVALID_FMT=false VERBOSE=false +CHECK_CLOSED=false # Github API access token (Optional - necessary for private repositories.) GH_API_TOKEN="${CI_TODO_CHECKER_PAT:-""}" @@ -36,6 +37,7 @@ NC='\033[0m' # No Color # # `--strict`: Toggle strict mode; Will fail if any TODOs are found that don't match the expected # `--verbose`: Toggle verbose mode; Will print out details about each TODO +# `--check-closed`: Check for closed issues and error out if found for arg in "$@"; do case $arg in --strict) @@ -46,6 +48,10 @@ for arg in "$@"; do VERBOSE=true shift ;; + --check-closed) + CHECK_CLOSED=true + shift + ;; esac done @@ -65,10 +71,10 @@ for todo in $todos; do # * TODO(repo#): (Default org "ethereum-optimism") # * TODO(org/repo#): # - # Check if it's just a number - if [[ $ISSUE_REFERENCE =~ ^[0-9]+$ ]]; then + # Check if it's just a number or a number with a leading # + if [[ $ISSUE_REFERENCE =~ ^[0-9]+$ ]] || [[ $ISSUE_REFERENCE =~ ^#([0-9]+)$ ]]; then REPO_FULL="$ORG/$REPO" - ISSUE_NUM="$ISSUE_REFERENCE" + ISSUE_NUM="${ISSUE_REFERENCE#\#}" # Remove leading # if present # Check for org_name/repo_name#number format elif [[ $ISSUE_REFERENCE =~ ^([^/]+)/([^#]+)#([0-9]+)$ ]]; then REPO_FULL="${BASH_REMATCH[1]}/${BASH_REMATCH[2]}" @@ -104,14 +110,16 @@ for todo in $todos; do # Check issue state STATE=$(echo "$RESPONSE" | jq -r .state) - if [[ "$STATE" == "closed" ]]; then + if [[ "$STATE" == "closed" ]] && $CHECK_CLOSED; then echo -e "${RED}[Error]:${NC} Issue #$ISSUE_NUM is closed. Please remove the TODO in ${GREEN}$FILE:$LINE_NUM${NC} referencing ${YELLOW}$ISSUE_REFERENCE${NC} (${CYAN}https://github.com/$GH_URL_PATH${NC})" exit 1 fi - ((OPEN_COUNT++)) - TITLE=$(echo "$RESPONSE" | jq -r .title) - OPEN_ISSUES+=("$REPO_FULL/issues/$ISSUE_NUM|$TITLE|$FILE:$LINE_NUM") + if [[ "$STATE" == "open" ]]; then + ((OPEN_COUNT++)) + TITLE=$(echo "$RESPONSE" | jq -r .title) + OPEN_ISSUES+=("$REPO_FULL/issues/$ISSUE_NUM|$TITLE|$FILE:$LINE_NUM") + fi done # Print summary diff --git a/packages/contracts-bedrock/.gas-snapshot b/packages/contracts-bedrock/.gas-snapshot index b3ea3b88545e7..ecfb713d05a0e 100644 --- a/packages/contracts-bedrock/.gas-snapshot +++ b/packages/contracts-bedrock/.gas-snapshot @@ -1,11 +1,17 @@ -GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_0() (gas: 369356) -GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_1() (gas: 2967496) -GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_0() (gas: 564483) -GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_1() (gas: 4076526) -GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_0() (gas: 466947) -GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_1() (gas: 3512629) -GasBenchMark_L1StandardBridge_Finalize:test_finalizeETHWithdrawal_benchmark() (gas: 72624) -GasBenchMark_L2OutputOracle:test_proposeL2Output_benchmark() (gas: 92973) -GasBenchMark_OptimismPortal:test_depositTransaction_benchmark() (gas: 68433) -GasBenchMark_OptimismPortal:test_depositTransaction_benchmark_1() (gas: 68903) -GasBenchMark_OptimismPortal:test_proveWithdrawalTransaction_benchmark() (gas: 155618) \ No newline at end of file +GasBenchMark_L1BlockIsthmus_DepositsComplete:test_depositsComplete_benchmark() (gas: 7567) +GasBenchMark_L1BlockIsthmus_DepositsComplete_Warm:test_depositsComplete_benchmark() (gas: 5567) +GasBenchMark_L1BlockIsthmus_SetValuesIsthmus:test_setL1BlockValuesIsthmus_benchmark() (gas: 175657) +GasBenchMark_L1BlockIsthmus_SetValuesIsthmus_Warm:test_setL1BlockValuesIsthmus_benchmark() (gas: 5121) +GasBenchMark_L1Block_SetValuesEcotone:test_setL1BlockValuesEcotone_benchmark() (gas: 158531) +GasBenchMark_L1Block_SetValuesEcotone_Warm:test_setL1BlockValuesEcotone_benchmark() (gas: 7597) +GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_0() (gas: 369242) +GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_1() (gas: 2967382) +GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_0() (gas: 564362) +GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_1() (gas: 4076577) +GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_0() (gas: 467019) +GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_1() (gas: 3512701) +GasBenchMark_L1StandardBridge_Finalize:test_finalizeETHWithdrawal_benchmark() (gas: 72618) +GasBenchMark_L2OutputOracle:test_proposeL2Output_benchmark() (gas: 92970) +GasBenchMark_OptimismPortal:test_depositTransaction_benchmark() (gas: 68312) +GasBenchMark_OptimismPortal:test_depositTransaction_benchmark_1() (gas: 68943) +GasBenchMark_OptimismPortal:test_proveWithdrawalTransaction_benchmark() (gas: 155607) \ No newline at end of file diff --git a/packages/contracts-bedrock/CONTRIBUTING.md b/packages/contracts-bedrock/CONTRIBUTING.md index 02a5bc8dad4c1..a249ae5bedcab 100644 --- a/packages/contracts-bedrock/CONTRIBUTING.md +++ b/packages/contracts-bedrock/CONTRIBUTING.md @@ -68,7 +68,6 @@ You can run `just -l` to list them all, some of the key ones are: 1 `just gas-snapshot` Generates the gas snapshot for the smart contracts. 1. `just semver-lock` Generates the semver lockfile. 1. `just snapshots` Generates the storage and ABI snapshots. -1. `just autogen-invariant-docs` Generates the invariant test documentation. 1. `just clean` Removes all build artifacts for `forge` and `go` compilations. 1. `just validate-spacers` Validates the positions of the storage slot spacers. 1. `just validate-deploy-configs` Validates the deployment configurations in `deploy-config` diff --git a/packages/contracts-bedrock/README.md b/packages/contracts-bedrock/README.md index 461dca818b2cf..cc687ce6ae97c 100644 --- a/packages/contracts-bedrock/README.md +++ b/packages/contracts-bedrock/README.md @@ -9,11 +9,6 @@ High-level information about these contracts can be found within this README and ## 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) @@ -36,213 +31,7 @@ High-level information about these contracts can be found within this README and ## 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) - OptimismPortal(OptimismPortal) - SuperchainConfig(SuperchainConfig) - SystemConfig(SystemConfig) - DisputeGameFactory(DisputeGameFactory) - FaultDisputeGame(FaultDisputeGame) - AnchorStateRegistry(AnchorStateRegistry) - DelayedWETH(DelayedWETH) - end - - subgraph "User Interactions (Permissionless)" - Users(Users) - Challengers(Challengers) - end - - subgraph "System Interactions" - Guardian(Guardian) - Batcher(Batcher) - end - - subgraph "Layer 2 Interactions" - L2Nodes(Layer 2 Nodes) - end - - L2Nodes -.->|fetch transaction batches| BatchDataEOA - L2Nodes -.->|fetch deposit events| OptimismPortal - - Batcher -->|publish transaction batches| BatchDataEOA - - ExternalERC20 <-->|mint/burn/transfer tokens| L1StandardBridge - ExternalERC721 <-->|mint/burn/transfer tokens| L1ERC721Bridge - - L1StandardBridge <-->|send/receive messages| L1CrossDomainMessenger - L1StandardBridge -.->|query pause state| SuperchainConfig - - L1ERC721Bridge <-->|send/receive messages| L1CrossDomainMessenger - L1ERC721Bridge -.->|query pause state| SuperchainConfig - - L1CrossDomainMessenger <-->|send/receive messages| OptimismPortal - L1CrossDomainMessenger -.->|query pause state| SuperchainConfig - - OptimismPortal -.->|query pause state| SuperchainConfig - OptimismPortal -.->|query config| SystemConfig - OptimismPortal -.->|query state proposals| DisputeGameFactory - - DisputeGameFactory -->|generate instances| FaultDisputeGame - - FaultDisputeGame -->|store bonds| DelayedWETH - FaultDisputeGame -->|query/update anchor states| AnchorStateRegistry - - Users <-->|deposit/withdraw ETH/ERC20s| L1StandardBridge - Users <-->|deposit/withdraw ERC721s| L1ERC721Bridge - Users -->|prove/execute withdrawals| OptimismPortal - - Challengers -->|propose output roots| DisputeGameFactory - Challengers -->|verify/challenge/defend proposals| FaultDisputeGame - - Guardian -->|pause/unpause| SuperchainConfig - Guardian -->|safety net actions| OptimismPortal - Guardian -->|safety net actions| DisputeGameFactory - Guardian -->|safety net actions| DelayedWETH - - 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,OptimismPortal,SuperchainConfig,SystemConfig,DisputeGameFactory,FaultDisputeGame,DelayedWETH,AnchorStateRegistry l1Contracts; - class BatchDataEOA l1EOA; - class Users,Challengers userInt; - class Batcher,Guardian systemUser; - class L2Nodes l2Nodes; -``` - -#### 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; -``` - -#### Notes for Core L2 Smart Contracts - -- 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). - -### Smart Contract Proxies - -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. - -```mermaid -graph LR - ProxyAdminOwner(Proxy Admin Owner) - ProxyAdmin(ProxyAdmin) - - subgraph "Logical Smart Contract" - Proxy(Proxy) - Implementation(Implementation) - end - - ProxyAdminOwner -->|manages| ProxyAdmin - ProxyAdmin -->|upgrades| Proxy - Proxy -->|delegatecall| Implementation - - classDef l1Contracts stroke:#bbf,stroke-width:2px; - classDef systemUser stroke:#f9a,stroke-width:2px; - class Proxy l1Contracts; - class ProxyAdminOwner systemUser; -``` +Refer to the [Optimism Overview page within the OP Stack Specs](https://specs.optimism.io/protocol/overview.html#architecture-overview) for a detailed architecture overview of core L1 contracts, core L2 contracts, and smart contract proxies. ## External Usage diff --git a/packages/contracts-bedrock/VERSIONING.md b/packages/contracts-bedrock/VERSIONING.md index 213fae3a6074e..fefc2211b3e58 100644 --- a/packages/contracts-bedrock/VERSIONING.md +++ b/packages/contracts-bedrock/VERSIONING.md @@ -81,7 +81,9 @@ To accommodate this, once contract changes are ready for governance approval, th - After merge, the new commit on the `proposal/op-contracts/vX.Y.Z` branch is the commit hash that will be tagged as `op-contracts/vX.Y.Z-rc.1`, used to deploy the contracts, and proposed to governance. - Sometimes additional release candidates are needed before proposal—see [Additional Release Candidates](#additional-release-candidates) for more information on this flow. - Once the governance approval is posted, any lock on contracts on `develop` is released. -- Once governance approves the proposal, merge the proposal branch into `develop` and set the version of all contracts to the appropriate `X.Y.Z` after considering any changes made to `develop` since the release candidate was created. +- Once governance approves the proposal: + - Create the official `op-contracts/vX.Y.Z` off of this `proposal/op-contracts/vX.Y.Z` branch. It should be at the same commit as the most recent release candidate. + - Merge the proposal branch into `develop` and set the version of all contracts to the appropriate `X.Y.Z` after considering any changes made to `develop` since the release candidate was created. - See [Merging Back to Develop After Governance Approval](#merging-back-to-develop-after-governance-approval) for more information on how to choose the resulting contract versions when merging back into `develop`. ### Additional Release Candidates diff --git a/packages/contracts-bedrock/deploy-config/mainnet.json b/packages/contracts-bedrock/deploy-config/mainnet.json index 807c12fe1939c..cd217ba111538 100644 --- a/packages/contracts-bedrock/deploy-config/mainnet.json +++ b/packages/contracts-bedrock/deploy-config/mainnet.json @@ -42,7 +42,7 @@ "systemConfigStartBlock": 17422444, "requiredProtocolVersion": "0x0000000000000000000000000000000000000003000000010000000000000000", "recommendedProtocolVersion": "0x0000000000000000000000000000000000000003000000010000000000000000", - "faultGameAbsolutePrestate": "0x03e806a2859a875267a563462a06d4d1d1b455a9efee959a46e21e54b6caf69a", + "faultGameAbsolutePrestate": "0x038512e02c4c3f7bdaec27d00edf55b7155e0905301e1a88083e4e0a6764d54c", "faultGameMaxDepth": 73, "faultGameClockExtension": 10800, "faultGameMaxClockDuration": 302400, diff --git a/packages/contracts-bedrock/foundry.toml b/packages/contracts-bedrock/foundry.toml index 9edf752f983d6..cef9f85bbaebd 100644 --- a/packages/contracts-bedrock/foundry.toml +++ b/packages/contracts-bedrock/foundry.toml @@ -49,7 +49,8 @@ fs_permissions = [ { access='read', path = './forge-artifacts/' }, { access='write', path='./semver-lock.json' }, { access='read-write', path='./.testdata/' }, - { access='read', path='./kout-deployment' } + { access='read', path='./kout-deployment' }, + { access='read', path='./test/fixtures' }, ] libs = ["node_modules", "lib"] diff --git a/packages/contracts-bedrock/invariant-docs/AddressAliasHelper.md b/packages/contracts-bedrock/invariant-docs/AddressAliasHelper.md deleted file mode 100644 index f7787a4361225..0000000000000 --- a/packages/contracts-bedrock/invariant-docs/AddressAliasHelper.md +++ /dev/null @@ -1,6 +0,0 @@ -# `AddressAliasHelper` Invariants - -## Address aliases are always able to be undone. -**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 deleted file mode 100644 index eb11cba92315e..0000000000000 --- a/packages/contracts-bedrock/invariant-docs/Burn.Eth.md +++ /dev/null @@ -1,6 +0,0 @@ -# `Burn.Eth` Invariants - -## `eth(uint256)` always burns the exact amount of eth passed. -**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 deleted file mode 100644 index 5c343bca23fdf..0000000000000 --- a/packages/contracts-bedrock/invariant-docs/Burn.Gas.md +++ /dev/null @@ -1,6 +0,0 @@ -# `Burn.Gas` Invariants - -## `gas(uint256)` always burns at least the amount of gas passed. -**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 deleted file mode 100644 index 4329859f24a3a..0000000000000 --- a/packages/contracts-bedrock/invariant-docs/CrossDomainMessenger.md +++ /dev/null @@ -1,15 +0,0 @@ -# `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#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#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. -- The inner min gas limit is for the call from the `L1CrossDomainMessenger` to the target contract. \ No newline at end of file diff --git a/packages/contracts-bedrock/invariant-docs/ETHLiquidity.md b/packages/contracts-bedrock/invariant-docs/ETHLiquidity.md deleted file mode 100644 index bbf6eb0614763..0000000000000 --- a/packages/contracts-bedrock/invariant-docs/ETHLiquidity.md +++ /dev/null @@ -1,5 +0,0 @@ -# `ETHLiquidity` Invariants - -## Calls to mint/burn repeatedly should never cause the actor's balance to increase beyond the starting balance. -**Test:** [`ETHLiquidity.t.sol#L83`](../test/invariants/ETHLiquidity.t.sol#L83) - diff --git a/packages/contracts-bedrock/invariant-docs/Encoding.md b/packages/contracts-bedrock/invariant-docs/Encoding.md deleted file mode 100644 index 460eff43df77d..0000000000000 --- a/packages/contracts-bedrock/invariant-docs/Encoding.md +++ /dev/null @@ -1,11 +0,0 @@ -# `Encoding` Invariants - -## `convertRoundTripAToB` never fails. -**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#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 deleted file mode 100644 index c54eb974cff72..0000000000000 --- a/packages/contracts-bedrock/invariant-docs/FaultDisputeGame.md +++ /dev/null @@ -1,6 +0,0 @@ -# `FaultDisputeGame` Invariants - -## FaultDisputeGame always returns all ETH on total resolution -**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 deleted file mode 100644 index acf407876d3c3..0000000000000 --- a/packages/contracts-bedrock/invariant-docs/Hashing.md +++ /dev/null @@ -1,16 +0,0 @@ -# `Hashing` Invariants - -## `hashCrossDomainMessage` reverts if `version` is > `1`. -**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#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#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 deleted file mode 100644 index bd27f490f563d..0000000000000 --- a/packages/contracts-bedrock/invariant-docs/InvariantTest.sol.md +++ /dev/null @@ -1,2 +0,0 @@ -# `InvariantTest.sol` Invariants - diff --git a/packages/contracts-bedrock/invariant-docs/L2OutputOracle.md b/packages/contracts-bedrock/invariant-docs/L2OutputOracle.md deleted file mode 100644 index 18804304e71cc..0000000000000 --- a/packages/contracts-bedrock/invariant-docs/L2OutputOracle.md +++ /dev/null @@ -1,6 +0,0 @@ -# `L2OutputOracle` Invariants - -## The block number of the output root proposals should monotonically increase. -**Test:** [`L2OutputOracle.t.sol#L58`](../test/invariants/L2OutputOracle.t.sol#L58) - -When a new output is submitted, it should never be allowed to correspond to a block number that is less than the current output. \ No newline at end of file diff --git a/packages/contracts-bedrock/invariant-docs/OptimismPortal.md b/packages/contracts-bedrock/invariant-docs/OptimismPortal.md deleted file mode 100644 index 07347e58bd774..0000000000000 --- a/packages/contracts-bedrock/invariant-docs/OptimismPortal.md +++ /dev/null @@ -1,21 +0,0 @@ -# `OptimismPortal` Invariants - -## Deposits of any value should always succeed unless `_to` = `address(0)` or `_isCreation` = `true`. -**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#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#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#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 deleted file mode 100644 index c9a00ec0941e1..0000000000000 --- a/packages/contracts-bedrock/invariant-docs/OptimismPortal2.md +++ /dev/null @@ -1,21 +0,0 @@ -# `OptimismPortal2` Invariants - -## Deposits of any value should always succeed unless `_to` = `address(0)` or `_isCreation` = `true`. -**Test:** [`OptimismPortal2.t.sol#L161`](../test/invariants/OptimismPortal2.t.sol#L161) - -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#L183`](../test/invariants/OptimismPortal2.t.sol#L183) - -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#L212`](../test/invariants/OptimismPortal2.t.sol#L212) - -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#L240`](../test/invariants/OptimismPortal2.t.sol#L240) - -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/OptimismSuperchainERC20.md b/packages/contracts-bedrock/invariant-docs/OptimismSuperchainERC20.md deleted file mode 100644 index 0e3150624da52..0000000000000 --- a/packages/contracts-bedrock/invariant-docs/OptimismSuperchainERC20.md +++ /dev/null @@ -1,10 +0,0 @@ -# `OptimismSuperchainERC20` Invariants - -## Calls to sendERC20 should always succeed as long as the actor has enough balance. Actor's balance should also not increase out of nowhere but instead should decrease by the amount sent. -**Test:** [`OptimismSuperchainERC20.t.sol#L194`](../test/invariants/OptimismSuperchainERC20.t.sol#L194) - - - -## Calls to relayERC20 should always succeeds when a message is received from another chain. Actor's balance should only increase by the amount relayed. -**Test:** [`OptimismSuperchainERC20.t.sol#L212`](../test/invariants/OptimismSuperchainERC20.t.sol#L212) - diff --git a/packages/contracts-bedrock/invariant-docs/README.md b/packages/contracts-bedrock/invariant-docs/README.md deleted file mode 100644 index cfa87fb4c1673..0000000000000 --- a/packages/contracts-bedrock/invariant-docs/README.md +++ /dev/null @@ -1,53 +0,0 @@ -# Invariant Docs - -This directory contains documentation for all defined invariant tests within `contracts-bedrock`. - - - - -## Table of Contents -- [AddressAliasHelper](./AddressAliasHelper.md) -- [Burn.Eth](./Burn.Eth.md) -- [Burn.Gas](./Burn.Gas.md) -- [CrossDomainMessenger](./CrossDomainMessenger.md) -- [ETHLiquidity](./ETHLiquidity.md) -- [Encoding](./Encoding.md) -- [FaultDisputeGame](./FaultDisputeGame.md) -- [Hashing](./Hashing.md) -- [InvariantTest.sol](./InvariantTest.sol.md) -- [L2OutputOracle](./L2OutputOracle.md) -- [OptimismPortal](./OptimismPortal.md) -- [OptimismPortal2](./OptimismPortal2.md) -- [OptimismSuperchainERC20](./OptimismSuperchainERC20.md) -- [ResourceMetering](./ResourceMetering.md) -- [SafeCall](./SafeCall.md) -- [SuperchainWETH](./SuperchainWETH.md) -- [SystemConfig](./SystemConfig.md) - - -## Usage - -To auto-generate documentation for invariant tests, run `just autogen-invariant-docs`. - -## Documentation Standard - -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 - -All `forge` invariant tests must exist within the `contracts/test/invariants` folder, and the file name should be -`.t.sol`, where `` is the name of the contract that is being tested. - -All tests within `forge` invariant files should follow the convention: - -```solidity -/** - * @custom:invariant - * - * <longDescription> - */ -function invariant_<shortDescription>() external { - // ... -} -``` diff --git a/packages/contracts-bedrock/invariant-docs/ResourceMetering.md b/packages/contracts-bedrock/invariant-docs/ResourceMetering.md deleted file mode 100644 index 967c24bf886f3..0000000000000 --- a/packages/contracts-bedrock/invariant-docs/ResourceMetering.md +++ /dev/null @@ -1,36 +0,0 @@ -# `ResourceMetering` Invariants - -## The base fee should increase if the last block used more than the target amount of gas. -**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#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#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#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#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#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#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 deleted file mode 100644 index 19ac6d8510305..0000000000000 --- a/packages/contracts-bedrock/invariant-docs/SafeCall.md +++ /dev/null @@ -1,11 +0,0 @@ -# `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#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#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/SuperchainWETH.md b/packages/contracts-bedrock/invariant-docs/SuperchainWETH.md deleted file mode 100644 index 4b52a6146f148..0000000000000 --- a/packages/contracts-bedrock/invariant-docs/SuperchainWETH.md +++ /dev/null @@ -1,5 +0,0 @@ -# `SuperchainWETH` Invariants - -## Calls to sendERC20 should always succeed as long as the actor has less than uint248 wei which is much greater than the total ETH supply. Actor's balance should also not increase out of nowhere. -**Test:** [`SuperchainWETH.t.sol#L181`](../test/invariants/SuperchainWETH.t.sol#L181) - diff --git a/packages/contracts-bedrock/invariant-docs/SystemConfig.md b/packages/contracts-bedrock/invariant-docs/SystemConfig.md deleted file mode 100644 index 59f9a999f10c2..0000000000000 --- a/packages/contracts-bedrock/invariant-docs/SystemConfig.md +++ /dev/null @@ -1,6 +0,0 @@ -# `SystemConfig` Invariants - -## Gas limit boundaries -**Test:** [`SystemConfig.t.sol#L70`](../test/invariants/SystemConfig.t.sol#L70) - -The gas limit of the `SystemConfig` contract can never be lower than the hard-coded lower bound or higher than the hard-coded upper bound. The lower bound must never be higher than the upper bound. \ No newline at end of file diff --git a/packages/contracts-bedrock/justfile b/packages/contracts-bedrock/justfile index 45cdd14cfae03..901ce17daa68f 100644 --- a/packages/contracts-bedrock/justfile +++ b/packages/contracts-bedrock/justfile @@ -1,100 +1,207 @@ -prebuild: - ./scripts/checks/check-foundry-install.sh +######################################################## +# INSTALL # +######################################################## + +# Installs dependencies. +install: + forge install +# Shows the status of the git submodules. dep-status: git submodule status -install: - forge install +######################################################## +# BUILD # +######################################################## + +# Checks that the correct version of Foundry is installed. +prebuild: + ./scripts/checks/check-foundry-install.sh + +# Builds the contracts. build: prebuild forge build +# Builds the go-ffi tool for contract tests. build-go-ffi: cd scripts/go-ffi && go build -autogen-invariant-docs: - go run ./scripts/autogen/generate-invariant-docs . +# Cleans build artifacts and deployments. +clean: + rm -rf ./artifacts ./forge-artifacts ./cache ./scripts/go-ffi/go-ffi ./deployments/hardhat/* + +######################################################## +# TEST # +######################################################## + +# Runs standard contract tests. test: build-go-ffi forge test -test-kontrol: - ./test/kontrol/scripts/run-kontrol.sh script - +# Runs standard contract tests with rerun flag. test-rerun: build-go-ffi forge test --rerun -vvv -genesis: - forge script scripts/L2Genesis.s.sol:L2Genesis --sig 'runWithStateDump()' +# Run Kontrol tests and build all dependencies. +test-kontrol: build-go-ffi build kontrol-summary-full test-kontrol-no-build + +# Run Kontrol tests without dependencies. +test-kontrol-no-build: + ./test/kontrol/scripts/run-kontrol.sh script +# Runs contract coverage. coverage: build-go-ffi forge coverage || (bash -c "forge coverage 2>&1 | grep -q 'Stack too deep' && echo -e '\\033[1;33mWARNING\\033[0m: Coverage failed with stack too deep, so overriding and exiting successfully' && exit 0 || exit 1") +# Runs contract coverage with lcov. coverage-lcov: build-go-ffi forge coverage --report lcov || (bash -c "forge coverage --report lcov 2>&1 | grep -q 'Stack too deep' && echo -e '\\033[1;33mWARNING\\033[0m: Coverage failed with stack too deep, so overriding and exiting successfully' && exit 0 || exit 1") + +######################################################## +# DEPLOY # +######################################################## + +# Generates the L2 genesis state. +genesis: + forge script scripts/L2Genesis.s.sol:L2Genesis --sig 'runWithStateDump()' + +# Deploys the contracts. deploy: ./scripts/deploy/deploy.sh + +######################################################## +# SNAPSHOTS # +######################################################## + +# Generates a gas snapshot without building. gas-snapshot-no-build: forge snapshot --match-contract GasBenchMark -statediff: - ./scripts/utils/statediff.sh && git diff --exit-code - +# Generates a gas snapshot. gas-snapshot: build-go-ffi gas-snapshot-no-build -gas-snapshot-check: build-go-ffi - forge snapshot --match-contract GasBenchMark --check +# Checks that the state diff is up to date. +statediff: + ./scripts/utils/statediff.sh && git diff --exit-code +# Generates default Kontrol summary. kontrol-summary: ./test/kontrol/scripts/make-summary-deployment.sh +# Generates fault proofs Kontrol summary. kontrol-summary-fp: KONTROL_FP_DEPLOYMENT=true ./test/kontrol/scripts/make-summary-deployment.sh +# Generates all Kontrol summaries (default and FP). +kontrol-summary-full: kontrol-summary kontrol-summary-fp + +# Generates ABI snapshots for contracts. snapshots-abi-storage: go run ./scripts/autogen/generate-snapshots . +# Updates the semver-lock.json file. +semver-lock: + forge script scripts/autogen/SemverLock.s.sol + +# Generates core snapshots without building contracts. Currently just an alias for +# snapshots-abi-storage because we no longer run Kontrol snapshots here. Run +# kontrol-summary-full to build the Kontrol summaries if necessary. +snapshots-no-build: snapshots-abi-storage + +# Builds contracts and then generates core snapshots. snapshots: build snapshots-no-build -snapshots-no-build: snapshots-abi-storage kontrol-summary-fp kontrol-summary +######################################################## +# CHECKS # +######################################################## + +# Checks that the gas snapshot is up to date without building. +gas-snapshot-check-no-build: + forge snapshot --match-contract GasBenchMark --check + +# Checks that the gas snapshot is up to date. +gas-snapshot-check: build-go-ffi gas-snapshot-check-no-build + +# Checks that the Kontrol deployment script has not changed. +kontrol-deployment-check: + ./scripts/checks/check-kontrol-deployment.sh + +# Checks if the snapshots are up to date without building. +snapshots-check-no-build: + ./scripts/checks/check-snapshots.sh --no-build + +# Checks if the snapshots are up to date. snapshots-check: ./scripts/checks/check-snapshots.sh -semver-lock: - forge script scripts/autogen/SemverLock.s.sol - -validate-deploy-configs: - ./scripts/checks/check-deploy-configs.sh +# Checks interface correctness without building. +interfaces-check-no-build: + ./scripts/checks/check-interfaces.sh -validate-spacers-no-build: - go run ./scripts/checks/spacers +# Checks that all interfaces are appropriately named and accurately reflect the corresponding +# contract that they're meant to represent. We run "clean" before building because leftover +# artifacts can cause the script to detect issues incorrectly.2 +interfaces-check: clean build interfaces-check-no-build -validate-spacers: build validate-spacers-no-build +# Checks that the size of the contracts is within the limit. +size-check: + forge build --sizes --skip "/**/test/**" --skip "/**/scripts/**" -clean: - rm -rf ./artifacts ./forge-artifacts ./cache ./scripts/go-ffi/go-ffi ./.testdata ./deployments/hardhat/* +# Checks that any contracts with a modified semver lock also have a modified semver version. +# Does not build contracts. +semver-diff-check-no-build: + ./scripts/checks/check-semver-diff.sh -pre-pr-no-build: gas-snapshot-no-build snapshots-no-build semver-lock autogen-invariant-docs lint +# Checks that any contracts with a modified semver lock also have a modified semver version. +semver-diff-check: build semver-diff-check-no-build -pre-pr: clean build-go-ffi build pre-pr-no-build +# Checks that semver natspec is equal to the actual semver version. +# Does not build contracts. +semver-natspec-check-no-build: + ./scripts/checks/check-semver-natspec-match.sh -pre-pr-full: test validate-deploy-configs validate-spacers pre-pr +# Checks that semver natspec is equal to the actual semver version. +semver-natspec-check: build semver-natspec-check-no-build +# Checks that forge test names are correctly formatted. lint-forge-tests-check: go run ./scripts/checks/names -lint-contracts-check: +# Checks that contracts are properly linted. +lint-check: forge fmt --check -lint-check: lint-contracts-check +# Checks that the deploy configs are valid. +validate-deploy-configs: + ./scripts/checks/check-deploy-configs.sh -lint-contracts-fix: - forge fmt +# Checks that spacer variables are correctly inserted without building. +validate-spacers-no-build: + go run ./scripts/checks/spacers + +# Checks that spacer variables are correctly inserted. +validate-spacers: build validate-spacers-no-build + +# TODO: Also run lint-forge-tests-check but we need to fix the test names first. +# Runs all checks. +check: gas-snapshot-check-no-build kontrol-deployment-check snapshots-check-no-build lint-check semver-diff-check-no-build semver-natspec-check-no-build validate-deploy-configs validate-spacers-no-build interfaces-check-no-build -lint-fix: lint-contracts-fix +######################################################## +# DEV TOOLS # +######################################################## + +# Cleans, builds, lints, and runs all checks. +pre-pr: clean build-go-ffi build lint gas-snapshot-no-build snapshots-no-build semver-lock check + +# Fixes linting errors. +lint-fix: + forge fmt + +# Fixes linting errors and checks that the code is correctly formatted. lint: lint-fix lint-check diff --git a/packages/contracts-bedrock/scripts/Artifacts.s.sol b/packages/contracts-bedrock/scripts/Artifacts.s.sol index b054d2e272541..bfac0c367bfcb 100644 --- a/packages/contracts-bedrock/scripts/Artifacts.s.sol +++ b/packages/contracts-bedrock/scripts/Artifacts.s.sol @@ -11,7 +11,7 @@ import { StorageSlot } from "scripts/libraries/ForgeArtifacts.sol"; import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; import { LibString } from "@solady/utils/LibString.sol"; import { ForgeArtifacts } from "scripts/libraries/ForgeArtifacts.sol"; -import { IAddressManager } from "scripts/interfaces/IAddressManager.sol"; +import { IAddressManager } from "src/legacy/interfaces/IAddressManager.sol"; import { Process } from "scripts/libraries/Process.sol"; /// @notice Represents a deployment. Is serialized to JSON as a key/value @@ -28,13 +28,15 @@ struct Deployment { abstract contract Artifacts { /// @notice Foundry cheatcode VM. Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); - /// @notice Error for when attempting to fetch a deployment and it does not exist + /// @notice Error for when attempting to fetch a deployment and it does not exist error DeploymentDoesNotExist(string); /// @notice Error for when trying to save an invalid deployment error InvalidDeployment(string); - /// @notice The set of deployments that have been done during execution. + /// @notice Error for when attempting to load the initialized slot of an unsupported contract. + error UnsupportedInitializableContract(string); + /// @notice The set of deployments that have been done during execution. mapping(string => Deployment) internal _namedDeployments; /// @notice The same as `_namedDeployments` but as an array. Deployment[] internal _newDeployments; @@ -152,6 +154,10 @@ abstract contract Artifacts { return payable(Predeploys.SCHEMA_REGISTRY); } else if (digest == keccak256(bytes("EAS"))) { return payable(Predeploys.EAS); + } else if (digest == keccak256(bytes("OptimismSuperchainERC20Factory"))) { + return payable(Predeploys.OPTIMISM_SUPERCHAIN_ERC20_FACTORY); + } else if (digest == keccak256(bytes("OptimismSuperchainERC20Beacon"))) { + return payable(Predeploys.OPTIMISM_SUPERCHAIN_ERC20_BEACON); } return payable(address(0)); } @@ -211,6 +217,13 @@ abstract contract Artifacts { /// @notice Returns the value of the internal `_initialized` storage slot for a given contract. function loadInitializedSlot(string memory _contractName) public returns (uint8 initialized_) { + // FaultDisputeGame and PermissionedDisputeGame are initializable but cannot be loaded with + // this function yet because they are not properly labeled in the deploy script. + // TODO: Remove this restriction once the deploy script is fixed. + if (LibString.eq(_contractName, "FaultDisputeGame") || LibString.eq(_contractName, "PermissionedDisputeGame")) { + revert UnsupportedInitializableContract(_contractName); + } + address contractAddress; // Check if the contract name ends with `Proxy` and, if so, get the implementation address if (LibString.endsWith(_contractName, "Proxy")) { diff --git a/packages/contracts-bedrock/scripts/DeployAuthSystem.s.sol b/packages/contracts-bedrock/scripts/DeployAuthSystem.s.sol new file mode 100644 index 0000000000000..0ddcbc1a7aa05 --- /dev/null +++ b/packages/contracts-bedrock/scripts/DeployAuthSystem.s.sol @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +import { Script } from "forge-std/Script.sol"; +import { CommonBase } from "forge-std/Base.sol"; +import { stdToml } from "forge-std/StdToml.sol"; + +import { GnosisSafe as Safe } from "safe-contracts/GnosisSafe.sol"; + +import { DeployUtils } from "scripts/libraries/DeployUtils.sol"; +import { Solarray } from "scripts/libraries/Solarray.sol"; + +// This file follows the pattern of Superchain.s.sol. Refer to that file for more details. +contract DeployAuthSystemInput is CommonBase { + using stdToml for string; + + // Generic safe inputs + // Note: these will need to be replaced with settings specific to the different Safes in the system. + uint256 internal _threshold; + address[] internal _owners; + + function set(bytes4 _sel, uint256 _value) public { + if (_sel == this.threshold.selector) _threshold = _value; + else revert("DeployAuthSystemInput: unknown selector"); + } + + function set(bytes4 _sel, address[] memory _addrs) public { + if (_sel == this.owners.selector) { + require(_owners.length == 0, "DeployAuthSystemInput: owners already set"); + for (uint256 i = 0; i < _addrs.length; i++) { + _owners.push(_addrs[i]); + } + } else { + revert("DeployAuthSystemInput: unknown selector"); + } + } + + function threshold() public view returns (uint256) { + require(_threshold != 0, "DeployAuthSystemInput: threshold not set"); + return _threshold; + } + + function owners() public view returns (address[] memory) { + require(_owners.length != 0, "DeployAuthSystemInput: owners not set"); + return _owners; + } +} + +contract DeployAuthSystemOutput is CommonBase { + Safe internal _safe; + + function set(bytes4 sel, address _address) public { + if (sel == this.safe.selector) _safe = Safe(payable(_address)); + else revert("DeployAuthSystemOutput: unknown selector"); + } + + function checkOutput() public view { + address[] memory addrs = Solarray.addresses(address(this.safe())); + DeployUtils.assertValidContractAddresses(addrs); + } + + function safe() public view returns (Safe) { + DeployUtils.assertValidContractAddress(address(_safe)); + return _safe; + } +} + +contract DeployAuthSystem is Script { + function run(DeployAuthSystemInput _dasi, DeployAuthSystemOutput _daso) public { + deploySafe(_dasi, _daso); + } + + function deploySafe(DeployAuthSystemInput _dasi, DeployAuthSystemOutput _daso) public { + address[] memory owners = _dasi.owners(); + uint256 threshold = _dasi.threshold(); + + // TODO: replace with a real deployment. The safe deployment logic is fairly complex, so for the purposes of + // this scaffolding PR we'll just etch the code. + address safe = makeAddr("safe"); + vm.etch(safe, type(Safe).runtimeCode); + vm.store(safe, bytes32(uint256(3)), bytes32(uint256(owners.length))); + vm.store(safe, bytes32(uint256(4)), bytes32(uint256(threshold))); + + _daso.set(_daso.safe.selector, safe); + } + + function etchIOContracts() public returns (DeployAuthSystemInput dasi_, DeployAuthSystemOutput daso_) { + (dasi_, daso_) = getIOContracts(); + vm.etch(address(dasi_), type(DeployAuthSystemInput).runtimeCode); + vm.etch(address(daso_), type(DeployAuthSystemOutput).runtimeCode); + vm.allowCheatcodes(address(dasi_)); + vm.allowCheatcodes(address(daso_)); + } + + function getIOContracts() public view returns (DeployAuthSystemInput dasi_, DeployAuthSystemOutput daso_) { + dasi_ = DeployAuthSystemInput(DeployUtils.toIOAddress(msg.sender, "optimism.DeployAuthSystemInput")); + daso_ = DeployAuthSystemOutput(DeployUtils.toIOAddress(msg.sender, "optimism.DeployAuthSystemOutput")); + } +} diff --git a/packages/contracts-bedrock/scripts/DeployImplementations.s.sol b/packages/contracts-bedrock/scripts/DeployImplementations.s.sol index 1cf2466228374..bdebf297c3f61 100644 --- a/packages/contracts-bedrock/scripts/DeployImplementations.s.sol +++ b/packages/contracts-bedrock/scripts/DeployImplementations.s.sol @@ -3,11 +3,32 @@ pragma solidity 0.8.15; import { Script } from "forge-std/Script.sol"; -import { DelayedWETH } from "src/dispute/weth/DelayedWETH.sol"; +import { LibString } from "@solady/utils/LibString.sol"; + +import { IResourceMetering } from "src/L1/interfaces/IResourceMetering.sol"; +import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol"; + +import { Constants } from "src/libraries/Constants.sol"; +import { Predeploys } from "src/libraries/Predeploys.sol"; +import { Bytes } from "src/libraries/Bytes.sol"; + +import { ProxyAdmin } from "src/universal/ProxyAdmin.sol"; +import { Proxy } from "src/universal/Proxy.sol"; +import { L1ChugSplashProxy } from "src/legacy/L1ChugSplashProxy.sol"; +import { ResolvedDelegateProxy } from "src/legacy/ResolvedDelegateProxy.sol"; +import { AddressManager } from "src/legacy/AddressManager.sol"; + +import { DelayedWETH } from "src/dispute/DelayedWETH.sol"; import { PreimageOracle } from "src/cannon/PreimageOracle.sol"; import { IPreimageOracle } from "src/cannon/interfaces/IPreimageOracle.sol"; import { MIPS } from "src/cannon/MIPS.sol"; +import { DisputeGameFactory } from "src/dispute/DisputeGameFactory.sol"; +import { AnchorStateRegistry } from "src/dispute/AnchorStateRegistry.sol"; +import { PermissionedDisputeGame } from "src/dispute/PermissionedDisputeGame.sol"; +import { SuperchainConfig } from "src/L1/SuperchainConfig.sol"; +import { ProtocolVersions } from "src/L1/ProtocolVersions.sol"; +import { OPContractsManager } from "src/L1/OPContractsManager.sol"; import { OptimismPortal2 } from "src/L1/OptimismPortal2.sol"; import { SystemConfig } from "src/L1/SystemConfig.sol"; import { L1CrossDomainMessenger } from "src/L1/L1CrossDomainMessenger.sol"; @@ -15,335 +36,1095 @@ import { L1ERC721Bridge } from "src/L1/L1ERC721Bridge.sol"; import { L1StandardBridge } from "src/L1/L1StandardBridge.sol"; import { OptimismMintableERC20Factory } from "src/universal/OptimismMintableERC20Factory.sol"; +import { OPContractsManagerInterop } from "src/L1/OPContractsManagerInterop.sol"; +import { OptimismPortalInterop } from "src/L1/OptimismPortalInterop.sol"; +import { SystemConfigInterop } from "src/L1/SystemConfigInterop.sol"; + +import { Blueprint } from "src/libraries/Blueprint.sol"; + import { DeployUtils } from "scripts/libraries/DeployUtils.sol"; import { Solarray } from "scripts/libraries/Solarray.sol"; +import { BaseDeployIO } from "scripts/utils/BaseDeployIO.sol"; // See DeploySuperchain.s.sol for detailed comments on the script architecture used here. -contract DeployImplementationsInput { - struct Input { - uint256 withdrawalDelaySeconds; - uint256 minProposalSizeBytes; - uint256 challengePeriodSeconds; - uint256 proofMaturityDelaySeconds; - uint256 disputeGameFinalityDelaySeconds; +contract DeployImplementationsInput is BaseDeployIO { + bytes32 internal _salt; + uint256 internal _withdrawalDelaySeconds; + uint256 internal _minProposalSizeBytes; + uint256 internal _challengePeriodSeconds; + uint256 internal _proofMaturityDelaySeconds; + uint256 internal _disputeGameFinalityDelaySeconds; + + // The release version to set OPCM implementations for, of the format `op-contracts/vX.Y.Z`. + string internal _release; + + // Outputs from DeploySuperchain.s.sol. + SuperchainConfig internal _superchainConfigProxy; + ProtocolVersions internal _protocolVersionsProxy; + + string internal _standardVersionsToml; + + function set(bytes4 sel, uint256 _value) public { + require(_value != 0, "DeployImplementationsInput: cannot set zero value"); + + if (sel == this.withdrawalDelaySeconds.selector) { + _withdrawalDelaySeconds = _value; + } else if (sel == this.minProposalSizeBytes.selector) { + _minProposalSizeBytes = _value; + } else if (sel == this.challengePeriodSeconds.selector) { + require(_value <= type(uint64).max, "DeployImplementationsInput: challengePeriodSeconds too large"); + _challengePeriodSeconds = _value; + } else if (sel == this.proofMaturityDelaySeconds.selector) { + _proofMaturityDelaySeconds = _value; + } else if (sel == this.disputeGameFinalityDelaySeconds.selector) { + _disputeGameFinalityDelaySeconds = _value; + } else { + revert("DeployImplementationsInput: unknown selector"); + } } - bool public inputSet = false; - Input internal inputs; - - function loadInputFile(string memory _infile) public { - _infile; - Input memory parsedInput; - loadInput(parsedInput); - require(false, "DeployImplementationsInput: not implemented"); + function set(bytes4 sel, string memory _value) public { + require(!LibString.eq(_value, ""), "DeployImplementationsInput: cannot set empty string"); + if (sel == this.release.selector) _release = _value; + else if (sel == this.standardVersionsToml.selector) _standardVersionsToml = _value; + else revert("DeployImplementationsInput: unknown selector"); } - function loadInput(Input memory _input) public { - require(!inputSet, "DeployImplementationsInput: input already set"); - require( - _input.challengePeriodSeconds <= type(uint64).max, "DeployImplementationsInput: challenge period too large" - ); - - inputSet = true; - inputs = _input; + function set(bytes4 sel, address _addr) public { + require(_addr != address(0), "DeployImplementationsInput: cannot set zero address"); + if (sel == this.superchainConfigProxy.selector) _superchainConfigProxy = SuperchainConfig(_addr); + else if (sel == this.protocolVersionsProxy.selector) _protocolVersionsProxy = ProtocolVersions(_addr); + else revert("DeployImplementationsInput: unknown selector"); } - function assertInputSet() internal view { - require(inputSet, "DeployImplementationsInput: input not set"); + function set(bytes4 sel, bytes32 _value) public { + if (sel == this.salt.selector) _salt = _value; + else revert("DeployImplementationsInput: unknown selector"); } - function input() public view returns (Input memory) { - assertInputSet(); - return inputs; + function salt() public view returns (bytes32) { + // TODO check if implementations are deployed based on code+salt and skip deploy if so. + return _salt; } function withdrawalDelaySeconds() public view returns (uint256) { - assertInputSet(); - return inputs.withdrawalDelaySeconds; + require(_withdrawalDelaySeconds != 0, "DeployImplementationsInput: not set"); + return _withdrawalDelaySeconds; } function minProposalSizeBytes() public view returns (uint256) { - assertInputSet(); - return inputs.minProposalSizeBytes; + require(_minProposalSizeBytes != 0, "DeployImplementationsInput: not set"); + return _minProposalSizeBytes; } function challengePeriodSeconds() public view returns (uint256) { - assertInputSet(); - return inputs.challengePeriodSeconds; + require(_challengePeriodSeconds != 0, "DeployImplementationsInput: not set"); + require( + _challengePeriodSeconds <= type(uint64).max, "DeployImplementationsInput: challengePeriodSeconds too large" + ); + return _challengePeriodSeconds; } function proofMaturityDelaySeconds() public view returns (uint256) { - assertInputSet(); - return inputs.proofMaturityDelaySeconds; + require(_proofMaturityDelaySeconds != 0, "DeployImplementationsInput: not set"); + return _proofMaturityDelaySeconds; } function disputeGameFinalityDelaySeconds() public view returns (uint256) { - assertInputSet(); - return inputs.disputeGameFinalityDelaySeconds; + require(_disputeGameFinalityDelaySeconds != 0, "DeployImplementationsInput: not set"); + return _disputeGameFinalityDelaySeconds; + } + + function release() public view returns (string memory) { + require(!LibString.eq(_release, ""), "DeployImplementationsInput: not set"); + return _release; + } + + function standardVersionsToml() public view returns (string memory) { + require(!LibString.eq(_standardVersionsToml, ""), "DeployImplementationsInput: not set"); + return _standardVersionsToml; } -} -contract DeployImplementationsOutput { - struct Output { - DelayedWETH delayedWETHImpl; - OptimismPortal2 optimismPortal2Impl; - PreimageOracle preimageOracleSingleton; - MIPS mipsSingleton; - SystemConfig systemConfigImpl; - L1CrossDomainMessenger l1CrossDomainMessengerImpl; - L1ERC721Bridge l1ERC721BridgeImpl; - L1StandardBridge l1StandardBridgeImpl; - OptimismMintableERC20Factory optimismMintableERC20FactoryImpl; + function superchainConfigProxy() public view returns (SuperchainConfig) { + require(address(_superchainConfigProxy) != address(0), "DeployImplementationsInput: not set"); + return _superchainConfigProxy; } - Output internal outputs; + function protocolVersionsProxy() public view returns (ProtocolVersions) { + require(address(_protocolVersionsProxy) != address(0), "DeployImplementationsInput: not set"); + return _protocolVersionsProxy; + } + + function superchainProxyAdmin() public returns (ProxyAdmin) { + SuperchainConfig proxy = this.superchainConfigProxy(); + // Can infer the superchainProxyAdmin from the superchainConfigProxy. + vm.prank(address(0)); + ProxyAdmin proxyAdmin = ProxyAdmin(Proxy(payable(address(proxy))).admin()); + require(address(proxyAdmin) != address(0), "DeployImplementationsInput: not set"); + return proxyAdmin; + } +} + +contract DeployImplementationsOutput is BaseDeployIO { + OPContractsManager internal _opcmProxy; + OPContractsManager internal _opcmImpl; + DelayedWETH internal _delayedWETHImpl; + OptimismPortal2 internal _optimismPortalImpl; + PreimageOracle internal _preimageOracleSingleton; + MIPS internal _mipsSingleton; + SystemConfig internal _systemConfigImpl; + L1CrossDomainMessenger internal _l1CrossDomainMessengerImpl; + L1ERC721Bridge internal _l1ERC721BridgeImpl; + L1StandardBridge internal _l1StandardBridgeImpl; + OptimismMintableERC20Factory internal _optimismMintableERC20FactoryImpl; + DisputeGameFactory internal _disputeGameFactoryImpl; function set(bytes4 sel, address _addr) public { + require(_addr != address(0), "DeployImplementationsOutput: cannot set zero address"); + // forgefmt: disable-start - if (sel == this.optimismPortal2Impl.selector) outputs.optimismPortal2Impl = OptimismPortal2(payable(_addr)); - else if (sel == this.delayedWETHImpl.selector) outputs.delayedWETHImpl = DelayedWETH(payable(_addr)); - else if (sel == this.preimageOracleSingleton.selector) outputs.preimageOracleSingleton = PreimageOracle(_addr); - else if (sel == this.mipsSingleton.selector) outputs.mipsSingleton = MIPS(_addr); - else if (sel == this.systemConfigImpl.selector) outputs.systemConfigImpl = SystemConfig(_addr); - else if (sel == this.l1CrossDomainMessengerImpl.selector) outputs.l1CrossDomainMessengerImpl = L1CrossDomainMessenger(_addr); - else if (sel == this.l1ERC721BridgeImpl.selector) outputs.l1ERC721BridgeImpl = L1ERC721Bridge(_addr); - else if (sel == this.l1StandardBridgeImpl.selector) outputs.l1StandardBridgeImpl = L1StandardBridge(payable(_addr)); - else if (sel == this.optimismMintableERC20FactoryImpl.selector) outputs.optimismMintableERC20FactoryImpl = OptimismMintableERC20Factory(_addr); + if (sel == this.opcmProxy.selector) _opcmProxy = OPContractsManager(payable(_addr)); + else if (sel == this.opcmImpl.selector) _opcmImpl = OPContractsManager(payable(_addr)); + else if (sel == this.optimismPortalImpl.selector) _optimismPortalImpl = OptimismPortal2(payable(_addr)); + else if (sel == this.delayedWETHImpl.selector) _delayedWETHImpl = DelayedWETH(payable(_addr)); + else if (sel == this.preimageOracleSingleton.selector) _preimageOracleSingleton = PreimageOracle(_addr); + else if (sel == this.mipsSingleton.selector) _mipsSingleton = MIPS(_addr); + else if (sel == this.systemConfigImpl.selector) _systemConfigImpl = SystemConfig(_addr); + else if (sel == this.l1CrossDomainMessengerImpl.selector) _l1CrossDomainMessengerImpl = L1CrossDomainMessenger(_addr); + else if (sel == this.l1ERC721BridgeImpl.selector) _l1ERC721BridgeImpl = L1ERC721Bridge(_addr); + else if (sel == this.l1StandardBridgeImpl.selector) _l1StandardBridgeImpl = L1StandardBridge(payable(_addr)); + else if (sel == this.optimismMintableERC20FactoryImpl.selector) _optimismMintableERC20FactoryImpl = OptimismMintableERC20Factory(_addr); + else if (sel == this.disputeGameFactoryImpl.selector) _disputeGameFactoryImpl = DisputeGameFactory(_addr); else revert("DeployImplementationsOutput: unknown selector"); // forgefmt: disable-end } - function writeOutputFile(string memory _outfile) public pure { - _outfile; - require(false, "DeployImplementationsOutput: not implemented"); + function checkOutput(DeployImplementationsInput _dii) public { + // With 12 addresses, we'd get a stack too deep error if we tried to do this inline as a + // single call to `Solarray.addresses`. So we split it into two calls. + address[] memory addrs1 = Solarray.addresses( + address(this.opcmProxy()), + address(this.opcmImpl()), + address(this.optimismPortalImpl()), + address(this.delayedWETHImpl()), + address(this.preimageOracleSingleton()), + address(this.mipsSingleton()) + ); + + address[] memory addrs2 = Solarray.addresses( + address(this.systemConfigImpl()), + address(this.l1CrossDomainMessengerImpl()), + address(this.l1ERC721BridgeImpl()), + address(this.l1StandardBridgeImpl()), + address(this.optimismMintableERC20FactoryImpl()), + address(this.disputeGameFactoryImpl()) + ); + + DeployUtils.assertValidContractAddresses(Solarray.extend(addrs1, addrs2)); + + assertValidDeploy(_dii); } - function output() public view returns (Output memory) { - return outputs; + function opcmProxy() public returns (OPContractsManager) { + DeployUtils.assertValidContractAddress(address(_opcmProxy)); + DeployUtils.assertImplementationSet(address(_opcmProxy)); + return _opcmProxy; } - function checkOutput() public view { - address[] memory addrs = Solarray.addresses( - address(outputs.optimismPortal2Impl), - address(outputs.delayedWETHImpl), - address(outputs.preimageOracleSingleton), - address(outputs.mipsSingleton), - address(outputs.systemConfigImpl), - address(outputs.l1CrossDomainMessengerImpl), - address(outputs.l1ERC721BridgeImpl), - address(outputs.l1StandardBridgeImpl), - address(outputs.optimismMintableERC20FactoryImpl) - ); - DeployUtils.assertValidContractAddresses(addrs); + function opcmImpl() public view returns (OPContractsManager) { + DeployUtils.assertValidContractAddress(address(_opcmImpl)); + return _opcmImpl; } - function optimismPortal2Impl() public view returns (OptimismPortal2) { - DeployUtils.assertValidContractAddress(address(outputs.optimismPortal2Impl)); - return outputs.optimismPortal2Impl; + function optimismPortalImpl() public view returns (OptimismPortal2) { + DeployUtils.assertValidContractAddress(address(_optimismPortalImpl)); + return _optimismPortalImpl; } function delayedWETHImpl() public view returns (DelayedWETH) { - DeployUtils.assertValidContractAddress(address(outputs.delayedWETHImpl)); - return outputs.delayedWETHImpl; + DeployUtils.assertValidContractAddress(address(_delayedWETHImpl)); + return _delayedWETHImpl; } function preimageOracleSingleton() public view returns (PreimageOracle) { - DeployUtils.assertValidContractAddress(address(outputs.preimageOracleSingleton)); - return outputs.preimageOracleSingleton; + DeployUtils.assertValidContractAddress(address(_preimageOracleSingleton)); + return _preimageOracleSingleton; } function mipsSingleton() public view returns (MIPS) { - DeployUtils.assertValidContractAddress(address(outputs.mipsSingleton)); - return outputs.mipsSingleton; + DeployUtils.assertValidContractAddress(address(_mipsSingleton)); + return _mipsSingleton; } function systemConfigImpl() public view returns (SystemConfig) { - DeployUtils.assertValidContractAddress(address(outputs.systemConfigImpl)); - return outputs.systemConfigImpl; + DeployUtils.assertValidContractAddress(address(_systemConfigImpl)); + return _systemConfigImpl; } function l1CrossDomainMessengerImpl() public view returns (L1CrossDomainMessenger) { - DeployUtils.assertValidContractAddress(address(outputs.l1CrossDomainMessengerImpl)); - return outputs.l1CrossDomainMessengerImpl; + DeployUtils.assertValidContractAddress(address(_l1CrossDomainMessengerImpl)); + return _l1CrossDomainMessengerImpl; } function l1ERC721BridgeImpl() public view returns (L1ERC721Bridge) { - DeployUtils.assertValidContractAddress(address(outputs.l1ERC721BridgeImpl)); - return outputs.l1ERC721BridgeImpl; + DeployUtils.assertValidContractAddress(address(_l1ERC721BridgeImpl)); + return _l1ERC721BridgeImpl; } function l1StandardBridgeImpl() public view returns (L1StandardBridge) { - DeployUtils.assertValidContractAddress(address(outputs.l1StandardBridgeImpl)); - return outputs.l1StandardBridgeImpl; + DeployUtils.assertValidContractAddress(address(_l1StandardBridgeImpl)); + return _l1StandardBridgeImpl; } function optimismMintableERC20FactoryImpl() public view returns (OptimismMintableERC20Factory) { - DeployUtils.assertValidContractAddress(address(outputs.optimismMintableERC20FactoryImpl)); - return outputs.optimismMintableERC20FactoryImpl; + DeployUtils.assertValidContractAddress(address(_optimismMintableERC20FactoryImpl)); + return _optimismMintableERC20FactoryImpl; + } + + function disputeGameFactoryImpl() public view returns (DisputeGameFactory) { + DeployUtils.assertValidContractAddress(address(_disputeGameFactoryImpl)); + return _disputeGameFactoryImpl; + } + + // -------- Deployment Assertions -------- + function assertValidDeploy(DeployImplementationsInput _dii) public { + assertValidDelayedWETHImpl(_dii); + assertValidDisputeGameFactoryImpl(_dii); + assertValidL1CrossDomainMessengerImpl(_dii); + assertValidL1ERC721BridgeImpl(_dii); + assertValidL1StandardBridgeImpl(_dii); + assertValidMipsSingleton(_dii); + assertValidOpcmProxy(_dii); + assertValidOpcmImpl(_dii); + assertValidOptimismMintableERC20FactoryImpl(_dii); + assertValidOptimismPortalImpl(_dii); + assertValidPreimageOracleSingleton(_dii); + assertValidSystemConfigImpl(_dii); + } + + function assertValidOpcmProxy(DeployImplementationsInput _dii) internal { + // First we check the proxy as itself. + Proxy proxy = Proxy(payable(address(opcmProxy()))); + vm.prank(address(0)); + address admin = proxy.admin(); + require(admin == address(_dii.superchainProxyAdmin()), "OPCMP-10"); + + // Then we check the proxy as OPCM. + DeployUtils.assertInitialized({ _contractAddress: address(opcmProxy()), _slot: 0, _offset: 0 }); + require(address(opcmProxy().superchainConfig()) == address(_dii.superchainConfigProxy()), "OPCMP-20"); + require(address(opcmProxy().protocolVersions()) == address(_dii.protocolVersionsProxy()), "OPCMP-30"); + require(LibString.eq(opcmProxy().latestRelease(), _dii.release()), "OPCMP-50"); // Initial release is latest. + } + + function assertValidOpcmImpl(DeployImplementationsInput _dii) internal { + Proxy proxy = Proxy(payable(address(opcmProxy()))); + vm.prank(address(0)); + OPContractsManager impl = OPContractsManager(proxy.implementation()); + DeployUtils.assertInitialized({ _contractAddress: address(impl), _slot: 0, _offset: 0 }); + require(address(impl.superchainConfig()) == address(_dii.superchainConfigProxy()), "OPCMI-10"); + require(address(impl.protocolVersions()) == address(_dii.protocolVersionsProxy()), "OPCMI-20"); + } + + function assertValidOptimismPortalImpl(DeployImplementationsInput) internal view { + OptimismPortal2 portal = optimismPortalImpl(); + + DeployUtils.assertInitialized({ _contractAddress: address(portal), _slot: 0, _offset: 0 }); + + require(address(portal.disputeGameFactory()) == address(0), "PORTAL-10"); + require(address(portal.systemConfig()) == address(0), "PORTAL-20"); + require(address(portal.superchainConfig()) == address(0), "PORTAL-30"); + require(portal.l2Sender() == Constants.DEFAULT_L2_SENDER, "PORTAL-40"); + + // This slot is the custom gas token _balance and this check ensures + // that it stays unset for forwards compatibility with custom gas token. + require(vm.load(address(portal), bytes32(uint256(61))) == bytes32(0), "PORTAL-50"); + } + + function assertValidDelayedWETHImpl(DeployImplementationsInput _dii) internal view { + DelayedWETH delayedWETH = delayedWETHImpl(); + + DeployUtils.assertInitialized({ _contractAddress: address(delayedWETH), _slot: 0, _offset: 0 }); + + require(delayedWETH.owner() == address(0), "DW-10"); + require(delayedWETH.delay() == _dii.withdrawalDelaySeconds(), "DW-20"); + require(delayedWETH.config() == ISuperchainConfig(address(0)), "DW-30"); + } + + function assertValidPreimageOracleSingleton(DeployImplementationsInput _dii) internal view { + PreimageOracle oracle = preimageOracleSingleton(); + + require(oracle.minProposalSize() == _dii.minProposalSizeBytes(), "PO-10"); + require(oracle.challengePeriod() == _dii.challengePeriodSeconds(), "PO-20"); + } + + function assertValidMipsSingleton(DeployImplementationsInput) internal view { + MIPS mips = mipsSingleton(); + + require(address(mips.oracle()) == address(preimageOracleSingleton()), "MIPS-10"); + } + + function assertValidSystemConfigImpl(DeployImplementationsInput) internal view { + SystemConfig systemConfig = systemConfigImpl(); + + DeployUtils.assertInitialized({ _contractAddress: address(systemConfig), _slot: 0, _offset: 0 }); + + require(systemConfig.owner() == address(0xdead), "SYSCON-10"); + require(systemConfig.overhead() == 0, "SYSCON-20"); + require(systemConfig.scalar() == uint256(0x01) << 248, "SYSCON-30"); + require(systemConfig.basefeeScalar() == 0, "SYSCON-40"); + require(systemConfig.blobbasefeeScalar() == 0, "SYSCON-50"); + require(systemConfig.batcherHash() == bytes32(0), "SYSCON-60"); + require(systemConfig.gasLimit() == 1, "SYSCON-70"); + require(systemConfig.unsafeBlockSigner() == address(0), "SYSCON-80"); + + IResourceMetering.ResourceConfig memory resourceConfig = systemConfig.resourceConfig(); + require(resourceConfig.maxResourceLimit == 1, "SYSCON-90"); + require(resourceConfig.elasticityMultiplier == 1, "SYSCON-100"); + require(resourceConfig.baseFeeMaxChangeDenominator == 2, "SYSCON-110"); + require(resourceConfig.systemTxMaxGas == 0, "SYSCON-120"); + require(resourceConfig.minimumBaseFee == 0, "SYSCON-130"); + require(resourceConfig.maximumBaseFee == 0, "SYSCON-140"); + + require(systemConfig.startBlock() == type(uint256).max, "SYSCON-150"); + require(systemConfig.batchInbox() == address(0), "SYSCON-160"); + require(systemConfig.l1CrossDomainMessenger() == address(0), "SYSCON-170"); + require(systemConfig.l1ERC721Bridge() == address(0), "SYSCON-180"); + require(systemConfig.l1StandardBridge() == address(0), "SYSCON-190"); + require(systemConfig.disputeGameFactory() == address(0), "SYSCON-200"); + require(systemConfig.optimismPortal() == address(0), "SYSCON-210"); + require(systemConfig.optimismMintableERC20Factory() == address(0), "SYSCON-220"); + } + + function assertValidL1CrossDomainMessengerImpl(DeployImplementationsInput) internal view { + L1CrossDomainMessenger messenger = l1CrossDomainMessengerImpl(); + + DeployUtils.assertInitialized({ _contractAddress: address(messenger), _slot: 0, _offset: 20 }); + + require(address(messenger.OTHER_MESSENGER()) == Predeploys.L2_CROSS_DOMAIN_MESSENGER, "L1xDM-10"); + require(address(messenger.otherMessenger()) == Predeploys.L2_CROSS_DOMAIN_MESSENGER, "L1xDM-20"); + require(address(messenger.PORTAL()) == address(0), "L1xDM-30"); + require(address(messenger.portal()) == address(0), "L1xDM-40"); + require(address(messenger.superchainConfig()) == address(0), "L1xDM-50"); + + bytes32 xdmSenderSlot = vm.load(address(messenger), bytes32(uint256(204))); + require(address(uint160(uint256(xdmSenderSlot))) == Constants.DEFAULT_L2_SENDER, "L1xDM-60"); + } + + function assertValidL1ERC721BridgeImpl(DeployImplementationsInput) internal view { + L1ERC721Bridge bridge = l1ERC721BridgeImpl(); + + DeployUtils.assertInitialized({ _contractAddress: address(bridge), _slot: 0, _offset: 0 }); + + require(address(bridge.OTHER_BRIDGE()) == Predeploys.L2_ERC721_BRIDGE, "L721B-10"); + require(address(bridge.otherBridge()) == Predeploys.L2_ERC721_BRIDGE, "L721B-20"); + require(address(bridge.MESSENGER()) == address(0), "L721B-30"); + require(address(bridge.messenger()) == address(0), "L721B-40"); + require(address(bridge.superchainConfig()) == address(0), "L721B-50"); + } + + function assertValidL1StandardBridgeImpl(DeployImplementationsInput) internal view { + L1StandardBridge bridge = l1StandardBridgeImpl(); + + DeployUtils.assertInitialized({ _contractAddress: address(bridge), _slot: 0, _offset: 0 }); + + require(address(bridge.MESSENGER()) == address(0), "L1SB-10"); + require(address(bridge.messenger()) == address(0), "L1SB-20"); + require(address(bridge.OTHER_BRIDGE()) == Predeploys.L2_STANDARD_BRIDGE, "L1SB-30"); + require(address(bridge.otherBridge()) == Predeploys.L2_STANDARD_BRIDGE, "L1SB-40"); + require(address(bridge.superchainConfig()) == address(0), "L1SB-50"); + } + + function assertValidOptimismMintableERC20FactoryImpl(DeployImplementationsInput) internal view { + OptimismMintableERC20Factory factory = optimismMintableERC20FactoryImpl(); + + DeployUtils.assertInitialized({ _contractAddress: address(factory), _slot: 0, _offset: 0 }); + + require(address(factory.BRIDGE()) == address(0), "MERC20F-10"); + require(address(factory.bridge()) == address(0), "MERC20F-20"); + } + + function assertValidDisputeGameFactoryImpl(DeployImplementationsInput) internal view { + DisputeGameFactory factory = disputeGameFactoryImpl(); + + DeployUtils.assertInitialized({ _contractAddress: address(factory), _slot: 0, _offset: 0 }); + + require(address(factory.owner()) == address(0), "DG-10"); } } contract DeployImplementations is Script { // -------- Core Deployment Methods -------- - function run(string memory _infile) public { - (DeployImplementationsInput dsi, DeployImplementationsOutput dso) = etchIOContracts(); - dsi.loadInputFile(_infile); - run(dsi, dso); - string memory outfile = ""; // This will be derived from input file name, e.g. `foo.in.toml` -> `foo.out.toml` - dso.writeOutputFile(outfile); - require(false, "DeployImplementations: run is not implemented"); + function run(DeployImplementationsInput _dii, DeployImplementationsOutput _dio) public { + // Deploy the implementations. + deploySystemConfigImpl(_dii, _dio); + deployL1CrossDomainMessengerImpl(_dii, _dio); + deployL1ERC721BridgeImpl(_dii, _dio); + deployL1StandardBridgeImpl(_dii, _dio); + deployOptimismMintableERC20FactoryImpl(_dii, _dio); + deployOptimismPortalImpl(_dii, _dio); + deployDelayedWETHImpl(_dii, _dio); + deployPreimageOracleSingleton(_dii, _dio); + deployMipsSingleton(_dii, _dio); + deployDisputeGameFactoryImpl(_dii, _dio); + + // Deploy the OP Contracts Manager with the new implementations set. + deployOPContractsManager(_dii, _dio); + + _dio.checkOutput(_dii); } - function run(DeployImplementationsInput.Input memory _input) - public - returns (DeployImplementationsOutput.Output memory) + // -------- Deployment Steps -------- + + // --- OP Contracts Manager --- + + function opcmSystemConfigSetter( + DeployImplementationsInput, + DeployImplementationsOutput _dio + ) + internal + view + virtual + returns (OPContractsManager.ImplementationSetter memory) { - (DeployImplementationsInput dsi, DeployImplementationsOutput dso) = etchIOContracts(); - dsi.loadInput(_input); - run(dsi, dso); - return dso.output(); + return OPContractsManager.ImplementationSetter({ + name: "SystemConfig", + info: OPContractsManager.Implementation(address(_dio.systemConfigImpl()), SystemConfig.initialize.selector) + }); } - function run(DeployImplementationsInput _dsi, DeployImplementationsOutput _dso) public { - require(_dsi.inputSet(), "DeployImplementations: input not set"); + // Deploy and initialize a proxied OPContractsManager. + function createOPCMContract( + DeployImplementationsInput _dii, + DeployImplementationsOutput _dio, + OPContractsManager.Blueprints memory _blueprints, + string memory _release, + OPContractsManager.ImplementationSetter[] memory _setters + ) + internal + virtual + returns (OPContractsManager opcmProxy_) + { + ProxyAdmin proxyAdmin = _dii.superchainProxyAdmin(); - deploySystemConfigImpl(_dsi, _dso); - deployL1CrossDomainMessengerImpl(_dsi, _dso); - deployL1ERC721BridgeImpl(_dsi, _dso); - deployL1StandardBridgeImpl(_dsi, _dso); - deployOptimismMintableERC20FactoryImpl(_dsi, _dso); - deployOptimismPortalImpl(_dsi, _dso); - deployDelayedWETHImpl(_dsi, _dso); - deployPreimageOracleSingleton(_dsi, _dso); - deployMipsSingleton(_dsi, _dso); + vm.broadcast(msg.sender); + Proxy proxy = new Proxy(address(msg.sender)); - _dso.checkOutput(); - } + deployOPContractsManagerImpl(_dii, _dio); + OPContractsManager opcmImpl = _dio.opcmImpl(); - // -------- Deployment Steps -------- + OPContractsManager.InitializerInputs memory initializerInputs = + OPContractsManager.InitializerInputs(_blueprints, _setters, _release, true); - function deploySystemConfigImpl(DeployImplementationsInput, DeployImplementationsOutput _dso) public { - vm.broadcast(msg.sender); - SystemConfig systemConfigImpl = new SystemConfig(); + vm.startBroadcast(msg.sender); + proxy.upgradeToAndCall( + address(opcmImpl), abi.encodeWithSelector(opcmImpl.initialize.selector, initializerInputs) + ); - vm.label(address(systemConfigImpl), "systemConfigImpl"); - _dso.set(_dso.systemConfigImpl.selector, address(systemConfigImpl)); + proxy.changeAdmin(address(proxyAdmin)); // transfer ownership of Proxy contract to the ProxyAdmin contract + vm.stopBroadcast(); + + opcmProxy_ = OPContractsManager(address(proxy)); } - function deployL1CrossDomainMessengerImpl(DeployImplementationsInput, DeployImplementationsOutput _dso) public { - vm.broadcast(msg.sender); - L1CrossDomainMessenger l1CrossDomainMessengerImpl = new L1CrossDomainMessenger(); + function deployOPContractsManager( + DeployImplementationsInput _dii, + DeployImplementationsOutput _dio + ) + public + virtual + { + string memory release = _dii.release(); - vm.label(address(l1CrossDomainMessengerImpl), "L1CrossDomainMessengerImpl"); - _dso.set(_dso.l1CrossDomainMessengerImpl.selector, address(l1CrossDomainMessengerImpl)); + // First we deploy the blueprints for the singletons deployed by OPCM. + // forgefmt: disable-start + bytes32 salt = _dii.salt(); + OPContractsManager.Blueprints memory blueprints; + + vm.startBroadcast(msg.sender); + blueprints.addressManager = deployBytecode(Blueprint.blueprintDeployerBytecode(type(AddressManager).creationCode), salt); + blueprints.proxy = deployBytecode(Blueprint.blueprintDeployerBytecode(type(Proxy).creationCode), salt); + blueprints.proxyAdmin = deployBytecode(Blueprint.blueprintDeployerBytecode(type(ProxyAdmin).creationCode), salt); + blueprints.l1ChugSplashProxy = deployBytecode(Blueprint.blueprintDeployerBytecode(type(L1ChugSplashProxy).creationCode), salt); + blueprints.resolvedDelegateProxy = deployBytecode(Blueprint.blueprintDeployerBytecode(type(ResolvedDelegateProxy).creationCode), salt); + blueprints.anchorStateRegistry = deployBytecode(Blueprint.blueprintDeployerBytecode(type(AnchorStateRegistry).creationCode), salt); + (blueprints.permissionedDisputeGame1, blueprints.permissionedDisputeGame2) = deployBigBytecode(type(PermissionedDisputeGame).creationCode, salt); + vm.stopBroadcast(); + // forgefmt: disable-end + + OPContractsManager.ImplementationSetter[] memory setters = new OPContractsManager.ImplementationSetter[](9); + setters[0] = OPContractsManager.ImplementationSetter({ + name: "L1ERC721Bridge", + info: OPContractsManager.Implementation(address(_dio.l1ERC721BridgeImpl()), L1ERC721Bridge.initialize.selector) + }); + setters[1] = OPContractsManager.ImplementationSetter({ + name: "OptimismPortal", + info: OPContractsManager.Implementation(address(_dio.optimismPortalImpl()), OptimismPortal2.initialize.selector) + }); + setters[2] = opcmSystemConfigSetter(_dii, _dio); + setters[3] = OPContractsManager.ImplementationSetter({ + name: "OptimismMintableERC20Factory", + info: OPContractsManager.Implementation( + address(_dio.optimismMintableERC20FactoryImpl()), OptimismMintableERC20Factory.initialize.selector + ) + }); + setters[4] = OPContractsManager.ImplementationSetter({ + name: "L1CrossDomainMessenger", + info: OPContractsManager.Implementation( + address(_dio.l1CrossDomainMessengerImpl()), L1CrossDomainMessenger.initialize.selector + ) + }); + setters[5] = OPContractsManager.ImplementationSetter({ + name: "L1StandardBridge", + info: OPContractsManager.Implementation( + address(_dio.l1StandardBridgeImpl()), L1StandardBridge.initialize.selector + ) + }); + setters[6] = OPContractsManager.ImplementationSetter({ + name: "DisputeGameFactory", + info: OPContractsManager.Implementation( + address(_dio.disputeGameFactoryImpl()), DisputeGameFactory.initialize.selector + ) + }); + setters[7] = OPContractsManager.ImplementationSetter({ + name: "DelayedWETH", + info: OPContractsManager.Implementation(address(_dio.delayedWETHImpl()), DelayedWETH.initialize.selector) + }); + setters[8] = OPContractsManager.ImplementationSetter({ + name: "MIPS", + // MIPS is a singleton for all chains, so it doesn't need to be initialized, so the + // selector is just `bytes4(0)`. + info: OPContractsManager.Implementation(address(_dio.mipsSingleton()), bytes4(0)) + }); + + // This call contains a broadcast to deploy OPCM which is proxied. + OPContractsManager opcmProxy = createOPCMContract(_dii, _dio, blueprints, release, setters); + + vm.label(address(opcmProxy), "OPContractsManager"); + _dio.set(_dio.opcmProxy.selector, address(opcmProxy)); } - function deployL1ERC721BridgeImpl(DeployImplementationsInput, DeployImplementationsOutput _dso) public { - vm.broadcast(msg.sender); - L1ERC721Bridge l1ERC721BridgeImpl = new L1ERC721Bridge(); + // --- Core Contracts --- + + function deploySystemConfigImpl(DeployImplementationsInput _dii, DeployImplementationsOutput _dio) public virtual { + string memory release = _dii.release(); + string memory stdVerToml = _dii.standardVersionsToml(); + // Using snake case for contract name to match the TOML file in superchain-registry. + string memory contractName = "system_config"; + SystemConfig impl; + + address existingImplementation = getReleaseAddress(release, contractName, stdVerToml); + if (existingImplementation != address(0)) { + impl = SystemConfig(existingImplementation); + } else if (isDevelopRelease(release)) { + // Deploy a new implementation for development builds. + vm.broadcast(msg.sender); + impl = new SystemConfig(); + } else { + revert(string.concat("DeployImplementations: failed to deploy release ", release)); + } + + vm.label(address(impl), "SystemConfigImpl"); + _dio.set(_dio.systemConfigImpl.selector, address(impl)); + } - vm.label(address(l1ERC721BridgeImpl), "L1ERC721BridgeImpl"); - _dso.set(_dso.l1ERC721BridgeImpl.selector, address(l1ERC721BridgeImpl)); + function deployL1CrossDomainMessengerImpl( + DeployImplementationsInput _dii, + DeployImplementationsOutput _dio + ) + public + virtual + { + string memory release = _dii.release(); + string memory stdVerToml = _dii.standardVersionsToml(); + string memory contractName = "l1_cross_domain_messenger"; + L1CrossDomainMessenger impl; + + address existingImplementation = getReleaseAddress(release, contractName, stdVerToml); + if (existingImplementation != address(0)) { + impl = L1CrossDomainMessenger(existingImplementation); + } else if (isDevelopRelease(release)) { + vm.broadcast(msg.sender); + impl = new L1CrossDomainMessenger(); + } else { + revert(string.concat("DeployImplementations: failed to deploy release ", release)); + } + + vm.label(address(impl), "L1CrossDomainMessengerImpl"); + _dio.set(_dio.l1CrossDomainMessengerImpl.selector, address(impl)); } - function deployL1StandardBridgeImpl(DeployImplementationsInput, DeployImplementationsOutput _dso) public { - vm.broadcast(msg.sender); - L1StandardBridge l1StandardBridgeImpl = new L1StandardBridge(); + function deployL1ERC721BridgeImpl( + DeployImplementationsInput _dii, + DeployImplementationsOutput _dio + ) + public + virtual + { + string memory release = _dii.release(); + string memory stdVerToml = _dii.standardVersionsToml(); + string memory contractName = "l1_erc721_bridge"; + L1ERC721Bridge impl; + + address existingImplementation = getReleaseAddress(release, contractName, stdVerToml); + if (existingImplementation != address(0)) { + impl = L1ERC721Bridge(existingImplementation); + } else if (isDevelopRelease(release)) { + vm.broadcast(msg.sender); + impl = new L1ERC721Bridge(); + } else { + revert(string.concat("DeployImplementations: failed to deploy release ", release)); + } + + vm.label(address(impl), "L1ERC721BridgeImpl"); + _dio.set(_dio.l1ERC721BridgeImpl.selector, address(impl)); + } - vm.label(address(l1StandardBridgeImpl), "L1StandardBridgeImpl"); - _dso.set(_dso.l1StandardBridgeImpl.selector, address(l1StandardBridgeImpl)); + function deployL1StandardBridgeImpl( + DeployImplementationsInput _dii, + DeployImplementationsOutput _dio + ) + public + virtual + { + string memory release = _dii.release(); + string memory stdVerToml = _dii.standardVersionsToml(); + string memory contractName = "l1_standard_bridge"; + L1StandardBridge impl; + + address existingImplementation = getReleaseAddress(release, contractName, stdVerToml); + if (existingImplementation != address(0)) { + impl = L1StandardBridge(payable(existingImplementation)); + } else if (isDevelopRelease(release)) { + vm.broadcast(msg.sender); + impl = new L1StandardBridge(); + } else { + revert(string.concat("DeployImplementations: failed to deploy release ", release)); + } + + vm.label(address(impl), "L1StandardBridgeImpl"); + _dio.set(_dio.l1StandardBridgeImpl.selector, address(impl)); } function deployOptimismMintableERC20FactoryImpl( - DeployImplementationsInput, - DeployImplementationsOutput _dso + DeployImplementationsInput _dii, + DeployImplementationsOutput _dio + ) + public + virtual + { + string memory release = _dii.release(); + string memory stdVerToml = _dii.standardVersionsToml(); + string memory contractName = "optimism_mintable_erc20_factory"; + OptimismMintableERC20Factory impl; + + address existingImplementation = getReleaseAddress(release, contractName, stdVerToml); + if (existingImplementation != address(0)) { + impl = OptimismMintableERC20Factory(existingImplementation); + } else if (isDevelopRelease(release)) { + vm.broadcast(msg.sender); + impl = new OptimismMintableERC20Factory(); + } else { + revert(string.concat("DeployImplementations: failed to deploy release ", release)); + } + + vm.label(address(impl), "OptimismMintableERC20FactoryImpl"); + _dio.set(_dio.optimismMintableERC20FactoryImpl.selector, address(impl)); + } + + function deployOPContractsManagerImpl( + DeployImplementationsInput _dii, + DeployImplementationsOutput _dio ) public + virtual { + SuperchainConfig superchainConfigProxy = _dii.superchainConfigProxy(); + ProtocolVersions protocolVersionsProxy = _dii.protocolVersionsProxy(); + vm.broadcast(msg.sender); - OptimismMintableERC20Factory optimismMintableERC20FactoryImpl = new OptimismMintableERC20Factory(); + // TODO: Eventually we will want to select the correct implementation based on the release. + OPContractsManager impl = new OPContractsManager(superchainConfigProxy, protocolVersionsProxy); - vm.label(address(optimismMintableERC20FactoryImpl), "OptimismMintableERC20FactoryImpl"); - _dso.set(_dso.optimismMintableERC20FactoryImpl.selector, address(optimismMintableERC20FactoryImpl)); + vm.label(address(impl), "OPContractsManagerImpl"); + _dio.set(_dio.opcmImpl.selector, address(impl)); } + // --- Fault Proofs Contracts --- + // The fault proofs contracts are configured as follows: - // - DisputeGameFactory: Proxied, bespoke per chain. - // - AnchorStateRegistry: Proxied, bespoke per chain. - // - FaultDisputeGame: Not proxied, bespoke per chain. - // - PermissionedDisputeGame: Not proxied, bespoke per chain. - // - DelayedWETH: Proxied, and two bespoke ones per chain (one for each DisputeGame). - // - PreimageOracle: Not proxied, shared by all standard chains. - // - MIPS: Not proxied, shared by all standard chains. - // - OptimismPortal2: Proxied, shared by all standard chains. + // | Contract | Proxied | Deployment | MCP Ready | + // |-------------------------|---------|-----------------------------------|------------| + // | DisputeGameFactory | Yes | Bespoke | Yes | + // | AnchorStateRegistry | Yes | Bespoke | No | + // | FaultDisputeGame | No | Bespoke | No | Not yet supported by OPCM + // | PermissionedDisputeGame | No | Bespoke | No | + // | DelayedWETH | Yes | Two bespoke (one per DisputeGame) | No | + // | PreimageOracle | No | Shared | N/A | + // | MIPS | No | Shared | N/A | + // | OptimismPortal2 | Yes | Shared | No | // // This script only deploys the shared contracts. The bespoke contracts are deployed by // `DeployOPChain.s.sol`. When the shared contracts are proxied, the contracts deployed here are // "implementations", and when shared contracts are not proxied, they are "singletons". So // here we deploy: // + // - DisputeGameFactory (implementation) // - OptimismPortal2 (implementation) // - DelayedWETH (implementation) // - PreimageOracle (singleton) // - MIPS (singleton) + // + // For contracts which are not MCP ready neither the Proxy nor the implementation can be shared, therefore they + // are deployed by `DeployOpChain.s.sol`. - function deployOptimismPortalImpl(DeployImplementationsInput _dsi, DeployImplementationsOutput _dso) public { - uint256 proofMaturityDelaySeconds = _dsi.proofMaturityDelaySeconds(); - uint256 disputeGameFinalityDelaySeconds = _dsi.disputeGameFinalityDelaySeconds(); + function deployOptimismPortalImpl( + DeployImplementationsInput _dii, + DeployImplementationsOutput _dio + ) + public + virtual + { + string memory release = _dii.release(); + string memory stdVerToml = _dii.standardVersionsToml(); + string memory contractName = "optimism_portal"; + OptimismPortal2 impl; + + address existingImplementation = getReleaseAddress(release, contractName, stdVerToml); + if (existingImplementation != address(0)) { + impl = OptimismPortal2(payable(existingImplementation)); + } else if (isDevelopRelease(release)) { + uint256 proofMaturityDelaySeconds = _dii.proofMaturityDelaySeconds(); + uint256 disputeGameFinalityDelaySeconds = _dii.disputeGameFinalityDelaySeconds(); + vm.broadcast(msg.sender); + impl = new OptimismPortal2(proofMaturityDelaySeconds, disputeGameFinalityDelaySeconds); + } else { + revert(string.concat("DeployImplementations: failed to deploy release ", release)); + } + + vm.label(address(impl), "OptimismPortalImpl"); + _dio.set(_dio.optimismPortalImpl.selector, address(impl)); + } - vm.broadcast(msg.sender); - OptimismPortal2 optimismPortal2Impl = new OptimismPortal2({ - _proofMaturityDelaySeconds: proofMaturityDelaySeconds, - _disputeGameFinalityDelaySeconds: disputeGameFinalityDelaySeconds - }); + function deployDelayedWETHImpl(DeployImplementationsInput _dii, DeployImplementationsOutput _dio) public virtual { + string memory release = _dii.release(); + string memory stdVerToml = _dii.standardVersionsToml(); + string memory contractName = "delayed_weth"; + DelayedWETH impl; + + address existingImplementation = getReleaseAddress(release, contractName, stdVerToml); + if (existingImplementation != address(0)) { + impl = DelayedWETH(payable(existingImplementation)); + } else if (isDevelopRelease(release)) { + uint256 withdrawalDelaySeconds = _dii.withdrawalDelaySeconds(); + vm.broadcast(msg.sender); + impl = new DelayedWETH(withdrawalDelaySeconds); + } else { + revert(string.concat("DeployImplementations: failed to deploy release ", release)); + } + + vm.label(address(impl), "DelayedWETHImpl"); + _dio.set(_dio.delayedWETHImpl.selector, address(impl)); + } - vm.label(address(optimismPortal2Impl), "OptimismPortal2Impl"); - _dso.set(_dso.optimismPortal2Impl.selector, address(optimismPortal2Impl)); + function deployPreimageOracleSingleton( + DeployImplementationsInput _dii, + DeployImplementationsOutput _dio + ) + public + virtual + { + string memory release = _dii.release(); + string memory stdVerToml = _dii.standardVersionsToml(); + string memory contractName = "preimage_oracle"; + PreimageOracle singleton; + + address existingImplementation = getReleaseAddress(release, contractName, stdVerToml); + if (existingImplementation != address(0)) { + singleton = PreimageOracle(payable(existingImplementation)); + } else if (isDevelopRelease(release)) { + uint256 minProposalSizeBytes = _dii.minProposalSizeBytes(); + uint256 challengePeriodSeconds = _dii.challengePeriodSeconds(); + vm.broadcast(msg.sender); + singleton = new PreimageOracle(minProposalSizeBytes, challengePeriodSeconds); + } else { + revert(string.concat("DeployImplementations: failed to deploy release ", release)); + } + + vm.label(address(singleton), "PreimageOracleSingleton"); + _dio.set(_dio.preimageOracleSingleton.selector, address(singleton)); } - function deployDelayedWETHImpl(DeployImplementationsInput _dsi, DeployImplementationsOutput _dso) public { - uint256 withdrawalDelaySeconds = _dsi.withdrawalDelaySeconds(); + function deployMipsSingleton(DeployImplementationsInput _dii, DeployImplementationsOutput _dio) public virtual { + string memory release = _dii.release(); + string memory stdVerToml = _dii.standardVersionsToml(); + string memory contractName = "mips"; + MIPS singleton; + + address existingImplementation = getReleaseAddress(release, contractName, stdVerToml); + if (existingImplementation != address(0)) { + singleton = MIPS(payable(existingImplementation)); + } else if (isDevelopRelease(release)) { + IPreimageOracle preimageOracle = IPreimageOracle(_dio.preimageOracleSingleton()); + vm.broadcast(msg.sender); + singleton = new MIPS(preimageOracle); + } else { + revert(string.concat("DeployImplementations: failed to deploy release ", release)); + } + + vm.label(address(singleton), "MIPSSingleton"); + _dio.set(_dio.mipsSingleton.selector, address(singleton)); + } - vm.broadcast(msg.sender); - DelayedWETH delayedWETHImpl = new DelayedWETH({ _delay: withdrawalDelaySeconds }); + function deployDisputeGameFactoryImpl( + DeployImplementationsInput _dii, + DeployImplementationsOutput _dio + ) + public + virtual + { + string memory release = _dii.release(); + string memory stdVerToml = _dii.standardVersionsToml(); + string memory contractName = "dispute_game_factory"; + DisputeGameFactory impl; + + address existingImplementation = getReleaseAddress(release, contractName, stdVerToml); + if (existingImplementation != address(0)) { + impl = DisputeGameFactory(payable(existingImplementation)); + } else if (isDevelopRelease(release)) { + vm.broadcast(msg.sender); + impl = new DisputeGameFactory(); + } else { + revert(string.concat("DeployImplementations: failed to deploy release ", release)); + } + + vm.label(address(impl), "DisputeGameFactoryImpl"); + _dio.set(_dio.disputeGameFactoryImpl.selector, address(impl)); + } + + // -------- Utilities -------- + + function etchIOContracts() public returns (DeployImplementationsInput dii_, DeployImplementationsOutput dio_) { + (dii_, dio_) = getIOContracts(); + vm.etch(address(dii_), type(DeployImplementationsInput).runtimeCode); + vm.etch(address(dio_), type(DeployImplementationsOutput).runtimeCode); + } - vm.label(address(delayedWETHImpl), "DelayedWETHImpl"); - _dso.set(_dso.delayedWETHImpl.selector, address(delayedWETHImpl)); + function getIOContracts() public view returns (DeployImplementationsInput dii_, DeployImplementationsOutput dio_) { + dii_ = DeployImplementationsInput(DeployUtils.toIOAddress(msg.sender, "optimism.DeployImplementationsInput")); + dio_ = DeployImplementationsOutput(DeployUtils.toIOAddress(msg.sender, "optimism.DeployImplementationsOutput")); } - function deployPreimageOracleSingleton(DeployImplementationsInput _dsi, DeployImplementationsOutput _dso) public { - uint256 minProposalSizeBytes = _dsi.minProposalSizeBytes(); - uint256 challengePeriodSeconds = _dsi.challengePeriodSeconds(); + function deployBytecode(bytes memory _bytecode, bytes32 _salt) public returns (address newContract_) { + assembly ("memory-safe") { + newContract_ := create2(0, add(_bytecode, 0x20), mload(_bytecode), _salt) + } + require(newContract_ != address(0), "DeployImplementations: create2 failed"); + } - vm.broadcast(msg.sender); - PreimageOracle preimageOracleSingleton = - new PreimageOracle({ _minProposalSize: minProposalSizeBytes, _challengePeriod: challengePeriodSeconds }); + function deployBigBytecode( + bytes memory _bytecode, + bytes32 _salt + ) + public + returns (address newContract1_, address newContract2_) + { + // Preamble needs 3 bytes. + uint256 maxInitCodeSize = 24576 - 3; + require(_bytecode.length > maxInitCodeSize, "DeployImplementations: Use deployBytecode instead"); - vm.label(address(preimageOracleSingleton), "PreimageOracleSingleton"); - _dso.set(_dso.preimageOracleSingleton.selector, address(preimageOracleSingleton)); + bytes memory part1Slice = Bytes.slice(_bytecode, 0, maxInitCodeSize); + bytes memory part1 = Blueprint.blueprintDeployerBytecode(part1Slice); + bytes memory part2Slice = Bytes.slice(_bytecode, maxInitCodeSize, _bytecode.length - maxInitCodeSize); + bytes memory part2 = Blueprint.blueprintDeployerBytecode(part2Slice); + + newContract1_ = deployBytecode(part1, _salt); + newContract2_ = deployBytecode(part2, _salt); + } + + // Zero address is returned if the address is not found in '_standardVersionsToml'. + function getReleaseAddress( + string memory _version, + string memory _contractName, + string memory _standardVersionsToml + ) + internal + pure + returns (address addr_) + { + string memory baseKey = string.concat('.releases["', _version, '"].', _contractName); + string memory implAddressKey = string.concat(baseKey, ".implementation_address"); + string memory addressKey = string.concat(baseKey, ".address"); + try vm.parseTomlAddress(_standardVersionsToml, implAddressKey) returns (address parsedAddr_) { + addr_ = parsedAddr_; + } catch { + try vm.parseTomlAddress(_standardVersionsToml, addressKey) returns (address parsedAddr_) { + addr_ = parsedAddr_; + } catch { + addr_ = address(0); + } + } + } + + // A release is considered a 'develop' release if it does not start with 'op-contracts'. + function isDevelopRelease(string memory _release) internal pure returns (bool) { + return !LibString.startsWith(_release, "op-contracts"); } +} - function deployMipsSingleton(DeployImplementationsInput, DeployImplementationsOutput _dso) public { - IPreimageOracle preimageOracle = IPreimageOracle(_dso.preimageOracleSingleton()); +// Similar to how DeploySuperchain.s.sol contains a lot of comments to thoroughly document the script +// architecture, this comment block documents how to update the deploy scripts to support new features. +// +// Using the base scripts and contracts (DeploySuperchain, DeployImplementations, DeployOPChain, and +// the corresponding OPContractsManager) deploys a standard chain. For nonstandard and in-development +// features we need to modify some or all of those contracts, and we do that via inheritance. Using +// interop as an example, they've made the following changes to L1 contracts: +// - `OptimismPortalInterop is OptimismPortal`: A different portal implementation is used, and +// it's ABI is the same. +// - `SystemConfigInterop is SystemConfig`: A different system config implementation is used, and +// it's initializer has a different signature. This signature is different because there is a +// new input parameter, the `dependencyManager`. +// - Because of the different system config initializer, there is a new input parameter (dependencyManager). +// +// Similar to how inheritance was used to develop the new portal and system config contracts, we use +// inheritance to modify up to all of the deployer contracts. For this interop example, what this +// means is we need: +// - An `OPContractsManagerInterop is OPContractsManager` that knows how to encode the calldata for the +// new system config initializer. +// - A `DeployImplementationsInterop is DeployImplementations` that: +// - Deploys OptimismPortalInterop instead of OptimismPortal. +// - Deploys SystemConfigInterop instead of SystemConfig. +// - Deploys OPContractsManagerInterop instead of OPContractsManager, which contains the updated logic +// for encoding the SystemConfig initializer. +// - Updates the OPCM release setter logic to use the updated initializer. +// - A `DeployOPChainInterop is DeployOPChain` that allows the updated input parameter to be passed. +// +// Most of the complexity in the above flow comes from the the new input for the updated SystemConfig +// initializer. If all function signatures were the same, all we'd have to change is the contract +// implementations that are deployed then set in the OPCM. For now, to simplify things until we +// resolve https://github.com/ethereum-optimism/optimism/issues/11783, we just assume this new role +// is the same as the proxy admin owner. +contract DeployImplementationsInterop is DeployImplementations { + function createOPCMContract( + DeployImplementationsInput _dii, + DeployImplementationsOutput _dio, + OPContractsManager.Blueprints memory _blueprints, + string memory _release, + OPContractsManager.ImplementationSetter[] memory _setters + ) + internal + override + returns (OPContractsManager opcmProxy_) + { + ProxyAdmin proxyAdmin = _dii.superchainProxyAdmin(); vm.broadcast(msg.sender); - MIPS mipsSingleton = new MIPS(preimageOracle); + Proxy proxy = new Proxy(address(msg.sender)); + + deployOPContractsManagerImpl(_dii, _dio); // overriding function + OPContractsManager opcmImpl = _dio.opcmImpl(); + + OPContractsManager.InitializerInputs memory initializerInputs = + OPContractsManager.InitializerInputs(_blueprints, _setters, _release, true); - vm.label(address(mipsSingleton), "MIPSSingleton"); - _dso.set(_dso.mipsSingleton.selector, address(mipsSingleton)); + vm.startBroadcast(msg.sender); + proxy.upgradeToAndCall( + address(opcmImpl), abi.encodeWithSelector(opcmImpl.initialize.selector, initializerInputs) + ); + + proxy.changeAdmin(address(proxyAdmin)); // transfer ownership of Proxy contract to the ProxyAdmin contract + vm.stopBroadcast(); + + opcmProxy_ = OPContractsManagerInterop(address(proxy)); } - // -------- Utilities -------- + function deployOptimismPortalImpl( + DeployImplementationsInput _dii, + DeployImplementationsOutput _dio + ) + public + override + { + string memory release = _dii.release(); + string memory stdVerToml = _dii.standardVersionsToml(); + string memory contractName = "optimism_portal"; + OptimismPortal2 impl; + + address existingImplementation = getReleaseAddress(release, contractName, stdVerToml); + if (existingImplementation != address(0)) { + impl = OptimismPortalInterop(payable(existingImplementation)); + } else if (isDevelopRelease(release)) { + uint256 proofMaturityDelaySeconds = _dii.proofMaturityDelaySeconds(); + uint256 disputeGameFinalityDelaySeconds = _dii.disputeGameFinalityDelaySeconds(); + vm.broadcast(msg.sender); + impl = new OptimismPortalInterop(proofMaturityDelaySeconds, disputeGameFinalityDelaySeconds); + } else { + revert(string.concat("DeployImplementations: failed to deploy release ", release)); + } + + vm.label(address(impl), "OptimismPortalImpl"); + _dio.set(_dio.optimismPortalImpl.selector, address(impl)); + } - function etchIOContracts() internal returns (DeployImplementationsInput dsi_, DeployImplementationsOutput dso_) { - (dsi_, dso_) = getIOContracts(); - vm.etch(address(dsi_), type(DeployImplementationsInput).runtimeCode); - vm.etch(address(dso_), type(DeployImplementationsOutput).runtimeCode); + function deploySystemConfigImpl( + DeployImplementationsInput _dii, + DeployImplementationsOutput _dio + ) + public + override + { + string memory release = _dii.release(); + string memory stdVerToml = _dii.standardVersionsToml(); + + string memory contractName = "system_config"; + SystemConfig impl; + + address existingImplementation = getReleaseAddress(release, contractName, stdVerToml); + if (existingImplementation != address(0)) { + impl = SystemConfigInterop(existingImplementation); + } else if (isDevelopRelease(release)) { + vm.broadcast(msg.sender); + impl = new SystemConfigInterop(); + } else { + revert(string.concat("DeployImplementations: failed to deploy release ", release)); + } + + vm.label(address(impl), "SystemConfigImpl"); + _dio.set(_dio.systemConfigImpl.selector, address(impl)); } - function getIOContracts() public view returns (DeployImplementationsInput dsi_, DeployImplementationsOutput dso_) { - dsi_ = DeployImplementationsInput(DeployUtils.toIOAddress(msg.sender, "optimism.DeployImplementationsInput")); - dso_ = DeployImplementationsOutput(DeployUtils.toIOAddress(msg.sender, "optimism.DeployImplementationsOutput")); + function deployOPContractsManagerImpl( + DeployImplementationsInput _dii, + DeployImplementationsOutput _dio + ) + public + override + { + SuperchainConfig superchainConfigProxy = _dii.superchainConfigProxy(); + ProtocolVersions protocolVersionsProxy = _dii.protocolVersionsProxy(); + + vm.broadcast(msg.sender); + // TODO: Eventually we will want to select the correct implementation based on the release. + OPContractsManager impl = new OPContractsManagerInterop(superchainConfigProxy, protocolVersionsProxy); + + vm.label(address(impl), "OPContractsManagerImpl"); + _dio.set(_dio.opcmImpl.selector, address(impl)); + } + + function opcmSystemConfigSetter( + DeployImplementationsInput, + DeployImplementationsOutput _dio + ) + internal + view + override + returns (OPContractsManager.ImplementationSetter memory) + { + return OPContractsManager.ImplementationSetter({ + name: "SystemConfig", + info: OPContractsManager.Implementation( + address(_dio.systemConfigImpl()), SystemConfigInterop.initialize.selector + ) + }); } } diff --git a/packages/contracts-bedrock/scripts/DeployOPChain.s.sol b/packages/contracts-bedrock/scripts/DeployOPChain.s.sol index e42bd5df324d1..6cecb41d36eb5 100644 --- a/packages/contracts-bedrock/scripts/DeployOPChain.s.sol +++ b/packages/contracts-bedrock/scripts/DeployOPChain.s.sol @@ -3,18 +3,30 @@ pragma solidity 0.8.15; import { Script } from "forge-std/Script.sol"; +import { SafeCast } from "@openzeppelin/contracts/utils/math/SafeCast.sol"; + import { DeployUtils } from "scripts/libraries/DeployUtils.sol"; import { Solarray } from "scripts/libraries/Solarray.sol"; +import { BaseDeployIO } from "scripts/utils/BaseDeployIO.sol"; + +import { IResourceMetering } from "src/L1/interfaces/IResourceMetering.sol"; +import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol"; +import { IBigStepper } from "src/dispute/interfaces/IBigStepper.sol"; +import { Constants } from "src/libraries/Constants.sol"; +import { Predeploys } from "src/libraries/Predeploys.sol"; import { ProxyAdmin } from "src/universal/ProxyAdmin.sol"; +import { Proxy } from "src/universal/Proxy.sol"; import { AddressManager } from "src/legacy/AddressManager.sol"; -import { DelayedWETH } from "src/dispute/weth/DelayedWETH.sol"; +import { DelayedWETH } from "src/dispute/DelayedWETH.sol"; import { DisputeGameFactory } from "src/dispute/DisputeGameFactory.sol"; import { AnchorStateRegistry } from "src/dispute/AnchorStateRegistry.sol"; import { FaultDisputeGame } from "src/dispute/FaultDisputeGame.sol"; import { PermissionedDisputeGame } from "src/dispute/PermissionedDisputeGame.sol"; +import { Claim, GameType, GameTypes, Hash, OutputRoot } from "src/dispute/lib/Types.sol"; +import { OPContractsManager } from "src/L1/OPContractsManager.sol"; import { OptimismPortal2 } from "src/L1/OptimismPortal2.sol"; import { SystemConfig } from "src/L1/SystemConfig.sol"; import { L1CrossDomainMessenger } from "src/L1/L1CrossDomainMessenger.sol"; @@ -22,300 +34,513 @@ import { L1ERC721Bridge } from "src/L1/L1ERC721Bridge.sol"; import { L1StandardBridge } from "src/L1/L1StandardBridge.sol"; import { OptimismMintableERC20Factory } from "src/universal/OptimismMintableERC20Factory.sol"; -contract DeployOPChainInput { - struct Roles { - address opChainProxyAdminOwner; - address systemConfigOwner; - address batcher; - address unsafeBlockSigner; - address proposer; - address challenger; - } +contract DeployOPChainInput is BaseDeployIO { + address internal _opChainProxyAdminOwner; + address internal _systemConfigOwner; + address internal _batcher; + address internal _unsafeBlockSigner; + address internal _proposer; + address internal _challenger; // TODO Add fault proofs inputs in a future PR. - struct Input { - Roles roles; - uint32 basefeeScalar; - uint32 blobBaseFeeScalar; - uint256 l2ChainId; - } - - bool public inputSet = false; - Input internal inputs; - - function loadInputFile(string memory _infile) public { - _infile; - Input memory parsedInput; - loadInput(parsedInput); - require(false, "DeployOPChainInput: not implemented"); - } - - function loadInput(Input memory _input) public { - require(!inputSet, "DeployOPChainInput: input already set"); - - require(_input.roles.opChainProxyAdminOwner != address(0), "DeployOPChainInput: null opChainProxyAdminOwner"); - require(_input.roles.systemConfigOwner != address(0), "DeployOPChainInput: null systemConfigOwner"); - require(_input.roles.batcher != address(0), "DeployOPChainInput: null batcher"); - require(_input.roles.unsafeBlockSigner != address(0), "DeployOPChainInput: null unsafeBlockSigner"); - require(_input.roles.proposer != address(0), "DeployOPChainInput: null proposer"); - require(_input.roles.challenger != address(0), "DeployOPChainInput: null challenger"); - - inputSet = true; - inputs = _input; - } - - function assertInputSet() internal view { - require(inputSet, "DeployOPChainInput: input not set"); - } - - function input() public view returns (Input memory) { - assertInputSet(); - return inputs; + uint32 internal _basefeeScalar; + uint32 internal _blobBaseFeeScalar; + uint256 internal _l2ChainId; + OPContractsManager internal _opcmProxy; + + function set(bytes4 _sel, address _addr) public { + require(_addr != address(0), "DeployOPChainInput: cannot set zero address"); + if (_sel == this.opChainProxyAdminOwner.selector) _opChainProxyAdminOwner = _addr; + else if (_sel == this.systemConfigOwner.selector) _systemConfigOwner = _addr; + else if (_sel == this.batcher.selector) _batcher = _addr; + else if (_sel == this.unsafeBlockSigner.selector) _unsafeBlockSigner = _addr; + else if (_sel == this.proposer.selector) _proposer = _addr; + else if (_sel == this.challenger.selector) _challenger = _addr; + else if (_sel == this.opcmProxy.selector) _opcmProxy = OPContractsManager(_addr); + else revert("DeployOPChainInput: unknown selector"); + } + + function set(bytes4 _sel, uint256 _value) public { + if (_sel == this.basefeeScalar.selector) { + _basefeeScalar = SafeCast.toUint32(_value); + } else if (_sel == this.blobBaseFeeScalar.selector) { + _blobBaseFeeScalar = SafeCast.toUint32(_value); + } else if (_sel == this.l2ChainId.selector) { + require(_value != 0 && _value != block.chainid, "DeployOPChainInput: invalid l2ChainId"); + _l2ChainId = _value; + } else { + revert("DeployOPChainInput: unknown selector"); + } } function opChainProxyAdminOwner() public view returns (address) { - assertInputSet(); - return inputs.roles.opChainProxyAdminOwner; + require(_opChainProxyAdminOwner != address(0), "DeployOPChainInput: not set"); + return _opChainProxyAdminOwner; } function systemConfigOwner() public view returns (address) { - assertInputSet(); - return inputs.roles.systemConfigOwner; + require(_systemConfigOwner != address(0), "DeployOPChainInput: not set"); + return _systemConfigOwner; } function batcher() public view returns (address) { - assertInputSet(); - return inputs.roles.batcher; + require(_batcher != address(0), "DeployOPChainInput: not set"); + return _batcher; } function unsafeBlockSigner() public view returns (address) { - assertInputSet(); - return inputs.roles.unsafeBlockSigner; + require(_unsafeBlockSigner != address(0), "DeployOPChainInput: not set"); + return _unsafeBlockSigner; } function proposer() public view returns (address) { - assertInputSet(); - return inputs.roles.proposer; + require(_proposer != address(0), "DeployOPChainInput: not set"); + return _proposer; } function challenger() public view returns (address) { - assertInputSet(); - return inputs.roles.challenger; + require(_challenger != address(0), "DeployOPChainInput: not set"); + return _challenger; } function basefeeScalar() public view returns (uint32) { - assertInputSet(); - return inputs.basefeeScalar; + require(_basefeeScalar != 0, "DeployOPChainInput: not set"); + return _basefeeScalar; } function blobBaseFeeScalar() public view returns (uint32) { - assertInputSet(); - return inputs.blobBaseFeeScalar; + require(_blobBaseFeeScalar != 0, "DeployOPChainInput: not set"); + return _blobBaseFeeScalar; } function l2ChainId() public view returns (uint256) { - assertInputSet(); - return inputs.l2ChainId; + require(_l2ChainId != 0, "DeployOPChainInput: not set"); + require(_l2ChainId != block.chainid, "DeployOPChainInput: invalid l2ChainId"); + return _l2ChainId; + } + + function startingAnchorRoots() public pure returns (bytes memory) { + // WARNING: For now always hardcode the starting permissioned game anchor root to 0xdead, + // and we do not set anything for the permissioned game. This is because we currently only + // support deploying straight to permissioned games, and the starting root does not + // matter for that, as long as it is non-zero, since no games will be played. We do not + // deploy the permissionless game (and therefore do not set a starting root for it here) + // because to to update to the permissionless game, we will need to update its starting + // anchor root and deploy a new permissioned dispute game contract anyway. + // + // You can `console.logBytes(abi.encode(defaultStartingAnchorRoots))` to get the bytes that + // are hardcoded into `op-chain-ops/deployer/opcm/opchain.go` + AnchorStateRegistry.StartingAnchorRoot[] memory defaultStartingAnchorRoots = + new AnchorStateRegistry.StartingAnchorRoot[](1); + defaultStartingAnchorRoots[0] = AnchorStateRegistry.StartingAnchorRoot({ + gameType: GameTypes.PERMISSIONED_CANNON, + outputRoot: OutputRoot({ root: Hash.wrap(bytes32(hex"dead")), l2BlockNumber: 0 }) + }); + return abi.encode(defaultStartingAnchorRoots); + } + + function opcmProxy() public returns (OPContractsManager) { + require(address(_opcmProxy) != address(0), "DeployOPChainInput: not set"); + DeployUtils.assertValidContractAddress(address(_opcmProxy)); + DeployUtils.assertImplementationSet(address(_opcmProxy)); + return _opcmProxy; } } -contract DeployOPChainOutput { - struct Output { - ProxyAdmin opChainProxyAdmin; - AddressManager addressManager; - L1ERC721Bridge l1ERC721BridgeProxy; - SystemConfig systemConfigProxy; - OptimismMintableERC20Factory optimismMintableERC20FactoryProxy; - L1StandardBridge l1StandardBridgeProxy; - L1CrossDomainMessenger l1CrossDomainMessengerProxy; - // Fault proof contracts below. - OptimismPortal2 optimismPortalProxy; - DisputeGameFactory disputeGameFactoryProxy; - DisputeGameFactory disputeGameFactoryImpl; - AnchorStateRegistry anchorStateRegistryProxy; - AnchorStateRegistry anchorStateRegistryImpl; - FaultDisputeGame faultDisputeGame; - PermissionedDisputeGame permissionedDisputeGame; - DelayedWETH delayedWETHPermissionedGameProxy; - DelayedWETH delayedWETHPermissionlessGameProxy; - } - - Output internal outputs; +contract DeployOPChainOutput is BaseDeployIO { + ProxyAdmin internal _opChainProxyAdmin; + AddressManager internal _addressManager; + L1ERC721Bridge internal _l1ERC721BridgeProxy; + SystemConfig internal _systemConfigProxy; + OptimismMintableERC20Factory internal _optimismMintableERC20FactoryProxy; + L1StandardBridge internal _l1StandardBridgeProxy; + L1CrossDomainMessenger internal _l1CrossDomainMessengerProxy; + OptimismPortal2 internal _optimismPortalProxy; + DisputeGameFactory internal _disputeGameFactoryProxy; + AnchorStateRegistry internal _anchorStateRegistryProxy; + AnchorStateRegistry internal _anchorStateRegistryImpl; + FaultDisputeGame internal _faultDisputeGame; + PermissionedDisputeGame internal _permissionedDisputeGame; + DelayedWETH internal _delayedWETHPermissionedGameProxy; + DelayedWETH internal _delayedWETHPermissionlessGameProxy; function set(bytes4 sel, address _addr) public { + require(_addr != address(0), "DeployOPChainOutput: cannot set zero address"); // forgefmt: disable-start - if (sel == this.opChainProxyAdmin.selector) outputs.opChainProxyAdmin = ProxyAdmin(_addr) ; - else if (sel == this.addressManager.selector) outputs.addressManager = AddressManager(_addr) ; - else if (sel == this.l1ERC721BridgeProxy.selector) outputs.l1ERC721BridgeProxy = L1ERC721Bridge(_addr) ; - else if (sel == this.systemConfigProxy.selector) outputs.systemConfigProxy = SystemConfig(_addr) ; - else if (sel == this.optimismMintableERC20FactoryProxy.selector) outputs.optimismMintableERC20FactoryProxy = OptimismMintableERC20Factory(_addr) ; - else if (sel == this.l1StandardBridgeProxy.selector) outputs.l1StandardBridgeProxy = L1StandardBridge(payable(_addr)) ; - else if (sel == this.l1CrossDomainMessengerProxy.selector) outputs.l1CrossDomainMessengerProxy = L1CrossDomainMessenger(_addr) ; - else if (sel == this.optimismPortalProxy.selector) outputs.optimismPortalProxy = OptimismPortal2(payable(_addr)) ; - else if (sel == this.disputeGameFactoryProxy.selector) outputs.disputeGameFactoryProxy = DisputeGameFactory(_addr) ; - else if (sel == this.disputeGameFactoryImpl.selector) outputs.disputeGameFactoryImpl = DisputeGameFactory(_addr) ; - else if (sel == this.anchorStateRegistryProxy.selector) outputs.anchorStateRegistryProxy = AnchorStateRegistry(_addr) ; - else if (sel == this.anchorStateRegistryImpl.selector) outputs.anchorStateRegistryImpl = AnchorStateRegistry(_addr) ; - else if (sel == this.faultDisputeGame.selector) outputs.faultDisputeGame = FaultDisputeGame(_addr) ; - else if (sel == this.permissionedDisputeGame.selector) outputs.permissionedDisputeGame = PermissionedDisputeGame(_addr) ; - else if (sel == this.delayedWETHPermissionedGameProxy.selector) outputs.delayedWETHPermissionedGameProxy = DelayedWETH(payable(_addr)) ; - else if (sel == this.delayedWETHPermissionlessGameProxy.selector) outputs.delayedWETHPermissionlessGameProxy = DelayedWETH(payable(_addr)) ; + if (sel == this.opChainProxyAdmin.selector) _opChainProxyAdmin = ProxyAdmin(_addr) ; + else if (sel == this.addressManager.selector) _addressManager = AddressManager(_addr) ; + else if (sel == this.l1ERC721BridgeProxy.selector) _l1ERC721BridgeProxy = L1ERC721Bridge(_addr) ; + else if (sel == this.systemConfigProxy.selector) _systemConfigProxy = SystemConfig(_addr) ; + else if (sel == this.optimismMintableERC20FactoryProxy.selector) _optimismMintableERC20FactoryProxy = OptimismMintableERC20Factory(_addr) ; + else if (sel == this.l1StandardBridgeProxy.selector) _l1StandardBridgeProxy = L1StandardBridge(payable(_addr)) ; + else if (sel == this.l1CrossDomainMessengerProxy.selector) _l1CrossDomainMessengerProxy = L1CrossDomainMessenger(_addr) ; + else if (sel == this.optimismPortalProxy.selector) _optimismPortalProxy = OptimismPortal2(payable(_addr)) ; + else if (sel == this.disputeGameFactoryProxy.selector) _disputeGameFactoryProxy = DisputeGameFactory(_addr) ; + else if (sel == this.anchorStateRegistryProxy.selector) _anchorStateRegistryProxy = AnchorStateRegistry(_addr) ; + else if (sel == this.anchorStateRegistryImpl.selector) _anchorStateRegistryImpl = AnchorStateRegistry(_addr) ; + else if (sel == this.faultDisputeGame.selector) _faultDisputeGame = FaultDisputeGame(_addr) ; + else if (sel == this.permissionedDisputeGame.selector) _permissionedDisputeGame = PermissionedDisputeGame(_addr) ; + else if (sel == this.delayedWETHPermissionedGameProxy.selector) _delayedWETHPermissionedGameProxy = DelayedWETH(payable(_addr)) ; + else if (sel == this.delayedWETHPermissionlessGameProxy.selector) _delayedWETHPermissionlessGameProxy = DelayedWETH(payable(_addr)) ; else revert("DeployOPChainOutput: unknown selector"); // forgefmt: disable-end } - function writeOutputFile(string memory _outfile) public pure { - _outfile; - require(false, "DeployOPChainOutput: not implemented"); - } - - function output() public view returns (Output memory) { - return outputs; - } - - function checkOutput() public view { + function checkOutput(DeployOPChainInput _doi) public { // With 16 addresses, we'd get a stack too deep error if we tried to do this inline as a // single call to `Solarray.addresses`. So we split it into two calls. address[] memory addrs1 = Solarray.addresses( - address(outputs.opChainProxyAdmin), - address(outputs.addressManager), - address(outputs.l1ERC721BridgeProxy), - address(outputs.systemConfigProxy), - address(outputs.optimismMintableERC20FactoryProxy), - address(outputs.l1StandardBridgeProxy), - address(outputs.l1CrossDomainMessengerProxy) + address(_opChainProxyAdmin), + address(_addressManager), + address(_l1ERC721BridgeProxy), + address(_systemConfigProxy), + address(_optimismMintableERC20FactoryProxy), + address(_l1StandardBridgeProxy), + address(_l1CrossDomainMessengerProxy) ); address[] memory addrs2 = Solarray.addresses( - address(outputs.optimismPortalProxy), - address(outputs.disputeGameFactoryProxy), - address(outputs.disputeGameFactoryImpl), - address(outputs.anchorStateRegistryProxy), - address(outputs.anchorStateRegistryImpl), - address(outputs.faultDisputeGame), - address(outputs.permissionedDisputeGame), - address(outputs.delayedWETHPermissionedGameProxy), - address(outputs.delayedWETHPermissionlessGameProxy) + address(_optimismPortalProxy), + address(_disputeGameFactoryProxy), + address(_anchorStateRegistryProxy), + address(_anchorStateRegistryImpl), + // address(_faultDisputeGame), + address(_permissionedDisputeGame), + address(_delayedWETHPermissionedGameProxy), + address(_delayedWETHPermissionlessGameProxy) ); DeployUtils.assertValidContractAddresses(Solarray.extend(addrs1, addrs2)); + + assertValidDeploy(_doi); } function opChainProxyAdmin() public view returns (ProxyAdmin) { - DeployUtils.assertValidContractAddress(address(outputs.opChainProxyAdmin)); - return outputs.opChainProxyAdmin; + DeployUtils.assertValidContractAddress(address(_opChainProxyAdmin)); + return _opChainProxyAdmin; } function addressManager() public view returns (AddressManager) { - DeployUtils.assertValidContractAddress(address(outputs.addressManager)); - return outputs.addressManager; + DeployUtils.assertValidContractAddress(address(_addressManager)); + return _addressManager; } function l1ERC721BridgeProxy() public view returns (L1ERC721Bridge) { - DeployUtils.assertValidContractAddress(address(outputs.l1ERC721BridgeProxy)); - return outputs.l1ERC721BridgeProxy; + DeployUtils.assertValidContractAddress(address(_l1ERC721BridgeProxy)); + return _l1ERC721BridgeProxy; } function systemConfigProxy() public view returns (SystemConfig) { - DeployUtils.assertValidContractAddress(address(outputs.systemConfigProxy)); - return outputs.systemConfigProxy; + DeployUtils.assertValidContractAddress(address(_systemConfigProxy)); + return _systemConfigProxy; } function optimismMintableERC20FactoryProxy() public view returns (OptimismMintableERC20Factory) { - DeployUtils.assertValidContractAddress(address(outputs.optimismMintableERC20FactoryProxy)); - return outputs.optimismMintableERC20FactoryProxy; + DeployUtils.assertValidContractAddress(address(_optimismMintableERC20FactoryProxy)); + return _optimismMintableERC20FactoryProxy; } function l1StandardBridgeProxy() public view returns (L1StandardBridge) { - DeployUtils.assertValidContractAddress(address(outputs.l1StandardBridgeProxy)); - return outputs.l1StandardBridgeProxy; + DeployUtils.assertValidContractAddress(address(_l1StandardBridgeProxy)); + return _l1StandardBridgeProxy; } function l1CrossDomainMessengerProxy() public view returns (L1CrossDomainMessenger) { - DeployUtils.assertValidContractAddress(address(outputs.l1CrossDomainMessengerProxy)); - return outputs.l1CrossDomainMessengerProxy; + DeployUtils.assertValidContractAddress(address(_l1CrossDomainMessengerProxy)); + return _l1CrossDomainMessengerProxy; } function optimismPortalProxy() public view returns (OptimismPortal2) { - DeployUtils.assertValidContractAddress(address(outputs.optimismPortalProxy)); - return outputs.optimismPortalProxy; + DeployUtils.assertValidContractAddress(address(_optimismPortalProxy)); + return _optimismPortalProxy; } function disputeGameFactoryProxy() public view returns (DisputeGameFactory) { - DeployUtils.assertValidContractAddress(address(outputs.disputeGameFactoryProxy)); - return outputs.disputeGameFactoryProxy; - } - - function disputeGameFactoryImpl() public view returns (DisputeGameFactory) { - DeployUtils.assertValidContractAddress(address(outputs.disputeGameFactoryImpl)); - return outputs.disputeGameFactoryImpl; + DeployUtils.assertValidContractAddress(address(_disputeGameFactoryProxy)); + return _disputeGameFactoryProxy; } function anchorStateRegistryProxy() public view returns (AnchorStateRegistry) { - DeployUtils.assertValidContractAddress(address(outputs.anchorStateRegistryProxy)); - return outputs.anchorStateRegistryProxy; + DeployUtils.assertValidContractAddress(address(_anchorStateRegistryProxy)); + return _anchorStateRegistryProxy; } function anchorStateRegistryImpl() public view returns (AnchorStateRegistry) { - DeployUtils.assertValidContractAddress(address(outputs.anchorStateRegistryImpl)); - return outputs.anchorStateRegistryImpl; + DeployUtils.assertValidContractAddress(address(_anchorStateRegistryImpl)); + return _anchorStateRegistryImpl; } function faultDisputeGame() public view returns (FaultDisputeGame) { - DeployUtils.assertValidContractAddress(address(outputs.faultDisputeGame)); - return outputs.faultDisputeGame; + DeployUtils.assertValidContractAddress(address(_faultDisputeGame)); + return _faultDisputeGame; } function permissionedDisputeGame() public view returns (PermissionedDisputeGame) { - DeployUtils.assertValidContractAddress(address(outputs.permissionedDisputeGame)); - return outputs.permissionedDisputeGame; + DeployUtils.assertValidContractAddress(address(_permissionedDisputeGame)); + return _permissionedDisputeGame; } function delayedWETHPermissionedGameProxy() public view returns (DelayedWETH) { - DeployUtils.assertValidContractAddress(address(outputs.delayedWETHPermissionedGameProxy)); - return outputs.delayedWETHPermissionedGameProxy; + DeployUtils.assertValidContractAddress(address(_delayedWETHPermissionedGameProxy)); + return _delayedWETHPermissionedGameProxy; } function delayedWETHPermissionlessGameProxy() public view returns (DelayedWETH) { - DeployUtils.assertValidContractAddress(address(outputs.delayedWETHPermissionlessGameProxy)); - return outputs.delayedWETHPermissionlessGameProxy; + DeployUtils.assertValidContractAddress(address(_delayedWETHPermissionlessGameProxy)); + return _delayedWETHPermissionlessGameProxy; } -} -contract DeployOPChain is Script { - // -------- Core Deployment Methods -------- - function run(string memory _infile) public { - (DeployOPChainInput dsi, DeployOPChainOutput dso) = etchIOContracts(); - dsi.loadInputFile(_infile); - run(dsi, dso); - string memory outfile = ""; // This will be derived from input file name, e.g. `foo.in.toml` -> `foo.out.toml` - dso.writeOutputFile(outfile); - require(false, "DeployOPChain: run is not implemented"); + // -------- Deployment Assertions -------- + + function assertValidDeploy(DeployOPChainInput _doi) internal { + assertValidAnchorStateRegistryImpl(_doi); + assertValidAnchorStateRegistryProxy(_doi); + assertValidDelayedWETHs(_doi); + assertValidDisputeGameFactory(_doi); + assertValidL1CrossDomainMessenger(_doi); + assertValidL1ERC721Bridge(_doi); + assertValidL1StandardBridge(_doi); + assertValidOptimismMintableERC20Factory(_doi); + assertValidOptimismPortal(_doi); + assertValidPermissionedDisputeGame(_doi); + assertValidSystemConfig(_doi); + } + + function assertValidPermissionedDisputeGame(DeployOPChainInput _doi) internal { + PermissionedDisputeGame game = permissionedDisputeGame(); + + require(GameType.unwrap(game.gameType()) == GameType.unwrap(GameTypes.PERMISSIONED_CANNON), "DPG-10"); + require(Claim.unwrap(game.absolutePrestate()) == bytes32(hex"dead"), "DPG-20"); + + OPContractsManager opcm = _doi.opcmProxy(); + (address mips,) = opcm.implementations(opcm.latestRelease(), "MIPS"); + require(game.vm() == IBigStepper(mips), "DPG-30"); + + require(address(game.weth()) == address(delayedWETHPermissionedGameProxy()), "DPG-40"); + require(address(game.anchorStateRegistry()) == address(anchorStateRegistryProxy()), "DPG-50"); + require(game.l2ChainId() == _doi.l2ChainId(), "DPG-60"); + } + + function assertValidAnchorStateRegistryProxy(DeployOPChainInput) internal { + // First we check the proxy as itself. + Proxy proxy = Proxy(payable(address(anchorStateRegistryProxy()))); + vm.prank(address(0)); + address admin = proxy.admin(); + require(admin == address(opChainProxyAdmin()), "ANCHORP-10"); + + // Then we check the proxy as ASR. + DeployUtils.assertInitialized({ _contractAddress: address(anchorStateRegistryProxy()), _slot: 0, _offset: 0 }); + + vm.prank(address(0)); + address impl = proxy.implementation(); + require(impl == address(anchorStateRegistryImpl()), "ANCHORP-20"); + require( + address(anchorStateRegistryProxy().disputeGameFactory()) == address(disputeGameFactoryProxy()), "ANCHORP-30" + ); } - function run(DeployOPChainInput.Input memory _input) public returns (DeployOPChainOutput.Output memory) { - (DeployOPChainInput dsi, DeployOPChainOutput dso) = etchIOContracts(); - dsi.loadInput(_input); - run(dsi, dso); - return dso.output(); + function assertValidAnchorStateRegistryImpl(DeployOPChainInput) internal view { + AnchorStateRegistry registry = anchorStateRegistryImpl(); + + DeployUtils.assertInitialized({ _contractAddress: address(registry), _slot: 0, _offset: 0 }); + + require(address(registry.disputeGameFactory()) == address(disputeGameFactoryProxy()), "ANCHORI-10"); } - function run(DeployOPChainInput _dsi, DeployOPChainOutput _dso) public view { - require(_dsi.inputSet(), "DeployOPChain: input not set"); + function assertValidSystemConfig(DeployOPChainInput _doi) internal { + SystemConfig systemConfig = systemConfigProxy(); + + DeployUtils.assertInitialized({ _contractAddress: address(systemConfig), _slot: 0, _offset: 0 }); + + require(systemConfig.owner() == _doi.systemConfigOwner(), "SYSCON-10"); + require(systemConfig.basefeeScalar() == _doi.basefeeScalar(), "SYSCON-20"); + require(systemConfig.blobbasefeeScalar() == _doi.blobBaseFeeScalar(), "SYSCON-30"); + require(systemConfig.batcherHash() == bytes32(uint256(uint160(_doi.batcher()))), "SYSCON-40"); + require(systemConfig.gasLimit() == uint64(30000000), "SYSCON-50"); // TODO allow other gas limits? + require(systemConfig.unsafeBlockSigner() == _doi.unsafeBlockSigner(), "SYSCON-60"); + require(systemConfig.scalar() >> 248 == 1, "SYSCON-70"); - // TODO call OP Stack Manager deploy method + IResourceMetering.ResourceConfig memory rConfig = Constants.DEFAULT_RESOURCE_CONFIG(); + IResourceMetering.ResourceConfig memory outputConfig = systemConfig.resourceConfig(); + require(outputConfig.maxResourceLimit == rConfig.maxResourceLimit, "SYSCON-80"); + require(outputConfig.elasticityMultiplier == rConfig.elasticityMultiplier, "SYSCON-90"); + require(outputConfig.baseFeeMaxChangeDenominator == rConfig.baseFeeMaxChangeDenominator, "SYSCON-100"); + require(outputConfig.systemTxMaxGas == rConfig.systemTxMaxGas, "SYSCON-110"); + require(outputConfig.minimumBaseFee == rConfig.minimumBaseFee, "SYSCON-120"); + require(outputConfig.maximumBaseFee == rConfig.maximumBaseFee, "SYSCON-130"); + + require(systemConfig.startBlock() == block.number, "SYSCON-140"); + require( + systemConfig.batchInbox() == _doi.opcmProxy().chainIdToBatchInboxAddress(_doi.l2ChainId()), "SYSCON-150" + ); + + require(systemConfig.l1CrossDomainMessenger() == address(l1CrossDomainMessengerProxy()), "SYSCON-160"); + require(systemConfig.l1ERC721Bridge() == address(l1ERC721BridgeProxy()), "SYSCON-170"); + require(systemConfig.l1StandardBridge() == address(l1StandardBridgeProxy()), "SYSCON-180"); + require(systemConfig.disputeGameFactory() == address(disputeGameFactoryProxy()), "SYSCON-190"); + require(systemConfig.optimismPortal() == address(optimismPortalProxy()), "SYSCON-200"); + require( + systemConfig.optimismMintableERC20Factory() == address(optimismMintableERC20FactoryProxy()), "SYSCON-210" + ); + (address gasPayingToken,) = systemConfig.gasPayingToken(); + require(gasPayingToken == Constants.ETHER, "SYSCON-220"); + } + + function assertValidL1CrossDomainMessenger(DeployOPChainInput _doi) internal { + L1CrossDomainMessenger messenger = l1CrossDomainMessengerProxy(); + + DeployUtils.assertInitialized({ _contractAddress: address(messenger), _slot: 0, _offset: 20 }); + + require(address(messenger.OTHER_MESSENGER()) == Predeploys.L2_CROSS_DOMAIN_MESSENGER, "L1xDM-10"); + require(address(messenger.otherMessenger()) == Predeploys.L2_CROSS_DOMAIN_MESSENGER, "L1xDM-20"); + + require(address(messenger.PORTAL()) == address(optimismPortalProxy()), "L1xDM-30"); + require(address(messenger.portal()) == address(optimismPortalProxy()), "L1xDM-40"); + require(address(messenger.superchainConfig()) == address(_doi.opcmProxy().superchainConfig()), "L1xDM-50"); + + bytes32 xdmSenderSlot = vm.load(address(messenger), bytes32(uint256(204))); + require(address(uint160(uint256(xdmSenderSlot))) == Constants.DEFAULT_L2_SENDER, "L1xDM-60"); + } + + function assertValidL1StandardBridge(DeployOPChainInput _doi) internal { + L1StandardBridge bridge = l1StandardBridgeProxy(); + L1CrossDomainMessenger messenger = l1CrossDomainMessengerProxy(); + + DeployUtils.assertInitialized({ _contractAddress: address(bridge), _slot: 0, _offset: 0 }); + + require(address(bridge.MESSENGER()) == address(messenger), "L1SB-10"); + require(address(bridge.messenger()) == address(messenger), "L1SB-20"); + require(address(bridge.OTHER_BRIDGE()) == Predeploys.L2_STANDARD_BRIDGE, "L1SB-30"); + require(address(bridge.otherBridge()) == Predeploys.L2_STANDARD_BRIDGE, "L1SB-40"); + require(address(bridge.superchainConfig()) == address(_doi.opcmProxy().superchainConfig()), "L1SB-50"); + } + + function assertValidOptimismMintableERC20Factory(DeployOPChainInput) internal view { + OptimismMintableERC20Factory factory = optimismMintableERC20FactoryProxy(); + + DeployUtils.assertInitialized({ _contractAddress: address(factory), _slot: 0, _offset: 0 }); + + require(factory.BRIDGE() == address(l1StandardBridgeProxy()), "MERC20F-10"); + require(factory.bridge() == address(l1StandardBridgeProxy()), "MERC20F-20"); + } + + function assertValidL1ERC721Bridge(DeployOPChainInput _doi) internal { + L1ERC721Bridge bridge = l1ERC721BridgeProxy(); + + DeployUtils.assertInitialized({ _contractAddress: address(bridge), _slot: 0, _offset: 0 }); + + require(address(bridge.OTHER_BRIDGE()) == Predeploys.L2_ERC721_BRIDGE, "L721B-10"); + require(address(bridge.otherBridge()) == Predeploys.L2_ERC721_BRIDGE, "L721B-20"); + + require(address(bridge.MESSENGER()) == address(l1CrossDomainMessengerProxy()), "L721B-30"); + require(address(bridge.messenger()) == address(l1CrossDomainMessengerProxy()), "L721B-40"); + require(address(bridge.superchainConfig()) == address(_doi.opcmProxy().superchainConfig()), "L721B-50"); + } + + function assertValidOptimismPortal(DeployOPChainInput _doi) internal { + OptimismPortal2 portal = optimismPortalProxy(); + ISuperchainConfig superchainConfig = ISuperchainConfig(address(_doi.opcmProxy().superchainConfig())); + + require(address(portal.disputeGameFactory()) == address(disputeGameFactoryProxy()), "PORTAL-10"); + require(address(portal.systemConfig()) == address(systemConfigProxy()), "PORTAL-20"); + require(address(portal.superchainConfig()) == address(superchainConfig), "PORTAL-30"); + require(portal.guardian() == superchainConfig.guardian(), "PORTAL-40"); + require(portal.paused() == superchainConfig.paused(), "PORTAL-50"); + require(portal.l2Sender() == Constants.DEFAULT_L2_SENDER, "PORTAL-60"); + + // This slot is the custom gas token _balance and this check ensures + // that it stays unset for forwards compatibility with custom gas token. + require(vm.load(address(portal), bytes32(uint256(61))) == bytes32(0)); + } + + function assertValidDisputeGameFactory(DeployOPChainInput) internal view { + DisputeGameFactory factory = disputeGameFactoryProxy(); + + DeployUtils.assertInitialized({ _contractAddress: address(factory), _slot: 0, _offset: 0 }); + + require( + address(factory.gameImpls(GameTypes.PERMISSIONED_CANNON)) == address(permissionedDisputeGame()), "DF-10" + ); + require(factory.owner() == address(opChainProxyAdmin()), "DF-20"); + } + + function assertValidDelayedWETHs(DeployOPChainInput) internal view { + // TODO add in once FP support is added. + } +} + +contract DeployOPChain is Script { + // -------- Core Deployment Methods -------- + + function run(DeployOPChainInput _doi, DeployOPChainOutput _doo) public { + OPContractsManager opcmProxy = _doi.opcmProxy(); + + OPContractsManager.Roles memory roles = OPContractsManager.Roles({ + opChainProxyAdminOwner: _doi.opChainProxyAdminOwner(), + systemConfigOwner: _doi.systemConfigOwner(), + batcher: _doi.batcher(), + unsafeBlockSigner: _doi.unsafeBlockSigner(), + proposer: _doi.proposer(), + challenger: _doi.challenger() + }); + OPContractsManager.DeployInput memory deployInput = OPContractsManager.DeployInput({ + roles: roles, + basefeeScalar: _doi.basefeeScalar(), + blobBasefeeScalar: _doi.blobBaseFeeScalar(), + l2ChainId: _doi.l2ChainId(), + startingAnchorRoots: _doi.startingAnchorRoots() + }); + + vm.broadcast(msg.sender); + OPContractsManager.DeployOutput memory deployOutput = opcmProxy.deploy(deployInput); + + vm.label(address(deployOutput.opChainProxyAdmin), "opChainProxyAdmin"); + vm.label(address(deployOutput.addressManager), "addressManager"); + vm.label(address(deployOutput.l1ERC721BridgeProxy), "l1ERC721BridgeProxy"); + vm.label(address(deployOutput.systemConfigProxy), "systemConfigProxy"); + vm.label(address(deployOutput.optimismMintableERC20FactoryProxy), "optimismMintableERC20FactoryProxy"); + vm.label(address(deployOutput.l1StandardBridgeProxy), "l1StandardBridgeProxy"); + vm.label(address(deployOutput.l1CrossDomainMessengerProxy), "l1CrossDomainMessengerProxy"); + vm.label(address(deployOutput.optimismPortalProxy), "optimismPortalProxy"); + vm.label(address(deployOutput.disputeGameFactoryProxy), "disputeGameFactoryProxy"); + vm.label(address(deployOutput.anchorStateRegistryProxy), "anchorStateRegistryProxy"); + vm.label(address(deployOutput.anchorStateRegistryImpl), "anchorStateRegistryImpl"); + // vm.label(address(deployOutput.faultDisputeGame), "faultDisputeGame"); + vm.label(address(deployOutput.permissionedDisputeGame), "permissionedDisputeGame"); + vm.label(address(deployOutput.delayedWETHPermissionedGameProxy), "delayedWETHPermissionedGameProxy"); + vm.label(address(deployOutput.delayedWETHPermissionlessGameProxy), "delayedWETHPermissionlessGameProxy"); + + _doo.set(_doo.opChainProxyAdmin.selector, address(deployOutput.opChainProxyAdmin)); + _doo.set(_doo.addressManager.selector, address(deployOutput.addressManager)); + _doo.set(_doo.l1ERC721BridgeProxy.selector, address(deployOutput.l1ERC721BridgeProxy)); + _doo.set(_doo.systemConfigProxy.selector, address(deployOutput.systemConfigProxy)); + _doo.set( + _doo.optimismMintableERC20FactoryProxy.selector, address(deployOutput.optimismMintableERC20FactoryProxy) + ); + _doo.set(_doo.l1StandardBridgeProxy.selector, address(deployOutput.l1StandardBridgeProxy)); + _doo.set(_doo.l1CrossDomainMessengerProxy.selector, address(deployOutput.l1CrossDomainMessengerProxy)); + _doo.set(_doo.optimismPortalProxy.selector, address(deployOutput.optimismPortalProxy)); + _doo.set(_doo.disputeGameFactoryProxy.selector, address(deployOutput.disputeGameFactoryProxy)); + _doo.set(_doo.anchorStateRegistryProxy.selector, address(deployOutput.anchorStateRegistryProxy)); + _doo.set(_doo.anchorStateRegistryImpl.selector, address(deployOutput.anchorStateRegistryImpl)); + // _doo.set(_doo.faultDisputeGame.selector, address(deployOutput.faultDisputeGame)); + _doo.set(_doo.permissionedDisputeGame.selector, address(deployOutput.permissionedDisputeGame)); + _doo.set(_doo.delayedWETHPermissionedGameProxy.selector, address(deployOutput.delayedWETHPermissionedGameProxy)); + _doo.set( + _doo.delayedWETHPermissionlessGameProxy.selector, address(deployOutput.delayedWETHPermissionlessGameProxy) + ); - _dso.checkOutput(); + _doo.checkOutput(_doi); } // -------- Utilities -------- - function etchIOContracts() internal returns (DeployOPChainInput dsi_, DeployOPChainOutput dso_) { - (dsi_, dso_) = getIOContracts(); - vm.etch(address(dsi_), type(DeployOPChainInput).runtimeCode); - vm.etch(address(dso_), type(DeployOPChainOutput).runtimeCode); + function etchIOContracts() public returns (DeployOPChainInput doi_, DeployOPChainOutput doo_) { + (doi_, doo_) = getIOContracts(); + vm.etch(address(doi_), type(DeployOPChainInput).runtimeCode); + vm.etch(address(doo_), type(DeployOPChainOutput).runtimeCode); } - function getIOContracts() public view returns (DeployOPChainInput dsi_, DeployOPChainOutput dso_) { - dsi_ = DeployOPChainInput(DeployUtils.toIOAddress(msg.sender, "optimism.DeployOPChainInput")); - dso_ = DeployOPChainOutput(DeployUtils.toIOAddress(msg.sender, "optimism.DeployOPChainOutput")); + function getIOContracts() public view returns (DeployOPChainInput doi_, DeployOPChainOutput doo_) { + doi_ = DeployOPChainInput(DeployUtils.toIOAddress(msg.sender, "optimism.DeployOPChainInput")); + doo_ = DeployOPChainOutput(DeployUtils.toIOAddress(msg.sender, "optimism.DeployOPChainOutput")); } } diff --git a/packages/contracts-bedrock/scripts/DeploySuperchain.s.sol b/packages/contracts-bedrock/scripts/DeploySuperchain.s.sol index 8a3e004b2c10c..7726d5709076d 100644 --- a/packages/contracts-bedrock/scripts/DeploySuperchain.s.sol +++ b/packages/contracts-bedrock/scripts/DeploySuperchain.s.sol @@ -2,6 +2,7 @@ pragma solidity 0.8.15; import { Script } from "forge-std/Script.sol"; +import { stdToml } from "forge-std/StdToml.sol"; import { SuperchainConfig } from "src/L1/SuperchainConfig.sol"; import { ProtocolVersions, ProtocolVersion } from "src/L1/ProtocolVersions.sol"; @@ -10,269 +11,292 @@ import { Proxy } from "src/universal/Proxy.sol"; import { DeployUtils } from "scripts/libraries/DeployUtils.sol"; import { Solarray } from "scripts/libraries/Solarray.sol"; -/** - * This comment block defines the requirements and rationale for the architecture used in this forge - * script, along with other scripts that are being written as new Superchain-first deploy scripts to - * complement the OP Stack Manager. The script architecture is a bit different than a standard forge - * deployment script. - * - * There are three categories of users that are expected to interact with the scripts: - * 1. End users that want to run live contract deployments. - * 2. Solidity developers that want to use or test these script in a standard forge test environment. - * 3. Go developers that want to run the deploy scripts as part of e2e testing with other aspects of the OP Stack. - * - * We want each user to interact with the scripts in the way that's simplest for their use case: - * 1. End users: TOML input files that define config, and TOML output files with all output data. - * 2. Solidity developers: Direct calls to the script with input structs and output structs. - * 3. Go developers: The forge scripts can be executed directly in Go. - * - * The following architecture is used to meet the requirements of each user. We use this file's - * `DeploySuperchain` script as an example, but it applies to other scripts as well. - * - * This `DeploySuperchain.s.sol` file contains three contracts: - * 1. `DeploySuperchainInput`: Responsible for parsing, storing, and exposing the input data. - * 2. `DeploySuperchainOutput`: Responsible for storing and exposing the output data. - * 3. `DeploySuperchain`: The core script that executes the deployment. It reads inputs from the - * input contract, and writes outputs to the output contract. - * - * Because the core script performs calls to the input and output contracts, Go developers can - * intercept calls to these addresses (analogous to how forge intercepts calls to the `Vm` address - * to execute cheatcodes), to avoid the need for file I/O or hardcoding the input/output structs. - * - * Public getter methods on the input and output contracts allow individual fields to be accessed - * in a strong, type-safe manner (as opposed to a single struct getter where the caller may - * inadvertently transpose two addresses, for example). - * - * Each deployment step in the core deploy script is modularized into its own function that performs - * the deploy and sets the output on the Output contract, allowing for easy composition and testing - * of deployment steps. The output setter methods requires keying off the four-byte selector of the - * each output field's getter method, ensuring that the output is set for the correct field and - * minimizing the amount of boilerplate needed for each output field. - * - * This script doubles as a reference for documenting the pattern used and therefore contains - * comments explaining the patterns used. Other scripts are not expected to have this level of - * documentation. - * - * Additionally, we intentionally use "Input" and "Output" terminology to clearly distinguish these - * scripts from the existing ones that "Config" and "Artifacts" terminology. - */ - -contract DeploySuperchainInput { - // The input struct contains all the input data required for the deployment. - struct Input { - Roles roles; - bool paused; - ProtocolVersion requiredProtocolVersion; - ProtocolVersion recommendedProtocolVersion; - } - - struct Roles { - address proxyAdminOwner; - address protocolVersionsOwner; - address guardian; - } - - // This flag tells us if all inputs have been set. An `input()` getter method that returns all - // inputs reverts if this flag is false. This ensures the deploy script cannot proceed until all - // inputs are validated and set. - bool public inputSet = false; - - // The full input struct is kept in storage. It is not exposed because the return type would be - // a tuple, and it's more convenient for the return type to be the struct itself. Therefore the - // struct is exposed via the `input()` getter method below. - Input internal inputs; - - // Load the input from a TOML file. - function loadInputFile(string memory _infile) public { - _infile; - Input memory parsedInput; - loadInput(parsedInput); - require(false, "DeploySuperchainInput: not implemented"); - } - - // Load the input from a struct. - function loadInput(Input memory _input) public { - // As a defensive measure, we only allow inputs to be set once. - require(!inputSet, "DeploySuperchainInput: input already set"); - - // All assertions on inputs happen here. You cannot set any inputs in Solidity unless - // they're all valid. For Go testing, the input and outputs are set individually by - // treating the input and output contracts as precompiles and intercepting calls to them. - require(_input.roles.proxyAdminOwner != address(0), "DeploySuperchainInput: null proxyAdminOwner"); - require(_input.roles.protocolVersionsOwner != address(0), "DeploySuperchainInput: null protocolVersionsOwner"); - require(_input.roles.guardian != address(0), "DeploySuperchainInput: null guardian"); - - // We now set all values in storage. - inputSet = true; - inputs = _input; +import { BaseDeployIO } from "scripts/utils/BaseDeployIO.sol"; + +// This comment block defines the requirements and rationale for the architecture used in this forge +// script, along with other scripts that are being written as new Superchain-first deploy scripts to +// complement the OP Contracts Manager. The script architecture is a bit different than a standard forge +// deployment script. +// +// There are three categories of users that are expected to interact with the scripts: +// 1. End users that want to run live contract deployments. These users are expected to run these scripts via +// 'op-deployer' which uses a go interface to interact with the scripts. +// 2. Solidity developers that want to use or test these scripts in a standard forge test environment. +// 3. Go developers that want to run the deploy scripts as part of e2e testing with other aspects of the OP Stack. +// +// We want each user to interact with the scripts in the way that's simplest for their use case: +// 1. Solidity developers: Direct calls to the script, with the input and output contracts configured. +// 2. Go developers: The forge scripts can be executed directly in Go. +// +// The following architecture is used to meet the requirements of each user. We use this file's +// `DeploySuperchain` script as an example, but it applies to other scripts as well. +// +// This `DeploySuperchain.s.sol` file contains three contracts: +// 1. `DeploySuperchainInput`: Responsible for parsing, storing, and exposing the input data. +// 2. `DeploySuperchainOutput`: Responsible for storing and exposing the output data. +// 3. `DeploySuperchain`: The core script that executes the deployment. It reads inputs from the +// input contract, and writes outputs to the output contract. +// +// Because the core script performs calls to the input and output contracts, Go developers can +// intercept calls to these addresses (analogous to how forge intercepts calls to the `Vm` address +// to execute cheatcodes), to avoid the need for hardcoding the input/output values. +// +// Public getter methods on the input and output contracts allow individual fields to be accessed +// in a strong, type-safe manner (as opposed to a single struct getter where the caller may +// inadvertently transpose two addresses, for example). +// +// Each deployment step in the core deploy script is modularized into its own function that performs +// the deploy and sets the output on the Output contract, allowing for easy composition and testing +// of deployment steps. The output setter methods requires keying off the four-byte selector of +// each output field's getter method, ensuring that the output is set for the correct field and +// minimizing the amount of boilerplate needed for each output field. +// +// This script doubles as a reference for documenting the pattern used and therefore contains +// comments explaining the patterns used. Other scripts are not expected to have this level of +// documentation. +// +// Additionally, we intentionally use "Input" and "Output" terminology to clearly distinguish these +// scripts from the existing ones that use the "Config" and "Artifacts" terminology. Within scripts +// we use variable names that are shorthand for the full contract names, for example: +// - `dsi` for DeploySuperchainInput +// - `dso` for DeploySuperchainOutput +// - `dio` for DeployImplementationsInput +// - `dio` for DeployImplementationsOutput +// - `doo` for DeployOPChainInput +// - `doo` for DeployOPChainOutput +// - etc. + +// All contracts of the form `Deploy<X>Input` should inherit from `BaseDeployIO`, as it provides +// shared functionality for all deploy scripts, such as access to cheat codes. +contract DeploySuperchainInput is BaseDeployIO { + using stdToml for string; + + // All inputs are set in storage individually. We put any roles first, followed by the remaining + // inputs. Inputs are internal and prefixed with an underscore, because we will expose a getter + // method that returns the input value. We use a getter method to allow us to make assertions on + // the input to ensure it's valid before returning it. We also intentionally do not use a struct + // to hold all inputs, because as features are developed the set of inputs will change, and + // modifying structs in Solidity is not very simple. + + // Role inputs. + address internal _guardian; + address internal _protocolVersionsOwner; + address internal _superchainProxyAdminOwner; + + // Other inputs. + bool internal _paused; + ProtocolVersion internal _recommendedProtocolVersion; + ProtocolVersion internal _requiredProtocolVersion; + + // These `set` methods let each input be set individually. The selector of an input's getter method + // is used to determine which field to set. + function set(bytes4 _sel, address _address) public { + require(_address != address(0), "DeploySuperchainInput: cannot set zero address"); + if (_sel == this.guardian.selector) _guardian = _address; + else if (_sel == this.protocolVersionsOwner.selector) _protocolVersionsOwner = _address; + else if (_sel == this.superchainProxyAdminOwner.selector) _superchainProxyAdminOwner = _address; + else revert("DeploySuperchainInput: unknown selector"); } - function assertInputSet() internal view { - require(inputSet, "DeploySuperchainInput: input not set"); + function set(bytes4 _sel, bool _value) public { + if (_sel == this.paused.selector) _paused = _value; + else revert("DeploySuperchainInput: unknown selector"); } - // This exposes the full input data as a struct, and it reverts if the input has not been set. - function input() public view returns (Input memory) { - assertInputSet(); - return inputs; + function set(bytes4 _sel, ProtocolVersion _value) public { + require(ProtocolVersion.unwrap(_value) != 0, "DeploySuperchainInput: cannot set null protocol version"); + if (_sel == this.recommendedProtocolVersion.selector) _recommendedProtocolVersion = _value; + else if (_sel == this.requiredProtocolVersion.selector) _requiredProtocolVersion = _value; + else revert("DeploySuperchainInput: unknown selector"); } - // Each field of the input struct is exposed via it's own getter method. Using public storage - // variables here would be more verbose, but would also be more error-prone, as it would - // require the caller to remember to check the `inputSet` flag before accessing any of the - // fields. With getter methods, we can be sure that the input is set before accessing any field. + // Each input field is exposed via it's own getter method. Using public storage variables here + // would be less verbose, but would also be more error-prone, as it would require the caller to + // validate that each input is set before accessing it. With getter methods, we can automatically + // validate that each input is set before allowing any field to be accessed. - function proxyAdminOwner() public view returns (address) { - assertInputSet(); - return inputs.roles.proxyAdminOwner; + function superchainProxyAdminOwner() public view returns (address) { + require(_superchainProxyAdminOwner != address(0), "DeploySuperchainInput: superchainProxyAdminOwner not set"); + return _superchainProxyAdminOwner; } function protocolVersionsOwner() public view returns (address) { - assertInputSet(); - return inputs.roles.protocolVersionsOwner; + require(_protocolVersionsOwner != address(0), "DeploySuperchainInput: protocolVersionsOwner not set"); + return _protocolVersionsOwner; } function guardian() public view returns (address) { - assertInputSet(); - return inputs.roles.guardian; + require(_guardian != address(0), "DeploySuperchainInput: guardian not set"); + return _guardian; } function paused() public view returns (bool) { - assertInputSet(); - return inputs.paused; + return _paused; } function requiredProtocolVersion() public view returns (ProtocolVersion) { - assertInputSet(); - return inputs.requiredProtocolVersion; + require( + ProtocolVersion.unwrap(_requiredProtocolVersion) != 0, + "DeploySuperchainInput: requiredProtocolVersion not set" + ); + return _requiredProtocolVersion; } function recommendedProtocolVersion() public view returns (ProtocolVersion) { - assertInputSet(); - return inputs.recommendedProtocolVersion; + require( + ProtocolVersion.unwrap(_recommendedProtocolVersion) != 0, + "DeploySuperchainInput: recommendedProtocolVersion not set" + ); + return _recommendedProtocolVersion; } } -contract DeploySuperchainOutput { - // The output struct contains all the output data from the deployment. - struct Output { - ProxyAdmin superchainProxyAdmin; - SuperchainConfig superchainConfigImpl; - SuperchainConfig superchainConfigProxy; - ProtocolVersions protocolVersionsImpl; - ProtocolVersions protocolVersionsProxy; - } - - // We use a similar pattern as the input contract to expose outputs. Because outputs are set - // individually, and deployment steps are modular and composable, we do not have an equivalent - // to the overall `inputSet` variable. However, we do hold everything in a struct, then - // similarly expose each field via a getter method. This getter method reverts if the output has - // not been set, ensuring that the caller cannot access any output fields until they have been set. - Output internal outputs; +// All contracts of the form `Deploy<X>Output` should inherit from `BaseDeployIO`, as it provides +// shared functionality for all deploy scripts, such as access to cheat codes. +contract DeploySuperchainOutput is BaseDeployIO { + // All outputs are stored in storage individually, with the same rationale as doing so for + // inputs, and the same pattern is used below to expose the outputs. + ProtocolVersions internal _protocolVersionsImpl; + ProtocolVersions internal _protocolVersionsProxy; + SuperchainConfig internal _superchainConfigImpl; + SuperchainConfig internal _superchainConfigProxy; + ProxyAdmin internal _superchainProxyAdmin; // This method lets each field be set individually. The selector of an output's getter method // is used to determine which field to set. function set(bytes4 sel, address _address) public { - if (sel == this.superchainProxyAdmin.selector) outputs.superchainProxyAdmin = ProxyAdmin(_address); - else if (sel == this.superchainConfigImpl.selector) outputs.superchainConfigImpl = SuperchainConfig(_address); - else if (sel == this.superchainConfigProxy.selector) outputs.superchainConfigProxy = SuperchainConfig(_address); - else if (sel == this.protocolVersionsImpl.selector) outputs.protocolVersionsImpl = ProtocolVersions(_address); - else if (sel == this.protocolVersionsProxy.selector) outputs.protocolVersionsProxy = ProtocolVersions(_address); + require(_address != address(0), "DeploySuperchainOutput: cannot set zero address"); + if (sel == this.superchainProxyAdmin.selector) _superchainProxyAdmin = ProxyAdmin(_address); + else if (sel == this.superchainConfigImpl.selector) _superchainConfigImpl = SuperchainConfig(_address); + else if (sel == this.superchainConfigProxy.selector) _superchainConfigProxy = SuperchainConfig(_address); + else if (sel == this.protocolVersionsImpl.selector) _protocolVersionsImpl = ProtocolVersions(_address); + else if (sel == this.protocolVersionsProxy.selector) _protocolVersionsProxy = ProtocolVersions(_address); else revert("DeploySuperchainOutput: unknown selector"); } - // Save the output to a TOML file. - function writeOutputFile(string memory _outfile) public pure { - _outfile; - require(false, "DeploySuperchainOutput: not implemented"); - } - - function output() public view returns (Output memory) { - return outputs; - } - - function checkOutput() public view { + // This function can be called to ensure all outputs are correct. + // It fetches the output values using external calls to the getter methods for safety. + function checkOutput(DeploySuperchainInput _dsi) public { address[] memory addrs = Solarray.addresses( - address(outputs.superchainProxyAdmin), - address(outputs.superchainConfigImpl), - address(outputs.superchainConfigProxy), - address(outputs.protocolVersionsImpl), - address(outputs.protocolVersionsProxy) + address(this.superchainProxyAdmin()), + address(this.superchainConfigImpl()), + address(this.superchainConfigProxy()), + address(this.protocolVersionsImpl()), + address(this.protocolVersionsProxy()) ); DeployUtils.assertValidContractAddresses(addrs); + + // To read the implementations we prank as the zero address due to the proxyCallIfNotAdmin modifier. + vm.startPrank(address(0)); + address actualSuperchainConfigImpl = Proxy(payable(address(_superchainConfigProxy))).implementation(); + address actualProtocolVersionsImpl = Proxy(payable(address(_protocolVersionsProxy))).implementation(); + vm.stopPrank(); + + require(actualSuperchainConfigImpl == address(_superchainConfigImpl), "100"); + require(actualProtocolVersionsImpl == address(_protocolVersionsImpl), "200"); + + // TODO Also add the assertions for the implementation contracts from ChainAssertions.sol + assertValidDeploy(_dsi); } function superchainProxyAdmin() public view returns (ProxyAdmin) { - DeployUtils.assertValidContractAddress(address(outputs.superchainProxyAdmin)); - return outputs.superchainProxyAdmin; + // This does not have to be a contract address, it could be an EOA. + return _superchainProxyAdmin; } function superchainConfigImpl() public view returns (SuperchainConfig) { - DeployUtils.assertValidContractAddress(address(outputs.superchainConfigImpl)); - return outputs.superchainConfigImpl; + DeployUtils.assertValidContractAddress(address(_superchainConfigImpl)); + return _superchainConfigImpl; } function superchainConfigProxy() public view returns (SuperchainConfig) { - DeployUtils.assertValidContractAddress(address(outputs.superchainConfigProxy)); - return outputs.superchainConfigProxy; + DeployUtils.assertValidContractAddress(address(_superchainConfigProxy)); + return _superchainConfigProxy; } function protocolVersionsImpl() public view returns (ProtocolVersions) { - DeployUtils.assertValidContractAddress(address(outputs.protocolVersionsImpl)); - return outputs.protocolVersionsImpl; + DeployUtils.assertValidContractAddress(address(_protocolVersionsImpl)); + return _protocolVersionsImpl; } function protocolVersionsProxy() public view returns (ProtocolVersions) { - DeployUtils.assertValidContractAddress(address(outputs.protocolVersionsProxy)); - return outputs.protocolVersionsProxy; + DeployUtils.assertValidContractAddress(address(_protocolVersionsProxy)); + return _protocolVersionsProxy; } -} -// For all broadcasts in this script we explicitly specify the deployer as `msg.sender` because for -// testing we deploy this script from a test contract. If we provide no argument, the foundry -// default sender is be the broadcaster during test, but the broadcaster needs to be the deployer -// since they are set to the initial proxy admin owner. -contract DeploySuperchain is Script { - // -------- Core Deployment Methods -------- - - // This entrypoint is for end-users to deploy from an input file and write to an output file. - // In this usage, we don't need the input and output contract functionality, so we deploy them - // here and abstract that architectural detail away from the end user. - function run(string memory _infile) public { - // End-user without file IO, so etch the IO helper contracts. - (DeploySuperchainInput dsi, DeploySuperchainOutput dso) = etchIOContracts(); - - // Load the input file into the input contract. - dsi.loadInputFile(_infile); - - // Run the deployment script and write outputs to the DeploySuperchainOutput contract. - run(dsi, dso); + // -------- Deployment Assertions -------- + function assertValidDeploy(DeploySuperchainInput _dsi) public { + assertValidSuperchainProxyAdmin(_dsi); + assertValidSuperchainConfig(_dsi); + assertValidProtocolVersions(_dsi); + } - // Write the output data to a file. The file - string memory outfile = ""; // This will be derived from input file name, e.g. `foo.in.toml` -> `foo.out.toml` - dso.writeOutputFile(outfile); - require(false, "DeploySuperchain: run is not implemented"); + function assertValidSuperchainProxyAdmin(DeploySuperchainInput _dsi) internal view { + require(superchainProxyAdmin().owner() == _dsi.superchainProxyAdminOwner(), "SPA-10"); } - // This entrypoint is for use with Solidity tests, where the input and outputs are structs. - function run(DeploySuperchainInput.Input memory _input) public returns (DeploySuperchainOutput.Output memory) { - // Solidity without file IO, so etch the IO helper contracts. - (DeploySuperchainInput dsi, DeploySuperchainOutput dso) = etchIOContracts(); + function assertValidSuperchainConfig(DeploySuperchainInput _dsi) internal { + // Proxy checks. + SuperchainConfig superchainConfig = superchainConfigProxy(); + DeployUtils.assertInitialized({ _contractAddress: address(superchainConfig), _slot: 0, _offset: 0 }); + require(superchainConfig.guardian() == _dsi.guardian(), "SUPCON-10"); + require(superchainConfig.paused() == _dsi.paused(), "SUPCON-20"); - // Load the input struct into the input contract. - dsi.loadInput(_input); + vm.startPrank(address(0)); + require( + Proxy(payable(address(superchainConfig))).implementation() == address(superchainConfigImpl()), "SUPCON-30" + ); + require(Proxy(payable(address(superchainConfig))).admin() == address(superchainProxyAdmin()), "SUPCON-40"); + vm.stopPrank(); + + // Implementation checks + superchainConfig = superchainConfigImpl(); + require(superchainConfig.guardian() == address(0), "SUPCON-50"); + require(superchainConfig.paused() == false, "SUPCON-60"); + } + + function assertValidProtocolVersions(DeploySuperchainInput _dsi) internal { + // Proxy checks. + ProtocolVersions pv = protocolVersionsProxy(); + DeployUtils.assertInitialized({ _contractAddress: address(pv), _slot: 0, _offset: 0 }); + require(pv.owner() == _dsi.protocolVersionsOwner(), "PV-10"); + require( + ProtocolVersion.unwrap(pv.required()) == ProtocolVersion.unwrap(_dsi.requiredProtocolVersion()), "PV-20" + ); + require( + ProtocolVersion.unwrap(pv.recommended()) == ProtocolVersion.unwrap(_dsi.recommendedProtocolVersion()), + "PV-30" + ); - // Run the deployment script and write outputs to the DeploySuperchainOutput contract. - run(dsi, dso); + vm.startPrank(address(0)); + require(Proxy(payable(address(pv))).implementation() == address(protocolVersionsImpl()), "PV-40"); + require(Proxy(payable(address(pv))).admin() == address(superchainProxyAdmin()), "PV-50"); + vm.stopPrank(); - // Return the output struct from the output contract. - return dso.output(); + // Implementation checks. + pv = protocolVersionsImpl(); + require(pv.owner() == address(0xdead), "PV-60"); + require(ProtocolVersion.unwrap(pv.required()) == 0, "PV-70"); + require(ProtocolVersion.unwrap(pv.recommended()) == 0, "PV-80"); } +} + +// For all broadcasts in this script we explicitly specify the deployer as `msg.sender` because for +// testing we deploy this script from a test contract. If we provide no argument, the foundry +// default sender would be the broadcaster during test, but the broadcaster needs to be the deployer +// since they are set to the initial proxy admin owner. +contract DeploySuperchain is Script { + // -------- Core Deployment Methods -------- - // This entrypoint is useful for testing purposes, as it doesn't use any file I/O. function run(DeploySuperchainInput _dsi, DeploySuperchainOutput _dso) public { - // Verify that the input contract has been set. - require(_dsi.inputSet(), "DeploySuperchain: input not set"); + // Notice that we do not do any explicit verification here that inputs are set. This is because + // the verification happens elsewhere: + // - Getter methods on the input contract provide sanity checks that values are set, when applicable. + // - The individual methods below that we use to compose the deployment are responsible for handling + // their own verification. + // This pattern ensures that other deploy scripts that might compose these contracts and + // methods in different ways are still protected from invalid inputs without need to implement + // additional verification logic. // Deploy the proxy admin, with the owner set to the deployer. deploySuperchainProxyAdmin(_dsi, _dso); @@ -286,7 +310,7 @@ contract DeploySuperchain is Script { transferProxyAdminOwnership(_dsi, _dso); // Output assertions, to make sure outputs were assigned correctly. - _dso.checkOutput(); + _dso.checkOutput(_dsi); } // -------- Deployment Steps -------- @@ -294,7 +318,7 @@ contract DeploySuperchain is Script { function deploySuperchainProxyAdmin(DeploySuperchainInput, DeploySuperchainOutput _dso) public { // Deploy the proxy admin, with the owner set to the deployer. // We explicitly specify the deployer as `msg.sender` because for testing we deploy this script from a test - // contract. If we provide no argument, the foundry default sender is be the broadcaster during test, but the + // contract. If we provide no argument, the foundry default sender would be the broadcaster during test, but the // broadcaster needs to be the deployer since they are set to the initial proxy admin owner. vm.broadcast(msg.sender); ProxyAdmin superchainProxyAdmin = new ProxyAdmin(msg.sender); @@ -362,23 +386,28 @@ contract DeploySuperchain is Script { } function transferProxyAdminOwnership(DeploySuperchainInput _dsi, DeploySuperchainOutput _dso) public { - address proxyAdminOwner = _dsi.proxyAdminOwner(); + address superchainProxyAdminOwner = _dsi.superchainProxyAdminOwner(); ProxyAdmin superchainProxyAdmin = _dso.superchainProxyAdmin(); DeployUtils.assertValidContractAddress(address(superchainProxyAdmin)); vm.broadcast(msg.sender); - superchainProxyAdmin.transferOwnership(proxyAdminOwner); + superchainProxyAdmin.transferOwnership(superchainProxyAdminOwner); } // -------- Utilities -------- - function etchIOContracts() internal returns (DeploySuperchainInput dsi_, DeploySuperchainOutput dso_) { + // This etches the IO contracts into memory so that we can use them in tests. + // When interacting with the script programmatically (e.g. in a Solidity test), this must be called. + function etchIOContracts() public returns (DeploySuperchainInput dsi_, DeploySuperchainOutput dso_) { (dsi_, dso_) = getIOContracts(); vm.etch(address(dsi_), type(DeploySuperchainInput).runtimeCode); vm.etch(address(dso_), type(DeploySuperchainOutput).runtimeCode); + vm.allowCheatcodes(address(dsi_)); + vm.allowCheatcodes(address(dso_)); } + // This returns the addresses of the IO contracts for this script. function getIOContracts() public view returns (DeploySuperchainInput dsi_, DeploySuperchainOutput dso_) { dsi_ = DeploySuperchainInput(DeployUtils.toIOAddress(msg.sender, "optimism.DeploySuperchainInput")); dso_ = DeploySuperchainOutput(DeployUtils.toIOAddress(msg.sender, "optimism.DeploySuperchainOutput")); diff --git a/packages/contracts-bedrock/scripts/L2Genesis.s.sol b/packages/contracts-bedrock/scripts/L2Genesis.s.sol index 7d45686539360..ceae376ee5c2d 100644 --- a/packages/contracts-bedrock/scripts/L2Genesis.s.sol +++ b/packages/contracts-bedrock/scripts/L2Genesis.s.sol @@ -1,31 +1,41 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Testing import { Script } from "forge-std/Script.sol"; import { console2 as console } from "forge-std/console2.sol"; -import { Deployer } from "scripts/deploy/Deployer.sol"; +import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; +// Scripts +import { Deployer } from "scripts/deploy/Deployer.sol"; import { Config, OutputMode, OutputModeUtils, Fork, ForkUtils, LATEST_FORK } from "scripts/libraries/Config.sol"; import { Artifacts } from "scripts/Artifacts.s.sol"; import { DeployConfig } from "scripts/deploy/DeployConfig.s.sol"; -import { Predeploys } from "src/libraries/Predeploys.sol"; -import { Preinstalls } from "src/libraries/Preinstalls.sol"; -import { L2CrossDomainMessenger } from "src/L2/L2CrossDomainMessenger.sol"; -import { L1Block } from "src/L2/L1Block.sol"; -import { GasPriceOracle } from "src/L2/GasPriceOracle.sol"; -import { L2StandardBridge } from "src/L2/L2StandardBridge.sol"; -import { L2ERC721Bridge } from "src/L2/L2ERC721Bridge.sol"; +import { Process } from "scripts/libraries/Process.sol"; +import { SetPreinstalls } from "scripts/SetPreinstalls.s.sol"; + +// Contracts import { SequencerFeeVault } from "src/L2/SequencerFeeVault.sol"; -import { OptimismMintableERC20Factory } from "src/universal/OptimismMintableERC20Factory.sol"; -import { OptimismMintableERC721Factory } from "src/universal/OptimismMintableERC721Factory.sol"; import { BaseFeeVault } from "src/L2/BaseFeeVault.sol"; import { L1FeeVault } from "src/L2/L1FeeVault.sol"; -import { GovernanceToken } from "src/governance/GovernanceToken.sol"; -import { L1CrossDomainMessenger } from "src/L1/L1CrossDomainMessenger.sol"; -import { L1StandardBridge } from "src/L1/L1StandardBridge.sol"; +import { OptimismSuperchainERC20Beacon } from "src/L2/OptimismSuperchainERC20Beacon.sol"; +import { OptimismMintableERC721Factory } from "src/universal/OptimismMintableERC721Factory.sol"; import { FeeVault } from "src/universal/FeeVault.sol"; -import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; -import { Process } from "scripts/libraries/Process.sol"; +import { GovernanceToken } from "src/governance/GovernanceToken.sol"; + +// Libraries +import { Predeploys } from "src/libraries/Predeploys.sol"; +import { Preinstalls } from "src/libraries/Preinstalls.sol"; + +// Interfaces +import { IOptimismMintableERC20Factory } from "src/universal/interfaces/IOptimismMintableERC20Factory.sol"; +import { IL2StandardBridge } from "src/L2/interfaces/IL2StandardBridge.sol"; +import { IL2ERC721Bridge } from "src/L2/interfaces/IL2ERC721Bridge.sol"; +import { IStandardBridge } from "src/universal/interfaces/IStandardBridge.sol"; +import { ICrossDomainMessenger } from "src/universal/interfaces/ICrossDomainMessenger.sol"; +import { IL2CrossDomainMessenger } from "src/L2/interfaces/IL2CrossDomainMessenger.sol"; +import { IGasPriceOracle } from "src/L2/interfaces/IGasPriceOracle.sol"; +import { IL1Block } from "src/L2/interfaces/IL1Block.sol"; interface IInitializable { function initialize(address _addr) external; @@ -122,6 +132,21 @@ contract L2Genesis is Deployer { runWithOptions(OutputMode.ALL, LATEST_FORK, artifactDependencies()); } + /// @notice This is used by new experimental interop deploy tooling. + function runWithEnv() public { + // The setUp() is skipped (since we insert a custom DeployConfig, and do not use Artifacts) + deployer = makeAddr("deployer"); + runWithOptions( + OutputMode.NONE, + Config.fork(), + L1Dependencies({ + l1CrossDomainMessengerProxy: payable(vm.envAddress("L2GENESIS_L1CrossDomainMessengerProxy")), + l1StandardBridgeProxy: payable(vm.envAddress("L2GENESIS_L1StandardBridgeProxy")), + l1ERC721BridgeProxy: payable(vm.envAddress("L2GENESIS_L1ERC721BridgeProxy")) + }) + ); + } + /// @notice This is used by foundry tests to enable the latest fork with the /// given L1 dependencies. function runWithLatestLocal(L1Dependencies memory _l1Dependencies) public { @@ -254,6 +279,8 @@ contract L2Genesis is Deployer { setL2ToL2CrossDomainMessenger(); // 23 setSuperchainWETH(); // 24 setETHLiquidity(); // 25 + setOptimismSuperchainERC20Factory(); // 26 + setOptimismSuperchainERC20Beacon(); // 27 } } @@ -277,10 +304,10 @@ contract L2Genesis is Deployer { function setL2CrossDomainMessenger(address payable _l1CrossDomainMessengerProxy) public { address impl = _setImplementationCode(Predeploys.L2_CROSS_DOMAIN_MESSENGER); - L2CrossDomainMessenger(impl).initialize({ _l1CrossDomainMessenger: L1CrossDomainMessenger(address(0)) }); + IL2CrossDomainMessenger(impl).initialize({ _l1CrossDomainMessenger: ICrossDomainMessenger(address(0)) }); - L2CrossDomainMessenger(Predeploys.L2_CROSS_DOMAIN_MESSENGER).initialize({ - _l1CrossDomainMessenger: L1CrossDomainMessenger(_l1CrossDomainMessengerProxy) + IL2CrossDomainMessenger(Predeploys.L2_CROSS_DOMAIN_MESSENGER).initialize({ + _l1CrossDomainMessenger: ICrossDomainMessenger(_l1CrossDomainMessengerProxy) }); } @@ -296,10 +323,10 @@ contract L2Genesis is Deployer { impl = _setImplementationCode(Predeploys.L2_STANDARD_BRIDGE); } - L2StandardBridge(payable(impl)).initialize({ _otherBridge: L1StandardBridge(payable(address(0))) }); + IL2StandardBridge(payable(impl)).initialize({ _otherBridge: IStandardBridge(payable(address(0))) }); - L2StandardBridge(payable(Predeploys.L2_STANDARD_BRIDGE)).initialize({ - _otherBridge: L1StandardBridge(_l1StandardBridgeProxy) + IL2StandardBridge(payable(Predeploys.L2_STANDARD_BRIDGE)).initialize({ + _otherBridge: IStandardBridge(_l1StandardBridgeProxy) }); } @@ -307,9 +334,9 @@ contract L2Genesis is Deployer { function setL2ERC721Bridge(address payable _l1ERC721BridgeProxy) public { address impl = _setImplementationCode(Predeploys.L2_ERC721_BRIDGE); - L2ERC721Bridge(impl).initialize({ _l1ERC721Bridge: payable(address(0)) }); + IL2ERC721Bridge(impl).initialize({ _l1ERC721Bridge: payable(address(0)) }); - L2ERC721Bridge(Predeploys.L2_ERC721_BRIDGE).initialize({ _l1ERC721Bridge: payable(_l1ERC721BridgeProxy) }); + IL2ERC721Bridge(Predeploys.L2_ERC721_BRIDGE).initialize({ _l1ERC721Bridge: payable(_l1ERC721BridgeProxy) }); } /// @notice This predeploy is following the safety invariant #2, @@ -333,9 +360,9 @@ contract L2Genesis is Deployer { function setOptimismMintableERC20Factory() public { address impl = _setImplementationCode(Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY); - OptimismMintableERC20Factory(impl).initialize({ _bridge: address(0) }); + IOptimismMintableERC20Factory(impl).initialize({ _bridge: address(0) }); - OptimismMintableERC20Factory(Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY).initialize({ + IOptimismMintableERC20Factory(Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY).initialize({ _bridge: Predeploys.L2_STANDARD_BRIDGE }); } @@ -357,7 +384,7 @@ contract L2Genesis is Deployer { /// @notice This predeploy is following the safety invariant #1. function setL1Block() public { if (cfg.useInterop()) { - string memory cname = "L1BlockInterop"; + string memory cname = "L1BlockIsthmus"; address impl = Predeploys.predeployToCodeNamespace(Predeploys.L1_BLOCK_ATTRIBUTES); console.log("Setting %s implementation at: %s", cname, impl); vm.etch(impl, vm.getDeployedCode(string.concat(cname, ".sol:", cname))); @@ -505,30 +532,35 @@ contract L2Genesis is Deployer { _setImplementationCode(Predeploys.SUPERCHAIN_WETH); } + /// @notice This predeploy is following the safety invariant #1. + /// This contract has no initializer. + function setOptimismSuperchainERC20Factory() internal { + _setImplementationCode(Predeploys.OPTIMISM_SUPERCHAIN_ERC20_FACTORY); + } + + /// @notice This predeploy is following the safety invariant #2. + function setOptimismSuperchainERC20Beacon() internal { + address superchainERC20Impl = Predeploys.OPTIMISM_SUPERCHAIN_ERC20; + console.log("Setting %s implementation at: %s", "OptimismSuperchainERC20", superchainERC20Impl); + vm.etch(superchainERC20Impl, vm.getDeployedCode("OptimismSuperchainERC20.sol:OptimismSuperchainERC20")); + + OptimismSuperchainERC20Beacon beacon = new OptimismSuperchainERC20Beacon(superchainERC20Impl); + address beaconImpl = Predeploys.predeployToCodeNamespace(Predeploys.OPTIMISM_SUPERCHAIN_ERC20_BEACON); + + console.log("Setting %s implementation at: %s", "OptimismSuperchainERC20Beacon", beaconImpl); + vm.etch(beaconImpl, address(beacon).code); + + /// Reset so its not included state dump + vm.etch(address(beacon), ""); + vm.resetNonce(address(beacon)); + } + /// @notice Sets all the preinstalls. - /// Warning: the creator-accounts of the preinstall contracts have 0 nonce values. - /// When performing a regular user-initiated contract-creation of a preinstall, - /// the creation will fail (but nonce will be bumped and not blocked). - /// The preinstalls themselves are all inserted with a nonce of 1, reflecting regular user execution. - function setPreinstalls() internal { - _setPreinstallCode(Preinstalls.MultiCall3); - _setPreinstallCode(Preinstalls.Create2Deployer); - _setPreinstallCode(Preinstalls.Safe_v130); - _setPreinstallCode(Preinstalls.SafeL2_v130); - _setPreinstallCode(Preinstalls.MultiSendCallOnly_v130); - _setPreinstallCode(Preinstalls.SafeSingletonFactory); - _setPreinstallCode(Preinstalls.DeterministicDeploymentProxy); - _setPreinstallCode(Preinstalls.MultiSend_v130); - _setPreinstallCode(Preinstalls.Permit2); - _setPreinstallCode(Preinstalls.SenderCreator_v060); // ERC 4337 v0.6.0 - _setPreinstallCode(Preinstalls.EntryPoint_v060); // ERC 4337 v0.6.0 - _setPreinstallCode(Preinstalls.SenderCreator_v070); // ERC 4337 v0.7.0 - _setPreinstallCode(Preinstalls.EntryPoint_v070); // ERC 4337 v0.7.0 - _setPreinstallCode(Preinstalls.BeaconBlockRoots); - // 4788 sender nonce must be incremented, since it's part of later upgrade-transactions. - // For the upgrade-tx to not create a contract that conflicts with an already-existing copy, - // the nonce must be bumped. - vm.setNonce(Preinstalls.BeaconBlockRootsSender, 1); + function setPreinstalls() public { + address tmpSetPreinstalls = address(uint160(uint256(keccak256("SetPreinstalls")))); + vm.etch(tmpSetPreinstalls, vm.getDeployedCode("SetPreinstalls.s.sol:SetPreinstalls")); + SetPreinstalls(tmpSetPreinstalls).setPreinstalls(); + vm.etch(tmpSetPreinstalls, ""); } /// @notice Activate Ecotone network upgrade. @@ -536,14 +568,14 @@ contract L2Genesis is Deployer { require(Preinstalls.BeaconBlockRoots.code.length > 0, "L2Genesis: must have beacon-block-roots contract"); console.log("Activating ecotone in GasPriceOracle contract"); - vm.prank(L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).DEPOSITOR_ACCOUNT()); - GasPriceOracle(Predeploys.GAS_PRICE_ORACLE).setEcotone(); + vm.prank(IL1Block(Predeploys.L1_BLOCK_ATTRIBUTES).DEPOSITOR_ACCOUNT()); + IGasPriceOracle(Predeploys.GAS_PRICE_ORACLE).setEcotone(); } function activateFjord() public { console.log("Activating fjord in GasPriceOracle contract"); - vm.prank(L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).DEPOSITOR_ACCOUNT()); - GasPriceOracle(Predeploys.GAS_PRICE_ORACLE).setFjord(); + vm.prank(IL1Block(Predeploys.L1_BLOCK_ATTRIBUTES).DEPOSITOR_ACCOUNT()); + IGasPriceOracle(Predeploys.GAS_PRICE_ORACLE).setFjord(); } /// @notice Sets the bytecode in state @@ -555,17 +587,6 @@ contract L2Genesis is Deployer { return impl; } - /// @notice Sets the bytecode in state - function _setPreinstallCode(address _addr) internal { - string memory cname = Preinstalls.getName(_addr); - console.log("Setting %s preinstall code at: %s", cname, _addr); - vm.etch(_addr, Preinstalls.getDeployedCode(_addr, cfg.l2ChainID())); - // during testing in a shared L1/L2 account namespace some preinstalls may already have been inserted and used. - if (vm.getNonce(_addr) == 0) { - vm.setNonce(_addr, 1); - } - } - /// @notice Writes the genesis allocs, i.e. the state dump, to disk function writeGenesisAllocs(string memory _path) public { /// Reset so its not included state dump diff --git a/packages/contracts-bedrock/scripts/SetPreinstalls.s.sol b/packages/contracts-bedrock/scripts/SetPreinstalls.s.sol new file mode 100644 index 0000000000000..46e68a17c941e --- /dev/null +++ b/packages/contracts-bedrock/scripts/SetPreinstalls.s.sol @@ -0,0 +1,50 @@ +// 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 { Preinstalls } from "src/libraries/Preinstalls.sol"; + +/// @title SetPreinstalls +/// @notice Sets all preinstalls in the VM state. There is no default "run()" entrypoint, +/// as this is used in L2Genesis.s.sol, and standalone in the Go test setup for L1 state. +contract SetPreinstalls is Script { + /// @notice Sets all the preinstalls. + /// Warning: the creator-accounts of the preinstall contracts have 0 nonce values. + /// When performing a regular user-initiated contract-creation of a preinstall, + /// the creation will fail (but nonce will be bumped and not blocked). + /// The preinstalls themselves are all inserted with a nonce of 1, reflecting regular user execution. + function setPreinstalls() public { + _setPreinstallCode(Preinstalls.MultiCall3); + _setPreinstallCode(Preinstalls.Create2Deployer); + _setPreinstallCode(Preinstalls.Safe_v130); + _setPreinstallCode(Preinstalls.SafeL2_v130); + _setPreinstallCode(Preinstalls.MultiSendCallOnly_v130); + _setPreinstallCode(Preinstalls.SafeSingletonFactory); + _setPreinstallCode(Preinstalls.DeterministicDeploymentProxy); + _setPreinstallCode(Preinstalls.MultiSend_v130); + _setPreinstallCode(Preinstalls.Permit2); + _setPreinstallCode(Preinstalls.SenderCreator_v060); // ERC 4337 v0.6.0 + _setPreinstallCode(Preinstalls.EntryPoint_v060); // ERC 4337 v0.6.0 + _setPreinstallCode(Preinstalls.SenderCreator_v070); // ERC 4337 v0.7.0 + _setPreinstallCode(Preinstalls.EntryPoint_v070); // ERC 4337 v0.7.0 + _setPreinstallCode(Preinstalls.BeaconBlockRoots); + _setPreinstallCode(Preinstalls.CreateX); + // 4788 sender nonce must be incremented, since it's part of later upgrade-transactions. + // For the upgrade-tx to not create a contract that conflicts with an already-existing copy, + // the nonce must be bumped. + vm.setNonce(Preinstalls.BeaconBlockRootsSender, 1); + } + + /// @notice Sets the bytecode in state + function _setPreinstallCode(address _addr) internal { + string memory cname = Preinstalls.getName(_addr); + console.log("Setting %s preinstall code at: %s", cname, _addr); + vm.etch(_addr, Preinstalls.getDeployedCode(_addr, block.chainid)); + // during testing in a shared L1/L2 account namespace some preinstalls may already have been inserted and used. + if (vm.getNonce(_addr) == 0) { + vm.setNonce(_addr, 1); + } + } +} diff --git a/packages/contracts-bedrock/scripts/autogen/generate-invariant-docs/main.go b/packages/contracts-bedrock/scripts/autogen/generate-invariant-docs/main.go deleted file mode 100644 index 0f0f5c77e63d8..0000000000000 --- a/packages/contracts-bedrock/scripts/autogen/generate-invariant-docs/main.go +++ /dev/null @@ -1,256 +0,0 @@ -package main - -import ( - "flag" - "fmt" - "os" - "path/filepath" - "slices" - "strings" -) - -const ( - NatspecInv = "@custom:invariant" - BaseInvariantGhUrl = "../test/invariants/" -) - -// Contract represents an invariant test contract -type Contract struct { - Name string - FileName string - Docs []InvariantDoc -} - -// InvariantDoc represents the documentation of an invariant -type InvariantDoc struct { - Header string - Desc string - LineNo int -} - -var writtenFiles []string - -// Generate the docs -func main() { - flag.Parse() - if flag.NArg() != 1 { - fmt.Println("Expected path of contracts-bedrock as CLI argument") - os.Exit(1) - } - rootDir := flag.Arg(0) - - invariantsDir := filepath.Join(rootDir, "test/invariants") - fmt.Printf("invariants dir: %s\n", invariantsDir) - docsDir := filepath.Join(rootDir, "invariant-docs") - fmt.Printf("invariant docs dir: %s\n", docsDir) - - // Forge - fmt.Println("Generating docs for forge invariants...") - if err := docGen(invariantsDir, docsDir); err != nil { - fmt.Printf("Failed to generate invariant docs: %v\n", err) - os.Exit(1) - } - - fmt.Println("Generating table-of-contents...") - // Generate an updated table of contents - if err := tocGen(docsDir); err != nil { - fmt.Printf("Failed to generate TOC of docs: %v\n", err) - os.Exit(1) - } - fmt.Println("Done!") -} - -// Lazy-parses all test files in the `test/invariants` directory -// to generate documentation on all invariant tests. -func docGen(invariantsDir, docsDir string) error { - - // Grab all files within the invariants test dir - files, err := os.ReadDir(invariantsDir) - if err != nil { - return fmt.Errorf("error reading directory: %w", err) - } - - // Array to store all found invariant documentation comments. - var docs []Contract - - for _, file := range files { - // Read the contents of the invariant test file. - fileName := file.Name() - filePath := filepath.Join(invariantsDir, fileName) - fileContents, err := os.ReadFile(filePath) - if err != nil { - return fmt.Errorf("error reading file %q: %w", filePath, err) - } - - // Split the file into individual lines and trim whitespace. - lines := strings.Split(string(fileContents), "\n") - for i, line := range lines { - lines[i] = strings.TrimSpace(line) - } - - // Create an object to store all invariant test docs for the current contract - name := strings.Replace(fileName, ".t.sol", "", 1) - contract := Contract{Name: name, FileName: fileName} - - var currentDoc InvariantDoc - - // Loop through all lines to find comments. - for i := 0; i < len(lines); i++ { - line := lines[i] - - // We have an invariant doc - if strings.HasPrefix(line, "/// "+NatspecInv) { - // Assign the header of the invariant doc. - currentDoc = InvariantDoc{ - Header: strings.TrimSpace(strings.Replace(line, "/// "+NatspecInv, "", 1)), - Desc: "", - } - i++ - - // If the header is multi-line, continue appending to the `currentDoc`'s header. - for { - if i >= len(lines) { - break - } - line = lines[i] - i++ - if !(strings.HasPrefix(line, "///") && strings.TrimSpace(line) != "///") { - break - } - currentDoc.Header += " " + strings.TrimSpace(strings.Replace(line, "///", "", 1)) - } - - // Process the description - for { - if i >= len(lines) { - break - } - line = lines[i] - i++ - if !strings.HasPrefix(line, "///") { - break - } - line = strings.TrimSpace(strings.Replace(line, "///", "", 1)) - - // If the line has any contents, insert it into the desc. - // Otherwise, consider it a linebreak. - if len(line) > 0 { - currentDoc.Desc += line + " " - } else { - currentDoc.Desc += "\n" - } - } - - // Set the line number of the test - currentDoc.LineNo = i - - // Add the doc to the contract - contract.Docs = append(contract.Docs, currentDoc) - } - } - - // Add the contract to the array of docs - docs = append(docs, contract) - } - - for _, contract := range docs { - filePath := filepath.Join(docsDir, contract.Name+".md") - alreadyWritten := slices.Contains(writtenFiles, filePath) - - // If the file has already been written, append the extra docs to the end. - // Otherwise, write the file from scratch. - var fileContent string - if alreadyWritten { - existingContent, err := os.ReadFile(filePath) - if err != nil { - return fmt.Errorf("error reading existing file %q: %w", filePath, err) - } - fileContent = string(existingContent) + "\n" + renderContractDoc(contract, false) - } else { - fileContent = renderContractDoc(contract, true) - } - - err = os.WriteFile(filePath, []byte(fileContent), 0644) - if err != nil { - return fmt.Errorf("error writing file %q: %w", filePath, err) - } - - if !alreadyWritten { - writtenFiles = append(writtenFiles, filePath) - } - } - - _, _ = fmt.Fprintf(os.Stderr, - "Generated invariant test documentation for:\n"+ - " - %d contracts\n"+ - " - %d invariant tests\n"+ - "successfully!\n", - len(docs), - func() int { - total := 0 - for _, contract := range docs { - total += len(contract.Docs) - } - return total - }(), - ) - return nil -} - -// Generate a table of contents for all invariant docs and place it in the README. -func tocGen(docsDir string) error { - autoTOCPrefix := "<!-- START autoTOC -->\n" - autoTOCPostfix := "<!-- END autoTOC -->\n" - - files, err := os.ReadDir(docsDir) - if err != nil { - return fmt.Errorf("error reading directory %q: %w", docsDir, err) - } - - // Generate a table of contents section. - var tocList []string - for _, file := range files { - fileName := file.Name() - if fileName != "README.md" { - tocList = append(tocList, fmt.Sprintf("- [%s](./%s)", strings.Replace(fileName, ".md", "", 1), fileName)) - } - } - toc := fmt.Sprintf("%s\n## Table of Contents\n%s\n%s", - autoTOCPrefix, strings.Join(tocList, "\n"), autoTOCPostfix) - - // Write the table of contents to the README. - readmePath := filepath.Join(docsDir, "README.md") - readmeContents, err := os.ReadFile(readmePath) - if err != nil { - return fmt.Errorf("error reading README file %q: %w", readmePath, err) - } - readmeParts := strings.Split(string(readmeContents), autoTOCPrefix) - above := readmeParts[0] - readmeParts = strings.Split(readmeParts[1], autoTOCPostfix) - below := readmeParts[1] - err = os.WriteFile(readmePath, []byte(above+toc+below), 0644) - if err != nil { - return fmt.Errorf("error writing README file %q: %w", readmePath, err) - } - return nil -} - -// Render a `Contract` object into valid markdown. -func renderContractDoc(contract Contract, header bool) string { - var sb strings.Builder - - if header { - sb.WriteString(fmt.Sprintf("# `%s` Invariants\n", contract.Name)) - } - sb.WriteString("\n") - - for i, doc := range contract.Docs { - line := fmt.Sprintf("%s#L%d", contract.FileName, doc.LineNo) - sb.WriteString(fmt.Sprintf("## %s\n**Test:** [`%s`](%s%s)\n\n%s", doc.Header, line, BaseInvariantGhUrl, line, doc.Desc)) - if i != len(contract.Docs)-1 { - sb.WriteString("\n\n") - } - } - - return sb.String() -} diff --git a/packages/contracts-bedrock/scripts/checks/check-interfaces.sh b/packages/contracts-bedrock/scripts/checks/check-interfaces.sh new file mode 100755 index 0000000000000..ed2c8e798eb14 --- /dev/null +++ b/packages/contracts-bedrock/scripts/checks/check-interfaces.sh @@ -0,0 +1,249 @@ +#!/usr/bin/env bash +set -euo pipefail + +# This script checks for ABI consistency between interfaces and their corresponding contracts. +# It compares the ABIs of interfaces (files starting with 'I') with their implementation contracts, +# excluding certain predefined files. Constructors are expected to be represented in interfaces by a +# pseudo-constructor function `__constructor__(...)` with arguments the same as the contract's constructor. +# The script reports any differences found and exits with an error if inconsistencies are detected. +# NOTE: Script is fast enough but could be parallelized if necessary. + +# Parse flags +no_diff=false +if [[ "${1:-}" == "--no-diff" ]]; then + no_diff=true +fi + +# Grab the directory of the contracts-bedrock package +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +CONTRACTS_BASE=$(dirname "$(dirname "$SCRIPT_DIR")") + +# Define contracts that should be excluded from the check +EXCLUDE_CONTRACTS=( + # External dependencies + "IERC20" + "IERC721" + "IERC721Enumerable" + "IERC721Upgradeable" + "IERC721Metadata" + "IERC165" + "IERC165Upgradeable" + "ERC721TokenReceiver" + "ERC1155TokenReceiver" + "ERC777TokensRecipient" + "Guard" + "IProxy" + "Vm" + "VmSafe" + "IMulticall3" + "IERC721TokenReceiver" + "IProxyCreationCallback" + "IBeacon" + + # EAS + "IEAS" + "ISchemaResolver" + "ISchemaRegistry" + + # Kontrol + "KontrolCheatsBase" + + # TODO: Interfaces that need to be fixed + "IOptimismSuperchainERC20" + "IOptimismMintableERC721" + "IOptimismMintableERC20" + "ILegacyMintableERC20" + "IInitializable" + "IPreimageOracle" + "ICrossL2Inbox" + "IL2ToL2CrossDomainMessenger" + "MintableAndBurnable" + "IWETH" + "IDelayedWETH" + "IResolvedDelegateProxy" + + # TODO: Kontrol interfaces that need to be removed + "IL1ERC721Bridge" + "IL1StandardBridge" + "IL1CrossDomainMessenger" + "ISuperchainConfig" + "IOptimismPortal" +) + +# Find all JSON files in the forge-artifacts folder +JSON_FILES=$(find "$CONTRACTS_BASE/forge-artifacts" -type f -name "*.json") + +# Initialize a flag to track if any issues are detected +issues_detected=false + +# Create a temporary file to store files that have already been reported +REPORTED_INTERFACES_FILE=$(mktemp) + +# Clean up the temporary file on exit +cleanup() { + rm -f "$REPORTED_INTERFACES_FILE" +} + +# Trap exit and error signals and call cleanup function +trap cleanup EXIT ERR + +# Check if a contract is excluded +is_excluded() { + for exclude in "${EXCLUDE_CONTRACTS[@]}"; do + if [[ "$exclude" == "$1" ]]; then + return 0 + fi + done + return 1 +} + +# Iterate over all JSON files +for interface_file in $JSON_FILES; do + # Grab the contract name from the file name + contract_name=$(basename "$interface_file" .json | cut -d '.' -f 1) + + # Extract all contract definitions in a single pass + contract_definitions=$(jq -r '.ast.nodes[] | select(.nodeType == "ContractDefinition") | "\(.contractKind),\(.name)"' "$interface_file") + + # Continue if no contract definitions are found + # Can happen in Solidity files that don't declare any contracts/interfaces + if [ -z "$contract_definitions" ]; then + continue + fi + + # Iterate over the found contract definitions and figure out which one + # matches the file name. We do this so that we can figure out if this is an + # interface or a contract based on the contract kind. + found=false + contract_temp="" + contract_kind="" + for definition in $contract_definitions; do + IFS=',' read -r contract_kind contract_temp <<< "$definition" + if [[ "$contract_name" == "$contract_temp" ]]; then + found=true + break + fi + done + + # Continue if no matching contract name is found. Can happen in Solidity + # files where no contracts/interfaces are defined with the same name as the + # file. Still OK because a separate artifact *will* be generated for the + # specific contract/interface. + if [ "$found" = false ]; then + continue + fi + + # If contract kind is not "interface", skip the file + if [ "$contract_kind" != "interface" ]; then + continue + fi + + # If contract name does not start with an "I", throw an error + if [[ "$contract_name" != I* ]]; then + if ! grep -q "^$contract_name$" "$REPORTED_INTERFACES_FILE"; then + echo "$contract_name" >> "$REPORTED_INTERFACES_FILE" + if ! is_excluded "$contract_name"; then + echo "Issue found in ABI for interface $contract_name from file $interface_file." + echo "Interface $contract_name does not start with 'I'." + issues_detected=true + fi + fi + continue + fi + + # Extract contract semver + contract_semver=$(jq -r '.ast.nodes[] | select(.nodeType == "PragmaDirective") | .literals | join("")' "$interface_file") + + # If semver is not exactly "solidity^0.8.0", throw an error + if [ "$contract_semver" != "solidity^0.8.0" ]; then + if ! grep -q "^$contract_name$" "$REPORTED_INTERFACES_FILE"; then + echo "$contract_name" >> "$REPORTED_INTERFACES_FILE" + if ! is_excluded "$contract_name"; then + echo "Issue found in ABI for interface $contract_name from file $interface_file." + echo "Interface $contract_name does not have correct compiler version (MUST be exactly solidity ^0.8.0)." + issues_detected=true + fi + fi + continue + fi + + # Construct the corresponding contract name by removing the leading "I" + contract_basename=${contract_name:1} + corresponding_contract_file="$CONTRACTS_BASE/forge-artifacts/$contract_basename.sol/$contract_basename.json" + + # Skip the file if the corresponding contract file does not exist + if [ ! -f "$corresponding_contract_file" ]; then + continue + fi + + # Extract and compare ABIs excluding constructors + interface_abi=$(jq '[.abi[]]' < "$interface_file") + contract_abi=$(jq '[.abi[]]' < "$corresponding_contract_file") + + # Function to normalize ABI by replacing interface name with contract name. + # Base contracts aren't allowed to inherit from their interfaces in order + # to guarantee a 1:1 match between interfaces and contracts. This means + # that the interface will redefine types in the base contract. We normalize + # the ABI as if the interface and contract are the same name. + normalize_abi() { + # Here we just remove the leading "I" from any contract, enum, or + # struct type. It's not beautiful but it's good enough for now. It + # would miss certain edge cases like if an interface really is using + # the contract type instead of the interface type but that's unlikely + # to happen in practice and should be an easy fix if it does. + local abi="$1" + + # Remove the leading "I" from types. + abi="${abi//\"internalType\": \"contract I/\"internalType\": \"contract }" + abi="${abi//\"internalType\": \"enum I/\"internalType\": \"enum }" + abi="${abi//\"internalType\": \"struct I/\"internalType\": \"struct }" + + # Handle translating pseudo-constructors. + abi=$(echo "$abi" | jq 'map(if .type == "function" and .name == "__constructor__" then .type = "constructor" | del(.name) | del(.outputs) else . end)') + + echo "$abi" + } + + # Normalize the ABIs + normalized_interface_abi=$(normalize_abi "$interface_abi") + normalized_contract_abi=$(normalize_abi "$contract_abi") + + # Use jq to compare the ABIs + if ! diff_result=$(diff -u <(echo "$normalized_interface_abi" | jq 'sort') <(echo "$normalized_contract_abi" | jq 'sort')); then + if ! grep -q "^$contract_name$" "$REPORTED_INTERFACES_FILE"; then + echo "$contract_name" >> "$REPORTED_INTERFACES_FILE" + if ! is_excluded "$contract_name"; then + echo "Issue found in ABI for interface $contract_name from file $interface_file." + echo "Differences found in ABI between interface $contract_name and actual contract $contract_basename." + if [ "$no_diff" = false ]; then + echo "$diff_result" + fi + issues_detected=true + fi + fi + continue + fi +done + +# Check for unnecessary exclusions +for exclude_item in "${EXCLUDE_CONTRACTS[@]}"; do + if ! grep -q "^$exclude_item$" "$REPORTED_INTERFACES_FILE"; then + echo "Warning: $exclude_item is in the exclude list but WAS NOT reported as an issue. It" + echo "may be unnecessary in the EXCLUDE_CONTRACTS list, but you MUST verify this before" + echo "removing it by performing a clean and full build before re-running this script." + fi +done + +# Fail the script if any issues were detected +if [ "$issues_detected" = true ]; then + echo "Issues were detected while validating interface files." + echo "If the interface is an external dependency or should otherwise be excluded from this" + echo "check, add the interface name to the EXCLUDE_CONTRACTS list in the script. This will prevent" + echo "the script from comparing it against a corresponding contract." + echo "IMPORTANT: Interface files are NOT yet generated automatically. You must fix any" + echo "listed discrepancies manually by updating the specified interface file. Automated" + echo "interface generation is dependent on a few Forge bug fixes." + exit 1 +else + exit 0 +fi diff --git a/packages/contracts-bedrock/scripts/checks/check-kontrol-deployment.sh b/packages/contracts-bedrock/scripts/checks/check-kontrol-deployment.sh new file mode 100755 index 0000000000000..bfa78ae35a700 --- /dev/null +++ b/packages/contracts-bedrock/scripts/checks/check-kontrol-deployment.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +set -euo pipefail + +# This script checks if the KontrolDeployment.sol file has changed. Removal of +# the DeploymentSummary.t.sol test file means that our primary risk vector for +# KontrolDeployment.sol is an *accidental* change to the file. Changes must +# therefore be explicitly acknowledged by bumping the hash below. + +# Get relevant directories +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +CONTRACTS_BASE=$(dirname "$(dirname "$SCRIPT_DIR")") + +# Generate the SHA-512 hash using OpenSSL (very portable) +generated_hash=$(openssl dgst -sha512 "${CONTRACTS_BASE}/test/kontrol/deployment/KontrolDeployment.sol" | awk '{print $2}') + +# Define the known hash +known_hash="1664d9c22266b55b43086fa03c0e9d0447b092abc86cba79b86ad36c49167062c2b58a78757a20a5fd257d307599edce8f8f604cc6b2ee86715144015a8c977d" + +# Compare the generated hash with the known hash +if [ "$generated_hash" = "$known_hash" ]; then + echo "KontrolDeployment.sol matches the known hash." +else + echo "KontrolDeployment.sol does not match the known hash. Please update the known hash." + echo "Old hash: $known_hash" + echo "New hash: $generated_hash" + exit 1 +fi diff --git a/packages/contracts-bedrock/scripts/checks/check-semver-diff.sh b/packages/contracts-bedrock/scripts/checks/check-semver-diff.sh new file mode 100755 index 0000000000000..15a3ebb50da20 --- /dev/null +++ b/packages/contracts-bedrock/scripts/checks/check-semver-diff.sh @@ -0,0 +1,88 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Grab the directory of the contracts-bedrock package. +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) + +# Load semver-utils. +# shellcheck source=/dev/null +source "$SCRIPT_DIR/utils/semver-utils.sh" + +# Path to semver-lock.json. +SEMVER_LOCK="semver-lock.json" + +# Create a temporary directory. +temp_dir=$(mktemp -d) +trap 'rm -rf "$temp_dir"' EXIT + +# Exit early if semver-lock.json has not changed. +if ! git diff origin/develop...HEAD --name-only | grep -q "$SEMVER_LOCK"; then + echo "No changes detected in semver-lock.json" + exit 0 +fi + +# Get the upstream semver-lock.json. +git show origin/develop:packages/contracts-bedrock/semver-lock.json > "$temp_dir/upstream_semver_lock.json" + +# Copy the local semver-lock.json. +cp "$SEMVER_LOCK" "$temp_dir/local_semver_lock.json" + +# Get the changed contracts. +changed_contracts=$(jq -r ' + def changes: + to_entries as $local + | input as $upstream + | $local | map( + select( + .key as $key + | .value != $upstream[$key] + ) + ) | map(.key); + changes[] +' "$temp_dir/local_semver_lock.json" "$temp_dir/upstream_semver_lock.json") + +# Flag to track if any errors are detected. +has_errors=false + +# Check each changed contract for a semver version change. +for contract in $changed_contracts; do + # Check if the contract file exists. + if [ ! -f "$contract" ]; then + echo "❌ Error: Contract file $contract not found" + has_errors=true + continue + fi + + # Extract the old and new source files. + old_source_file="$temp_dir/old_${contract##*/}" + new_source_file="$temp_dir/new_${contract##*/}" + git show origin/develop:packages/contracts-bedrock/"$contract" > "$old_source_file" 2>/dev/null || true + cp "$contract" "$new_source_file" + + # Extract the old and new versions. + old_version=$(extract_version "$old_source_file" 2>/dev/null || echo "N/A") + new_version=$(extract_version "$new_source_file" 2>/dev/null || echo "N/A") + + # Check if the versions were extracted successfully. + if [ "$old_version" = "N/A" ] || [ "$new_version" = "N/A" ]; then + echo "❌ Error: unable to extract version for $contract" + echo " this is probably a bug in check-semver-diff.sh" + echo " please report or fix the issue if possible" + has_errors=true + fi + + # Check if the version changed. + if [ "$old_version" = "$new_version" ]; then + echo "❌ Error: src/$contract has changes in semver-lock.json but no version change" + echo " Old version: $old_version" + echo " New version: $new_version" + has_errors=true + else + echo "✅ $contract: version changed from $old_version to $new_version" + fi +done + +# Exit with error if any issues were found. +if [ "$has_errors" = true ]; then + exit 1 +fi diff --git a/packages/contracts-bedrock/scripts/checks/check-semver-natspec-match.sh b/packages/contracts-bedrock/scripts/checks/check-semver-natspec-match.sh new file mode 100755 index 0000000000000..de4de3f8497a0 --- /dev/null +++ b/packages/contracts-bedrock/scripts/checks/check-semver-natspec-match.sh @@ -0,0 +1,74 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Grab the directory of the contracts-bedrock package +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +CONTRACTS_BASE=$(dirname "$(dirname "$SCRIPT_DIR")") +ARTIFACTS_DIR="$CONTRACTS_BASE/forge-artifacts" +CONTRACTS_DIR="$CONTRACTS_BASE/src" + +# Load semver-utils +# shellcheck source=/dev/null +source "$SCRIPT_DIR/utils/semver-utils.sh" + +# Flag to track if any errors are detected +has_errors=false + +# Iterate through each artifact file +for artifact_file in "$ARTIFACTS_DIR"/**/*.json; do + # Get the contract name and find the corresponding source file + contract_name=$(basename "$artifact_file" .json) + contract_file=$(find "$CONTRACTS_DIR" -name "$contract_name.sol") + + # Try to extract version as a constant + raw_metadata=$(jq -r '.rawMetadata' "$artifact_file") + artifact_version=$(echo "$raw_metadata" | jq -r '.output.devdoc.stateVariables.version."custom:semver"') + + is_constant=true + if [ "$artifact_version" = "null" ]; then + # If not found as a constant, try to extract as a function + artifact_version=$(echo "$raw_metadata" | jq -r '.output.devdoc.methods."version()"."custom:semver"') + is_constant=false + fi + + # If @custom:semver is not found in either location, skip this file + if [ "$artifact_version" = "null" ]; then + continue + fi + + # If source file is not found, report an error + if [ -z "$contract_file" ]; then + echo "❌ $contract_name: Source file not found" + continue + fi + + # Extract version from source based on whether it's a constant or function + if [ "$is_constant" = true ]; then + source_version=$(extract_constant_version "$contract_file") + else + source_version=$(extract_function_version "$contract_file") + fi + + # If source version is not found, report an error + if [ "$source_version" = "" ]; then + echo "❌ Error: failed to find version string for $contract_name" + echo " this is probably a bug in check-contract-semver.sh" + echo " please report or fix the issue if possible" + has_errors=true + fi + + # Compare versions + if [ "$source_version" != "$artifact_version" ]; then + echo "❌ Error: $contract_name has different semver in code and devdoc" + echo " Code: $source_version" + echo " Devdoc: $artifact_version" + has_errors=true + else + echo "✅ $contract_name: code: $source_version, devdoc: $artifact_version" + fi +done + +# If any errors were detected, exit with a non-zero status +if [ "$has_errors" = true ]; then + exit 1 +fi diff --git a/packages/contracts-bedrock/scripts/checks/check-snapshots.sh b/packages/contracts-bedrock/scripts/checks/check-snapshots.sh index dca296ee83903..66a04dc331d41 100755 --- a/packages/contracts-bedrock/scripts/checks/check-snapshots.sh +++ b/packages/contracts-bedrock/scripts/checks/check-snapshots.sh @@ -1,13 +1,17 @@ #!/usr/bin/env bash - set -euo pipefail -# Generate the snapshots -just snapshots +# Check for the --no-build flag +# Generate snapshots +if [ "$1" == "--no-build" ]; then + just snapshots-no-build +else + just snapshots +fi -# Check if the generated `snapshots` or `test/kontrol` files are different from the committed versions -if git diff --exit-code snapshots test/kontrol > /dev/null; then - [ -z "$(git ls-files --others --exclude-standard snapshots test/kontrol)" ] || exit 1 +# Check if the generated `snapshots` files are different from the committed versions +if git diff --exit-code snapshots > /dev/null; then + [ -z "$(git ls-files --others --exclude-standard snapshots)" ] || exit 1 else - exit 1 + exit 1 fi diff --git a/packages/contracts-bedrock/scripts/checks/utils/semver-utils.sh b/packages/contracts-bedrock/scripts/checks/utils/semver-utils.sh new file mode 100755 index 0000000000000..5f8d80156a452 --- /dev/null +++ b/packages/contracts-bedrock/scripts/checks/utils/semver-utils.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Function to extract version from contract source as a constant +extract_constant_version() { + local file=$1 + grep -o 'string.*constant.*version.*=.*"[^"]*"' "$file" | sed 's/.*"\([^"]*\)".*/\1/' || echo "" +} + +# Function to extract version from contract source as a function +extract_function_version() { + local file=$1 + sed -n '/function.*version()/,/return/p' "$file" | grep -o '"[^"]*"' | sed 's/"//g' || echo "" +} + +# Function to extract version from either constant or function +extract_version() { + local file=$1 + version=$(extract_constant_version "$file") + if [ -z "$version" ]; then + version=$(extract_function_version "$file") + fi + echo "$version" +} diff --git a/packages/contracts-bedrock/scripts/deploy/ChainAssertions.sol b/packages/contracts-bedrock/scripts/deploy/ChainAssertions.sol index 2a9f78940577e..7e5a9164f4662 100644 --- a/packages/contracts-bedrock/scripts/deploy/ChainAssertions.sol +++ b/packages/contracts-bedrock/scripts/deploy/ChainAssertions.sol @@ -1,28 +1,37 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import { ProxyAdmin } from "src/universal/ProxyAdmin.sol"; -import { ResourceMetering } from "src/L1/ResourceMetering.sol"; +// Testing +import { Vm } from "forge-std/Vm.sol"; +import { console2 as console } from "forge-std/console2.sol"; + +// Scripts import { DeployConfig } from "scripts/deploy/DeployConfig.s.sol"; import { Deployer } from "scripts/deploy/Deployer.sol"; -import { SystemConfig } from "src/L1/SystemConfig.sol"; +import { ISystemConfigV0 } from "scripts/interfaces/ISystemConfigV0.sol"; + +// Contracts +import { ProxyAdmin } from "src/universal/ProxyAdmin.sol"; + +// Libraries 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"; import { Predeploys } from "src/libraries/Predeploys.sol"; import { Types } from "scripts/libraries/Types.sol"; -import { Vm } from "forge-std/Vm.sol"; -import { ISystemConfigV0 } from "scripts/interfaces/ISystemConfigV0.sol"; -import { console2 as console } from "forge-std/console2.sol"; + +// Interfaces +import { IResourceMetering } from "src/L1/interfaces/IResourceMetering.sol"; +import { ISystemConfig } from "src/L1/interfaces/ISystemConfig.sol"; +import { IL2OutputOracle } from "src/L1/interfaces/IL2OutputOracle.sol"; +import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol"; +import { IL1CrossDomainMessenger } from "src/L1/interfaces/IL1CrossDomainMessenger.sol"; +import { IOptimismPortal } from "src/L1/interfaces/IOptimismPortal.sol"; +import { IOptimismPortal2 } from "src/L1/interfaces/IOptimismPortal2.sol"; +import { IL1ERC721Bridge } from "src/L1/interfaces/IL1ERC721Bridge.sol"; +import { IL1StandardBridge } from "src/L1/interfaces/IL1StandardBridge.sol"; +import { ProtocolVersion, IProtocolVersions } from "src/L1/interfaces/IProtocolVersions.sol"; +import { IDisputeGameFactory } from "src/dispute/interfaces/IDisputeGameFactory.sol"; +import { IDelayedWETH } from "src/dispute/interfaces/IDelayedWETH.sol"; +import { IOptimismMintableERC20Factory } from "src/universal/interfaces/IOptimismMintableERC20Factory.sol"; library ChainAssertions { Vm internal constant vm = Vm(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D); @@ -39,8 +48,8 @@ library ChainAssertions { view { console.log("Running post-deploy assertions"); - ResourceMetering.ResourceConfig memory rcfg = SystemConfig(_prox.SystemConfig).resourceConfig(); - ResourceMetering.ResourceConfig memory dflt = Constants.DEFAULT_RESOURCE_CONFIG(); + IResourceMetering.ResourceConfig memory rcfg = ISystemConfig(_prox.SystemConfig).resourceConfig(); + IResourceMetering.ResourceConfig memory dflt = Constants.DEFAULT_RESOURCE_CONFIG(); require(keccak256(abi.encode(rcfg)) == keccak256(abi.encode(dflt))); checkSystemConfig({ _contracts: _prox, _cfg: _cfg, _isProxy: true }); @@ -62,12 +71,12 @@ library ChainAssertions { /// @notice Asserts that the SystemConfig is setup correctly function checkSystemConfig(Types.ContractSet memory _contracts, DeployConfig _cfg, bool _isProxy) internal view { console.log("Running chain assertions on the SystemConfig"); - SystemConfig config = SystemConfig(_contracts.SystemConfig); + ISystemConfig config = ISystemConfig(_contracts.SystemConfig); // Check that the contract is initialized assertSlotValueIsOne({ _contractAddress: address(config), _slot: 0, _offset: 0 }); - ResourceMetering.ResourceConfig memory resourceConfig = config.resourceConfig(); + IResourceMetering.ResourceConfig memory resourceConfig = config.resourceConfig(); if (_isProxy) { require(config.owner() == _cfg.finalSystemOwner()); @@ -78,7 +87,7 @@ library ChainAssertions { require(config.unsafeBlockSigner() == _cfg.p2pSequencerAddress()); require(config.scalar() >> 248 == 1); // Check _config - ResourceMetering.ResourceConfig memory rconfig = Constants.DEFAULT_RESOURCE_CONFIG(); + IResourceMetering.ResourceConfig memory rconfig = Constants.DEFAULT_RESOURCE_CONFIG(); require(resourceConfig.maxResourceLimit == rconfig.maxResourceLimit); require(resourceConfig.elasticityMultiplier == rconfig.elasticityMultiplier); require(resourceConfig.baseFeeMaxChangeDenominator == rconfig.baseFeeMaxChangeDenominator); @@ -127,7 +136,7 @@ library ChainAssertions { /// @notice Asserts that the L1CrossDomainMessenger is setup correctly function checkL1CrossDomainMessenger(Types.ContractSet memory _contracts, Vm _vm, bool _isProxy) internal view { console.log("Running chain assertions on the L1CrossDomainMessenger"); - L1CrossDomainMessenger messenger = L1CrossDomainMessenger(_contracts.L1CrossDomainMessenger); + IL1CrossDomainMessenger messenger = IL1CrossDomainMessenger(_contracts.L1CrossDomainMessenger); // Check that the contract is initialized assertSlotValueIsOne({ _contractAddress: address(messenger), _slot: 0, _offset: 20 }); @@ -151,7 +160,7 @@ library ChainAssertions { /// @notice Asserts that the L1StandardBridge is setup correctly function checkL1StandardBridge(Types.ContractSet memory _contracts, bool _isProxy) internal view { console.log("Running chain assertions on the L1StandardBridge"); - L1StandardBridge bridge = L1StandardBridge(payable(_contracts.L1StandardBridge)); + IL1StandardBridge bridge = IL1StandardBridge(payable(_contracts.L1StandardBridge)); // Check that the contract is initialized assertSlotValueIsOne({ _contractAddress: address(bridge), _slot: 0, _offset: 0 }); @@ -174,7 +183,7 @@ 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); + IDisputeGameFactory factory = IDisputeGameFactory(_contracts.DisputeGameFactory); // Check that the contract is initialized assertSlotValueIsOne({ _contractAddress: address(factory), _slot: 0, _offset: 0 }); @@ -193,7 +202,7 @@ library ChainAssertions { view { console.log("Running chain assertions on the DelayedWETH"); - DelayedWETH weth = DelayedWETH(payable(_contracts.DelayedWETH)); + IDelayedWETH weth = IDelayedWETH(payable(_contracts.DelayedWETH)); // Check that the contract is initialized assertSlotValueIsOne({ _contractAddress: address(weth), _slot: 0, _offset: 0 }); @@ -201,7 +210,7 @@ library ChainAssertions { if (_isProxy) { require(weth.owner() == _expectedOwner); require(weth.delay() == _cfg.faultGameWithdrawalDelay()); - require(weth.config() == SuperchainConfig(_contracts.SuperchainConfig)); + require(weth.config() == ISuperchainConfig(_contracts.SuperchainConfig)); } else { require(weth.owner() == _expectedOwner); require(weth.delay() == _cfg.faultGameWithdrawalDelay()); @@ -219,7 +228,7 @@ library ChainAssertions { view { console.log("Running chain assertions on the permissioned DelayedWETH"); - DelayedWETH weth = DelayedWETH(payable(_contracts.PermissionedDelayedWETH)); + IDelayedWETH weth = IDelayedWETH(payable(_contracts.PermissionedDelayedWETH)); // Check that the contract is initialized assertSlotValueIsOne({ _contractAddress: address(weth), _slot: 0, _offset: 0 }); @@ -227,7 +236,7 @@ library ChainAssertions { if (_isProxy) { require(weth.owner() == _expectedOwner); require(weth.delay() == _cfg.faultGameWithdrawalDelay()); - require(weth.config() == SuperchainConfig(_contracts.SuperchainConfig)); + require(weth.config() == ISuperchainConfig(_contracts.SuperchainConfig)); } else { require(weth.owner() == _expectedOwner); require(weth.delay() == _cfg.faultGameWithdrawalDelay()); @@ -245,7 +254,7 @@ library ChainAssertions { view { console.log("Running chain assertions on the L2OutputOracle"); - L2OutputOracle oracle = L2OutputOracle(_contracts.L2OutputOracle); + IL2OutputOracle oracle = IL2OutputOracle(_contracts.L2OutputOracle); // Check that the contract is initialized assertSlotValueIsOne({ _contractAddress: address(oracle), _slot: 0, _offset: 0 }); @@ -282,7 +291,7 @@ library ChainAssertions { /// @notice Asserts that the OptimismMintableERC20Factory is setup correctly function checkOptimismMintableERC20Factory(Types.ContractSet memory _contracts, bool _isProxy) internal view { console.log("Running chain assertions on the OptimismMintableERC20Factory"); - OptimismMintableERC20Factory factory = OptimismMintableERC20Factory(_contracts.OptimismMintableERC20Factory); + IOptimismMintableERC20Factory factory = IOptimismMintableERC20Factory(_contracts.OptimismMintableERC20Factory); // Check that the contract is initialized assertSlotValueIsOne({ _contractAddress: address(factory), _slot: 0, _offset: 0 }); @@ -299,7 +308,7 @@ library ChainAssertions { /// @notice Asserts that the L1ERC721Bridge is setup correctly function checkL1ERC721Bridge(Types.ContractSet memory _contracts, bool _isProxy) internal view { console.log("Running chain assertions on the L1ERC721Bridge"); - L1ERC721Bridge bridge = L1ERC721Bridge(_contracts.L1ERC721Bridge); + IL1ERC721Bridge bridge = IL1ERC721Bridge(_contracts.L1ERC721Bridge); // Check that the contract is initialized assertSlotValueIsOne({ _contractAddress: address(bridge), _slot: 0, _offset: 0 }); @@ -322,7 +331,7 @@ library ChainAssertions { function checkOptimismPortal(Types.ContractSet memory _contracts, DeployConfig _cfg, bool _isProxy) internal view { console.log("Running chain assertions on the OptimismPortal"); - OptimismPortal portal = OptimismPortal(payable(_contracts.OptimismPortal)); + IOptimismPortal portal = IOptimismPortal(payable(_contracts.OptimismPortal)); // Check that the contract is initialized assertSlotValueIsOne({ _contractAddress: address(portal), _slot: 0, _offset: 0 }); @@ -337,7 +346,7 @@ library ChainAssertions { require(address(portal.systemConfig()) == _contracts.SystemConfig); require(portal.guardian() == guardian); require(address(portal.superchainConfig()) == address(_contracts.SuperchainConfig)); - require(portal.paused() == SuperchainConfig(_contracts.SuperchainConfig).paused()); + require(portal.paused() == ISuperchainConfig(_contracts.SuperchainConfig).paused()); require(portal.l2Sender() == Constants.DEFAULT_L2_SENDER); } else { require(address(portal.l2Oracle()) == address(0)); @@ -358,7 +367,7 @@ library ChainAssertions { { console.log("Running chain assertions on the OptimismPortal2"); - OptimismPortal2 portal = OptimismPortal2(payable(_contracts.OptimismPortal2)); + IOptimismPortal2 portal = IOptimismPortal2(payable(_contracts.OptimismPortal2)); // Check that the contract is initialized assertSlotValueIsOne({ _contractAddress: address(portal), _slot: 0, _offset: 0 }); @@ -373,7 +382,7 @@ library ChainAssertions { require(address(portal.systemConfig()) == _contracts.SystemConfig); require(portal.guardian() == guardian); require(address(portal.superchainConfig()) == address(_contracts.SuperchainConfig)); - require(portal.paused() == SuperchainConfig(_contracts.SuperchainConfig).paused()); + require(portal.paused() == ISuperchainConfig(_contracts.SuperchainConfig).paused()); require(portal.l2Sender() == Constants.DEFAULT_L2_SENDER); } else { require(address(portal.disputeGameFactory()) == address(0)); @@ -396,7 +405,7 @@ library ChainAssertions { view { console.log("Running chain assertions on the ProtocolVersions"); - ProtocolVersions versions = ProtocolVersions(_contracts.ProtocolVersions); + IProtocolVersions versions = IProtocolVersions(_contracts.ProtocolVersions); // Check that the contract is initialized assertSlotValueIsOne({ _contractAddress: address(versions), _slot: 0, _offset: 0 }); @@ -422,7 +431,7 @@ library ChainAssertions { view { console.log("Running chain assertions on the SuperchainConfig"); - SuperchainConfig superchainConfig = SuperchainConfig(_contracts.SuperchainConfig); + ISuperchainConfig superchainConfig = ISuperchainConfig(_contracts.SuperchainConfig); // Check that the contract is initialized assertSlotValueIsOne({ _contractAddress: address(superchainConfig), _slot: 0, _offset: 0 }); diff --git a/packages/contracts-bedrock/scripts/deploy/Deploy.s.sol b/packages/contracts-bedrock/scripts/deploy/Deploy.s.sol index 6c70faab1e796..722cd7c61ecff 100644 --- a/packages/contracts-bedrock/scripts/deploy/Deploy.s.sol +++ b/packages/contracts-bedrock/scripts/deploy/Deploy.s.sol @@ -1,62 +1,67 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; +// Testing import { VmSafe } from "forge-std/Vm.sol"; import { Script } from "forge-std/Script.sol"; - import { console2 as console } from "forge-std/console2.sol"; import { stdJson } from "forge-std/StdJson.sol"; +import { AlphabetVM } from "test/mocks/AlphabetVM.sol"; +import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; +// Safe import { GnosisSafe as Safe } from "safe-contracts/GnosisSafe.sol"; import { OwnerManager } from "safe-contracts/base/OwnerManager.sol"; import { GnosisSafeProxyFactory as SafeProxyFactory } from "safe-contracts/proxies/GnosisSafeProxyFactory.sol"; import { Enum as SafeOps } from "safe-contracts/common/Enum.sol"; +// Scripts import { Deployer } from "scripts/deploy/Deployer.sol"; +import { Chains } from "scripts/libraries/Chains.sol"; +import { Config } from "scripts/libraries/Config.sol"; +import { LibStateDiff } from "scripts/libraries/LibStateDiff.sol"; +import { Process } from "scripts/libraries/Process.sol"; +import { ForgeArtifacts } from "scripts/libraries/ForgeArtifacts.sol"; +import { ChainAssertions } from "scripts/deploy/ChainAssertions.sol"; +// Contracts import { ProxyAdmin } from "src/universal/ProxyAdmin.sol"; import { AddressManager } from "src/legacy/AddressManager.sol"; 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 { OptimismPortalInterop } from "src/L1/OptimismPortalInterop.sol"; import { L1ChugSplashProxy } from "src/legacy/L1ChugSplashProxy.sol"; import { ResolvedDelegateProxy } from "src/legacy/ResolvedDelegateProxy.sol"; -import { L1CrossDomainMessenger } from "src/L1/L1CrossDomainMessenger.sol"; -import { L2OutputOracle } from "src/L1/L2OutputOracle.sol"; -import { OptimismMintableERC20Factory } from "src/universal/OptimismMintableERC20Factory.sol"; -import { SuperchainConfig } from "src/L1/SuperchainConfig.sol"; -import { SystemConfig } from "src/L1/SystemConfig.sol"; -import { SystemConfigInterop } from "src/L1/SystemConfigInterop.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"; -import { ProtocolVersions, ProtocolVersion } from "src/L1/ProtocolVersions.sol"; +import { MIPS2 } from "src/cannon/MIPS2.sol"; import { StorageSetter } from "src/universal/StorageSetter.sol"; + +// Libraries +import { Constants } from "src/libraries/Constants.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; -import { Chains } from "scripts/libraries/Chains.sol"; -import { Config } from "scripts/libraries/Config.sol"; +import { Types } from "scripts/libraries/Types.sol"; +import "src/dispute/lib/Types.sol"; +// Interfaces +import { IOptimismPortal } from "src/L1/interfaces/IOptimismPortal.sol"; +import { IOptimismPortal2 } from "src/L1/interfaces/IOptimismPortal2.sol"; +import { IOptimismPortalInterop } from "src/L1/interfaces/IOptimismPortalInterop.sol"; +import { ICrossDomainMessenger } from "src/universal/interfaces/ICrossDomainMessenger.sol"; +import { IL1CrossDomainMessenger } from "src/L1/interfaces/IL1CrossDomainMessenger.sol"; +import { IL2OutputOracle } from "src/L1/interfaces/IL2OutputOracle.sol"; +import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol"; +import { ISystemConfig } from "src/L1/interfaces/ISystemConfig.sol"; +import { IDataAvailabilityChallenge } from "src/L1/interfaces/IDataAvailabilityChallenge.sol"; +import { IL1ERC721Bridge } from "src/L1/interfaces/IL1ERC721Bridge.sol"; +import { IL1StandardBridge } from "src/L1/interfaces/IL1StandardBridge.sol"; +import { IProtocolVersions, ProtocolVersion } from "src/L1/interfaces/IProtocolVersions.sol"; import { IBigStepper } from "src/dispute/interfaces/IBigStepper.sol"; +import { IDisputeGameFactory } from "src/dispute/interfaces/IDisputeGameFactory.sol"; +import { IDisputeGame } from "src/dispute/interfaces/IDisputeGame.sol"; +import { IDelayedWETH } from "src/dispute/interfaces/IDelayedWETH.sol"; +import { IAnchorStateRegistry } from "src/dispute/interfaces/IAnchorStateRegistry.sol"; import { IPreimageOracle } from "src/cannon/interfaces/IPreimageOracle.sol"; -import { AlphabetVM } from "test/mocks/AlphabetVM.sol"; -import "src/dispute/lib/Types.sol"; -import { ChainAssertions } from "scripts/deploy/ChainAssertions.sol"; -import { Types } from "scripts/libraries/Types.sol"; -import { LibStateDiff } from "scripts/libraries/LibStateDiff.sol"; -import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; -import { ForgeArtifacts } from "scripts/libraries/ForgeArtifacts.sol"; -import { Process } from "scripts/libraries/Process.sol"; +import { IOptimismMintableERC20Factory } from "src/universal/interfaces/IOptimismMintableERC20Factory.sol"; /// @title Deploy /// @notice Script used to deploy a bedrock system. The entire system is deployed within the `run` function. @@ -74,8 +79,8 @@ contract Deploy is Deployer { /// 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; + IAnchorStateRegistry anchorStateRegistry; + IDelayedWETH weth; GameType gameType; Claim absolutePrestate; IBigStepper faultVm; @@ -273,6 +278,39 @@ contract Deploy is Deployer { _run(); } + /// @notice Deploy a new OP Chain using an existing SuperchainConfig and ProtocolVersions + /// @param _superchainConfigProxy Address of the existing SuperchainConfig proxy + /// @param _protocolVersionsProxy Address of the existing ProtocolVersions proxy + /// @param includeDump Whether to include a state dump after deployment + function runWithSuperchain( + address payable _superchainConfigProxy, + address payable _protocolVersionsProxy, + bool includeDump + ) + public + { + require(_superchainConfigProxy != address(0), "must specify address for superchain config proxy"); + require(_protocolVersionsProxy != address(0), "must specify address for protocol versions proxy"); + + vm.chainId(cfg.l1ChainID()); + + console.log("Deploying a fresh OP Stack with existing SuperchainConfig and ProtocolVersions"); + + Proxy scProxy = Proxy(_superchainConfigProxy); + save("SuperchainConfig", scProxy.implementation()); + save("SuperchainConfigProxy", _superchainConfigProxy); + + Proxy pvProxy = Proxy(_protocolVersionsProxy); + save("ProtocolVersions", pvProxy.implementation()); + save("ProtocolVersionsProxy", _protocolVersionsProxy); + + _run(false); + + if (includeDump) { + vm.dumpState(Config.stateDumpPath("")); + } + } + function runWithStateDump() public { vm.chainId(cfg.l1ChainID()); _run(); @@ -284,13 +322,27 @@ contract Deploy is Deployer { _run(); } - /// @notice Internal function containing the deploy logic. + /// @notice Compatibility function for tests that override _run(). function _run() internal virtual { + _run(true); + } + + /// @notice Internal function containing the deploy logic. + function _run(bool _needsSuperchain) internal { console.log("start of L1 Deploy!"); deploySafe("SystemOwnerSafe"); console.log("deployed Safe!"); - setupSuperchain(); - console.log("set up superchain!"); + + // Deploy a new ProxyAdmin and AddressManager + // This proxy will be used on the SuperchainConfig and ProtocolVersions contracts, as well as the contracts + // in the OP Chain system. + setupAdmin(); + + if (_needsSuperchain) { + setupSuperchain(); + console.log("set up superchain!"); + } + if (cfg.useAltDA()) { bytes32 typeHash = keccak256(bytes(cfg.daCommitmentType())); bytes32 keccakHash = keccak256(bytes("KeccakCommitment")); @@ -306,6 +358,13 @@ contract Deploy is Deployer { // High Level Deployment Functions // //////////////////////////////////////////////////////////////// + /// @notice Deploy the address manager and proxy admin contracts. + function setupAdmin() public { + deployAddressManager(); + deployProxyAdmin(); + transferProxyAdminOwnership(); + } + /// @notice Deploy a full system with a new SuperchainConfig /// The Superchain system has 2 singleton contracts which lie outside of an OP Chain: /// 1. The SuperchainConfig contract @@ -313,13 +372,6 @@ contract Deploy is Deployer { function setupSuperchain() public { console.log("Setting up Superchain"); - // Deploy a new ProxyAdmin and AddressManager - // This proxy will be used on the SuperchainConfig and ProtocolVersions contracts, as well as the contracts - // in the OP Chain system. - deployAddressManager(); - deployProxyAdmin(); - transferProxyAdminOwnership(); - // Deploy the SuperchainConfigProxy deployERC1967Proxy("SuperchainConfigProxy"); deploySuperchainConfig(); @@ -613,23 +665,16 @@ contract Deploy is Deployer { /// @notice Deploy the SuperchainConfig contract function deploySuperchainConfig() public broadcast { - SuperchainConfig superchainConfig = new SuperchainConfig{ salt: _implSalt() }(); + ISuperchainConfig superchainConfig = ISuperchainConfig(_deploy("SuperchainConfig", hex"")); require(superchainConfig.guardian() == address(0)); bytes32 initialized = vm.load(address(superchainConfig), bytes32(0)); require(initialized != 0); - - save("SuperchainConfig", address(superchainConfig)); - console.log("SuperchainConfig deployed at %s", address(superchainConfig)); } /// @notice Deploy the L1CrossDomainMessenger function deployL1CrossDomainMessenger() public broadcast returns (address addr_) { - console.log("Deploying L1CrossDomainMessenger implementation"); - L1CrossDomainMessenger messenger = new L1CrossDomainMessenger{ salt: _implSalt() }(); - - save("L1CrossDomainMessenger", address(messenger)); - console.log("L1CrossDomainMessenger deployed at %s", address(messenger)); + IL1CrossDomainMessenger messenger = IL1CrossDomainMessenger(_deploy("L1CrossDomainMessenger", hex"")); // Override the `L1CrossDomainMessenger` contract to the deployed implementation. This is necessary // to check the `L1CrossDomainMessenger` implementation alongside dependent contracts, which @@ -643,13 +688,11 @@ contract Deploy is Deployer { /// @notice Deploy the OptimismPortal function deployOptimismPortal() public broadcast returns (address addr_) { - console.log("Deploying OptimismPortal implementation"); if (cfg.useInterop()) { console.log("Attempting to deploy OptimismPortal with interop, this config is a noop"); } - addr_ = address(new OptimismPortal{ salt: _implSalt() }()); - save("OptimismPortal", addr_); - console.log("OptimismPortal deployed at %s", addr_); + + addr_ = _deploy("OptimismPortal", hex""); // Override the `OptimismPortal` contract to the deployed implementation. This is necessary // to check the `OptimismPortal` implementation alongside dependent contracts, which @@ -661,32 +704,23 @@ contract Deploy is Deployer { /// @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" ); if (cfg.useInterop()) { - addr_ = address( - new OptimismPortalInterop{ salt: _implSalt() }({ - _proofMaturityDelaySeconds: cfg.proofMaturityDelaySeconds(), - _disputeGameFinalityDelaySeconds: cfg.disputeGameFinalityDelaySeconds() - }) + addr_ = _deploy( + "OptimismPortalInterop", + abi.encode(cfg.proofMaturityDelaySeconds(), cfg.disputeGameFinalityDelaySeconds()) ); + save("OptimismPortal2", addr_); } else { - addr_ = address( - new OptimismPortal2{ salt: _implSalt() }({ - _proofMaturityDelaySeconds: cfg.proofMaturityDelaySeconds(), - _disputeGameFinalityDelaySeconds: cfg.disputeGameFinalityDelaySeconds() - }) + addr_ = _deploy( + "OptimismPortal2", abi.encode(cfg.proofMaturityDelaySeconds(), cfg.disputeGameFinalityDelaySeconds()) ); } - save("OptimismPortal2", addr_); - console.log("OptimismPortal2 deployed at %s", addr_); - // Override the `OptimismPortal2` contract to the deployed implementation. This is necessary // to check the `OptimismPortal2` implementation alongside dependent contracts, which // are always proxies. @@ -697,11 +731,7 @@ contract Deploy is Deployer { /// @notice Deploy the L2OutputOracle function deployL2OutputOracle() public broadcast returns (address addr_) { - console.log("Deploying L2OutputOracle implementation"); - L2OutputOracle oracle = new L2OutputOracle{ salt: _implSalt() }(); - - save("L2OutputOracle", address(oracle)); - console.log("L2OutputOracle deployed at %s", address(oracle)); + IL2OutputOracle oracle = IL2OutputOracle(_deploy("L2OutputOracle", hex"")); // Override the `L2OutputOracle` contract to the deployed implementation. This is necessary // to check the `L2OutputOracle` implementation alongside dependent contracts, which @@ -720,11 +750,8 @@ contract Deploy is Deployer { /// @notice Deploy the OptimismMintableERC20Factory function deployOptimismMintableERC20Factory() public broadcast returns (address addr_) { - console.log("Deploying OptimismMintableERC20Factory implementation"); - OptimismMintableERC20Factory factory = new OptimismMintableERC20Factory{ salt: _implSalt() }(); - - save("OptimismMintableERC20Factory", address(factory)); - console.log("OptimismMintableERC20Factory deployed at %s", address(factory)); + IOptimismMintableERC20Factory factory = + IOptimismMintableERC20Factory(_deploy("OptimismMintableERC20Factory", hex"")); // Override the `OptimismMintableERC20Factory` contract to the deployed implementation. This is necessary // to check the `OptimismMintableERC20Factory` implementation alongside dependent contracts, which @@ -738,10 +765,7 @@ contract Deploy is Deployer { /// @notice Deploy the DisputeGameFactory 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)); + IDisputeGameFactory factory = IDisputeGameFactory(_deploy("DisputeGameFactory", hex"")); // Override the `DisputeGameFactory` contract to the deployed implementation. This is necessary to check the // `DisputeGameFactory` implementation alongside dependent contracts, which are always proxies. @@ -753,10 +777,7 @@ contract Deploy is Deployer { } 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)); + IDelayedWETH weth = IDelayedWETH(payable(_deploy("DelayedWETH", abi.encode(cfg.faultGameWithdrawalDelay())))); // Override the `DelayedWETH` contract to the deployed implementation. This is necessary // to check the `DelayedWETH` implementation alongside dependent contracts, which are @@ -775,10 +796,7 @@ contract Deploy is Deployer { /// @notice Deploy the ProtocolVersions function deployProtocolVersions() public broadcast returns (address addr_) { - console.log("Deploying ProtocolVersions implementation"); - ProtocolVersions versions = new ProtocolVersions{ salt: _implSalt() }(); - save("ProtocolVersions", address(versions)); - console.log("ProtocolVersions deployed at %s", address(versions)); + IProtocolVersions versions = IProtocolVersions(_deploy("ProtocolVersions", hex"")); // Override the `ProtocolVersions` contract to the deployed implementation. This is necessary // to check the `ProtocolVersions` implementation alongside dependent contracts, which @@ -803,37 +821,48 @@ contract Deploy is Deployer { addr_ = address(preimageOracle); } - /// @notice Deploy Mips + /// @notice Deploy Mips VM. Deploys either MIPS or MIPS2 depending on the environment function deployMips() public broadcast returns (address addr_) { + if (Config.useMultithreadedCannon()) { + addr_ = _deployMips2(); + } else { + addr_ = _deployMips(); + } + save("Mips", address(addr_)); + } + + /// @notice Deploy MIPS + function _deployMips() internal returns (address addr_) { console.log("Deploying Mips implementation"); MIPS mips = new MIPS{ salt: _implSalt() }(IPreimageOracle(mustGetAddress("PreimageOracle"))); - save("Mips", address(mips)); console.log("MIPS deployed at %s", address(mips)); - addr_ = address(mips); } + /// @notice Deploy MIPS2 + function _deployMips2() internal returns (address addr_) { + console.log("Deploying Mips2 implementation"); + MIPS2 mips2 = new MIPS2{ salt: _implSalt() }(IPreimageOracle(mustGetAddress("PreimageOracle"))); + console.log("MIPS2 deployed at %s", address(mips2)); + addr_ = address(mips2); + } + /// @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)); + IAnchorStateRegistry anchorStateRegistry = + IAnchorStateRegistry(_deploy("AnchorStateRegistry", abi.encode(mustGetAddress("DisputeGameFactoryProxy")))); addr_ = address(anchorStateRegistry); } /// @notice Deploy the SystemConfig function deploySystemConfig() public broadcast returns (address addr_) { - console.log("Deploying SystemConfig implementation"); if (cfg.useInterop()) { - addr_ = address(new SystemConfigInterop{ salt: _implSalt() }()); + addr_ = _deploy("SystemConfigInterop", hex""); + save("SystemConfig", addr_); } else { - addr_ = address(new SystemConfig{ salt: _implSalt() }()); + addr_ = _deploy("SystemConfig", hex""); } - save("SystemConfig", addr_); - console.log("SystemConfig deployed at %s", addr_); // Override the `SystemConfig` contract to the deployed implementation. This is necessary // to check the `SystemConfig` implementation alongside dependent contracts, which @@ -845,12 +874,7 @@ contract Deploy is Deployer { /// @notice Deploy the L1StandardBridge function deployL1StandardBridge() public broadcast returns (address addr_) { - console.log("Deploying L1StandardBridge implementation"); - - L1StandardBridge bridge = new L1StandardBridge{ salt: _implSalt() }(); - - save("L1StandardBridge", address(bridge)); - console.log("L1StandardBridge deployed at %s", address(bridge)); + IL1StandardBridge bridge = IL1StandardBridge(payable(_deploy("L1StandardBridge", hex""))); // Override the `L1StandardBridge` contract to the deployed implementation. This is necessary // to check the `L1StandardBridge` implementation alongside dependent contracts, which @@ -864,11 +888,7 @@ contract Deploy is Deployer { /// @notice Deploy the L1ERC721Bridge function deployL1ERC721Bridge() public broadcast returns (address addr_) { - console.log("Deploying L1ERC721Bridge implementation"); - L1ERC721Bridge bridge = new L1ERC721Bridge{ salt: _implSalt() }(); - - save("L1ERC721Bridge", address(bridge)); - console.log("L1ERC721Bridge deployed at %s", address(bridge)); + IL1ERC721Bridge bridge = IL1ERC721Bridge(_deploy("L1ERC721Bridge", hex"")); // Override the `L1ERC721Bridge` contract to the deployed implementation. This is necessary // to check the `L1ERC721Bridge` implementation alongside dependent contracts, which @@ -897,11 +917,8 @@ contract Deploy is Deployer { /// @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)); - + IDataAvailabilityChallenge dac = + IDataAvailabilityChallenge(payable(_deploy("DataAvailabilityChallenge", hex""))); addr_ = address(dac); } @@ -916,7 +933,7 @@ contract Deploy is Deployer { _upgradeAndCallViaSafe({ _proxy: superchainConfigProxy, _implementation: superchainConfig, - _innerCallData: abi.encodeCall(SuperchainConfig.initialize, (cfg.superchainConfigGuardian(), false)) + _innerCallData: abi.encodeCall(ISuperchainConfig.initialize, (cfg.superchainConfigGuardian(), false)) }); ChainAssertions.checkSuperchainConfig({ _contracts: _proxiesUnstrict(), _cfg: cfg, _isPaused: false }); @@ -931,10 +948,10 @@ contract Deploy is Deployer { _upgradeAndCallViaSafe({ _proxy: payable(disputeGameFactoryProxy), _implementation: disputeGameFactory, - _innerCallData: abi.encodeCall(DisputeGameFactory.initialize, (msg.sender)) + _innerCallData: abi.encodeCall(IDisputeGameFactory.initialize, (msg.sender)) }); - string memory version = DisputeGameFactory(disputeGameFactoryProxy).version(); + string memory version = IDisputeGameFactory(disputeGameFactoryProxy).version(); console.log("DisputeGameFactory version: %s", version); ChainAssertions.checkDisputeGameFactory({ _contracts: _proxiesUnstrict(), _expectedOwner: msg.sender }); @@ -949,10 +966,10 @@ contract Deploy is Deployer { _upgradeAndCallViaSafe({ _proxy: payable(delayedWETHProxy), _implementation: delayedWETH, - _innerCallData: abi.encodeCall(DelayedWETH.initialize, (msg.sender, SuperchainConfig(superchainConfigProxy))) + _innerCallData: abi.encodeCall(IDelayedWETH.initialize, (msg.sender, ISuperchainConfig(superchainConfigProxy))) }); - string memory version = DelayedWETH(payable(delayedWETHProxy)).version(); + string memory version = IDelayedWETH(payable(delayedWETHProxy)).version(); console.log("DelayedWETH version: %s", version); ChainAssertions.checkDelayedWETH({ @@ -972,10 +989,10 @@ contract Deploy is Deployer { _upgradeAndCallViaSafe({ _proxy: payable(delayedWETHProxy), _implementation: delayedWETH, - _innerCallData: abi.encodeCall(DelayedWETH.initialize, (msg.sender, SuperchainConfig(superchainConfigProxy))) + _innerCallData: abi.encodeCall(IDelayedWETH.initialize, (msg.sender, ISuperchainConfig(superchainConfigProxy))) }); - string memory version = DelayedWETH(payable(delayedWETHProxy)).version(); + string memory version = IDelayedWETH(payable(delayedWETHProxy)).version(); console.log("DelayedWETH version: %s", version); ChainAssertions.checkPermissionedDelayedWETH({ @@ -990,38 +1007,38 @@ contract Deploy is Deployer { console.log("Upgrading and initializing AnchorStateRegistry proxy"); address anchorStateRegistryProxy = mustGetAddress("AnchorStateRegistryProxy"); address anchorStateRegistry = mustGetAddress("AnchorStateRegistry"); - SuperchainConfig superchainConfig = SuperchainConfig(mustGetAddress("SuperchainConfigProxy")); + ISuperchainConfig superchainConfig = ISuperchainConfig(mustGetAddress("SuperchainConfigProxy")); - AnchorStateRegistry.StartingAnchorRoot[] memory roots = new AnchorStateRegistry.StartingAnchorRoot[](5); - roots[0] = AnchorStateRegistry.StartingAnchorRoot({ + IAnchorStateRegistry.StartingAnchorRoot[] memory roots = new IAnchorStateRegistry.StartingAnchorRoot[](5); + roots[0] = IAnchorStateRegistry.StartingAnchorRoot({ gameType: GameTypes.CANNON, outputRoot: OutputRoot({ root: Hash.wrap(cfg.faultGameGenesisOutputRoot()), l2BlockNumber: cfg.faultGameGenesisBlock() }) }); - roots[1] = AnchorStateRegistry.StartingAnchorRoot({ + roots[1] = IAnchorStateRegistry.StartingAnchorRoot({ gameType: GameTypes.PERMISSIONED_CANNON, outputRoot: OutputRoot({ root: Hash.wrap(cfg.faultGameGenesisOutputRoot()), l2BlockNumber: cfg.faultGameGenesisBlock() }) }); - roots[2] = AnchorStateRegistry.StartingAnchorRoot({ + roots[2] = IAnchorStateRegistry.StartingAnchorRoot({ gameType: GameTypes.ALPHABET, outputRoot: OutputRoot({ root: Hash.wrap(cfg.faultGameGenesisOutputRoot()), l2BlockNumber: cfg.faultGameGenesisBlock() }) }); - roots[3] = AnchorStateRegistry.StartingAnchorRoot({ + roots[3] = IAnchorStateRegistry.StartingAnchorRoot({ gameType: GameTypes.ASTERISC, outputRoot: OutputRoot({ root: Hash.wrap(cfg.faultGameGenesisOutputRoot()), l2BlockNumber: cfg.faultGameGenesisBlock() }) }); - roots[4] = AnchorStateRegistry.StartingAnchorRoot({ + roots[4] = IAnchorStateRegistry.StartingAnchorRoot({ gameType: GameTypes.FAST, outputRoot: OutputRoot({ root: Hash.wrap(cfg.faultGameGenesisOutputRoot()), @@ -1032,10 +1049,10 @@ contract Deploy is Deployer { _upgradeAndCallViaSafe({ _proxy: payable(anchorStateRegistryProxy), _implementation: anchorStateRegistry, - _innerCallData: abi.encodeCall(AnchorStateRegistry.initialize, (roots, superchainConfig)) + _innerCallData: abi.encodeCall(IAnchorStateRegistry.initialize, (roots, superchainConfig)) }); - string memory version = AnchorStateRegistry(payable(anchorStateRegistryProxy)).version(); + string memory version = IAnchorStateRegistry(payable(anchorStateRegistryProxy)).version(); console.log("AnchorStateRegistry version: %s", version); } @@ -1056,7 +1073,7 @@ contract Deploy is Deployer { _proxy: payable(systemConfigProxy), _implementation: systemConfig, _innerCallData: abi.encodeCall( - SystemConfig.initialize, + ISystemConfig.initialize, ( cfg.finalSystemOwner(), cfg.basefeeScalar(), @@ -1066,7 +1083,7 @@ contract Deploy is Deployer { cfg.p2pSequencerAddress(), Constants.DEFAULT_RESOURCE_CONFIG(), cfg.batchInboxAddress(), - SystemConfig.Addresses({ + ISystemConfig.Addresses({ l1CrossDomainMessenger: mustGetAddress("L1CrossDomainMessengerProxy"), l1ERC721Bridge: mustGetAddress("L1ERC721BridgeProxy"), l1StandardBridge: mustGetAddress("L1StandardBridgeProxy"), @@ -1079,7 +1096,7 @@ contract Deploy is Deployer { ) }); - SystemConfig config = SystemConfig(systemConfigProxy); + ISystemConfig config = ISystemConfig(systemConfigProxy); string memory version = config.version(); console.log("SystemConfig version: %s", version); @@ -1111,16 +1128,16 @@ contract Deploy is Deployer { _proxy: payable(l1StandardBridgeProxy), _implementation: l1StandardBridge, _innerCallData: abi.encodeCall( - L1StandardBridge.initialize, + IL1StandardBridge.initialize, ( - L1CrossDomainMessenger(l1CrossDomainMessengerProxy), - SuperchainConfig(superchainConfigProxy), - SystemConfig(systemConfigProxy) + ICrossDomainMessenger(l1CrossDomainMessengerProxy), + ISuperchainConfig(superchainConfigProxy), + ISystemConfig(systemConfigProxy) ) ) }); - string memory version = L1StandardBridge(payable(l1StandardBridgeProxy)).version(); + string memory version = IL1StandardBridge(payable(l1StandardBridgeProxy)).version(); console.log("L1StandardBridge version: %s", version); ChainAssertions.checkL1StandardBridge({ _contracts: _proxies(), _isProxy: true }); @@ -1138,12 +1155,12 @@ contract Deploy is Deployer { _proxy: payable(l1ERC721BridgeProxy), _implementation: l1ERC721Bridge, _innerCallData: abi.encodeCall( - L1ERC721Bridge.initialize, - (L1CrossDomainMessenger(payable(l1CrossDomainMessengerProxy)), SuperchainConfig(superchainConfigProxy)) + IL1ERC721Bridge.initialize, + (ICrossDomainMessenger(payable(l1CrossDomainMessengerProxy)), ISuperchainConfig(superchainConfigProxy)) ) }); - L1ERC721Bridge bridge = L1ERC721Bridge(l1ERC721BridgeProxy); + IL1ERC721Bridge bridge = IL1ERC721Bridge(l1ERC721BridgeProxy); string memory version = bridge.version(); console.log("L1ERC721Bridge version: %s", version); @@ -1160,10 +1177,10 @@ contract Deploy is Deployer { _upgradeAndCallViaSafe({ _proxy: payable(optimismMintableERC20FactoryProxy), _implementation: optimismMintableERC20Factory, - _innerCallData: abi.encodeCall(OptimismMintableERC20Factory.initialize, (l1StandardBridgeProxy)) + _innerCallData: abi.encodeCall(IOptimismMintableERC20Factory.initialize, (l1StandardBridgeProxy)) }); - OptimismMintableERC20Factory factory = OptimismMintableERC20Factory(optimismMintableERC20FactoryProxy); + IOptimismMintableERC20Factory factory = IOptimismMintableERC20Factory(optimismMintableERC20FactoryProxy); string memory version = factory.version(); console.log("OptimismMintableERC20Factory version: %s", version); @@ -1209,16 +1226,16 @@ contract Deploy is Deployer { _proxy: payable(l1CrossDomainMessengerProxy), _implementation: l1CrossDomainMessenger, _innerCallData: abi.encodeCall( - L1CrossDomainMessenger.initialize, + IL1CrossDomainMessenger.initialize, ( - SuperchainConfig(superchainConfigProxy), - OptimismPortal(payable(optimismPortalProxy)), - SystemConfig(systemConfigProxy) + ISuperchainConfig(superchainConfigProxy), + IOptimismPortal(payable(optimismPortalProxy)), + ISystemConfig(systemConfigProxy) ) ) }); - L1CrossDomainMessenger messenger = L1CrossDomainMessenger(l1CrossDomainMessengerProxy); + IL1CrossDomainMessenger messenger = IL1CrossDomainMessenger(l1CrossDomainMessengerProxy); string memory version = messenger.version(); console.log("L1CrossDomainMessenger version: %s", version); @@ -1235,7 +1252,7 @@ contract Deploy is Deployer { _proxy: payable(l2OutputOracleProxy), _implementation: l2OutputOracle, _innerCallData: abi.encodeCall( - L2OutputOracle.initialize, + IL2OutputOracle.initialize, ( cfg.l2OutputOracleSubmissionInterval(), cfg.l2BlockTime(), @@ -1248,7 +1265,7 @@ contract Deploy is Deployer { ) }); - L2OutputOracle oracle = L2OutputOracle(l2OutputOracleProxy); + IL2OutputOracle oracle = IL2OutputOracle(l2OutputOracleProxy); string memory version = oracle.version(); console.log("L2OutputOracle version: %s", version); @@ -1273,16 +1290,16 @@ contract Deploy is Deployer { _proxy: payable(optimismPortalProxy), _implementation: optimismPortal, _innerCallData: abi.encodeCall( - OptimismPortal.initialize, + IOptimismPortal.initialize, ( - L2OutputOracle(l2OutputOracleProxy), - SystemConfig(systemConfigProxy), - SuperchainConfig(superchainConfigProxy) + IL2OutputOracle(l2OutputOracleProxy), + ISystemConfig(systemConfigProxy), + ISuperchainConfig(superchainConfigProxy) ) ) }); - OptimismPortal portal = OptimismPortal(payable(optimismPortalProxy)); + IOptimismPortal portal = IOptimismPortal(payable(optimismPortalProxy)); string memory version = portal.version(); console.log("OptimismPortal version: %s", version); @@ -1302,17 +1319,17 @@ contract Deploy is Deployer { _proxy: payable(optimismPortalProxy), _implementation: optimismPortal2, _innerCallData: abi.encodeCall( - OptimismPortal2.initialize, + IOptimismPortal2.initialize, ( - DisputeGameFactory(disputeGameFactoryProxy), - SystemConfig(systemConfigProxy), - SuperchainConfig(superchainConfigProxy), + IDisputeGameFactory(disputeGameFactoryProxy), + ISystemConfig(systemConfigProxy), + ISuperchainConfig(superchainConfigProxy), GameType.wrap(uint32(cfg.respectedGameType())) ) ) }); - OptimismPortal2 portal = OptimismPortal2(payable(optimismPortalProxy)); + IOptimismPortal2 portal = IOptimismPortal2(payable(optimismPortalProxy)); string memory version = portal.version(); console.log("OptimismPortal2 version: %s", version); @@ -1332,7 +1349,7 @@ contract Deploy is Deployer { _proxy: payable(protocolVersionsProxy), _implementation: protocolVersions, _innerCallData: abi.encodeCall( - ProtocolVersions.initialize, + IProtocolVersions.initialize, ( finalSystemOwner, ProtocolVersion.wrap(requiredProtocolVersion), @@ -1341,7 +1358,7 @@ contract Deploy is Deployer { ) }); - ProtocolVersions versions = ProtocolVersions(protocolVersionsProxy); + IProtocolVersions versions = IProtocolVersions(protocolVersionsProxy); string memory version = versions.version(); console.log("ProtocolVersions version: %s", version); @@ -1351,7 +1368,7 @@ contract Deploy is Deployer { /// @notice Transfer ownership of the DisputeGameFactory contract to the final system owner function transferDisputeGameFactoryOwnership() public broadcast { console.log("Transferring DisputeGameFactory ownership to Safe"); - DisputeGameFactory disputeGameFactory = DisputeGameFactory(mustGetAddress("DisputeGameFactoryProxy")); + IDisputeGameFactory disputeGameFactory = IDisputeGameFactory(mustGetAddress("DisputeGameFactoryProxy")); address owner = disputeGameFactory.owner(); address safe = mustGetAddress("SystemOwnerSafe"); @@ -1365,7 +1382,7 @@ contract Deploy is Deployer { /// @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")); + IDelayedWETH weth = IDelayedWETH(mustGetAddress("DelayedWETHProxy")); address owner = weth.owner(); address safe = mustGetAddress("SystemOwnerSafe"); @@ -1379,7 +1396,7 @@ contract Deploy is Deployer { /// @notice Transfer ownership of the permissioned DelayedWETH contract to the final system owner function transferPermissionedDelayedWETHOwnership() public broadcast { console.log("Transferring permissioned DelayedWETH ownership to Safe"); - DelayedWETH weth = DelayedWETH(mustGetAddress("PermissionedDelayedWETHProxy")); + IDelayedWETH weth = IDelayedWETH(mustGetAddress("PermissionedDelayedWETHProxy")); address owner = weth.owner(); address safe = mustGetAddress("SystemOwnerSafe"); @@ -1395,25 +1412,14 @@ contract Deploy is Deployer { }); } - /// @notice Loads the mips absolute prestate from the prestate-proof for devnets otherwise - /// from the config. + /// @notice Load the appropriate mips absolute prestate for devenets depending on config environment. function loadMipsAbsolutePrestate() internal returns (Claim mipsAbsolutePrestate_) { if (block.chainid == Chains.LocalDevnet || block.chainid == Chains.GethDevnet) { - // Fetch the absolute prestate dump - string memory filePath = string.concat(vm.projectRoot(), "/../../op-program/bin/prestate-proof.json"); - string[] memory commands = new string[](3); - commands[0] = "bash"; - commands[1] = "-c"; - commands[2] = string.concat("[[ -f ", filePath, " ]] && echo \"present\""); - if (Process.run(commands).length == 0) { - revert("Cannon prestate dump not found, generate it with `make cannon-prestate` in the monorepo root."); + if (Config.useMultithreadedCannon()) { + return _loadDevnetMtMipsAbsolutePrestate(); + } else { + return _loadDevnetStMipsAbsolutePrestate(); } - commands[2] = string.concat("cat ", filePath, " | jq -r .pre"); - mipsAbsolutePrestate_ = Claim.wrap(abi.decode(Process.run(commands), (bytes32))); - console.log( - "[Cannon Dispute Game] Using devnet MIPS Absolute prestate: %s", - vm.toString(Claim.unwrap(mipsAbsolutePrestate_)) - ); } else { console.log( "[Cannon Dispute Game] Using absolute prestate from config: %x", cfg.faultGameAbsolutePrestate() @@ -1422,18 +1428,60 @@ contract Deploy is Deployer { } } + /// @notice Loads the singlethreaded mips absolute prestate from the prestate-proof for devnets otherwise + /// from the config. + function _loadDevnetStMipsAbsolutePrestate() internal returns (Claim mipsAbsolutePrestate_) { + // Fetch the absolute prestate dump + string memory filePath = string.concat(vm.projectRoot(), "/../../op-program/bin/prestate-proof.json"); + string[] memory commands = new string[](3); + commands[0] = "bash"; + commands[1] = "-c"; + commands[2] = string.concat("[[ -f ", filePath, " ]] && echo \"present\""); + if (Process.run(commands).length == 0) { + revert("Cannon prestate dump not found, generate it with `make cannon-prestate` in the monorepo root."); + } + commands[2] = string.concat("cat ", filePath, " | jq -r .pre"); + mipsAbsolutePrestate_ = Claim.wrap(abi.decode(Process.run(commands), (bytes32))); + console.log( + "[Cannon Dispute Game] Using devnet MIPS Absolute prestate: %s", + vm.toString(Claim.unwrap(mipsAbsolutePrestate_)) + ); + } + + /// @notice Loads the multithreaded mips absolute prestate from the prestate-proof-mt for devnets otherwise + /// from the config. + function _loadDevnetMtMipsAbsolutePrestate() internal returns (Claim mipsAbsolutePrestate_) { + // Fetch the absolute prestate dump + string memory filePath = string.concat(vm.projectRoot(), "/../../op-program/bin/prestate-proof-mt.json"); + string[] memory commands = new string[](3); + commands[0] = "bash"; + commands[1] = "-c"; + commands[2] = string.concat("[[ -f ", filePath, " ]] && echo \"present\""); + if (Process.run(commands).length == 0) { + revert( + "MT-Cannon prestate dump not found, generate it with `make cannon-prestate-mt` in the monorepo root." + ); + } + commands[2] = string.concat("cat ", filePath, " | jq -r .pre"); + mipsAbsolutePrestate_ = Claim.wrap(abi.decode(Process.run(commands), (bytes32))); + console.log( + "[MT-Cannon Dispute Game] Using devnet MIPS2 Absolute prestate: %s", + vm.toString(Claim.unwrap(mipsAbsolutePrestate_)) + ); + } + /// @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")); + IDisputeGameFactory factory = IDisputeGameFactory(mustGetAddress("DisputeGameFactoryProxy")); + IDelayedWETH weth = IDelayedWETH(mustGetAddress("DelayedWETHProxy")); // Set the Cannon FaultDisputeGame implementation in the factory. _setFaultGameImplementation({ _factory: factory, _allowUpgrade: _allowUpgrade, _params: FaultDisputeGameParams({ - anchorStateRegistry: AnchorStateRegistry(mustGetAddress("AnchorStateRegistryProxy")), + anchorStateRegistry: IAnchorStateRegistry(mustGetAddress("AnchorStateRegistryProxy")), weth: weth, gameType: GameTypes.CANNON, absolutePrestate: loadMipsAbsolutePrestate(), @@ -1447,15 +1495,15 @@ contract Deploy is Deployer { /// @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("PermissionedDelayedWETHProxy")); + IDisputeGameFactory factory = IDisputeGameFactory(mustGetAddress("DisputeGameFactoryProxy")); + IDelayedWETH weth = IDelayedWETH(mustGetAddress("PermissionedDelayedWETHProxy")); // Set the Cannon FaultDisputeGame implementation in the factory. _setFaultGameImplementation({ _factory: factory, _allowUpgrade: _allowUpgrade, _params: FaultDisputeGameParams({ - anchorStateRegistry: AnchorStateRegistry(mustGetAddress("AnchorStateRegistryProxy")), + anchorStateRegistry: IAnchorStateRegistry(mustGetAddress("AnchorStateRegistryProxy")), weth: weth, gameType: GameTypes.PERMISSIONED_CANNON, absolutePrestate: loadMipsAbsolutePrestate(), @@ -1469,15 +1517,15 @@ contract Deploy is Deployer { /// @notice Sets the implementation for the `ALPHABET` game type in the `DisputeGameFactory` function setAlphabetFaultGameImplementation(bool _allowUpgrade) public onlyDevnet broadcast { console.log("Setting Alphabet FaultDisputeGame implementation"); - DisputeGameFactory factory = DisputeGameFactory(mustGetAddress("DisputeGameFactoryProxy")); - DelayedWETH weth = DelayedWETH(mustGetAddress("DelayedWETHProxy")); + IDisputeGameFactory factory = IDisputeGameFactory(mustGetAddress("DisputeGameFactoryProxy")); + IDelayedWETH weth = IDelayedWETH(mustGetAddress("DelayedWETHProxy")); Claim outputAbsolutePrestate = Claim.wrap(bytes32(cfg.faultGameAbsolutePrestate())); _setFaultGameImplementation({ _factory: factory, _allowUpgrade: _allowUpgrade, _params: FaultDisputeGameParams({ - anchorStateRegistry: AnchorStateRegistry(mustGetAddress("AnchorStateRegistryProxy")), + anchorStateRegistry: IAnchorStateRegistry(mustGetAddress("AnchorStateRegistryProxy")), weth: weth, gameType: GameTypes.ALPHABET, absolutePrestate: outputAbsolutePrestate, @@ -1492,8 +1540,8 @@ contract Deploy is Deployer { /// @notice Sets the implementation for the `ALPHABET` game type in the `DisputeGameFactory` function setFastFaultGameImplementation(bool _allowUpgrade) public onlyDevnet broadcast { console.log("Setting Fast FaultDisputeGame implementation"); - DisputeGameFactory factory = DisputeGameFactory(mustGetAddress("DisputeGameFactoryProxy")); - DelayedWETH weth = DelayedWETH(mustGetAddress("DelayedWETHProxy")); + IDisputeGameFactory factory = IDisputeGameFactory(mustGetAddress("DisputeGameFactoryProxy")); + IDelayedWETH weth = IDelayedWETH(mustGetAddress("DelayedWETHProxy")); Claim outputAbsolutePrestate = Claim.wrap(bytes32(cfg.faultGameAbsolutePrestate())); PreimageOracle fastOracle = new PreimageOracle(cfg.preimageOracleMinProposalSize(), 0); @@ -1501,7 +1549,7 @@ contract Deploy is Deployer { _factory: factory, _allowUpgrade: _allowUpgrade, _params: FaultDisputeGameParams({ - anchorStateRegistry: AnchorStateRegistry(mustGetAddress("AnchorStateRegistryProxy")), + anchorStateRegistry: IAnchorStateRegistry(mustGetAddress("AnchorStateRegistryProxy")), weth: weth, gameType: GameTypes.FAST, absolutePrestate: outputAbsolutePrestate, @@ -1515,7 +1563,7 @@ contract Deploy is Deployer { /// @notice Sets the implementation for the given fault game type in the `DisputeGameFactory`. function _setFaultGameImplementation( - DisputeGameFactory _factory, + IDisputeGameFactory _factory, bool _allowUpgrade, FaultDisputeGameParams memory _params ) @@ -1533,36 +1581,47 @@ contract Deploy is Deployer { if (rawGameType != GameTypes.PERMISSIONED_CANNON.raw()) { _factory.setImplementation( _params.gameType, - new FaultDisputeGame({ - _gameType: _params.gameType, - _absolutePrestate: _params.absolutePrestate, - _maxGameDepth: _params.maxGameDepth, - _splitDepth: cfg.faultGameSplitDepth(), - _clockExtension: Duration.wrap(uint64(cfg.faultGameClockExtension())), - _maxClockDuration: _params.maxClockDuration, - _vm: _params.faultVm, - _weth: _params.weth, - _anchorStateRegistry: _params.anchorStateRegistry, - _l2ChainId: cfg.l2ChainID() - }) + IDisputeGame( + _deploy( + "FaultDisputeGame", + string.concat("FaultDisputeGame_", vm.toString(rawGameType)), + abi.encode( + _params.gameType, + _params.absolutePrestate, + _params.maxGameDepth, + cfg.faultGameSplitDepth(), + cfg.faultGameClockExtension(), + _params.maxClockDuration, + _params.faultVm, + _params.weth, + IAnchorStateRegistry(mustGetAddress("AnchorStateRegistryProxy")), + cfg.l2ChainID() + ) + ) + ) ); } else { _factory.setImplementation( _params.gameType, - new PermissionedDisputeGame({ - _gameType: _params.gameType, - _absolutePrestate: _params.absolutePrestate, - _maxGameDepth: _params.maxGameDepth, - _splitDepth: cfg.faultGameSplitDepth(), - _clockExtension: Duration.wrap(uint64(cfg.faultGameClockExtension())), - _maxClockDuration: Duration.wrap(uint64(cfg.faultGameMaxClockDuration())), - _vm: _params.faultVm, - _weth: _params.weth, - _anchorStateRegistry: _params.anchorStateRegistry, - _l2ChainId: cfg.l2ChainID(), - _proposer: cfg.l2OutputOracleProposer(), - _challenger: cfg.l2OutputOracleChallenger() - }) + IDisputeGame( + _deploy( + "PermissionedDisputeGame", + abi.encode( + _params.gameType, + _params.absolutePrestate, + _params.maxGameDepth, + cfg.faultGameSplitDepth(), + cfg.faultGameClockExtension(), + _params.maxClockDuration, + _params.faultVm, + _params.weth, + _params.anchorStateRegistry, + cfg.l2ChainID(), + cfg.l2OutputOracleProposer(), + cfg.l2OutputOracleChallenger() + ) + ) + ) ); } @@ -1600,12 +1659,12 @@ contract Deploy is Deployer { _proxy: payable(dataAvailabilityChallengeProxy), _implementation: dataAvailabilityChallenge, _innerCallData: abi.encodeCall( - DataAvailabilityChallenge.initialize, + IDataAvailabilityChallenge.initialize, (finalSystemOwner, daChallengeWindow, daResolveWindow, daBondSize, daResolverRefundPercentage) ) }); - DataAvailabilityChallenge dac = DataAvailabilityChallenge(payable(dataAvailabilityChallengeProxy)); + IDataAvailabilityChallenge dac = IDataAvailabilityChallenge(payable(dataAvailabilityChallengeProxy)); string memory version = dac.version(); console.log("DataAvailabilityChallenge version: %s", version); @@ -1615,4 +1674,36 @@ contract Deploy is Deployer { require(dac.bondSize() == daBondSize); require(dac.resolverRefundPercentage() == daResolverRefundPercentage); } + + /// @notice Deploys a contract via CREATE2. + /// @param _name The name of the contract. + /// @param _constructorParams The constructor parameters. + function _deploy(string memory _name, bytes memory _constructorParams) internal returns (address addr_) { + return _deploy(_name, _name, _constructorParams); + } + + /// @notice Deploys a contract via CREATE2. + /// @param _name The name of the contract. + /// @param _nickname The nickname of the contract. + /// @param _constructorParams The constructor parameters. + function _deploy( + string memory _name, + string memory _nickname, + bytes memory _constructorParams + ) + internal + returns (address addr_) + { + console.log("Deploying %s", _nickname); + bytes32 salt = _implSalt(); + bytes memory initCode = abi.encodePacked(vm.getCode(_name), _constructorParams); + address preComputedAddress = vm.computeCreate2Address(salt, keccak256(initCode)); + require(preComputedAddress.code.length == 0, "Deploy: contract already deployed"); + assembly { + addr_ := create2(0, add(initCode, 0x20), mload(initCode), salt) + } + require(addr_ != address(0), "deployment failed"); + save(_nickname, addr_); + console.log("%s deployed at %s", _nickname, addr_); + } } diff --git a/packages/contracts-bedrock/scripts/deploy/DeployOwnership.s.sol b/packages/contracts-bedrock/scripts/deploy/DeployOwnership.s.sol index 05fbfd54df937..252b4703b2037 100644 --- a/packages/contracts-bedrock/scripts/deploy/DeployOwnership.s.sol +++ b/packages/contracts-bedrock/scripts/deploy/DeployOwnership.s.sol @@ -11,10 +11,10 @@ import { GuardManager } from "safe-contracts/base/GuardManager.sol"; import { Deployer } from "scripts/deploy/Deployer.sol"; -import { LivenessGuard } from "src/Safe/LivenessGuard.sol"; -import { LivenessModule } from "src/Safe/LivenessModule.sol"; -import { DeputyGuardianModule } from "src/Safe/DeputyGuardianModule.sol"; -import { SuperchainConfig } from "src/L1/SuperchainConfig.sol"; +import { LivenessGuard } from "src/safe/LivenessGuard.sol"; +import { LivenessModule } from "src/safe/LivenessModule.sol"; +import { DeputyGuardianModule } from "src/safe/DeputyGuardianModule.sol"; +import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol"; import { Deploy } from "./Deploy.s.sol"; @@ -41,7 +41,7 @@ struct SecurityCouncilConfig { /// @notice Configuration for the Deputy Guardian Module struct DeputyGuardianModuleConfig { address deputyGuardian; - SuperchainConfig superchainConfig; + ISuperchainConfig superchainConfig; } /// @notice Configuration for the Guardian Safe. @@ -89,7 +89,7 @@ contract DeployOwnership is Deploy { safeConfig: SafeConfig({ threshold: 1, owners: exampleGuardianOwners }), deputyGuardianModuleConfig: DeputyGuardianModuleConfig({ deputyGuardian: mustGetAddress("FoundationOperationsSafe"), - superchainConfig: SuperchainConfig(mustGetAddress("SuperchainConfig")) + superchainConfig: ISuperchainConfig(mustGetAddress("SuperchainConfig")) }) }); } diff --git a/packages/contracts-bedrock/scripts/fpac/FPACOPS.s.sol b/packages/contracts-bedrock/scripts/fpac/FPACOPS.s.sol index 9d6ad4b719e73..2dc07b525bd06 100644 --- a/packages/contracts-bedrock/scripts/fpac/FPACOPS.s.sol +++ b/packages/contracts-bedrock/scripts/fpac/FPACOPS.s.sol @@ -1,13 +1,22 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Scripts +import { StdAssertions } from "forge-std/StdAssertions.sol"; +import "scripts/deploy/Deploy.s.sol"; + +// Contracts import { Proxy } from "src/universal/Proxy.sol"; + +// Libraries +import "src/dispute/lib/Types.sol"; + +// Interfaces import { IDisputeGame } from "src/dispute/interfaces/IDisputeGame.sol"; -import { AnchorStateRegistry, IAnchorStateRegistry } from "src/dispute/AnchorStateRegistry.sol"; +import { IAnchorStateRegistry } from "src/dispute/interfaces/IAnchorStateRegistry.sol"; import { IDelayedWETH } from "src/dispute/interfaces/IDelayedWETH.sol"; -import { StdAssertions } from "forge-std/StdAssertions.sol"; -import "src/dispute/lib/Types.sol"; -import "scripts/deploy/Deploy.s.sol"; +import { IFaultDisputeGame } from "src/dispute/interfaces/IFaultDisputeGame.sol"; +import { IPermissionedDisputeGame } from "src/dispute/interfaces/IPermissionedDisputeGame.sol"; /// @notice Deploys the Fault Proof Alpha Chad contracts. contract FPACOPS is Deploy, StdAssertions { @@ -70,11 +79,11 @@ contract FPACOPS is Deploy, StdAssertions { address dgfProxy = mustGetAddress("DisputeGameFactoryProxy"); Proxy(payable(dgfProxy)).upgradeToAndCall( - mustGetAddress("DisputeGameFactory"), abi.encodeCall(DisputeGameFactory.initialize, msg.sender) + mustGetAddress("DisputeGameFactory"), abi.encodeCall(IDisputeGameFactory.initialize, msg.sender) ); // Set the initialization bonds for the FaultDisputeGame and PermissionedDisputeGame. - DisputeGameFactory dgf = DisputeGameFactory(dgfProxy); + IDisputeGameFactory dgf = IDisputeGameFactory(dgfProxy); dgf.setInitBond(GameTypes.CANNON, 0.08 ether); dgf.setInitBond(GameTypes.PERMISSIONED_CANNON, 0.08 ether); } @@ -86,24 +95,24 @@ contract FPACOPS is Deploy, StdAssertions { address superchainConfigProxy = mustGetAddress("SuperchainConfigProxy"); Proxy(payable(wethProxy)).upgradeToAndCall( mustGetAddress("DelayedWETH"), - abi.encodeCall(DelayedWETH.initialize, (msg.sender, SuperchainConfig(superchainConfigProxy))) + abi.encodeCall(IDelayedWETH.initialize, (msg.sender, ISuperchainConfig(superchainConfigProxy))) ); } function initializeAnchorStateRegistryProxy() internal broadcast { console.log("Initializing AnchorStateRegistryProxy with AnchorStateRegistry."); address superchainConfigProxy = mustGetAddress("SuperchainConfigProxy"); - SuperchainConfig superchainConfig = SuperchainConfig(superchainConfigProxy); + ISuperchainConfig superchainConfig = ISuperchainConfig(superchainConfigProxy); - AnchorStateRegistry.StartingAnchorRoot[] memory roots = new AnchorStateRegistry.StartingAnchorRoot[](2); - roots[0] = AnchorStateRegistry.StartingAnchorRoot({ + IAnchorStateRegistry.StartingAnchorRoot[] memory roots = new IAnchorStateRegistry.StartingAnchorRoot[](2); + roots[0] = IAnchorStateRegistry.StartingAnchorRoot({ gameType: GameTypes.CANNON, outputRoot: OutputRoot({ root: Hash.wrap(cfg.faultGameGenesisOutputRoot()), l2BlockNumber: cfg.faultGameGenesisBlock() }) }); - roots[1] = AnchorStateRegistry.StartingAnchorRoot({ + roots[1] = IAnchorStateRegistry.StartingAnchorRoot({ gameType: GameTypes.PERMISSIONED_CANNON, outputRoot: OutputRoot({ root: Hash.wrap(cfg.faultGameGenesisOutputRoot()), @@ -114,14 +123,14 @@ contract FPACOPS is Deploy, StdAssertions { address asrProxy = mustGetAddress("AnchorStateRegistryProxy"); Proxy(payable(asrProxy)).upgradeToAndCall( mustGetAddress("AnchorStateRegistry"), - abi.encodeCall(AnchorStateRegistry.initialize, (roots, superchainConfig)) + abi.encodeCall(IAnchorStateRegistry.initialize, (roots, superchainConfig)) ); } /// @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")); + IDisputeGameFactory dgf = IDisputeGameFactory(mustGetAddress("DisputeGameFactoryProxy")); // Transfer the ownership of the DisputeGameFactory to the SystemOwnerSafe. dgf.transferOwnership(_systemOwnerSafe); @@ -134,7 +143,7 @@ contract FPACOPS is Deploy, StdAssertions { /// @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")); + IDelayedWETH weth = IDelayedWETH(mustGetAddress("DelayedWETHProxy")); // Transfer the ownership of the DelayedWETH to the SystemOwnerSafe. weth.transferOwnership(_systemOwnerSafe); @@ -146,7 +155,7 @@ contract FPACOPS is Deploy, StdAssertions { /// @notice Transfers admin rights of the `AnchorStateRegistryProxy` to the `ProxyAdmin`. function transferAnchorStateOwnershipFinal(address _proxyAdmin) internal broadcast { - AnchorStateRegistry asr = AnchorStateRegistry(mustGetAddress("AnchorStateRegistryProxy")); + IAnchorStateRegistry asr = IAnchorStateRegistry(mustGetAddress("AnchorStateRegistryProxy")); // Transfer the admin rights of the AnchorStateRegistryProxy to the ProxyAdmin. Proxy prox = Proxy(payable(address(asr))); @@ -163,7 +172,7 @@ contract FPACOPS is Deploy, StdAssertions { // Ensure the contracts are owned by the correct entities. address dgfProxyAddr = mustGetAddress("DisputeGameFactoryProxy"); - DisputeGameFactory dgfProxy = DisputeGameFactory(dgfProxyAddr); + IDisputeGameFactory dgfProxy = IDisputeGameFactory(dgfProxyAddr); assertEq(address(uint160(uint256(vm.load(dgfProxyAddr, Constants.PROXY_OWNER_ADDRESS)))), _proxyAdmin); ChainAssertions.checkDisputeGameFactory(contracts, _systemOwnerSafe); address wethProxyAddr = mustGetAddress("DelayedWETHProxy"); @@ -181,7 +190,7 @@ contract FPACOPS is Deploy, StdAssertions { assertEq(address(mips.oracle()), address(oracle)); // Check the AnchorStateRegistry configuration. - AnchorStateRegistry asr = AnchorStateRegistry(mustGetAddress("AnchorStateRegistryProxy")); + IAnchorStateRegistry asr = IAnchorStateRegistry(mustGetAddress("AnchorStateRegistryProxy")); (Hash root1, uint256 l2BlockNumber1) = asr.anchors(GameTypes.CANNON); (Hash root2, uint256 l2BlockNumber2) = asr.anchors(GameTypes.PERMISSIONED_CANNON); assertEq(root1.raw(), cfg.faultGameGenesisOutputRoot()); @@ -190,7 +199,7 @@ contract FPACOPS is Deploy, StdAssertions { assertEq(l2BlockNumber2, cfg.faultGameGenesisBlock()); // Check the FaultDisputeGame configuration. - FaultDisputeGame gameImpl = FaultDisputeGame(payable(address(dgfProxy.gameImpls(GameTypes.CANNON)))); + IFaultDisputeGame gameImpl = IFaultDisputeGame(payable(address(dgfProxy.gameImpls(GameTypes.CANNON)))); assertEq(gameImpl.maxGameDepth(), cfg.faultGameMaxDepth()); assertEq(gameImpl.splitDepth(), cfg.faultGameSplitDepth()); assertEq(gameImpl.clockExtension().raw(), cfg.faultGameClockExtension()); @@ -201,8 +210,8 @@ contract FPACOPS is Deploy, StdAssertions { assertEq(address(gameImpl.vm()), address(mips)); // Check the security override yoke configuration. - PermissionedDisputeGame soyGameImpl = - PermissionedDisputeGame(payable(address(dgfProxy.gameImpls(GameTypes.PERMISSIONED_CANNON)))); + IPermissionedDisputeGame soyGameImpl = + IPermissionedDisputeGame(payable(address(dgfProxy.gameImpls(GameTypes.PERMISSIONED_CANNON)))); assertEq(soyGameImpl.proposer(), cfg.l2OutputOracleProposer()); assertEq(soyGameImpl.challenger(), cfg.l2OutputOracleChallenger()); assertEq(soyGameImpl.maxGameDepth(), cfg.faultGameMaxDepth()); diff --git a/packages/contracts-bedrock/scripts/fpac/FPACOPS2.s.sol b/packages/contracts-bedrock/scripts/fpac/FPACOPS2.s.sol index 09171538010ca..0f5962a50d02a 100644 --- a/packages/contracts-bedrock/scripts/fpac/FPACOPS2.s.sol +++ b/packages/contracts-bedrock/scripts/fpac/FPACOPS2.s.sol @@ -1,13 +1,22 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Scripts +import { StdAssertions } from "forge-std/StdAssertions.sol"; +import "scripts/deploy/Deploy.s.sol"; + +// Contracts import { Proxy } from "src/universal/Proxy.sol"; + +// Libraries +import "src/dispute/lib/Types.sol"; + +// Interfaces import { IDisputeGame } from "src/dispute/interfaces/IDisputeGame.sol"; -import { AnchorStateRegistry, IAnchorStateRegistry } from "src/dispute/AnchorStateRegistry.sol"; +import { IAnchorStateRegistry } from "src/dispute/interfaces/IAnchorStateRegistry.sol"; import { IDelayedWETH } from "src/dispute/interfaces/IDelayedWETH.sol"; -import { StdAssertions } from "forge-std/StdAssertions.sol"; -import "src/dispute/lib/Types.sol"; -import "scripts/deploy/Deploy.s.sol"; +import { IFaultDisputeGame } from "src/dispute/interfaces/IFaultDisputeGame.sol"; +import { IPermissionedDisputeGame } from "src/dispute/interfaces/IPermissionedDisputeGame.sol"; /// @notice Deploys new implementations of the FaultDisputeGame contract and its dependencies /// assuming that the DisputeGameFactory contract does not need to be modified. Assumes @@ -85,18 +94,21 @@ contract FPACOPS2 is Deploy, StdAssertions { save( "CannonFaultDisputeGame", address( - new FaultDisputeGame({ - _gameType: GameTypes.CANNON, - _absolutePrestate: loadMipsAbsolutePrestate(), - _maxGameDepth: cfg.faultGameMaxDepth(), - _splitDepth: cfg.faultGameSplitDepth(), - _clockExtension: Duration.wrap(uint64(cfg.faultGameClockExtension())), - _maxClockDuration: Duration.wrap(uint64(cfg.faultGameMaxClockDuration())), - _vm: IBigStepper(mustGetAddress("Mips")), - _weth: DelayedWETH(mustGetAddress("DelayedWETHProxy")), - _anchorStateRegistry: AnchorStateRegistry(mustGetAddress("AnchorStateRegistryProxy")), - _l2ChainId: cfg.l2ChainID() - }) + _deploy( + "FaultDisputeGame", + abi.encode( + GameTypes.CANNON, + loadMipsAbsolutePrestate(), + cfg.faultGameMaxDepth(), + cfg.faultGameSplitDepth(), + Duration.wrap(uint64(cfg.faultGameClockExtension())), + Duration.wrap(uint64(cfg.faultGameMaxClockDuration())), + IBigStepper(mustGetAddress("Mips")), + IDelayedWETH(mustGetAddress("DelayedWETHProxy")), + IAnchorStateRegistry(mustGetAddress("AnchorStateRegistryProxy")), + cfg.l2ChainID() + ) + ) ) ); } @@ -108,20 +120,23 @@ contract FPACOPS2 is Deploy, StdAssertions { save( "PermissionedDisputeGame", address( - new PermissionedDisputeGame({ - _gameType: GameTypes.PERMISSIONED_CANNON, - _absolutePrestate: loadMipsAbsolutePrestate(), - _maxGameDepth: cfg.faultGameMaxDepth(), - _splitDepth: cfg.faultGameSplitDepth(), - _clockExtension: Duration.wrap(uint64(cfg.faultGameClockExtension())), - _maxClockDuration: Duration.wrap(uint64(cfg.faultGameMaxClockDuration())), - _vm: IBigStepper(mustGetAddress("Mips")), - _weth: DelayedWETH(mustGetAddress("PermissionedDelayedWETHProxy")), - _anchorStateRegistry: AnchorStateRegistry(mustGetAddress("AnchorStateRegistryProxy")), - _l2ChainId: cfg.l2ChainID(), - _proposer: cfg.l2OutputOracleProposer(), - _challenger: cfg.l2OutputOracleChallenger() - }) + _deploy( + "PermissionedDisputeGame", + abi.encode( + GameTypes.PERMISSIONED_CANNON, + loadMipsAbsolutePrestate(), + cfg.faultGameMaxDepth(), + cfg.faultGameSplitDepth(), + Duration.wrap(uint64(cfg.faultGameClockExtension())), + Duration.wrap(uint64(cfg.faultGameMaxClockDuration())), + IBigStepper(mustGetAddress("Mips")), + IDelayedWETH(mustGetAddress("PermissionedDelayedWETHProxy")), + IAnchorStateRegistry(mustGetAddress("AnchorStateRegistryProxy")), + cfg.l2ChainID(), + cfg.l2OutputOracleProposer(), + cfg.l2OutputOracleChallenger() + ) + ) ) ); } @@ -134,7 +149,7 @@ contract FPACOPS2 is Deploy, StdAssertions { address superchainConfigProxy = mustGetAddress("SuperchainConfigProxy"); Proxy(payable(wethProxy)).upgradeToAndCall( mustGetAddress("DelayedWETH"), - abi.encodeCall(DelayedWETH.initialize, (msg.sender, SuperchainConfig(superchainConfigProxy))) + abi.encodeCall(IDelayedWETH.initialize, (msg.sender, ISuperchainConfig(superchainConfigProxy))) ); } @@ -146,7 +161,7 @@ contract FPACOPS2 is Deploy, StdAssertions { address superchainConfigProxy = mustGetAddress("SuperchainConfigProxy"); Proxy(payable(wethProxy)).upgradeToAndCall( mustGetAddress("DelayedWETH"), - abi.encodeCall(DelayedWETH.initialize, (msg.sender, SuperchainConfig(superchainConfigProxy))) + abi.encodeCall(IDelayedWETH.initialize, (msg.sender, ISuperchainConfig(superchainConfigProxy))) ); } @@ -155,7 +170,7 @@ contract FPACOPS2 is Deploy, StdAssertions { function transferWethOwnershipFinal(address _proxyAdmin, address _systemOwnerSafe) internal broadcast { console.log("Transferring ownership of DelayedWETHProxy"); - DelayedWETH weth = DelayedWETH(mustGetAddress("DelayedWETHProxy")); + IDelayedWETH weth = IDelayedWETH(mustGetAddress("DelayedWETHProxy")); // Transfer the ownership of the DelayedWETH to the SystemOwnerSafe. weth.transferOwnership(_systemOwnerSafe); @@ -170,7 +185,7 @@ contract FPACOPS2 is Deploy, StdAssertions { function transferPermissionedWETHOwnershipFinal(address _proxyAdmin, address _systemOwnerSafe) internal broadcast { console.log("Transferring ownership of permissioned DelayedWETHProxy"); - DelayedWETH weth = DelayedWETH(mustGetAddress("PermissionedDelayedWETHProxy")); + IDelayedWETH weth = IDelayedWETH(mustGetAddress("PermissionedDelayedWETHProxy")); // Transfer the ownership of the DelayedWETH to the SystemOwnerSafe. weth.transferOwnership(_systemOwnerSafe); @@ -214,11 +229,11 @@ contract FPACOPS2 is Deploy, StdAssertions { assertEq(address(mips.oracle()), address(oracle)); // Grab ASR - AnchorStateRegistry asr = AnchorStateRegistry(mustGetAddress("AnchorStateRegistryProxy")); + IAnchorStateRegistry asr = IAnchorStateRegistry(mustGetAddress("AnchorStateRegistryProxy")); // Verify FaultDisputeGame configuration. address gameAddr = mustGetAddress("CannonFaultDisputeGame"); - FaultDisputeGame gameImpl = FaultDisputeGame(payable(gameAddr)); + IFaultDisputeGame gameImpl = IFaultDisputeGame(payable(gameAddr)); assertEq(gameImpl.maxGameDepth(), cfg.faultGameMaxDepth()); assertEq(gameImpl.splitDepth(), cfg.faultGameSplitDepth()); assertEq(gameImpl.clockExtension().raw(), cfg.faultGameClockExtension()); @@ -230,7 +245,7 @@ contract FPACOPS2 is Deploy, StdAssertions { // Verify security override yoke configuration. address soyGameAddr = mustGetAddress("PermissionedDisputeGame"); - PermissionedDisputeGame soyGameImpl = PermissionedDisputeGame(payable(soyGameAddr)); + IPermissionedDisputeGame soyGameImpl = IPermissionedDisputeGame(payable(soyGameAddr)); assertEq(soyGameImpl.proposer(), cfg.l2OutputOracleProposer()); assertEq(soyGameImpl.challenger(), cfg.l2OutputOracleChallenger()); assertEq(soyGameImpl.maxGameDepth(), cfg.faultGameMaxDepth()); diff --git a/packages/contracts-bedrock/scripts/fpac/viz/FaultDisputeGameViz.s.sol b/packages/contracts-bedrock/scripts/fpac/viz/FaultDisputeGameViz.s.sol index f03897dd0c26e..2e0dd45e4ebef 100644 --- a/packages/contracts-bedrock/scripts/fpac/viz/FaultDisputeGameViz.s.sol +++ b/packages/contracts-bedrock/scripts/fpac/viz/FaultDisputeGameViz.s.sol @@ -1,18 +1,21 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.15; +// Testing +import { FaultDisputeGame_Init } from "test/dispute/FaultDisputeGame.t.sol"; + +// Scripts import { Script } from "forge-std/Script.sol"; import { console2 as console } from "forge-std/console2.sol"; - -import { FaultDisputeGame_Init } from "test/dispute/FaultDisputeGame.t.sol"; -import { DisputeGameFactory } from "src/dispute/DisputeGameFactory.sol"; -import { FaultDisputeGame } from "src/dispute/FaultDisputeGame.sol"; -import { IFaultDisputeGame } from "src/dispute/interfaces/IFaultDisputeGame.sol"; import { Process } from "scripts/libraries/Process.sol"; +// Libraries import "src/dispute/lib/Types.sol"; import "src/dispute/lib/Errors.sol"; +// Interfaces +import { IFaultDisputeGame } from "src/dispute/interfaces/IFaultDisputeGame.sol"; + /** * @title FaultDisputeGameViz * @dev To run this script, make sure to install the `dagviz` & `eth_abi` python packages. @@ -43,7 +46,7 @@ contract FaultDisputeGameViz is Script, FaultDisputeGame_Init { * @dev Entry point */ function remote(address _addr) public { - gameProxy = FaultDisputeGame(payable(_addr)); + gameProxy = IFaultDisputeGame(payable(_addr)); buildGraph(); console.log("Saved graph to `./dispute_game.svg"); } diff --git a/packages/contracts-bedrock/scripts/go-ffi/differential-testing.go b/packages/contracts-bedrock/scripts/go-ffi/differential-testing.go index 3186c88b0cba0..af4deae5c09cb 100644 --- a/packages/contracts-bedrock/scripts/go-ffi/differential-testing.go +++ b/packages/contracts-bedrock/scripts/go-ffi/differential-testing.go @@ -359,10 +359,11 @@ func DiffTestUtils() { // Print the output fmt.Print(hexutil.Encode(packed[32:])) case "cannonMemoryProof": - // <pc, insn, [memAddr, memValue]> + // <pc, insn, [memAddr, memValue], [memAddr2, memValue2]> + // Generates a memory proof of `memAddr` for a trie containing memValue and memValue2 mem := memory.NewMemory() - if len(args) != 3 && len(args) != 5 { - panic("Error: cannonMemoryProofWithProof requires 2 or 4 arguments") + if len(args) != 3 && len(args) != 5 && len(args) != 7 { + panic("Error: cannonMemoryProofWithProof requires 2, 4, or 6 arguments") } pc, err := strconv.ParseUint(args[1], 10, 32) checkErr(err, "Error decoding addr") @@ -371,7 +372,7 @@ func DiffTestUtils() { mem.SetMemory(uint32(pc), uint32(insn)) var insnProof, memProof [896]byte - if len(args) == 5 { + if len(args) >= 5 { memAddr, err := strconv.ParseUint(args[3], 10, 32) checkErr(err, "Error decoding memAddr") memValue, err := strconv.ParseUint(args[4], 10, 32) @@ -379,6 +380,14 @@ func DiffTestUtils() { mem.SetMemory(uint32(memAddr), uint32(memValue)) memProof = mem.MerkleProof(uint32(memAddr)) } + if len(args) == 7 { + memAddr, err := strconv.ParseUint(args[5], 10, 32) + checkErr(err, "Error decoding memAddr") + memValue, err := strconv.ParseUint(args[6], 10, 32) + checkErr(err, "Error decoding memValue") + mem.SetMemory(uint32(memAddr), uint32(memValue)) + memProof = mem.MerkleProof(uint32(memAddr)) + } insnProof = mem.MerkleProof(uint32(pc)) output := struct { @@ -391,6 +400,40 @@ func DiffTestUtils() { packed, err := cannonMemoryProofArgs.Pack(&output) checkErr(err, "Error encoding output") fmt.Print(hexutil.Encode(packed[32:])) + case "cannonMemoryProof2": + // <pc, insn, [memAddr, memValue], memAddr2> + // Generates a memory proof of memAddr2 for a trie containing memValue + mem := memory.NewMemory() + if len(args) != 6 { + panic("Error: cannonMemoryProofWithProof2 requires 5 arguments") + } + pc, err := strconv.ParseUint(args[1], 10, 32) + checkErr(err, "Error decoding addr") + insn, err := strconv.ParseUint(args[2], 10, 32) + checkErr(err, "Error decoding insn") + mem.SetMemory(uint32(pc), uint32(insn)) + + var memProof [896]byte + memAddr, err := strconv.ParseUint(args[3], 10, 32) + checkErr(err, "Error decoding memAddr") + memValue, err := strconv.ParseUint(args[4], 10, 32) + checkErr(err, "Error decoding memValue") + mem.SetMemory(uint32(memAddr), uint32(memValue)) + + memAddr2, err := strconv.ParseUint(args[5], 10, 32) + checkErr(err, "Error decoding memAddr") + memProof = mem.MerkleProof(uint32(memAddr2)) + + output := struct { + MemRoot common.Hash + Proof []byte + }{ + MemRoot: mem.MerkleRoot(), + Proof: memProof[:], + } + packed, err := cannonMemoryProofArgs.Pack(&output) + checkErr(err, "Error encoding output") + fmt.Print(hexutil.Encode(packed[32:])) case "cannonMemoryProofWrongLeaf": // <pc, insn, memAddr, memValue> mem := memory.NewMemory() diff --git a/packages/contracts-bedrock/scripts/interfaces/IAddressManager.sol b/packages/contracts-bedrock/scripts/interfaces/IAddressManager.sol deleted file mode 100644 index f7e87cdc87027..0000000000000 --- a/packages/contracts-bedrock/scripts/interfaces/IAddressManager.sol +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.15; - -/// @title IAddressManager -/// @notice Minimal interface of the Legacy AddressManager. -interface IAddressManager { - /// @notice Emitted when an address is modified in the registry. - /// @param name String name being set in the registry. - /// @param newAddress Address set for the given name. - /// @param oldAddress Address that was previously set for the given name. - event AddressSet(string indexed name, address newAddress, address oldAddress); - - /// @notice Changes the address associated with a particular name. - /// @param _name String name to associate an address with. - /// @param _address Address to associate with the name. - function setAddress(string memory _name, address _address) external; - - /// @notice Retrieves the address associated with a given name. - /// @param _name Name to retrieve an address for. - /// @return Address associated with the given name. - function getAddress(string memory _name) external view returns (address); -} diff --git a/packages/contracts-bedrock/scripts/interfaces/IGnosisSafe.sol b/packages/contracts-bedrock/scripts/interfaces/IGnosisSafe.sol index 60434364fd9a9..068f3815134a2 100644 --- a/packages/contracts-bedrock/scripts/interfaces/IGnosisSafe.sol +++ b/packages/contracts-bedrock/scripts/interfaces/IGnosisSafe.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LGPL-3.0-only -pragma solidity ^0.8.10; +pragma solidity ^0.8.0; /// @title Enum - Collection of enums used in Safe contracts. /// @author Richard Meissner - @rmeissner diff --git a/packages/contracts-bedrock/scripts/interfaces/ISystemConfigV0.sol b/packages/contracts-bedrock/scripts/interfaces/ISystemConfigV0.sol index 2871d76b8238c..af1397d726452 100644 --- a/packages/contracts-bedrock/scripts/interfaces/ISystemConfigV0.sol +++ b/packages/contracts-bedrock/scripts/interfaces/ISystemConfigV0.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.15; +pragma solidity ^0.8.0; -import { ResourceMetering } from "src/L1/ResourceMetering.sol"; +import { IResourceMetering } from "src/L1/interfaces/IResourceMetering.sol"; /// @title ISystemConfigV0 /// @notice Minimal interface of the Legacy SystemConfig containing only getters. @@ -14,6 +14,6 @@ interface ISystemConfigV0 { function scalar() external view returns (uint256); function batcherHash() external view returns (bytes32); function gasLimit() external view returns (uint64); - function resourceConfig() external view returns (ResourceMetering.ResourceConfig memory); + function resourceConfig() external view returns (IResourceMetering.ResourceConfig memory); function unsafeBlockSigner() external view returns (address); } diff --git a/packages/contracts-bedrock/scripts/libraries/Config.sol b/packages/contracts-bedrock/scripts/libraries/Config.sol index d4253113ce8a5..06e59e9022466 100644 --- a/packages/contracts-bedrock/scripts/libraries/Config.sol +++ b/packages/contracts-bedrock/scripts/libraries/Config.sol @@ -138,6 +138,11 @@ library Config { } } + /// @notice Returns true if multithreaded Cannon is used for the deployment. + function useMultithreadedCannon() internal view returns (bool _enabled) { + _enabled = vm.envOr("USE_MT_CANNON", false); + } + /// @notice Returns the latest fork to use for genesis allocs generation. /// It reads the fork from the environment variable FORK. If it is /// unset, NONE is returned. diff --git a/packages/contracts-bedrock/scripts/libraries/DeployUtils.sol b/packages/contracts-bedrock/scripts/libraries/DeployUtils.sol index d690f0b6df6d4..92870309657ea 100644 --- a/packages/contracts-bedrock/scripts/libraries/DeployUtils.sol +++ b/packages/contracts-bedrock/scripts/libraries/DeployUtils.sol @@ -1,23 +1,222 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Scripts +import { Vm } from "forge-std/Vm.sol"; +import { console2 as console } from "forge-std/console2.sol"; +import { Artifacts } from "scripts/Artifacts.s.sol"; + +// Libraries import { LibString } from "@solady/utils/LibString.sol"; +// Contracts +import { Proxy } from "src/universal/Proxy.sol"; + library DeployUtils { - // This takes a sender and an identifier and returns a deterministic address based on the two. - // The result is used to etch the input and output contracts to a deterministic address based on - // those two values, where the identifier represents the input or output contract, such as - // `optimism.DeploySuperchainInput` or `optimism.DeployOPChainOutput`. - // Example: `toIOAddress(msg.sender, "optimism.DeploySuperchainInput")` + Vm internal constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); + + /// @notice Deploys a contract with the given name and arguments via CREATE. + /// @param _name Name of the contract to deploy. + /// @param _args ABI-encoded constructor arguments. + /// @return addr_ Address of the deployed contract. + function create1(string memory _name, bytes memory _args) internal returns (address payable addr_) { + bytes memory bytecode = abi.encodePacked(vm.getCode(_name), _args); + assembly { + addr_ := create(0, add(bytecode, 0x20), mload(bytecode)) + } + assertValidContractAddress(addr_); + } + + /// @notice Deploys a contract with the given name via CREATE. + /// @param _name Name of the contract to deploy. + /// @return Address of the deployed contract. + function create1(string memory _name) internal returns (address payable) { + return create1(_name, hex""); + } + + /// @notice Deploys a contract with the given name and arguments via CREATE and saves the result. + /// @param _save Artifacts contract. + /// @param _name Name of the contract to deploy. + /// @param _nick Nickname to save the address to. + /// @param _args ABI-encoded constructor arguments. + /// @return addr_ Address of the deployed contract. + function create1AndSave( + Artifacts _save, + string memory _name, + string memory _nick, + bytes memory _args + ) + internal + returns (address payable addr_) + { + console.log("Deploying %s", _nick); + addr_ = create1(_name, _args); + _save.save(_nick, addr_); + console.log("%s deployed at %s", _nick, addr_); + } + + /// @notice Deploys a contract with the given name via CREATE and saves the result. + /// @param _save Artifacts contract. + /// @param _name Name of the contract to deploy. + /// @param _nickname Nickname to save the address to. + /// @return addr_ Address of the deployed contract. + function create1AndSave( + Artifacts _save, + string memory _name, + string memory _nickname + ) + internal + returns (address payable addr_) + { + return create1AndSave(_save, _name, _nickname, hex""); + } + + /// @notice Deploys a contract with the given name and arguments via CREATE and saves the result. + /// @param _save Artifacts contract. + /// @param _name Name of the contract to deploy. + /// @param _args ABI-encoded constructor arguments. + /// @return addr_ Address of the deployed contract. + function create1AndSave( + Artifacts _save, + string memory _name, + bytes memory _args + ) + internal + returns (address payable addr_) + { + return create1AndSave(_save, _name, _name, _args); + } + + /// @notice Deploys a contract with the given name and arguments via CREATE2. + /// @param _name Name of the contract to deploy. + /// @param _args ABI-encoded constructor arguments. + /// @param _salt Salt for the CREATE2 operation. + /// @return addr_ Address of the deployed contract. + function create2(string memory _name, bytes memory _args, bytes32 _salt) internal returns (address payable addr_) { + bytes memory initCode = abi.encodePacked(vm.getCode(_name), _args); + address preComputedAddress = vm.computeCreate2Address(_salt, keccak256(initCode)); + require(preComputedAddress.code.length == 0, "DeployUtils: contract already deployed"); + assembly { + addr_ := create2(0, add(initCode, 0x20), mload(initCode), _salt) + } + assertValidContractAddress(addr_); + } + + /// @notice Deploys a contract with the given name via CREATE2. + /// @param _name Name of the contract to deploy. + /// @param _salt Salt for the CREATE2 operation. + /// @return Address of the deployed contract. + function create2(string memory _name, bytes32 _salt) internal returns (address payable) { + return create2(_name, hex"", _salt); + } + + /// @notice Deploys a contract with the given name and arguments via CREATE2 and saves the result. + /// @param _save Artifacts contract. + /// @param _name Name of the contract to deploy. + /// @param _nick Nickname to save the address to. + /// @param _args ABI-encoded constructor arguments. + /// @param _salt Salt for the CREATE2 operation. + /// @return addr_ Address of the deployed contract. + function create2AndSave( + Artifacts _save, + string memory _name, + string memory _nick, + bytes memory _args, + bytes32 _salt + ) + internal + returns (address payable addr_) + { + console.log("Deploying %s", _nick); + addr_ = create2(_name, _args, _salt); + _save.save(_nick, addr_); + console.log("%s deployed at %s", _nick, addr_); + } + + /// @notice Deploys a contract with the given name via CREATE2 and saves the result. + /// @param _save Artifacts contract. + /// @param _name Name of the contract to deploy. + /// @param _nick Nickname to save the address to. + /// @param _salt Salt for the CREATE2 operation. + /// @return addr_ Address of the deployed contract. + function create2AndSave( + Artifacts _save, + string memory _name, + string memory _nick, + bytes32 _salt + ) + internal + returns (address payable addr_) + { + return create2AndSave(_save, _name, _nick, hex"", _salt); + } + + /// @notice Deploys a contract with the given name and arguments via CREATE2 and saves the result. + /// @param _save Artifacts contract. + /// @param _name Name of the contract to deploy. + /// @param _args ABI-encoded constructor arguments. + /// @param _salt Salt for the CREATE2 operation. + /// @return addr_ Address of the deployed contract. + function create2AndSave( + Artifacts _save, + string memory _name, + bytes memory _args, + bytes32 _salt + ) + internal + returns (address payable addr_) + { + return create2AndSave(_save, _name, _name, _args, _salt); + } + + /// @notice Deploys a contract with the given name via CREATE2 and saves the result. + /// @param _save Artifacts contract. + /// @param _name Name of the contract to deploy. + /// @param _salt Salt for the CREATE2 operation. + /// @return addr_ Address of the deployed contract. + function create2AndSave( + Artifacts _save, + string memory _name, + bytes32 _salt + ) + internal + returns (address payable addr_) + { + return create2AndSave(_save, _name, _name, hex"", _salt); + } + + /// @notice Takes a sender and an identifier and returns a deterministic address based on the + /// two. The result is used to etch the input and output contracts to a deterministic + /// address based on those two values, where the identifier represents the input or + /// output contract, such as `optimism.DeploySuperchainInput` or + /// `optimism.DeployOPChainOutput`. + /// Example: `toIOAddress(msg.sender, "optimism.DeploySuperchainInput")` + /// @param _sender Address of the sender. + /// @param _identifier Additional identifier. + /// @return Deterministic address. function toIOAddress(address _sender, string memory _identifier) internal pure returns (address) { return address(uint160(uint256(keccak256(abi.encode(_sender, _identifier))))); } + /// @notice Asserts that the given address is a valid contract address. + /// @param _who Address to check. function assertValidContractAddress(address _who) internal view { require(_who != address(0), "DeployUtils: zero address"); require(_who.code.length > 0, string.concat("DeployUtils: no code at ", LibString.toHexStringChecksummed(_who))); } + /// @notice Asserts that the given proxy has an implementation set. + /// @param _proxy Proxy to check. + function assertImplementationSet(address _proxy) internal { + // We prank as the zero address due to the Proxy's `proxyCallIfNotAdmin` modifier. + // Pranking inside this function also means it can no longer be considered `view`. + vm.prank(address(0)); + address implementation = Proxy(payable(_proxy)).implementation(); + assertValidContractAddress(implementation); + } + + /// @notice Asserts that the given addresses are valid contract addresses. + /// @param _addrs Addresses to check. function assertValidContractAddresses(address[] memory _addrs) internal view { // Assert that all addresses are non-zero and have code. // We use LibString to avoid the need for adding cheatcodes to this contract. @@ -35,4 +234,16 @@ library DeployUtils { } } } + + /// @notice Asserts that for a given contract the value of a storage slot at an offset is 1 or + /// `type(uint8).max`. The value is set to 1 when a contract is initialized, and set to + /// `type(uint8).max` when `_disableInitializers` is called. + function assertInitialized(address _contractAddress, uint256 _slot, uint256 _offset) internal view { + bytes32 slotVal = vm.load(_contractAddress, bytes32(_slot)); + uint8 value = uint8((uint256(slotVal) >> (_offset * 8)) & 0xFF); + require( + value == 1 || value == type(uint8).max, + "Value at the given slot and offset does not indicate initialization" + ); + } } diff --git a/packages/contracts-bedrock/scripts/libraries/Executables.sol b/packages/contracts-bedrock/scripts/libraries/Executables.sol index 31f81da71ee59..0dc91e32072db 100644 --- a/packages/contracts-bedrock/scripts/libraries/Executables.sol +++ b/packages/contracts-bedrock/scripts/libraries/Executables.sol @@ -19,12 +19,16 @@ library Executables { string internal constant ls = "ls"; string internal constant git = "git"; - /// @notice Returns the commit hash of HEAD. + /// @notice Returns the commit hash of HEAD. If no git repository is + /// found, it will return the contents of the .gitcommit file. Otherwise, + /// it will return an error. The .gitcommit file is used to store the + /// git commit of the contracts when they are packaged into docker images + /// in order to avoid the need to have a git repository in the image. function gitCommitHash() internal returns (string memory) { string[] memory commands = new string[](3); commands[0] = bash; commands[1] = "-c"; - commands[2] = "cast abi-encode 'f(string)' $(git rev-parse HEAD)"; + commands[2] = "cast abi-encode 'f(string)' $(git rev-parse HEAD || cat .gitcommit)"; return abi.decode(Process.run(commands), (string)); } } diff --git a/packages/contracts-bedrock/scripts/libraries/ForgeArtifacts.sol b/packages/contracts-bedrock/scripts/libraries/ForgeArtifacts.sol index 315ed6d0c530f..4aa4309fad833 100644 --- a/packages/contracts-bedrock/scripts/libraries/ForgeArtifacts.sol +++ b/packages/contracts-bedrock/scripts/libraries/ForgeArtifacts.sol @@ -3,6 +3,7 @@ pragma solidity ^0.8.0; import { Vm } from "forge-std/Vm.sol"; import { stdJson } from "forge-std/StdJson.sol"; +import { LibString } from "@solady/utils/LibString.sol"; import { Executables } from "scripts/libraries/Executables.sol"; import { Process } from "scripts/libraries/Process.sol"; @@ -83,6 +84,67 @@ library ForgeArtifacts { ids_ = stdJson.readStringArray(string(res), ""); } + /// @notice Returns the kind of contract (i.e. library, contract, or interface). + /// @param _name The name of the contract to get the kind of. + /// @return kind_ The kind of contract ("library", "contract", or "interface"). + function getContractKind(string memory _name) internal returns (string memory kind_) { + string[] memory cmd = new string[](3); + cmd[0] = Executables.bash; + cmd[1] = "-c"; + cmd[2] = string.concat( + Executables.jq, + " -r '.ast.nodes[] | select(.nodeType == \"ContractDefinition\") | .contractKind' < ", + _getForgeArtifactPath(_name) + ); + bytes memory res = Process.run(cmd); + kind_ = string(res); + } + + /// @notice Returns whether or not a contract is proxied. + /// @param _name The name of the contract to check. + /// @return out_ Whether or not the contract is proxied. + function isProxiedContract(string memory _name) internal returns (bool out_) { + // TODO: Using the `@custom:proxied` tag is to determine if a contract is meant to be + // proxied is functional but developers can easily forget to add the tag when writing a new + // contract. We should consider determining whether a contract is proxied based on the + // deployment script since it's the source of truth for that. Current deployment script + // does not make this easy but an updated script should likely make this possible. + string[] memory cmd = new string[](3); + cmd[0] = Executables.bash; + cmd[1] = "-c"; + cmd[2] = string.concat( + Executables.jq, + " -r '.rawMetadata' ", + _getForgeArtifactPath(_name), + " | ", + Executables.jq, + " -r '.output.devdoc' | jq -r 'has(\"custom:proxied\")'" + ); + bytes memory res = Process.run(cmd); + out_ = stdJson.readBool(string(res), ""); + } + + /// @notice Returns whether or not a contract is predeployed. + /// @param _name The name of the contract to check. + /// @return out_ Whether or not the contract is predeployed. + function isPredeployedContract(string memory _name) internal returns (bool out_) { + // TODO: Similar to the above, using the `@custom:predeployed` tag is not reliable but + // functional for now. Deployment script should make this easier to determine. + string[] memory cmd = new string[](3); + cmd[0] = Executables.bash; + cmd[1] = "-c"; + cmd[2] = string.concat( + Executables.jq, + " -r '.rawMetadata' ", + _getForgeArtifactPath(_name), + " | ", + Executables.jq, + " -r '.output.devdoc' | jq -r 'has(\"custom:predeploy\")'" + ); + bytes memory res = Process.run(cmd); + out_ = stdJson.readBool(string(res), ""); + } + function _getForgeArtifactDirectory(string memory _name) internal returns (string memory dir_) { string[] memory cmd = new string[](3); cmd[0] = Executables.bash; @@ -128,6 +190,14 @@ library ForgeArtifacts { function getInitializedSlot(string memory _contractName) internal returns (StorageSlot memory slot_) { string memory storageLayout = getStorageLayout(_contractName); + // FaultDisputeGame and PermissionedDisputeGame use a different name for the initialized storage slot. + string memory slotName = "_initialized"; + string memory slotType = "t_uint8"; + if (LibString.eq(_contractName, "FaultDisputeGame") || LibString.eq(_contractName, "PermissionedDisputeGame")) { + slotName = "initialized"; + slotType = "t_bool"; + } + string[] memory command = new string[](3); command[0] = Executables.bash; command[1] = "-c"; @@ -138,7 +208,11 @@ library ForgeArtifacts { "'", " | ", Executables.jq, - " '.storage[] | select(.label == \"_initialized\" and .type == \"t_uint8\")'" + " '.storage[] | select(.label == \"", + slotName, + "\" and .type == \"", + slotType, + "\")'" ); bytes memory rawSlot = vm.parseJson(string(Process.run(command))); slot_ = abi.decode(rawSlot, (StorageSlot)); @@ -152,18 +226,21 @@ library ForgeArtifacts { initialized_ = uint8((uint256(slotVal) >> (slot.offset * 8)) & 0xFF) != 0; } - /// @notice Returns the function ABIs of all L1 contracts. - function getContractFunctionAbis( - string memory path, - string[] memory pathExcludes + /// @notice Returns the names of all contracts in a given directory. + /// @param _path The path to search for contracts. + /// @param _pathExcludes An array of paths to exclude from the search. + /// @return contractNames_ An array of contract names. + function getContractNames( + string memory _path, + string[] memory _pathExcludes ) internal - returns (Abi[] memory abis_) + returns (string[] memory contractNames_) { string memory pathExcludesPat; - for (uint256 i = 0; i < pathExcludes.length; i++) { - pathExcludesPat = string.concat(pathExcludesPat, " -path \"", pathExcludes[i], "\""); - if (i != pathExcludes.length - 1) { + for (uint256 i = 0; i < _pathExcludes.length; i++) { + pathExcludesPat = string.concat(pathExcludesPat, " -path \"", _pathExcludes[i], "\""); + if (i != _pathExcludes.length - 1) { pathExcludesPat = string.concat(pathExcludesPat, " -o "); } } @@ -174,7 +251,7 @@ library ForgeArtifacts { command[2] = string.concat( Executables.find, " ", - path, + _path, bytes(pathExcludesPat).length > 0 ? string.concat(" ! \\( ", pathExcludesPat, " \\)") : "", " -type f ", "-exec basename {} \\;", @@ -185,8 +262,19 @@ library ForgeArtifacts { Executables.jq, " -R -s 'split(\"\n\")[:-1]'" ); - string[] memory contractNames = abi.decode(vm.parseJson(string(Process.run(command))), (string[])); + contractNames_ = abi.decode(vm.parseJson(string(Process.run(command))), (string[])); + } + + /// @notice Returns the function ABIs of all L1 contracts. + function getContractFunctionAbis( + string memory path, + string[] memory pathExcludes + ) + internal + returns (Abi[] memory abis_) + { + string[] memory contractNames = getContractNames(path, pathExcludes); abis_ = new Abi[](contractNames.length); for (uint256 i; i < contractNames.length; i++) { diff --git a/packages/contracts-bedrock/scripts/libraries/Solarray.sol b/packages/contracts-bedrock/scripts/libraries/Solarray.sol index d6049c5654f3e..57ef9b320bb03 100644 --- a/packages/contracts-bedrock/scripts/libraries/Solarray.sol +++ b/packages/contracts-bedrock/scripts/libraries/Solarray.sol @@ -7,7 +7,7 @@ pragma solidity ^0.8.13; // since Solidity does not have great array UX. // // This library was generated using the `generator.py` script from the linked repo with the length -// set to 10, and then everything except the `addresses` functions was removed. +// set accordingly, and then everything except the `addresses` functions was removed. library Solarray { function addresses(address a) internal pure returns (address[] memory) { address[] memory arr = new address[](1); @@ -189,6 +189,38 @@ library Solarray { return arr; } + function addresses( + address a, + address b, + address c, + address d, + address e, + address f, + address g, + address h, + address i, + address j, + address k + ) + internal + pure + returns (address[] memory) + { + address[] memory arr = new address[](11); + arr[0] = a; + arr[1] = b; + arr[2] = c; + arr[3] = d; + arr[4] = e; + arr[5] = f; + arr[6] = g; + arr[7] = h; + arr[8] = i; + arr[9] = j; + arr[10] = k; + return arr; + } + function extend(address[] memory arr1, address[] memory arr2) internal pure returns (address[] memory newArr) { uint256 length1 = arr1.length; uint256 length2 = arr2.length; diff --git a/packages/contracts-bedrock/scripts/ops/calculate-checksum.sh b/packages/contracts-bedrock/scripts/ops/calculate-checksum.sh new file mode 100644 index 0000000000000..6278e37ffa74b --- /dev/null +++ b/packages/contracts-bedrock/scripts/ops/calculate-checksum.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +set -euo pipefail + +echoerr() { + echo "$@" 1>&2 +} + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +CONTRACTS_DIR="$SCRIPT_DIR/../.." + +cd "$CONTRACTS_DIR" + +echoerr "> Calculating contracts checksum..." + +find . -type f -name '*.sol' -exec sha256sum {} + > manifest.txt +sha256sum semver-lock.json >> manifest.txt +sha256sum foundry.toml >> manifest.txt +# need to specify the locale to ensure consistent sorting across platforms +LC_ALL=C sort -o manifest.txt manifest.txt +checksum=$(sha256sum manifest.txt | awk '{print $1}') +rm manifest.txt +echoerr "> Done." + +echo -n "$checksum" \ No newline at end of file diff --git a/packages/contracts-bedrock/scripts/ops/publish-artifacts.sh b/packages/contracts-bedrock/scripts/ops/publish-artifacts.sh new file mode 100644 index 0000000000000..309b2d818edaa --- /dev/null +++ b/packages/contracts-bedrock/scripts/ops/publish-artifacts.sh @@ -0,0 +1,54 @@ +#!/usr/bin/env bash + +set -euo pipefail + +echoerr() { + echo "$@" 1>&2 +} + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +CONTRACTS_DIR="$SCRIPT_DIR/../.." +DEPLOY_BUCKET="oplabs-contract-artifacts" + +cd "$CONTRACTS_DIR" + +# ensure that artifacts exists and is non-empty +if [ ! -d "forge-artifacts" ] || [ -z "$(ls -A forge-artifacts)" ]; then + echoerr "> No forge-artifacts directory found." + exit 1 +fi + +if [ ! -d "artifacts" ] || [ -z "$(ls -A artifacts)" ]; then + echoerr "> No artifacts directory found." + exit 1 +fi + +checksum=$(bash scripts/ops/calculate-checksum.sh) + +echoerr "> Checking for existing artifacts..." +exists=$(curl -s -o /dev/null --fail -LI "https://storage.googleapis.com/$DEPLOY_BUCKET/artifacts-v1-$checksum.tar.gz" || echo "fail") + +if [ "$exists" != "fail" ]; then + echoerr "> Existing artifacts found, nothing to do." + exit 0 +fi + +echoerr "> Archiving artifacts..." +archive_name="artifacts-v1-$checksum.tar.gz" + +# use gtar on darwin +if [[ "$OSTYPE" == "darwin"* ]]; then + tar="gtar" +else + tar="tar" +fi + +"$tar" -czf "$archive_name" artifacts forge-artifacts cache +du -sh "$archive_name" | awk '{$1=$1};1' # trim leading whitespace +echoerr "> Done." + +echoerr "> Uploading artifacts to GCS..." +gcloud storage cp "$archive_name" "gs://$DEPLOY_BUCKET/$archive_name" +echoerr "> Done." + +rm "$archive_name" \ No newline at end of file diff --git a/packages/contracts-bedrock/scripts/ops/pull-artifacts.sh b/packages/contracts-bedrock/scripts/ops/pull-artifacts.sh new file mode 100644 index 0000000000000..f119b087f38c3 --- /dev/null +++ b/packages/contracts-bedrock/scripts/ops/pull-artifacts.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash + +set -euo pipefail + +echoerr() { + echo "$@" 1>&2 +} + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +CONTRACTS_DIR="$SCRIPT_DIR/../.." + +cd "$CONTRACTS_DIR" + +checksum=$(bash scripts/ops/calculate-checksum.sh) +archive_name="artifacts-v1-$checksum.tar.gz" + +echoerr "> Checking for existing artifacts..." +exists=$(curl -s -o /dev/null --fail -LI "https://storage.googleapis.com/oplabs-contract-artifacts/$archive_name" || echo "fail") + +if [ "$exists" == "fail" ]; then + echoerr "> No existing artifacts found, exiting." + exit 0 +fi + +echoerr "> Cleaning up existing artifacts..." +rm -rf artifacts +rm -rf forge-artifacts +rm -rf cache +echoerr "> Done." + +echoerr "> Found existing artifacts. Downloading..." +curl -o "$archive_name" "https://storage.googleapis.com/oplabs-contract-artifacts/$archive_name" +echoerr "> Done." + +echoerr "> Extracting existing artifacts..." +tar -xzvf "$archive_name" +echoerr "> Done." + +echoerr "> Cleaning up." +rm "$archive_name" +echoerr "> Done." \ No newline at end of file diff --git a/packages/contracts-bedrock/scripts/periphery/deploy/DeployPeriphery.s.sol b/packages/contracts-bedrock/scripts/periphery/deploy/DeployPeriphery.s.sol index 856104eb27347..8f4b86b95d62d 100644 --- a/packages/contracts-bedrock/scripts/periphery/deploy/DeployPeriphery.s.sol +++ b/packages/contracts-bedrock/scripts/periphery/deploy/DeployPeriphery.s.sol @@ -10,7 +10,6 @@ import { PeripheryDeployConfig } from "scripts/periphery/deploy/PeripheryDeployC import { ProxyAdmin } from "src/universal/ProxyAdmin.sol"; import { Proxy } from "src/universal/Proxy.sol"; -import { L1StandardBridge } from "src/L1/L1StandardBridge.sol"; import { Faucet } from "src/periphery/faucet/Faucet.sol"; import { Drippie } from "src/periphery/drippie/Drippie.sol"; import { CheckGelatoLow } from "src/periphery/drippie/dripchecks/CheckGelatoLow.sol"; diff --git a/packages/contracts-bedrock/scripts/periphery/drippie/ManageDrippie.s.sol b/packages/contracts-bedrock/scripts/periphery/drippie/ManageDrippie.s.sol index 903216b3d16ac..f37a16f547f92 100644 --- a/packages/contracts-bedrock/scripts/periphery/drippie/ManageDrippie.s.sol +++ b/packages/contracts-bedrock/scripts/periphery/drippie/ManageDrippie.s.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.0; import { console2 as console } from "forge-std/console2.sol"; import { Script } from "forge-std/Script.sol"; -import { LibString } from "solady/src/utils/LibString.sol"; +import { LibString } from "@solady/utils/LibString.sol"; import { IAutomate as IGelato } from "gelato/interfaces/IAutomate.sol"; import { LibDataTypes as GelatoDataTypes } from "gelato/libraries/LibDataTypes.sol"; diff --git a/packages/contracts-bedrock/scripts/utils/BaseDeployIO.sol b/packages/contracts-bedrock/scripts/utils/BaseDeployIO.sol new file mode 100644 index 0000000000000..f8157ae392410 --- /dev/null +++ b/packages/contracts-bedrock/scripts/utils/BaseDeployIO.sol @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { CommonBase } from "forge-std/Base.sol"; + +/// @notice All contracts of the form `Deploy<X>Input` and `Deploy<X>Output` should inherit from this contract. +/// It provides a base set of functionality, such as access to cheat codes, that these scripts may need. +/// See the comments in `DeploySuperchain.s.sol` for more information on this pattern. +abstract contract BaseDeployIO is CommonBase { } diff --git a/packages/contracts-bedrock/semver-lock.json b/packages/contracts-bedrock/semver-lock.json index c9fe50d36c6e8..b9962af979ccf 100644 --- a/packages/contracts-bedrock/semver-lock.json +++ b/packages/contracts-bedrock/semver-lock.json @@ -1,222 +1,230 @@ { "src/EAS/EAS.sol": { - "initCodeHash": "0x1a097f352425b503a28c795dbfd390f2bc330e9c1f8a27bd26cf243b6c703499", - "sourceCodeHash": "0x23287e96b00c31ab57b05090525afdebf8e45ca09253a21b95052cf7d94e071b" + "initCodeHash": "0xf96d1ebc530ed95e2dffebcfa2b4a1f18103235e6352d97838b77b7a2c14567b", + "sourceCodeHash": "0x1902e1528cc6ff04a181036d9f1da70bd3f861b6cf1bb844d916501af5f40127" }, "src/EAS/SchemaRegistry.sol": { - "initCodeHash": "0xf4c3155413be4a4ebaaba66b9f9daaf12db7b090afdea739dfb8a543df357289", - "sourceCodeHash": "0x2ed7a2d6d66839fb3d207952f44b001bce349334adc40ce66d0503ce64e48548" + "initCodeHash": "0x06ae2c0b39c215b7fa450d382916ce6f5c6f9f2d630e572db6b72d688255b3fd", + "sourceCodeHash": "0x9ec99e63a991691e8756a663edf2ccfbe9b91161c134e24f38298da61ecd66dd" }, "src/L1/DataAvailabilityChallenge.sol": { - "initCodeHash": "0x9e9ac7238791b2eaade946e58b98f6f1f43f60b8b393664d85a553857a0ab5c7", - "sourceCodeHash": "0xf6c72a2cca24cfa7c9274d720e93b05d665a2751cca3d747105e6c511ccffc73" + "initCodeHash": "0xcc96cf2e4d841adb7ecb9dd84abeb0893dd62d913c0d47ab5b66a893c6e47e88", + "sourceCodeHash": "0xce01773740f4d50ac77f868343d654f6ca24f85d2770eb7e4043e98f609b1c15" }, "src/L1/DelayedVetoable.sol": { - "initCodeHash": "0x84f78e56211500a768b2c5bbafde8e7b411bd64c237297370d7d22326b68357c", - "sourceCodeHash": "0xc59b8574531162e016d7342aeb6e79d05574e90dbea6c0e5ede35b65010ad894" + "initCodeHash": "0xd504ab0568719a0fb960ebe73d0437645f5c4bd8f6619219858209ef002516dd", + "sourceCodeHash": "0x60af558156543d639a0a92e983ad0f045aac1f9ac4c3adaa1d4d97b37175e03a" }, "src/L1/L1CrossDomainMessenger.sol": { - "initCodeHash": "0x1f97347da46930d5b3cd40bd2699a6b78812e5f597793c8d59a90b0ef6800da8", - "sourceCodeHash": "0x56a2d3abed97eb7b292db758aac1e36fc08a12bfa44f7969824e26866a1417fa" + "initCodeHash": "0x48db42620b9f16e0dec2355f4076314f82fd0f60ef04c10cdbc266eac9472515", + "sourceCodeHash": "0xb77342e6b55b835e9597f7a1c4a2d52ddd56f5cfb7cd38da0bcc488c79a9011e" }, "src/L1/L1ERC721Bridge.sol": { - "initCodeHash": "0xd56de5c193758c0c2ef3456ef9331fbcb56f7f6f4185d4a2ceeebf4f31512013", - "sourceCodeHash": "0xa8b7c9682717efbc27212ead24ba345253d18f2068126b905cc7515603288553" + "initCodeHash": "0xfb8b3c51e1790a0b951eaba05ed7368309fbfc7ddc558b4ce1de29da087fb4bd", + "sourceCodeHash": "0xcb125e7f640cf5f372c7bf4f8e36150328914ceef99b6fd5d65ae12b6db430b5" }, "src/L1/L1StandardBridge.sol": { - "initCodeHash": "0x508977d2517b49649bef57899e2c2519c271953708b2c84325377dae64a92baf", - "sourceCodeHash": "0x0d07e526c1891abb81c7e94f73642caa8ee386ab036b3b2a67f1b21ca85089c5" + "initCodeHash": "0x2868b09ecbe9f2bbc885605c2886b4c79f1c8e4171626c63776603b1b84698a8", + "sourceCodeHash": "0xc03da137b3ea72e0109fb284229283b21a0303104afbe37d2fe86ad806392a7f" }, "src/L1/L2OutputOracle.sol": { - "initCodeHash": "0x14c3a582ca46ef2a6abad5590323f4de26ff4de54415c927c62e131ccbf8d9ba", - "sourceCodeHash": "0xf5fcf570721e25459fadbb37e02f9efe349e1c8afcbf1e3b5fdb09c9f612cdc0" + "initCodeHash": "0x433fac9de52d8ce8fc3471b78ef6cc9cff1019f480c9ad91b6e09ab8738a8edb", + "sourceCodeHash": "0xde4df0f9633dc0cdb1c9f634003ea5b0f7c5c1aebc407bc1b2f44c0ecf938649" }, - "src/L1/OPStackManager.sol": { - "initCodeHash": "0x1630942414d9711137028c48f37b6fcd7fbbedc147102e31ebcdcc03a9645c6a", - "sourceCodeHash": "0x8e9a47583c4c3d711c2b7cc5e0f86495e29d4e79c38415dd3d342e1d1aae4fb7" + "src/L1/OPContractsManager.sol": { + "initCodeHash": "0x7903f225091334a1910470bb1b5c111f13f6f2572faf03e0c74ad625e4c0d6f5", + "sourceCodeHash": "0x3a25b0ac70b1d434773c86f46b1f2a995722e33d3273762fd5abbb541bffa7db" }, "src/L1/OptimismPortal.sol": { - "initCodeHash": "0xfdc8cf0b0b26961f6ac493ee564761716447d263291bea4d366a7b94afe33392", - "sourceCodeHash": "0x9fe0a9001edecd2a04daada4ca9e17d66141b1c982f73653493b4703d2c675c4" + "initCodeHash": "0xbe2c0c81b3459014f287d8c89cdc0d27dde5d1f44e5d024fa1e4773ddc47c190", + "sourceCodeHash": "0xb3dd8068477dd304ef1562acf69c2ce460b08cc36aef53b5bbe489fd7d992104" }, "src/L1/OptimismPortal2.sol": { - "initCodeHash": "0x12071439501e60420ab217cea4477306864014b66722d09b8cb8e01369f343ec", - "sourceCodeHash": "0xf597b9dcb97e733948a7179b8951dd46e4bb1ebc0715dd9440ffdabe0ecb0843" + "initCodeHash": "0xc94c609e04ab8ffee880806550dffff53478dfffdfb079f7c487abe0e2996f3c", + "sourceCodeHash": "0x3fb97859f66c078573753b6ba5ec370449ab03b8eca9e7779fce8db5bb23b7c0" }, "src/L1/OptimismPortalInterop.sol": { - "initCodeHash": "0xa8ce00980799cb918b44fbbfdf4370a069d3bd15a92b2ed6850e98ebc0388b86", - "sourceCodeHash": "0xe3805faeb962594d5c2c18cdeb35c2db1248393650bec2ad5cadf41759f151f2" + "initCodeHash": "0x1c8372865dbf38225de4d843ca696a17f0d9e3cacf13c10a3d065ba19bdca05e", + "sourceCodeHash": "0xe6a7794799915f408cb57c73af266670de8a3f02408d3dbc2c97db25d3e42635" }, "src/L1/ProtocolVersions.sol": { - "initCodeHash": "0x72cd467e8bcf019c02675d72ab762e088bcc9cc0f1a4e9f587fa4589f7fdd1b8", - "sourceCodeHash": "0xbd56a23cd3221cb9d25029e80cd9f2afe2c615ae9c0b3956bf6ed373b8b805b6" + "initCodeHash": "0x8f033874dd8b36615b2209d553660dcff1ff91ca2bad3ca1de7b441dbfba4842", + "sourceCodeHash": "0x5a7e91e02224e02a5a4bbf0fea7e9bd4a1168e2fe5e787023c9a75bcb6c26204" }, "src/L1/SuperchainConfig.sol": { - "initCodeHash": "0xa71c67640d6a25c750fef910a5fe85776ebb7bb18c677bb1b9b95c2f3f561b0c", - "sourceCodeHash": "0xd6a894e371c2c7182b5960c507491f81c3775dda0efedd29475f7c30ca07b004" + "initCodeHash": "0xfca12d9016c746e5c275b186e0ca40cfd65cf45a5665aab7589a669fea3abb47", + "sourceCodeHash": "0x39489a85bc3a5c8560f82d41b31bf7fe22f5b648f4ed538f61695a73092ea9eb" }, "src/L1/SystemConfig.sol": { - "initCodeHash": "0x3324c93485f594bccb2af1a0c5a3551948ae9b347baea371764ce8fe239c39be", - "sourceCodeHash": "0xaed39fb8a0ce4b8d7a97ead42074e0c672fa18a58a57227b9d32abe2c3600223" + "initCodeHash": "0x2fc36af5b3c493a423a19e0b597f6ff230b756b861b68099f3192d69b6088dc0", + "sourceCodeHash": "0x06a50ac992175fdb434b13e8461893e83862c23ce399e697e6e8109728ad1a3d" }, "src/L1/SystemConfigInterop.sol": { - "initCodeHash": "0x42e1000d8542f9cbb197314d423760543d4d716d9640b2134c0d881557b22f4f", - "sourceCodeHash": "0xccb5b1ea5f1d5c4a583a2a6941db072fc3ad60ac3d08d085f17a672f6a7e2851" + "initCodeHash": "0x1f500e310170769ffc747e08ad1d5b0de4b0f58534001bc4d4d563ec058bb331", + "sourceCodeHash": "0xcb6008cb49a06f87eb5b6cb4651e5e4aafe0b1f33000eccd165226c04f6b63c6" }, "src/L2/BaseFeeVault.sol": { - "initCodeHash": "0x623bf6892f0bdb536f2916bc9eb45e52012ad2c80893ff87d750757966b9be68", - "sourceCodeHash": "0x3a725791a0f5ed84dc46dcdae26f6170a759b2fe3dc360d704356d088b76cfd6" + "initCodeHash": "0x3bfcd57e25ad54b66c374f63e24e33a6cf107044aa8f5f69ef21202c380b5c5b", + "sourceCodeHash": "0x2dc2284cf7c68e743da50e4113e96ffeab435de2390aeba2eab2f1e8ca411ce9" }, "src/L2/CrossL2Inbox.sol": { - "initCodeHash": "0x071b53cd8cf0503af856c4ee0ee34643e85059d53c096453891225472e02abfa", - "sourceCodeHash": "0x3c78129b91d9f06afa4787d4b3039f45a3b22b3edf5155ed73d4f0c3ab33c6c8" + "initCodeHash": "0x0ee27866b4bf864a0b68ab25ea9559d7f2722b0396d02f2e8e089c6a1a5a6a93", + "sourceCodeHash": "0xe6f453049035e0d77e4d7a92904b448bc17e04dd3d99e738b9af20e20986ce64" }, "src/L2/ETHLiquidity.sol": { - "initCodeHash": "0x98177562fca0de0dfea5313c9acefe2fdbd73dee5ce6c1232055601f208f0177", - "sourceCodeHash": "0x6dc23ceeed5a63fdc98ba8e5099df1822f3eeaa8c82afb1fa3235ff68a37b274" + "initCodeHash": "0x713c18f95a6a746d0703f475f3ae10c106c9b9ecb64d881a2e61b8969b581371", + "sourceCodeHash": "0x0b6afdc52d1ae88d9e4bbb5dc00920e7a6bd1e9d6595bfdbae64874190f39df0" }, "src/L2/GasPriceOracle.sol": { - "initCodeHash": "0xb16f1e370e58c7693fd113a21a1b1e7ccebc03d4f1e5a76786fc27847ef51ead", - "sourceCodeHash": "0x5529ee28aae94904a1c08a8b188f51a39a0f51fbd3b43f1abd4fee7bba57998c" + "initCodeHash": "0x03947f33b80774b92214083374262fe6a4defa61da548391b44d471f2e87e9e7", + "sourceCodeHash": "0x4f21025d4b5c9c74cf7040db6f8e9ce605b82931e3012fee51d3f5d9fbd7b73f" }, "src/L2/L1Block.sol": { - "initCodeHash": "0xfd099da051edf13b147f4382ab4bed9db546d0c48157736ba298fb7e178b20d9", - "sourceCodeHash": "0x24db623574743432626ed0d7dd938bbd2149b570a00328c772debd7eb179ff1d" + "initCodeHash": "0xd12353c5bf71c6765cc9292eecf262f216e67f117f4ba6287796a5207dbca00f", + "sourceCodeHash": "0xfe3a9585d9bfca8428e12759cab68a3114374e5c37371cfe08bb1976a9a5a041" }, - "src/L2/L1BlockInterop.sol": { - "initCodeHash": "0x6833a323934b3be1e5a5c7491c652b6e90bc5102416ddbb255b5f65aa6d5d4a1", - "sourceCodeHash": "0xd8ec2f814690d1ffd55e5b8496bca5a179d6d1772d61f71cdf8296c9058dc2c6" + "src/L2/L1BlockIsthmus.sol": { + "initCodeHash": "0xb7a7a113056e4ac44824350b79fed5ea423e880223edcf1220e8f8b3172f50c5", + "sourceCodeHash": "0x6be7e7402c4dfc10e1407e070712a3f9f352db45f8a8ab296e8f6bc56a341f47" }, "src/L2/L1FeeVault.sol": { - "initCodeHash": "0x623bf6892f0bdb536f2916bc9eb45e52012ad2c80893ff87d750757966b9be68", - "sourceCodeHash": "0x29c64c43e3deedfa63572d36ce511febb99e500352a003242aed339716d3e3ce" + "initCodeHash": "0x3bfcd57e25ad54b66c374f63e24e33a6cf107044aa8f5f69ef21202c380b5c5b", + "sourceCodeHash": "0x927cc729bf5c9f209112df597f649493f276c4c50e17a57f7da02c2be266b192" }, "src/L2/L2CrossDomainMessenger.sol": { - "initCodeHash": "0xad95e4e98adf35ea2baeb15348d751fc76e1bb0d001474d4eaefba47f7aeaf5f", - "sourceCodeHash": "0x440d299b7429c44f6faa4005b33428f9edc1283027d9c78a63eb3d76452bfa47" + "initCodeHash": "0xcc4527d21cceeedbb3cbf8e7028e22fe12bc1ab30365dbebd0713499451b959d", + "sourceCodeHash": "0x66e4ae82b58693cb394d70159308d50270ccdd56c495c5e2aaf55de1fdc78695" }, "src/L2/L2ERC721Bridge.sol": { - "initCodeHash": "0x72443939e0218f1faca4cabe957a77bb232db726d74d422bda15d1cb26857735", - "sourceCodeHash": "0xb0806d362ba5cc39acfb09e0606059a2b10a7c1d5bc1f86cd4561fd24f7dcada" + "initCodeHash": "0x827077e1a0ce6c8f9ee1196c409ea77d831efd440992b3969b05259083cdf0bd", + "sourceCodeHash": "0x51a44e1fcef9483cc58ba0c9895cb3eec675785145428ece9aa7acd1a1a5b57c" }, "src/L2/L2StandardBridge.sol": { - "initCodeHash": "0xfbfc7bd101022024b94114c26128c6028c25dec07e8d40fdcfdb180c0ba6ddee", - "sourceCodeHash": "0xb1a5fb22b124e8fa8eb5bae4b8e0770abbdbebe32be00480317cf4aaada28ed3" + "initCodeHash": "0x651eed10044d0b19b7e4eba864345df15e252be1401f39a552ec0d2f9c4df064", + "sourceCodeHash": "0xb55e58b5d4912edf05026878a5f5ac8019372212ed2a77843775d595fbf51b84" }, "src/L2/L2StandardBridgeInterop.sol": { - "initCodeHash": "0xd7f85eef12b60211104cddbd86d9f458cd31a0ba74f382404799bcf86ef003ba", - "sourceCodeHash": "0x00f415380689a5ee1762e93b032d5c3de2fcddb36b0a068cb5616f7e8001ddc0" + "initCodeHash": "0x9bc28e8511a4593362c2517ff90b26f9c1ecee382cce3950b47ca08892a872ef", + "sourceCodeHash": "0x6c814f4536d9fb8f384ed2195957f868abd15252e36d6dd243f3d60349a61994" }, "src/L2/L2ToL1MessagePasser.sol": { - "initCodeHash": "0x08bbede75cd6dfd076903b8f04d24f82fa7881576c135825098778632e37eebc", - "sourceCodeHash": "0x8388b9b8075f31d580fed815b66b45394e40fb1a63cd8cda2272d2c390fc908c" + "initCodeHash": "0x13fe3729beb9ed966c97bef09acb9fe5043fe651d453145073d05f2567fa988d", + "sourceCodeHash": "0xd08a2e6514dbd44e16aa312a1b27b2841a9eab5622cbd05a39c30f543fad673c" }, "src/L2/L2ToL2CrossDomainMessenger.sol": { - "initCodeHash": "0x3a18ecd5415ddcb7c26023f29f3acb3bc4e8a261091c3bc529b8b4d497b92469", - "sourceCodeHash": "0x972564d2e2fab111cd431f3c78d00c7b0f0ae422fa5e9a8bf5b202cdaef89bf9" + "initCodeHash": "0x3e4337542234c732a55e60fc20dcb1ad639ff2fb378e3f29e94b4059df9a637b", + "sourceCodeHash": "0x4b806cc85cead74c8df34ab08f4b6c6a95a1a387a335ec8a7cb2de4ea4e1cf41" }, "src/L2/OptimismSuperchainERC20.sol": { - "initCodeHash": "0xd49214518ea1a30a43fac09f28b2cee9be570894a500cef342762c9820a070b0", - "sourceCodeHash": "0x6943d40010dcbd1d51dc3668d0a154fbb1568ea49ebcf3aa039d65ef6eab321b" + "initCodeHash": "0x4fd71b5352b78d51d39625b6defa77a75be53067b32f3cba86bd17a46917adf9", + "sourceCodeHash": "0xad3934ea533544b3c130c80be26201354af85f9166cb2ce54d96e5e383ebb5c1" + }, + "src/L2/OptimismSuperchainERC20Beacon.sol": { + "initCodeHash": "0x99ce8095b23c124850d866cbc144fee6cee05dbc6bb5d83acadfe00b90cf42c7", + "sourceCodeHash": "0x5e58b7c867fafa49fe39d68d83875425e9cf94f05f2835bdcdaa08fc8bc6b68e" + }, + "src/L2/OptimismSuperchainERC20Factory.sol": { + "initCodeHash": "0x98011045722178751e4a1112892f7d9a11bc1f5e42ac18205b6d30a1f1476d24", + "sourceCodeHash": "0x9e72b2a77d82fcf3963734232ba9faff9d63962594a032041c2561f0a9f1b0b5" }, "src/L2/SequencerFeeVault.sol": { - "initCodeHash": "0xb94145f571e92ee615c6fe903b6568e8aac5fe760b6b65148ffc45d2fb0f5433", - "sourceCodeHash": "0x8f2a54104e5e7105ba03ba37e3ef9b6684a447245f0e0b787ba4cca12957b97c" + "initCodeHash": "0x2e6551705e493bacba8cffe22e564d5c401ae5bb02577a5424e0d32784e13e74", + "sourceCodeHash": "0xd56922cb04597dea469c65e5a49d4b3c50c171e603601e6f41da9517cae0b11a" }, "src/L2/SuperchainWETH.sol": { - "initCodeHash": "0x599e948350c70d699f8a8be945abffd126097de97fade056d29767128320fe75", - "sourceCodeHash": "0x3df29ee1321418914d88ce303b521bf8267ef234b919870b26639d08d7f806bd" + "initCodeHash": "0xd8766c7ab41d34d935febf5b48289f947804634bde38f8e346075b9f2d867275", + "sourceCodeHash": "0x6c1691c0fb5c86f1fd67e23495725c2cd86567556602e8cc0f28104ad6114bf4" }, "src/L2/WETH.sol": { - "initCodeHash": "0xde72ae96910e95249623c2d695749847e4c4adeaf96a7a35033afd77318a528a", - "sourceCodeHash": "0xbe200a6cb297a3ca1a7d174a9c886e3f17eb8edf617ad014a2ac4f6c2e2ac7f1" - }, - "src/Safe/DeputyGuardianModule.sol": { - "initCodeHash": "0xfe20f758f29c2ccef175aeac966183329440f838558d0d1529b9a895b2ac541c", - "sourceCodeHash": "0x6295b93d1adbfe9cdda1a5750aac97aabf34addf384dcdae86362ffa9e22e593" - }, - "src/Safe/LivenessGuard.sol": { - "initCodeHash": "0xf54289de5cef7ba0044e0d63310937fa231d6528aac91e13e531c845af42afac", - "sourceCodeHash": "0xea3872d8f196ae3c863363dfa4b57803cb2a24b0c100244d8f861891e901e03f" - }, - "src/Safe/LivenessModule.sol": { - "initCodeHash": "0xde144889fe7d98dbf300a98f5331edd535086a4af8ae6d88ca190c7f4c754a2d", - "sourceCodeHash": "0x3ff4a3f21202478935412d47fd5ef7f94a170402ddc50e5c062013ce5544c83f" + "initCodeHash": "0xfb253765520690623f177941c2cd9eba23e4c6d15063bccdd5e98081329d8956", + "sourceCodeHash": "0x2ab6be69795109a1ee04c5693a34d6ce0ff90b62e404cdeb18178bab18d06784" }, "src/cannon/MIPS.sol": { - "initCodeHash": "0x958942c497e15ca698064c2d7876c4f5751664fad3fd72092bae6e61a1ab3698", - "sourceCodeHash": "0xb6e219e8c2d81d75c48a1459907609e9096fe032a7447c88cd3e0d134752ac8e" + "initCodeHash": "0x4043f262804931bbbbecff64f87f2d0bdc4554b4d0a8b22df8fff940e8d239bf", + "sourceCodeHash": "0xba4674e1846afbbc708877332a38dfabd4b8d1e48ce07d8ebf0a45c9f27f16b0" }, "src/cannon/MIPS2.sol": { - "initCodeHash": "0xbb425bd1c3cad13a77f5c9676b577606e2f8f320687739f529b257a042f58d85", - "sourceCodeHash": "0xe66f19942947f53ccd658b94c1ef6db39e947419d4ec7436067c6cc44452ff73" + "initCodeHash": "0x67fb4107e25561ffcb3a9b6653f695e125773408d626a92036ea4b0814797021", + "sourceCodeHash": "0x5f4851e04dc9369552c94fb23aee8e8ca4ea9a9602917f0abb3b5f1347460bd5" }, "src/cannon/PreimageOracle.sol": { - "initCodeHash": "0xce7a1c3265e457a05d17b6d1a2ef93c4639caac3733c9cf88bfd192eae2c5788", - "sourceCodeHash": "0x0a3cd959b361f1da998365da8b3c14362007d73b36196cced0606a9f082e63a8" + "initCodeHash": "0x801e52f9c8439fcf7089575fa93272dfb874641dbfc7d82f36d979c987271c0b", + "sourceCodeHash": "0xdb9421a552e6d7581b3db9e4c2a02d8210ad6ca66ba0f8703d77f7cd4b8e132b" }, "src/dispute/AnchorStateRegistry.sol": { - "initCodeHash": "0x544f0398155e958b0de59f9448801e75c66042c95a7892e2264c015973be8bec", - "sourceCodeHash": "0x65944da862332e493bffd712648511041d4adff00e24cc0e539b9dd0ef013ba0" + "initCodeHash": "0x13d00eef8c3f769863fc766180acc8586f5da309ca0a098e67d4d90bd3243341", + "sourceCodeHash": "0x39a23c91d4c5380d285f49660b858d39f3fa27bdbfbc72e0e14587e7c57dfae9" + }, + "src/dispute/DelayedWETH.sol": { + "initCodeHash": "0x835b322de7d5c84b415e99f2cb1000411df18995b5476f2116ac6f897f2d0910", + "sourceCodeHash": "0xdbd64724b73f8f9d6f1cc72bb662a99b9955ab72950a8f6ffeb1d2454997f60b" }, "src/dispute/DisputeGameFactory.sol": { - "initCodeHash": "0x7a7cb8f2c95df2f9afb3ce9eaefe4a6f997ccce7ed8ffda5d425a65a2474a792", - "sourceCodeHash": "0x918c395ac5d77357f2551616aad0613e68893862edd14e554623eb16ee6ba148" + "initCodeHash": "0xb91623cca41e63e6e5a75c681b0d9ef7cb8bf68e7ff5e202a217629899fae099", + "sourceCodeHash": "0xc8f21c777b2c5a37c2d2f92e8eeceba3b231b500a7d9cb0b607b774478f8be6b" }, "src/dispute/FaultDisputeGame.sol": { - "initCodeHash": "0x8705f00408ff4405723bf59e2dce61a90aa49d8094da1c96a3652a2ebb169519", - "sourceCodeHash": "0x3df123ab9a19f7c097510afb191099e7c3098ab892111a13c8f061ab0f0e57a0" - }, - "src/dispute/weth/DelayedWETH.sol": { - "initCodeHash": "0xdad40c84fe75a0f112c219bcc9553e325bacc8e11860f692353ea3ff110fd7cc", - "sourceCodeHash": "0xb1e22abf844715243a065ead50cab02e53303c5464b2857a8ee667f8d49d4d12" + "initCodeHash": "0xdb724dfd12dcea804d1adbc5a7e919625615c62b940035cf4b9115ea3a63e0ae", + "sourceCodeHash": "0x223428ee91532af397cef72356430ff59221e0ac0cbf697a881d36bb1d672392" }, "src/legacy/DeployerWhitelist.sol": { - "initCodeHash": "0x8de80fb23b26dd9d849f6328e56ea7c173cd9e9ce1f05c9beea559d1720deb3d", - "sourceCodeHash": "0xb518a9f56136a910f2450098b4823c9982f93883fe4a9ef6f6b0a89355965d38" + "initCodeHash": "0x0b8177ed75b69eddbb9ce6537683f69a9935efed86a1d6faa8feaafbd151c1bd", + "sourceCodeHash": "0xc8fe9571fcf8fcb51a4dcb00ffa97f43a9ce811c323c4926e710b28c90a9005f" }, "src/legacy/L1BlockNumber.sol": { - "initCodeHash": "0xd586c4f93caf1753e53fcdc05eb547c1f3a69afda2904ae9f9d851b73e1c9c1d", - "sourceCodeHash": "0xed7d0d1695f28bf967626ee58debcf235204ecc5e814f53da369c94a9ed7cf0d" + "initCodeHash": "0x542955f1a84b304eaf291f76633b03e4c87c2654f7eff46c3bea94d27346ea1f", + "sourceCodeHash": "0x898c239e6367a0971a075df18030a033cdada26983fa8a5cd6e7b88ec90d4958" }, "src/legacy/LegacyMessagePasser.sol": { - "initCodeHash": "0x024ff54be1762f8946c6dc1796517bd5e622349a26a908f78a31872969f10369", - "sourceCodeHash": "0x31f66f771d912ed4fe06c166f4b1c44d9f2bce8537ab42271c3900360966999f" + "initCodeHash": "0xefc6ed9e325c2d614ea0d28c3eabfff1b345f7c6054e90253c6a091c29508267", + "sourceCodeHash": "0xaa08a61448f485b277af57251d2089cc6a80ce0a763bf7184d48ffed5034ef69" }, "src/periphery/op-nft/AttestationStation.sol": { - "initCodeHash": "0xf9b8ff2ecdcaca2b1521a96f0ebaea2d77aeb986ff1b9b7d82fb0cbc63f9169a", - "sourceCodeHash": "0x81ba07ca8d0bedf3b0d0ff054d68fcc6dca52a4da0ca5c8624cee92f20a87c37" + "initCodeHash": "0x2e665d9ee554430980f64bcb6d2611a1cb03dbacfd58bb0d6f5d32951a267bde", + "sourceCodeHash": "0xe0bc805b22c7d04b5a9444cddd4c0e1bcb3006c69c03610494277ab2cc83f553" }, "src/periphery/op-nft/Optimist.sol": { - "initCodeHash": "0x468354be7d17863a587b1f1daf220c17697e57c76cba8e0082d7afec4aafea49", - "sourceCodeHash": "0x3ceeaab5b013968b226b3c97e202a3af4946590763b2002d1bc36ae8776c78fe" + "initCodeHash": "0x8fccdef5fb6e6d51215b39acc449faad8ba15416699c9b3af77866f4297805a3", + "sourceCodeHash": "0xfa9354827b642803e10415ed30ca789be1bd23d88fac14f7adaa65c6eb1c1643" }, "src/periphery/op-nft/OptimistAllowlist.sol": { - "initCodeHash": "0xbe1a89f077473c298ce96be5eb5e5a0ec97968f24c7ef843e1f9fee1c57087e4", - "sourceCodeHash": "0x077967c4c1b99396481c91464237e696f12974c864470b2ef39ffa3756a58ac0" + "initCodeHash": "0x166dd3fc18cb238895f2faa7fdd635af48ce2c54e21ed2d6dae857c3731c4d6c", + "sourceCodeHash": "0x3a5f61046f729c9a70274b8b2a739382987ec5eb77705b259e8a3210a5f43462" }, "src/periphery/op-nft/OptimistInviter.sol": { - "initCodeHash": "0xefc67e1be541adfc92f9a5bef36746477299f5e76a4601c12f802af52fb02253", - "sourceCodeHash": "0x323f707d4cebc38f59f9241098a1d7e5e790ffcaf1719065edabf4cb794ac745" + "initCodeHash": "0x28dfa6676702a7abd19609cc773158d1f958210bc0a38c008d67a002dc1df862", + "sourceCodeHash": "0x3a0a294932d6deba043f6a2b46b4e8477ee96e7fb054d7e7229a43ce4352c68d" + }, + "src/safe/DeputyGuardianModule.sol": { + "initCodeHash": "0x308212d163aad169a5e42ce703a1ce36f5425ad96037850c0747177041f6596e", + "sourceCodeHash": "0xde1a289c1cb0bf92138daf8f3db7457be2f84bedaa111b536f646dd6e121718c" + }, + "src/safe/LivenessGuard.sol": { + "initCodeHash": "0xfd74ff89e7b689b38ab97515d64429ffaf6c0cd1ea6488c6a4743a0665419c85", + "sourceCodeHash": "0xa40ea6472d9c7e124791489c0899822d6f6b19b16e583d3b437674c615e4bac3" + }, + "src/safe/LivenessModule.sol": { + "initCodeHash": "0xcfccdd9e423c95a0ddc6e09ccb6333d5fc8429ed2b8fc872f1290d392ae13aad", + "sourceCodeHash": "0xd1479c60087f352385b6d5379ef3cc07839f671d617626b4c94ece91da781ef2" }, "src/universal/OptimismMintableERC20.sol": { - "initCodeHash": "0x7c6e1cf86cf8622d8beceafa3610ff88eceb3b0fafff0491bfa26a7b876c4d9a", - "sourceCodeHash": "0x52737b23e99bf79dd2c23196b3298e80aa41f740efc6adc7916e696833eb546a" + "initCodeHash": "0x28c88484e1932253d6d12954492ac8a70744dc15c84429089af9944e5b158fd9", + "sourceCodeHash": "0x740b4043436d1b314ee3ba145acfcde60b6abd8416ea594f2b8e890b5d0bce6b" }, "src/universal/OptimismMintableERC20Factory.sol": { - "initCodeHash": "0x29a49fc387ad84f82199947e49a0d1960902f63492d974c26afd72372e748648", - "sourceCodeHash": "0xbc6cf74368c244bdea8ed64c501129d0b6d41db421dc91d1de051f7b505a4977" + "initCodeHash": "0x9cd4102d3ca811d5dc67ae99ce7de95812264575a789f96a6057600e55dcab64", + "sourceCodeHash": "0xc70c8c11d6e754eabe746bbee47a5e1051f71f7a83913f62ebcce8db989a1357" }, "src/universal/OptimismMintableERC721.sol": { - "initCodeHash": "0xb400f430acf4d65bee9635e4935a6e1e3a0284fc50aea40ad8b7818dc826f31c", - "sourceCodeHash": "0xd4bb4d1e16f545976302109ab0234ae785afa52de820553d67ebd9f147e4b994" + "initCodeHash": "0xec037be7fc28e072944b0a9e55d4278b92d6c68ccb41049ab52eafca59c6e023", + "sourceCodeHash": "0x5ea7c1b0cef5609f25c4193f5795fc9ce8f3ae08dbbf2945afe38e5af58f32c3" }, "src/universal/OptimismMintableERC721Factory.sol": { - "initCodeHash": "0x5504069cb1377405bf5c6f1b37ea02057fdb452cf85922cc83dffd5390cad7da", - "sourceCodeHash": "0xf8f2f0f6bc3cdbacbb1ef8b3fa31897a1eb749af0ba14b19b0cbc1cf0e6271f8" + "initCodeHash": "0x1e247d46b5ac3cc8ac6b51193917cd5b88ff00fbea7bf768c65fa35a115f8607", + "sourceCodeHash": "0x1c4bc4727f08d80e8364561b49397ee57bb485072cb004b7a430559cbfa019a6" }, "src/universal/StorageSetter.sol": { - "initCodeHash": "0xb656d2aa6aff3e6435e747a0c23236d1b66f1f5c0b45e4b1a10d290a90223c5a", - "sourceCodeHash": "0xebfc968e6b78d7ea355547d427300739f14d000a11ff35f29d9ded3ddb7882da" + "initCodeHash": "0x00b8b883597e67e5c3548e7ba4139ed720893c0acb217dd170bec520cefdfab5", + "sourceCodeHash": "0xf63aff9c38f4c5e9cdbd1f910bc002e16008a592d26c0dcc67929e0024638edd" } } \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/abi/AnchorStateRegistry.json b/packages/contracts-bedrock/snapshots/abi/AnchorStateRegistry.json index aaa832eb1b703..c1a0fc693a9a5 100644 --- a/packages/contracts-bedrock/snapshots/abi/AnchorStateRegistry.json +++ b/packages/contracts-bedrock/snapshots/abi/AnchorStateRegistry.json @@ -79,7 +79,7 @@ "type": "tuple[]" }, { - "internalType": "contract SuperchainConfig", + "internalType": "contract ISuperchainConfig", "name": "_superchainConfig", "type": "address" } @@ -107,7 +107,7 @@ "name": "superchainConfig", "outputs": [ { - "internalType": "contract SuperchainConfig", + "internalType": "contract ISuperchainConfig", "name": "", "type": "address" } diff --git a/packages/contracts-bedrock/snapshots/abi/CrossL2Inbox.json b/packages/contracts-bedrock/snapshots/abi/CrossL2Inbox.json index 7253ac21bdcb2..6f8c10e82eedf 100644 --- a/packages/contracts-bedrock/snapshots/abi/CrossL2Inbox.json +++ b/packages/contracts-bedrock/snapshots/abi/CrossL2Inbox.json @@ -253,6 +253,11 @@ "name": "InvalidTimestamp", "type": "error" }, + { + "inputs": [], + "name": "NoExecutingDeposits", + "type": "error" + }, { "inputs": [], "name": "NotDepositor", diff --git a/packages/contracts-bedrock/snapshots/abi/DelayedWETH.json b/packages/contracts-bedrock/snapshots/abi/DelayedWETH.json index fe4fd5b63f613..a84394e6b0036 100644 --- a/packages/contracts-bedrock/snapshots/abi/DelayedWETH.json +++ b/packages/contracts-bedrock/snapshots/abi/DelayedWETH.json @@ -90,7 +90,7 @@ "name": "config", "outputs": [ { - "internalType": "contract SuperchainConfig", + "internalType": "contract ISuperchainConfig", "name": "", "type": "address" } @@ -157,7 +157,7 @@ "type": "address" }, { - "internalType": "contract SuperchainConfig", + "internalType": "contract ISuperchainConfig", "name": "_config", "type": "address" } diff --git a/packages/contracts-bedrock/snapshots/abi/DeputyGuardianModule.json b/packages/contracts-bedrock/snapshots/abi/DeputyGuardianModule.json index 688d68f6f2715..f1006749351ea 100644 --- a/packages/contracts-bedrock/snapshots/abi/DeputyGuardianModule.json +++ b/packages/contracts-bedrock/snapshots/abi/DeputyGuardianModule.json @@ -7,7 +7,7 @@ "type": "address" }, { - "internalType": "contract SuperchainConfig", + "internalType": "contract ISuperchainConfig", "name": "_superchainConfig", "type": "address" }, @@ -23,7 +23,7 @@ { "inputs": [ { - "internalType": "contract OptimismPortal2", + "internalType": "contract IOptimismPortal2", "name": "_portal", "type": "address" }, @@ -74,7 +74,7 @@ { "inputs": [ { - "internalType": "contract AnchorStateRegistry", + "internalType": "contract IAnchorStateRegistry", "name": "_registry", "type": "address" }, @@ -92,7 +92,7 @@ { "inputs": [ { - "internalType": "contract OptimismPortal2", + "internalType": "contract IOptimismPortal2", "name": "_portal", "type": "address" }, @@ -112,7 +112,7 @@ "name": "superchainConfig", "outputs": [ { - "internalType": "contract SuperchainConfig", + "internalType": "contract ISuperchainConfig", "name": "superchainConfig_", "type": "address" } diff --git a/packages/contracts-bedrock/snapshots/abi/DisputeGameFactory.json b/packages/contracts-bedrock/snapshots/abi/DisputeGameFactory.json index d4ae9165f9d7a..205b9861d18b2 100644 --- a/packages/contracts-bedrock/snapshots/abi/DisputeGameFactory.json +++ b/packages/contracts-bedrock/snapshots/abi/DisputeGameFactory.json @@ -81,7 +81,7 @@ "type": "bytes" } ], - "internalType": "struct IDisputeGameFactory.GameSearchResult[]", + "internalType": "struct DisputeGameFactory.GameSearchResult[]", "name": "games_", "type": "tuple[]" } diff --git a/packages/contracts-bedrock/snapshots/abi/L1BlockInterop.json b/packages/contracts-bedrock/snapshots/abi/L1BlockIsthmus.json similarity index 93% rename from packages/contracts-bedrock/snapshots/abi/L1BlockInterop.json rename to packages/contracts-bedrock/snapshots/abi/L1BlockIsthmus.json index 146691aff1a18..d827b32a9cab2 100644 --- a/packages/contracts-bedrock/snapshots/abi/L1BlockInterop.json +++ b/packages/contracts-bedrock/snapshots/abi/L1BlockIsthmus.json @@ -90,6 +90,13 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "depositsComplete", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [], "name": "gasPayingToken", @@ -160,6 +167,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "isDeposit", + "outputs": [ + { + "internalType": "bool", + "name": "isDeposit_", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -332,6 +352,13 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [], + "name": "setL1BlockValuesIsthmus", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [], "name": "timestamp", @@ -430,6 +457,11 @@ "name": "DependencySetSizeTooLarge", "type": "error" }, + { + "inputs": [], + "name": "NotCrossL2Inbox", + "type": "error" + }, { "inputs": [], "name": "NotDependency", diff --git a/packages/contracts-bedrock/snapshots/abi/L1CrossDomainMessenger.json b/packages/contracts-bedrock/snapshots/abi/L1CrossDomainMessenger.json index cc99f64c449e6..22a4353cc6564 100644 --- a/packages/contracts-bedrock/snapshots/abi/L1CrossDomainMessenger.json +++ b/packages/contracts-bedrock/snapshots/abi/L1CrossDomainMessenger.json @@ -74,7 +74,7 @@ "name": "PORTAL", "outputs": [ { - "internalType": "contract OptimismPortal", + "internalType": "contract IOptimismPortal", "name": "", "type": "address" } @@ -180,17 +180,17 @@ { "inputs": [ { - "internalType": "contract SuperchainConfig", + "internalType": "contract ISuperchainConfig", "name": "_superchainConfig", "type": "address" }, { - "internalType": "contract OptimismPortal", + "internalType": "contract IOptimismPortal", "name": "_portal", "type": "address" }, { - "internalType": "contract SystemConfig", + "internalType": "contract ISystemConfig", "name": "_systemConfig", "type": "address" } @@ -244,7 +244,7 @@ "name": "portal", "outputs": [ { - "internalType": "contract OptimismPortal", + "internalType": "contract IOptimismPortal", "name": "", "type": "address" } @@ -337,7 +337,7 @@ "name": "superchainConfig", "outputs": [ { - "internalType": "contract SuperchainConfig", + "internalType": "contract ISuperchainConfig", "name": "", "type": "address" } @@ -350,7 +350,7 @@ "name": "systemConfig", "outputs": [ { - "internalType": "contract SystemConfig", + "internalType": "contract ISystemConfig", "name": "", "type": "address" } diff --git a/packages/contracts-bedrock/snapshots/abi/L1ERC721Bridge.json b/packages/contracts-bedrock/snapshots/abi/L1ERC721Bridge.json index 386c8413a9ff5..33cd5b0a850b3 100644 --- a/packages/contracts-bedrock/snapshots/abi/L1ERC721Bridge.json +++ b/packages/contracts-bedrock/snapshots/abi/L1ERC721Bridge.json @@ -9,7 +9,7 @@ "name": "MESSENGER", "outputs": [ { - "internalType": "contract CrossDomainMessenger", + "internalType": "contract ICrossDomainMessenger", "name": "", "type": "address" } @@ -171,12 +171,12 @@ { "inputs": [ { - "internalType": "contract CrossDomainMessenger", + "internalType": "contract ICrossDomainMessenger", "name": "_messenger", "type": "address" }, { - "internalType": "contract SuperchainConfig", + "internalType": "contract ISuperchainConfig", "name": "_superchainConfig", "type": "address" } @@ -191,7 +191,7 @@ "name": "messenger", "outputs": [ { - "internalType": "contract CrossDomainMessenger", + "internalType": "contract ICrossDomainMessenger", "name": "", "type": "address" } @@ -230,7 +230,7 @@ "name": "superchainConfig", "outputs": [ { - "internalType": "contract SuperchainConfig", + "internalType": "contract ISuperchainConfig", "name": "", "type": "address" } diff --git a/packages/contracts-bedrock/snapshots/abi/L1StandardBridge.json b/packages/contracts-bedrock/snapshots/abi/L1StandardBridge.json index 2a93a9f8da24b..45480499fe9f4 100644 --- a/packages/contracts-bedrock/snapshots/abi/L1StandardBridge.json +++ b/packages/contracts-bedrock/snapshots/abi/L1StandardBridge.json @@ -13,7 +13,7 @@ "name": "MESSENGER", "outputs": [ { - "internalType": "contract CrossDomainMessenger", + "internalType": "contract ICrossDomainMessenger", "name": "", "type": "address" } @@ -417,17 +417,17 @@ { "inputs": [ { - "internalType": "contract CrossDomainMessenger", + "internalType": "contract ICrossDomainMessenger", "name": "_messenger", "type": "address" }, { - "internalType": "contract SuperchainConfig", + "internalType": "contract ISuperchainConfig", "name": "_superchainConfig", "type": "address" }, { - "internalType": "contract SystemConfig", + "internalType": "contract ISystemConfig", "name": "_systemConfig", "type": "address" } @@ -455,7 +455,7 @@ "name": "messenger", "outputs": [ { - "internalType": "contract CrossDomainMessenger", + "internalType": "contract ICrossDomainMessenger", "name": "", "type": "address" } @@ -494,7 +494,7 @@ "name": "superchainConfig", "outputs": [ { - "internalType": "contract SuperchainConfig", + "internalType": "contract ISuperchainConfig", "name": "", "type": "address" } @@ -507,7 +507,7 @@ "name": "systemConfig", "outputs": [ { - "internalType": "contract SystemConfig", + "internalType": "contract ISystemConfig", "name": "", "type": "address" } diff --git a/packages/contracts-bedrock/snapshots/abi/L2ERC721Bridge.json b/packages/contracts-bedrock/snapshots/abi/L2ERC721Bridge.json index d0df33b56960c..e9578ad9726c7 100644 --- a/packages/contracts-bedrock/snapshots/abi/L2ERC721Bridge.json +++ b/packages/contracts-bedrock/snapshots/abi/L2ERC721Bridge.json @@ -9,7 +9,7 @@ "name": "MESSENGER", "outputs": [ { - "internalType": "contract CrossDomainMessenger", + "internalType": "contract ICrossDomainMessenger", "name": "", "type": "address" } @@ -157,7 +157,7 @@ "name": "messenger", "outputs": [ { - "internalType": "contract CrossDomainMessenger", + "internalType": "contract ICrossDomainMessenger", "name": "", "type": "address" } diff --git a/packages/contracts-bedrock/snapshots/abi/L2StandardBridge.json b/packages/contracts-bedrock/snapshots/abi/L2StandardBridge.json index da71bae10f065..e562034818d51 100644 --- a/packages/contracts-bedrock/snapshots/abi/L2StandardBridge.json +++ b/packages/contracts-bedrock/snapshots/abi/L2StandardBridge.json @@ -13,7 +13,7 @@ "name": "MESSENGER", "outputs": [ { - "internalType": "contract CrossDomainMessenger", + "internalType": "contract ICrossDomainMessenger", "name": "", "type": "address" } @@ -267,7 +267,7 @@ "name": "messenger", "outputs": [ { - "internalType": "contract CrossDomainMessenger", + "internalType": "contract ICrossDomainMessenger", "name": "", "type": "address" } diff --git a/packages/contracts-bedrock/snapshots/abi/L2StandardBridgeInterop.json b/packages/contracts-bedrock/snapshots/abi/L2StandardBridgeInterop.json index d870c7180a30d..b2dc8dddd050c 100644 --- a/packages/contracts-bedrock/snapshots/abi/L2StandardBridgeInterop.json +++ b/packages/contracts-bedrock/snapshots/abi/L2StandardBridgeInterop.json @@ -8,7 +8,7 @@ "name": "MESSENGER", "outputs": [ { - "internalType": "contract CrossDomainMessenger", + "internalType": "contract ICrossDomainMessenger", "name": "", "type": "address" } @@ -285,7 +285,7 @@ "name": "messenger", "outputs": [ { - "internalType": "contract CrossDomainMessenger", + "internalType": "contract ICrossDomainMessenger", "name": "", "type": "address" } diff --git a/packages/contracts-bedrock/snapshots/abi/MIPS.json b/packages/contracts-bedrock/snapshots/abi/MIPS.json index 7053bcaca375b..afdc8c355ddc4 100644 --- a/packages/contracts-bedrock/snapshots/abi/MIPS.json +++ b/packages/contracts-bedrock/snapshots/abi/MIPS.json @@ -64,5 +64,15 @@ ], "stateMutability": "view", "type": "function" + }, + { + "inputs": [], + "name": "InvalidMemoryProof", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRMWInstruction", + "type": "error" } ] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/abi/MIPS2.json b/packages/contracts-bedrock/snapshots/abi/MIPS2.json index c45a8711640cb..2294e23e754e5 100644 --- a/packages/contracts-bedrock/snapshots/abi/MIPS2.json +++ b/packages/contracts-bedrock/snapshots/abi/MIPS2.json @@ -10,6 +10,19 @@ "stateMutability": "nonpayable", "type": "constructor" }, + { + "inputs": [], + "name": "oracle", + "outputs": [ + { + "internalType": "contract IPreimageOracle", + "name": "oracle_", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -51,5 +64,25 @@ ], "stateMutability": "view", "type": "function" + }, + { + "inputs": [], + "name": "InvalidExitedValue", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidMemoryProof", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRMWInstruction", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSecondMemoryProof", + "type": "error" } ] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/abi/MintManager.json b/packages/contracts-bedrock/snapshots/abi/MintManager.json index 36afd1e167194..e942fbd3eddc8 100644 --- a/packages/contracts-bedrock/snapshots/abi/MintManager.json +++ b/packages/contracts-bedrock/snapshots/abi/MintManager.json @@ -59,7 +59,7 @@ "name": "governanceToken", "outputs": [ { - "internalType": "contract GovernanceToken", + "internalType": "contract IGovernanceToken", "name": "", "type": "address" } diff --git a/packages/contracts-bedrock/snapshots/abi/OPContractsManager.json b/packages/contracts-bedrock/snapshots/abi/OPContractsManager.json new file mode 100644 index 0000000000000..57900b34e8e3c --- /dev/null +++ b/packages/contracts-bedrock/snapshots/abi/OPContractsManager.json @@ -0,0 +1,605 @@ +[ + { + "inputs": [ + { + "internalType": "contract SuperchainConfig", + "name": "_superchainConfig", + "type": "address" + }, + { + "internalType": "contract ProtocolVersions", + "name": "_protocolVersions", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "OUTPUT_VERSION", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "blueprints", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "addressManager", + "type": "address" + }, + { + "internalType": "address", + "name": "proxy", + "type": "address" + }, + { + "internalType": "address", + "name": "proxyAdmin", + "type": "address" + }, + { + "internalType": "address", + "name": "l1ChugSplashProxy", + "type": "address" + }, + { + "internalType": "address", + "name": "resolvedDelegateProxy", + "type": "address" + }, + { + "internalType": "address", + "name": "anchorStateRegistry", + "type": "address" + }, + { + "internalType": "address", + "name": "permissionedDisputeGame1", + "type": "address" + }, + { + "internalType": "address", + "name": "permissionedDisputeGame2", + "type": "address" + } + ], + "internalType": "struct OPContractsManager.Blueprints", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_l2ChainId", + "type": "uint256" + } + ], + "name": "chainIdToBatchInboxAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "address", + "name": "opChainProxyAdminOwner", + "type": "address" + }, + { + "internalType": "address", + "name": "systemConfigOwner", + "type": "address" + }, + { + "internalType": "address", + "name": "batcher", + "type": "address" + }, + { + "internalType": "address", + "name": "unsafeBlockSigner", + "type": "address" + }, + { + "internalType": "address", + "name": "proposer", + "type": "address" + }, + { + "internalType": "address", + "name": "challenger", + "type": "address" + } + ], + "internalType": "struct OPContractsManager.Roles", + "name": "roles", + "type": "tuple" + }, + { + "internalType": "uint32", + "name": "basefeeScalar", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "blobBasefeeScalar", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "l2ChainId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "startingAnchorRoots", + "type": "bytes" + } + ], + "internalType": "struct OPContractsManager.DeployInput", + "name": "_input", + "type": "tuple" + } + ], + "name": "deploy", + "outputs": [ + { + "components": [ + { + "internalType": "contract ProxyAdmin", + "name": "opChainProxyAdmin", + "type": "address" + }, + { + "internalType": "contract AddressManager", + "name": "addressManager", + "type": "address" + }, + { + "internalType": "contract L1ERC721Bridge", + "name": "l1ERC721BridgeProxy", + "type": "address" + }, + { + "internalType": "contract SystemConfig", + "name": "systemConfigProxy", + "type": "address" + }, + { + "internalType": "contract OptimismMintableERC20Factory", + "name": "optimismMintableERC20FactoryProxy", + "type": "address" + }, + { + "internalType": "contract L1StandardBridge", + "name": "l1StandardBridgeProxy", + "type": "address" + }, + { + "internalType": "contract L1CrossDomainMessenger", + "name": "l1CrossDomainMessengerProxy", + "type": "address" + }, + { + "internalType": "contract OptimismPortal2", + "name": "optimismPortalProxy", + "type": "address" + }, + { + "internalType": "contract DisputeGameFactory", + "name": "disputeGameFactoryProxy", + "type": "address" + }, + { + "internalType": "contract AnchorStateRegistry", + "name": "anchorStateRegistryProxy", + "type": "address" + }, + { + "internalType": "contract AnchorStateRegistry", + "name": "anchorStateRegistryImpl", + "type": "address" + }, + { + "internalType": "contract FaultDisputeGame", + "name": "faultDisputeGame", + "type": "address" + }, + { + "internalType": "contract PermissionedDisputeGame", + "name": "permissionedDisputeGame", + "type": "address" + }, + { + "internalType": "contract DelayedWETH", + "name": "delayedWETHPermissionedGameProxy", + "type": "address" + }, + { + "internalType": "contract DelayedWETH", + "name": "delayedWETHPermissionlessGameProxy", + "type": "address" + } + ], + "internalType": "struct OPContractsManager.DeployOutput", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + }, + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "name": "implementations", + "outputs": [ + { + "internalType": "address", + "name": "logic", + "type": "address" + }, + { + "internalType": "bytes4", + "name": "initializer", + "type": "bytes4" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "address", + "name": "addressManager", + "type": "address" + }, + { + "internalType": "address", + "name": "proxy", + "type": "address" + }, + { + "internalType": "address", + "name": "proxyAdmin", + "type": "address" + }, + { + "internalType": "address", + "name": "l1ChugSplashProxy", + "type": "address" + }, + { + "internalType": "address", + "name": "resolvedDelegateProxy", + "type": "address" + }, + { + "internalType": "address", + "name": "anchorStateRegistry", + "type": "address" + }, + { + "internalType": "address", + "name": "permissionedDisputeGame1", + "type": "address" + }, + { + "internalType": "address", + "name": "permissionedDisputeGame2", + "type": "address" + } + ], + "internalType": "struct OPContractsManager.Blueprints", + "name": "blueprints", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "components": [ + { + "internalType": "address", + "name": "logic", + "type": "address" + }, + { + "internalType": "bytes4", + "name": "initializer", + "type": "bytes4" + } + ], + "internalType": "struct OPContractsManager.Implementation", + "name": "info", + "type": "tuple" + } + ], + "internalType": "struct OPContractsManager.ImplementationSetter[]", + "name": "setters", + "type": "tuple[]" + }, + { + "internalType": "string", + "name": "release", + "type": "string" + }, + { + "internalType": "bool", + "name": "isLatest", + "type": "bool" + } + ], + "internalType": "struct OPContractsManager.InitializerInputs", + "name": "_initializerInputs", + "type": "tuple" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "latestRelease", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "protocolVersions", + "outputs": [ + { + "internalType": "contract ProtocolVersions", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "superchainConfig", + "outputs": [ + { + "internalType": "contract SuperchainConfig", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "systemConfigs", + "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": true, + "internalType": "uint256", + "name": "outputVersion", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "l2ChainId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "deployer", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "deployOutput", + "type": "bytes" + } + ], + "name": "Deployed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "who", + "type": "address" + } + ], + "name": "AddressHasNoCode", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "who", + "type": "address" + } + ], + "name": "AddressNotFound", + "type": "error" + }, + { + "inputs": [], + "name": "AlreadyReleased", + "type": "error" + }, + { + "inputs": [], + "name": "BytesArrayTooLong", + "type": "error" + }, + { + "inputs": [], + "name": "DeploymentFailed", + "type": "error" + }, + { + "inputs": [], + "name": "EmptyInitcode", + "type": "error" + }, + { + "inputs": [], + "name": "IdentityPrecompileCallFailed", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidChainId", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "role", + "type": "string" + } + ], + "name": "InvalidRoleAddress", + "type": "error" + }, + { + "inputs": [], + "name": "LatestReleaseNotSet", + "type": "error" + }, + { + "inputs": [], + "name": "NotABlueprint", + "type": "error" + }, + { + "inputs": [], + "name": "ReservedBitsSet", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "UnexpectedPreambleData", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "UnsupportedERCVersion", + "type": "error" + } +] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/abi/OPContractsManagerInterop.json b/packages/contracts-bedrock/snapshots/abi/OPContractsManagerInterop.json new file mode 100644 index 0000000000000..57900b34e8e3c --- /dev/null +++ b/packages/contracts-bedrock/snapshots/abi/OPContractsManagerInterop.json @@ -0,0 +1,605 @@ +[ + { + "inputs": [ + { + "internalType": "contract SuperchainConfig", + "name": "_superchainConfig", + "type": "address" + }, + { + "internalType": "contract ProtocolVersions", + "name": "_protocolVersions", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "OUTPUT_VERSION", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "blueprints", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "addressManager", + "type": "address" + }, + { + "internalType": "address", + "name": "proxy", + "type": "address" + }, + { + "internalType": "address", + "name": "proxyAdmin", + "type": "address" + }, + { + "internalType": "address", + "name": "l1ChugSplashProxy", + "type": "address" + }, + { + "internalType": "address", + "name": "resolvedDelegateProxy", + "type": "address" + }, + { + "internalType": "address", + "name": "anchorStateRegistry", + "type": "address" + }, + { + "internalType": "address", + "name": "permissionedDisputeGame1", + "type": "address" + }, + { + "internalType": "address", + "name": "permissionedDisputeGame2", + "type": "address" + } + ], + "internalType": "struct OPContractsManager.Blueprints", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_l2ChainId", + "type": "uint256" + } + ], + "name": "chainIdToBatchInboxAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "address", + "name": "opChainProxyAdminOwner", + "type": "address" + }, + { + "internalType": "address", + "name": "systemConfigOwner", + "type": "address" + }, + { + "internalType": "address", + "name": "batcher", + "type": "address" + }, + { + "internalType": "address", + "name": "unsafeBlockSigner", + "type": "address" + }, + { + "internalType": "address", + "name": "proposer", + "type": "address" + }, + { + "internalType": "address", + "name": "challenger", + "type": "address" + } + ], + "internalType": "struct OPContractsManager.Roles", + "name": "roles", + "type": "tuple" + }, + { + "internalType": "uint32", + "name": "basefeeScalar", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "blobBasefeeScalar", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "l2ChainId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "startingAnchorRoots", + "type": "bytes" + } + ], + "internalType": "struct OPContractsManager.DeployInput", + "name": "_input", + "type": "tuple" + } + ], + "name": "deploy", + "outputs": [ + { + "components": [ + { + "internalType": "contract ProxyAdmin", + "name": "opChainProxyAdmin", + "type": "address" + }, + { + "internalType": "contract AddressManager", + "name": "addressManager", + "type": "address" + }, + { + "internalType": "contract L1ERC721Bridge", + "name": "l1ERC721BridgeProxy", + "type": "address" + }, + { + "internalType": "contract SystemConfig", + "name": "systemConfigProxy", + "type": "address" + }, + { + "internalType": "contract OptimismMintableERC20Factory", + "name": "optimismMintableERC20FactoryProxy", + "type": "address" + }, + { + "internalType": "contract L1StandardBridge", + "name": "l1StandardBridgeProxy", + "type": "address" + }, + { + "internalType": "contract L1CrossDomainMessenger", + "name": "l1CrossDomainMessengerProxy", + "type": "address" + }, + { + "internalType": "contract OptimismPortal2", + "name": "optimismPortalProxy", + "type": "address" + }, + { + "internalType": "contract DisputeGameFactory", + "name": "disputeGameFactoryProxy", + "type": "address" + }, + { + "internalType": "contract AnchorStateRegistry", + "name": "anchorStateRegistryProxy", + "type": "address" + }, + { + "internalType": "contract AnchorStateRegistry", + "name": "anchorStateRegistryImpl", + "type": "address" + }, + { + "internalType": "contract FaultDisputeGame", + "name": "faultDisputeGame", + "type": "address" + }, + { + "internalType": "contract PermissionedDisputeGame", + "name": "permissionedDisputeGame", + "type": "address" + }, + { + "internalType": "contract DelayedWETH", + "name": "delayedWETHPermissionedGameProxy", + "type": "address" + }, + { + "internalType": "contract DelayedWETH", + "name": "delayedWETHPermissionlessGameProxy", + "type": "address" + } + ], + "internalType": "struct OPContractsManager.DeployOutput", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + }, + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "name": "implementations", + "outputs": [ + { + "internalType": "address", + "name": "logic", + "type": "address" + }, + { + "internalType": "bytes4", + "name": "initializer", + "type": "bytes4" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "address", + "name": "addressManager", + "type": "address" + }, + { + "internalType": "address", + "name": "proxy", + "type": "address" + }, + { + "internalType": "address", + "name": "proxyAdmin", + "type": "address" + }, + { + "internalType": "address", + "name": "l1ChugSplashProxy", + "type": "address" + }, + { + "internalType": "address", + "name": "resolvedDelegateProxy", + "type": "address" + }, + { + "internalType": "address", + "name": "anchorStateRegistry", + "type": "address" + }, + { + "internalType": "address", + "name": "permissionedDisputeGame1", + "type": "address" + }, + { + "internalType": "address", + "name": "permissionedDisputeGame2", + "type": "address" + } + ], + "internalType": "struct OPContractsManager.Blueprints", + "name": "blueprints", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "components": [ + { + "internalType": "address", + "name": "logic", + "type": "address" + }, + { + "internalType": "bytes4", + "name": "initializer", + "type": "bytes4" + } + ], + "internalType": "struct OPContractsManager.Implementation", + "name": "info", + "type": "tuple" + } + ], + "internalType": "struct OPContractsManager.ImplementationSetter[]", + "name": "setters", + "type": "tuple[]" + }, + { + "internalType": "string", + "name": "release", + "type": "string" + }, + { + "internalType": "bool", + "name": "isLatest", + "type": "bool" + } + ], + "internalType": "struct OPContractsManager.InitializerInputs", + "name": "_initializerInputs", + "type": "tuple" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "latestRelease", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "protocolVersions", + "outputs": [ + { + "internalType": "contract ProtocolVersions", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "superchainConfig", + "outputs": [ + { + "internalType": "contract SuperchainConfig", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "systemConfigs", + "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": true, + "internalType": "uint256", + "name": "outputVersion", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "l2ChainId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "deployer", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "deployOutput", + "type": "bytes" + } + ], + "name": "Deployed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "who", + "type": "address" + } + ], + "name": "AddressHasNoCode", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "who", + "type": "address" + } + ], + "name": "AddressNotFound", + "type": "error" + }, + { + "inputs": [], + "name": "AlreadyReleased", + "type": "error" + }, + { + "inputs": [], + "name": "BytesArrayTooLong", + "type": "error" + }, + { + "inputs": [], + "name": "DeploymentFailed", + "type": "error" + }, + { + "inputs": [], + "name": "EmptyInitcode", + "type": "error" + }, + { + "inputs": [], + "name": "IdentityPrecompileCallFailed", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidChainId", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "role", + "type": "string" + } + ], + "name": "InvalidRoleAddress", + "type": "error" + }, + { + "inputs": [], + "name": "LatestReleaseNotSet", + "type": "error" + }, + { + "inputs": [], + "name": "NotABlueprint", + "type": "error" + }, + { + "inputs": [], + "name": "ReservedBitsSet", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "UnexpectedPreambleData", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "UnsupportedERCVersion", + "type": "error" + } +] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/abi/OPStackManager.json b/packages/contracts-bedrock/snapshots/abi/OPStackManager.json deleted file mode 100644 index 3f3a48ded1ffa..0000000000000 --- a/packages/contracts-bedrock/snapshots/abi/OPStackManager.json +++ /dev/null @@ -1,121 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "uint256", - "name": "_l2ChainId", - "type": "uint256" - }, - { - "internalType": "uint32", - "name": "_basefeeScalar", - "type": "uint32" - }, - { - "internalType": "uint32", - "name": "_blobBasefeeScalar", - "type": "uint32" - }, - { - "components": [ - { - "internalType": "address", - "name": "proxyAdminOwner", - "type": "address" - }, - { - "internalType": "address", - "name": "systemConfigOwner", - "type": "address" - }, - { - "internalType": "address", - "name": "batcher", - "type": "address" - }, - { - "internalType": "address", - "name": "unsafeBlockSigner", - "type": "address" - }, - { - "internalType": "address", - "name": "proposer", - "type": "address" - }, - { - "internalType": "address", - "name": "challenger", - "type": "address" - } - ], - "internalType": "struct OPStackManager.Roles", - "name": "_roles", - "type": "tuple" - } - ], - "name": "deploy", - "outputs": [ - { - "internalType": "contract SystemConfig", - "name": "systemConfig_", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "l2ChainId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "contract SystemConfig", - "name": "systemConfig", - "type": "address" - } - ], - "name": "Deployed", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "reason", - "type": "string" - } - ], - "name": "DeploymentFailed", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidChainId", - "type": "error" - }, - { - "inputs": [], - "name": "NotImplemented", - "type": "error" - } -] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/abi/OptimismMintableERC20.json b/packages/contracts-bedrock/snapshots/abi/OptimismMintableERC20.json index 3c6f5e9ab3480..5a5763c73962b 100644 --- a/packages/contracts-bedrock/snapshots/abi/OptimismMintableERC20.json +++ b/packages/contracts-bedrock/snapshots/abi/OptimismMintableERC20.json @@ -43,6 +43,32 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PERMIT2", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "pure", + "type": "function" + }, { "inputs": [], "name": "REMOTE_TOKEN", @@ -60,12 +86,12 @@ "inputs": [ { "internalType": "address", - "name": "owner", + "name": "_owner", "type": "address" }, { "internalType": "address", - "name": "spender", + "name": "_spender", "type": "address" } ], @@ -272,6 +298,68 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "permit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [], "name": "remoteToken", diff --git a/packages/contracts-bedrock/snapshots/abi/OptimismPortal.json b/packages/contracts-bedrock/snapshots/abi/OptimismPortal.json index 88531b87da44a..7ccee328a9841 100644 --- a/packages/contracts-bedrock/snapshots/abi/OptimismPortal.json +++ b/packages/contracts-bedrock/snapshots/abi/OptimismPortal.json @@ -179,17 +179,17 @@ { "inputs": [ { - "internalType": "contract L2OutputOracle", + "internalType": "contract IL2OutputOracle", "name": "_l2Oracle", "type": "address" }, { - "internalType": "contract SystemConfig", + "internalType": "contract ISystemConfig", "name": "_systemConfig", "type": "address" }, { - "internalType": "contract SuperchainConfig", + "internalType": "contract ISuperchainConfig", "name": "_superchainConfig", "type": "address" } @@ -223,7 +223,7 @@ "name": "l2Oracle", "outputs": [ { - "internalType": "contract L2OutputOracle", + "internalType": "contract IL2OutputOracle", "name": "", "type": "address" } @@ -443,7 +443,7 @@ "name": "superchainConfig", "outputs": [ { - "internalType": "contract SuperchainConfig", + "internalType": "contract ISuperchainConfig", "name": "", "type": "address" } @@ -456,7 +456,7 @@ "name": "systemConfig", "outputs": [ { - "internalType": "contract SystemConfig", + "internalType": "contract ISystemConfig", "name": "", "type": "address" } diff --git a/packages/contracts-bedrock/snapshots/abi/OptimismPortal2.json b/packages/contracts-bedrock/snapshots/abi/OptimismPortal2.json index 92610763d6f0e..2f52ed573d37c 100644 --- a/packages/contracts-bedrock/snapshots/abi/OptimismPortal2.json +++ b/packages/contracts-bedrock/snapshots/abi/OptimismPortal2.json @@ -158,7 +158,7 @@ "name": "disputeGameFactory", "outputs": [ { - "internalType": "contract DisputeGameFactory", + "internalType": "contract IDisputeGameFactory", "name": "", "type": "address" } @@ -316,17 +316,17 @@ { "inputs": [ { - "internalType": "contract DisputeGameFactory", + "internalType": "contract IDisputeGameFactory", "name": "_disputeGameFactory", "type": "address" }, { - "internalType": "contract SystemConfig", + "internalType": "contract ISystemConfig", "name": "_systemConfig", "type": "address" }, { - "internalType": "contract SuperchainConfig", + "internalType": "contract ISuperchainConfig", "name": "_superchainConfig", "type": "address" }, @@ -648,7 +648,7 @@ "name": "superchainConfig", "outputs": [ { - "internalType": "contract SuperchainConfig", + "internalType": "contract ISuperchainConfig", "name": "", "type": "address" } @@ -661,7 +661,7 @@ "name": "systemConfig", "outputs": [ { - "internalType": "contract SystemConfig", + "internalType": "contract ISystemConfig", "name": "", "type": "address" } diff --git a/packages/contracts-bedrock/snapshots/abi/OptimismPortalInterop.json b/packages/contracts-bedrock/snapshots/abi/OptimismPortalInterop.json index 4d9979bee3443..5b9f72b9446c8 100644 --- a/packages/contracts-bedrock/snapshots/abi/OptimismPortalInterop.json +++ b/packages/contracts-bedrock/snapshots/abi/OptimismPortalInterop.json @@ -158,7 +158,7 @@ "name": "disputeGameFactory", "outputs": [ { - "internalType": "contract DisputeGameFactory", + "internalType": "contract IDisputeGameFactory", "name": "", "type": "address" } @@ -316,17 +316,17 @@ { "inputs": [ { - "internalType": "contract DisputeGameFactory", + "internalType": "contract IDisputeGameFactory", "name": "_disputeGameFactory", "type": "address" }, { - "internalType": "contract SystemConfig", + "internalType": "contract ISystemConfig", "name": "_systemConfig", "type": "address" }, { - "internalType": "contract SuperchainConfig", + "internalType": "contract ISuperchainConfig", "name": "_superchainConfig", "type": "address" }, @@ -666,7 +666,7 @@ "name": "superchainConfig", "outputs": [ { - "internalType": "contract SuperchainConfig", + "internalType": "contract ISuperchainConfig", "name": "", "type": "address" } @@ -679,7 +679,7 @@ "name": "systemConfig", "outputs": [ { - "internalType": "contract SystemConfig", + "internalType": "contract ISystemConfig", "name": "", "type": "address" } @@ -949,11 +949,6 @@ "name": "Unauthorized", "type": "error" }, - { - "inputs": [], - "name": "Unauthorized", - "type": "error" - }, { "inputs": [], "name": "UnexpectedList", diff --git a/packages/contracts-bedrock/snapshots/abi/OptimismSuperchainERC20Beacon.json b/packages/contracts-bedrock/snapshots/abi/OptimismSuperchainERC20Beacon.json new file mode 100644 index 0000000000000..0bdfc64ed2fe5 --- /dev/null +++ b/packages/contracts-bedrock/snapshots/abi/OptimismSuperchainERC20Beacon.json @@ -0,0 +1,39 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_implementation", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "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/OptimismSuperchainERC20Factory.json b/packages/contracts-bedrock/snapshots/abi/OptimismSuperchainERC20Factory.json new file mode 100644 index 0000000000000..7171cf1f31984 --- /dev/null +++ b/packages/contracts-bedrock/snapshots/abi/OptimismSuperchainERC20Factory.json @@ -0,0 +1,93 @@ +[ + { + "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": "deploy", + "outputs": [ + { + "internalType": "address", + "name": "_superchainERC20", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "superchainToken", + "type": "address" + } + ], + "name": "deployments", + "outputs": [ + { + "internalType": "address", + "name": "remoteToken", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "superchainToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "remoteToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "deployer", + "type": "address" + } + ], + "name": "OptimismSuperchainERC20Created", + "type": "event" + } +] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/abi/SystemConfig.json b/packages/contracts-bedrock/snapshots/abi/SystemConfig.json index 4b4ddd6c70a11..695231b9b1196 100644 --- a/packages/contracts-bedrock/snapshots/abi/SystemConfig.json +++ b/packages/contracts-bedrock/snapshots/abi/SystemConfig.json @@ -321,7 +321,7 @@ "type": "uint128" } ], - "internalType": "struct ResourceMetering.ResourceConfig", + "internalType": "struct IResourceMetering.ResourceConfig", "name": "_config", "type": "tuple" }, @@ -552,7 +552,7 @@ "type": "uint128" } ], - "internalType": "struct ResourceMetering.ResourceConfig", + "internalType": "struct IResourceMetering.ResourceConfig", "name": "", "type": "tuple" } diff --git a/packages/contracts-bedrock/snapshots/abi/SystemConfigInterop.json b/packages/contracts-bedrock/snapshots/abi/SystemConfigInterop.json index b32316ec9e423..64f72945615b4 100644 --- a/packages/contracts-bedrock/snapshots/abi/SystemConfigInterop.json +++ b/packages/contracts-bedrock/snapshots/abi/SystemConfigInterop.json @@ -342,7 +342,7 @@ "type": "uint128" } ], - "internalType": "struct ResourceMetering.ResourceConfig", + "internalType": "struct IResourceMetering.ResourceConfig", "name": "_config", "type": "tuple" }, @@ -469,7 +469,7 @@ "type": "uint128" } ], - "internalType": "struct ResourceMetering.ResourceConfig", + "internalType": "struct IResourceMetering.ResourceConfig", "name": "_config", "type": "tuple" }, @@ -713,7 +713,7 @@ "type": "uint128" } ], - "internalType": "struct ResourceMetering.ResourceConfig", + "internalType": "struct IResourceMetering.ResourceConfig", "name": "", "type": "tuple" } diff --git a/packages/contracts-bedrock/snapshots/state-diff/.gitkeep b/packages/contracts-bedrock/snapshots/state-diff/.gitkeep new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/packages/contracts-bedrock/snapshots/state-diff/Kontrol-31337.json b/packages/contracts-bedrock/snapshots/state-diff/Kontrol-31337.json deleted file mode 100644 index bc3a2be8e193a..0000000000000 --- a/packages/contracts-bedrock/snapshots/state-diff/Kontrol-31337.json +++ /dev/null @@ -1,20331 +0,0 @@ -{ - "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": "0xA8452Ec99ce0C64f20701dB7dD3abDb607c00496", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x608060405234801561001057600080fd5b50610ba2806100206000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c806361b69abd1161005057806361b69abd146100dc578063addacc0f146100ef578063d18af54d146100f757600080fd5b80631688f0b9146100775780632500510e146100b457806353e5d935146100c7575b600080fd5b61008a61008536600461070e565b61010a565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b61008a6100c2366004610767565b610192565b6100cf610272565b6040516100ab919061086c565b61008a6100ea366004610886565b6102ba565b6100cf61037d565b61008a6101053660046108d6565b61038f565b60006101178484846104ab565b83519091501561013b5760008060008551602087016000865af10361013b57600080fd5b6040805173ffffffffffffffffffffffffffffffffffffffff8084168252861660208201527f4f51faf6c4561ff95f067657e43439f0f856d97c04d9ec9070a6199ad418e235910160405180910390a19392505050565b60006101d68585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508792506104ab915050565b6040517fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606083901b166020820152909150603401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290527f08c379a00000000000000000000000000000000000000000000000000000000082526102699160040161086c565b60405180910390fd5b606060405180602001610284906105f6565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820381018352601f90910116604052919050565b6000826040516102c9906105f6565b73ffffffffffffffffffffffffffffffffffffffff9091168152602001604051809103906000f080158015610302573d6000803e3d6000fd5b508251909150156103275760008060008451602086016000865af10361032757600080fd5b6040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201527f4f51faf6c4561ff95f067657e43439f0f856d97c04d9ec9070a6199ad418e235910160405180910390a192915050565b60606040518060200161028490610603565b60008083836040516020016103d392919091825260601b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016602082015260340190565b6040516020818303038152906040528051906020012060001c90506103f986868361010a565b915073ffffffffffffffffffffffffffffffffffffffff8316156104a2576040517f1e52b51800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841690631e52b5189061046f9085908a908a908a90600401610942565b600060405180830381600087803b15801561048957600080fd5b505af115801561049d573d6000803e3d6000fd5b505050505b50949350505050565b6000808380519060200120836040516020016104d1929190918252602082015260400190565b6040516020818303038152906040528051906020012090506000604051806020016104fb906105f6565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820381018352601f909101166040819052610553919073ffffffffffffffffffffffffffffffffffffffff89169060200161098c565b6040516020818303038152906040529050818151826020016000f5925073ffffffffffffffffffffffffffffffffffffffff83166105ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f437265617465322063616c6c206661696c6564000000000000000000000000006044820152606401610269565b50509392505050565b61016f806109af83390190565b607880610b1e83390190565b73ffffffffffffffffffffffffffffffffffffffff8116811461063157600080fd5b50565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261067457600080fd5b813567ffffffffffffffff8082111561068f5761068f610634565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156106d5576106d5610634565b816040528381528660208588010111156106ee57600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060006060848603121561072357600080fd5b833561072e8161060f565b9250602084013567ffffffffffffffff81111561074a57600080fd5b61075686828701610663565b925050604084013590509250925092565b6000806000806060858703121561077d57600080fd5b84356107888161060f565b9350602085013567ffffffffffffffff808211156107a557600080fd5b818701915087601f8301126107b957600080fd5b8135818111156107c857600080fd5b8860208285010111156107da57600080fd5b95986020929092019750949560400135945092505050565b60005b8381101561080d5781810151838201526020016107f5565b8381111561081c576000848401525b50505050565b6000815180845261083a8160208601602086016107f2565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061087f6020830184610822565b9392505050565b6000806040838503121561089957600080fd5b82356108a48161060f565b9150602083013567ffffffffffffffff8111156108c057600080fd5b6108cc85828601610663565b9150509250929050565b600080600080608085870312156108ec57600080fd5b84356108f78161060f565b9350602085013567ffffffffffffffff81111561091357600080fd5b61091f87828801610663565b9350506040850135915060608501356109378161060f565b939692955090935050565b600073ffffffffffffffffffffffffffffffffffffffff80871683528086166020840152506080604083015261097b6080830185610822565b905082606083015295945050505050565b6000835161099e8184602088016107f2565b919091019182525060200191905056fe608060405234801561001057600080fd5b5060405161016f38038061016f83398101604081905261002f916100b9565b6001600160a01b0381166100945760405162461bcd60e51b815260206004820152602260248201527f496e76616c69642073696e676c65746f6e20616464726573732070726f766964604482015261195960f21b606482015260840160405180910390fd5b600080546001600160a01b0319166001600160a01b03929092169190911790556100e9565b6000602082840312156100cb57600080fd5b81516001600160a01b03811681146100e257600080fd5b9392505050565b6078806100f76000396000f3fe6080604052600073ffffffffffffffffffffffffffffffffffffffff8154167fa619486e00000000000000000000000000000000000000000000000000000000823503604d57808252602082f35b3682833781823684845af490503d82833e806066573d82fd5b503d81f3fea164736f6c634300080f000a6080604052600073ffffffffffffffffffffffffffffffffffffffff8154167fa619486e00000000000000000000000000000000000000000000000000000000823503604d57808252602082f35b3682833781823684845af490503d82833e806066573d82fd5b503d81f3fea164736f6c634300080f000aa164736f6c634300080f000a", - "deployedCode": "0x608060405234801561001057600080fd5b50600436106100725760003560e01c806361b69abd1161005057806361b69abd146100dc578063addacc0f146100ef578063d18af54d146100f757600080fd5b80631688f0b9146100775780632500510e146100b457806353e5d935146100c7575b600080fd5b61008a61008536600461070e565b61010a565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b61008a6100c2366004610767565b610192565b6100cf610272565b6040516100ab919061086c565b61008a6100ea366004610886565b6102ba565b6100cf61037d565b61008a6101053660046108d6565b61038f565b60006101178484846104ab565b83519091501561013b5760008060008551602087016000865af10361013b57600080fd5b6040805173ffffffffffffffffffffffffffffffffffffffff8084168252861660208201527f4f51faf6c4561ff95f067657e43439f0f856d97c04d9ec9070a6199ad418e235910160405180910390a19392505050565b60006101d68585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508792506104ab915050565b6040517fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606083901b166020820152909150603401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290527f08c379a00000000000000000000000000000000000000000000000000000000082526102699160040161086c565b60405180910390fd5b606060405180602001610284906105f6565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820381018352601f90910116604052919050565b6000826040516102c9906105f6565b73ffffffffffffffffffffffffffffffffffffffff9091168152602001604051809103906000f080158015610302573d6000803e3d6000fd5b508251909150156103275760008060008451602086016000865af10361032757600080fd5b6040805173ffffffffffffffffffffffffffffffffffffffff8084168252851660208201527f4f51faf6c4561ff95f067657e43439f0f856d97c04d9ec9070a6199ad418e235910160405180910390a192915050565b60606040518060200161028490610603565b60008083836040516020016103d392919091825260601b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016602082015260340190565b6040516020818303038152906040528051906020012060001c90506103f986868361010a565b915073ffffffffffffffffffffffffffffffffffffffff8316156104a2576040517f1e52b51800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841690631e52b5189061046f9085908a908a908a90600401610942565b600060405180830381600087803b15801561048957600080fd5b505af115801561049d573d6000803e3d6000fd5b505050505b50949350505050565b6000808380519060200120836040516020016104d1929190918252602082015260400190565b6040516020818303038152906040528051906020012090506000604051806020016104fb906105f6565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820381018352601f909101166040819052610553919073ffffffffffffffffffffffffffffffffffffffff89169060200161098c565b6040516020818303038152906040529050818151826020016000f5925073ffffffffffffffffffffffffffffffffffffffff83166105ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f437265617465322063616c6c206661696c6564000000000000000000000000006044820152606401610269565b50509392505050565b61016f806109af83390190565b607880610b1e83390190565b73ffffffffffffffffffffffffffffffffffffffff8116811461063157600080fd5b50565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261067457600080fd5b813567ffffffffffffffff8082111561068f5761068f610634565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156106d5576106d5610634565b816040528381528660208588010111156106ee57600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060006060848603121561072357600080fd5b833561072e8161060f565b9250602084013567ffffffffffffffff81111561074a57600080fd5b61075686828701610663565b925050604084013590509250925092565b6000806000806060858703121561077d57600080fd5b84356107888161060f565b9350602085013567ffffffffffffffff808211156107a557600080fd5b818701915087601f8301126107b957600080fd5b8135818111156107c857600080fd5b8860208285010111156107da57600080fd5b95986020929092019750949560400135945092505050565b60005b8381101561080d5781810151838201526020016107f5565b8381111561081c576000848401525b50505050565b6000815180845261083a8160208601602086016107f2565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061087f6020830184610822565b9392505050565b6000806040838503121561089957600080fd5b82356108a48161060f565b9150602083013567ffffffffffffffff8111156108c057600080fd5b6108cc85828601610663565b9150509250929050565b600080600080608085870312156108ec57600080fd5b84356108f78161060f565b9350602085013567ffffffffffffffff81111561091357600080fd5b61091f87828801610663565b9350506040850135915060608501356109378161060f565b939692955090935050565b600073ffffffffffffffffffffffffffffffffffffffff80871683528086166020840152506080604083015261097b6080830185610822565b905082606083015295945050505050565b6000835161099e8184602088016107f2565b919091019182525060200191905056fe608060405234801561001057600080fd5b5060405161016f38038061016f83398101604081905261002f916100b9565b6001600160a01b0381166100945760405162461bcd60e51b815260206004820152602260248201527f496e76616c69642073696e676c65746f6e20616464726573732070726f766964604482015261195960f21b606482015260840160405180910390fd5b600080546001600160a01b0319166001600160a01b03929092169190911790556100e9565b6000602082840312156100cb57600080fd5b81516001600160a01b03811681146100e257600080fd5b9392505050565b6078806100f76000396000f3fe6080604052600073ffffffffffffffffffffffffffffffffffffffff8154167fa619486e00000000000000000000000000000000000000000000000000000000823503604d57808252602082f35b3682833781823684845af490503d82833e806066573d82fd5b503d81f3fea164736f6c634300080f000a6080604052600073ffffffffffffffffffffffffffffffffffffffff8154167fa619486e00000000000000000000000000000000000000000000000000000000823503604d57808252602082f35b3682833781823684845af490503d82833e806066573d82fd5b503d81f3fea164736f6c634300080f000aa164736f6c634300080f000a", - "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": "0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x608060405234801561001057600080fd5b506001600455613fb6806100256000396000f3fe6080604052600436106101dc5760003560e01c8063affed0e011610102578063e19a9dd911610095578063f08a032311610064578063f08a032314610620578063f698da2514610640578063f8dc5dd9146106a7578063ffa1ad74146106c757610218565b8063e19a9dd9146105ab578063e318b52b146105cb578063e75235b8146105eb578063e86637db1461060057610218565b8063cc2f8452116100d1578063cc2f84521461051d578063d4d9bdcd1461054b578063d8d11f781461056b578063e009cfde1461058b57610218565b8063affed0e0146104a7578063b4faba09146104bd578063b63e800d146104dd578063c4ca3a9c146104fd57610218565b80635624b25b1161017a5780636a761202116101495780636a7612021461041a5780637d8329741461042d578063934f3a1114610465578063a0e67e2b1461048557610218565b80635624b25b146103805780635ae6bd37146103ad578063610b5925146103da578063694e80c3146103fa57610218565b80632f54bf6e116101b65780632f54bf6e146102f55780633408e47014610315578063468721a7146103325780635229073f1461035257610218565b80630d582f131461027e57806312fb68e0146102a05780632d9ad53d146102c057610218565b366102185760405134815233907f3d0ce9bfc3ed7d6862dbb28b2dea94561fe714a1b4d019aa8af39730d1ad7c3d9060200160405180910390a2005b34801561022457600080fd5b507f6c9a6c4a39284e37ed1cf53d337577d14212a4870fb976a4366c693b939918d580548061024f57005b36600080373360601b365260008060143601600080855af190503d6000803e80610278573d6000fd5b503d6000f35b34801561028a57600080fd5b5061029e6102993660046132ce565b610710565b005b3480156102ac57600080fd5b5061029e6102bb3660046133d4565b610966565b3480156102cc57600080fd5b506102e06102db366004613449565b610fbb565b60405190151581526020015b60405180910390f35b34801561030157600080fd5b506102e0610310366004613449565b611010565b34801561032157600080fd5b50465b6040519081526020016102ec565b34801561033e57600080fd5b506102e061034d366004613475565b611062565b34801561035e57600080fd5b5061037261036d366004613475565b611178565b6040516102ec92919061354a565b34801561038c57600080fd5b506103a061039b366004613565565b6111ae565b6040516102ec9190613587565b3480156103b957600080fd5b506103246103c836600461359a565b60076020526000908152604090205481565b3480156103e657600080fd5b5061029e6103f5366004613449565b611234565b34801561040657600080fd5b5061029e61041536600461359a565b611426565b6102e06104283660046135fc565b61153a565b34801561043957600080fd5b506103246104483660046132ce565b600860209081526000928352604080842090915290825290205481565b34801561047157600080fd5b5061029e6104803660046136d5565b611934565b34801561049157600080fd5b5061049a6119b0565b6040516102ec9190613793565b3480156104b357600080fd5b5061032460055481565b3480156104c957600080fd5b5061029e6104d83660046137a6565b611ac8565b3480156104e957600080fd5b5061029e6104f83660046137f6565b611aeb565b34801561050957600080fd5b506103246105183660046138eb565b611c26565b34801561052957600080fd5b5061053d6105383660046132ce565b611cf8565b6040516102ec92919061395c565b34801561055757600080fd5b5061029e61056636600461359a565b611e26565b34801561057757600080fd5b50610324610586366004613994565b611efa565b34801561059757600080fd5b5061029e6105a6366004613a55565b611f27565b3480156105b757600080fd5b5061029e6105c6366004613449565b612106565b3480156105d757600080fd5b5061029e6105e6366004613a8e565b612178565b3480156105f757600080fd5b50600454610324565b34801561060c57600080fd5b506103a061061b366004613994565b612504565b34801561062c57600080fd5b5061029e61063b366004613449565b61269d565b34801561064c57600080fd5b5061032460007f47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a794692184660408051602081019390935282015230606082015260800160405160208183030381529060405280519060200120905090565b3480156106b357600080fd5b5061029e6106c2366004613ad9565b612713565b3480156106d357600080fd5b506103a06040518060400160405280600581526020017f312e332e3000000000000000000000000000000000000000000000000000000081525081565b6107186129a5565b73ffffffffffffffffffffffffffffffffffffffff821615801590610754575073ffffffffffffffffffffffffffffffffffffffff8216600114155b8015610776575073ffffffffffffffffffffffffffffffffffffffff82163014155b6107e1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303300000000000000000000000000000000000000000000000000000060448201526064015b60405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8281166000908152600260205260409020541615610870576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303400000000000000000000000000000000000000000000000000000060448201526064016107d8565b60026020527fe90b7bceb6e7df5418fb78d8ee546e97c83a08bbccc01a0644d599ccd2a7c2e0805473ffffffffffffffffffffffffffffffffffffffff8481166000818152604081208054939094167fffffffffffffffffffffffff00000000000000000000000000000000000000009384161790935560018352835490911617909155600380549161090283613b49565b909155505060405173ffffffffffffffffffffffffffffffffffffffff831681527f9465fa0c962cc76958e6373a993326400c1c94f8be2fe3a952adfa7f60b2ea269060200160405180910390a180600454146109625761096281611426565b5050565b610971816041612a10565b825110156109db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323000000000000000000000000000000000000000000000000000000060448201526064016107d8565b6000808060008060005b86811015610faf576041818102890160208101516040820151919092015160ff16955090935091506000849003610cbc579193508391610a26876041612a10565b821015610a8f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323100000000000000000000000000000000000000000000000000000060448201526064016107d8565b8751610a9c836020612a4c565b1115610b04576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323200000000000000000000000000000000000000000000000000000060448201526064016107d8565b602082890181015189519091610b27908390610b21908790612a4c565b90612a4c565b1115610b8f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323300000000000000000000000000000000000000000000000000000060448201526064016107d8565b6040517f20c13b0b000000000000000000000000000000000000000000000000000000008082528a85016020019173ffffffffffffffffffffffffffffffffffffffff8916906320c13b0b90610beb908f908690600401613b81565b602060405180830381865afa158015610c08573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c2c9190613ba6565b7fffffffff000000000000000000000000000000000000000000000000000000001614610cb5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323400000000000000000000000000000000000000000000000000000060448201526064016107d8565b5050610eaf565b8360ff16600103610d8a5791935083913373ffffffffffffffffffffffffffffffffffffffff84161480610d1f575073ffffffffffffffffffffffffffffffffffffffff851660009081526008602090815260408083208d845290915290205415155b610d85576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323500000000000000000000000000000000000000000000000000000060448201526064016107d8565b610eaf565b601e8460ff161115610e4f576040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c81018b9052600190605c0160405160208183030381529060405280519060200120600486610def9190613be8565b6040805160008152602081018083529390935260ff90911690820152606081018590526080810184905260a0016020604051602081039080840390855afa158015610e3e573d6000803e3d6000fd5b505050602060405103519450610eaf565b6040805160008152602081018083528c905260ff861691810191909152606081018490526080810183905260019060a0016020604051602081039080840390855afa158015610ea2573d6000803e3d6000fd5b5050506020604051035194505b8573ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16118015610f10575073ffffffffffffffffffffffffffffffffffffffff8581166000908152600260205260409020541615155b8015610f33575073ffffffffffffffffffffffffffffffffffffffff8516600114155b610f99576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323600000000000000000000000000000000000000000000000000000060448201526064016107d8565b8495508080610fa790613b49565b9150506109e5565b50505050505050505050565b6000600173ffffffffffffffffffffffffffffffffffffffff83161480159061100a575073ffffffffffffffffffffffffffffffffffffffff8281166000908152600160205260409020541615155b92915050565b600073ffffffffffffffffffffffffffffffffffffffff821660011480159061100a57505073ffffffffffffffffffffffffffffffffffffffff90811660009081526002602052604090205416151590565b60003360011480159061109957503360009081526001602052604090205473ffffffffffffffffffffffffffffffffffffffff1615155b6110ff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303400000000000000000000000000000000000000000000000000000060448201526064016107d8565b61110c858585855a612a68565b905080156111445760405133907f6895c13664aa4f67288b25d7a21d7aaa34916e355fb9b6fae0a139a9085becb890600090a2611170565b60405133907facd2c8702804128fdb0db2bb49f6d127dd0181c13fd45dbfe16de0930e2bd37590600090a25b949350505050565b6000606061118886868686611062565b915060405160203d0181016040523d81523d6000602083013e8091505094509492505050565b606060006111bd836020613c0b565b67ffffffffffffffff8111156111d5576111d56132fa565b6040519080825280601f01601f1916602001820160405280156111ff576020820181803683370190505b50905060005b8381101561122c57848101546020808302840101528061122481613b49565b915050611205565b509392505050565b61123c6129a5565b73ffffffffffffffffffffffffffffffffffffffff811615801590611278575073ffffffffffffffffffffffffffffffffffffffff8116600114155b6112de576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303100000000000000000000000000000000000000000000000000000060448201526064016107d8565b73ffffffffffffffffffffffffffffffffffffffff818116600090815260016020526040902054161561136d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303200000000000000000000000000000000000000000000000000000060448201526064016107d8565b600160208181527fcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f805473ffffffffffffffffffffffffffffffffffffffff858116600081815260408082208054949095167fffffffffffffffffffffffff000000000000000000000000000000000000000094851617909455959095528254168417909155519182527fecdf3a3effea5783a3c4c2140e677577666428d44ed9d474a0b3a4c9943f844091015b60405180910390a150565b61142e6129a5565b60035481111561149a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303100000000000000000000000000000000000000000000000000000060448201526064016107d8565b6001811015611505576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303200000000000000000000000000000000000000000000000000000060448201526064016107d8565b60048190556040518181527f610f7ff2b304ae8903c3de74c60c6ab1f7d6226b3f52c5161905bb5ad4039c939060200161141b565b60008060006115548e8e8e8e8e8e8e8e8e8e600554612504565b60058054919250600061156683613b49565b909155505080516020820120915061157f828286611934565b5060006115aa7f4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c85490565b905073ffffffffffffffffffffffffffffffffffffffff81161561164a578073ffffffffffffffffffffffffffffffffffffffff166375f0bb528f8f8f8f8f8f8f8f8f8f8f336040518d63ffffffff1660e01b81526004016116179c9b9a99989796959493929190613cb2565b600060405180830381600087803b15801561163157600080fd5b505af1158015611645573d6000803e3d6000fd5b505050505b6116766116598a6109c4613dc8565b603f6116668c6040613c0b565b6116709190613de0565b90612aaf565b611682906101f4613dc8565b5a10156116eb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330313000000000000000000000000000000000000000000000000000000060448201526064016107d8565b60005a905061175c8f8f8f8f8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508e8c600014611749578e612a68565b6109c45a6117579190613e1b565b612a68565b93506117695a8290612ac6565b9050838061177657508915155b8061178057508715155b6117e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330313300000000000000000000000000000000000000000000000000000060448201526064016107d8565b600088156117fe576117fb828b8b8b8b612ae1565b90505b84156118425760408051858152602081018390527f442e715f626346e8c54381002da614f62bee8d27386535b2521ec8540898556e910160405180910390a161187c565b60408051858152602081018390527f23428b18acfb3ea64b08dc0c1d296ea9c09702c09083ca5272e64d115b687d23910160405180910390a15b505073ffffffffffffffffffffffffffffffffffffffff811615611923576040517f9327136800000000000000000000000000000000000000000000000000000000815260048101839052831515602482015273ffffffffffffffffffffffffffffffffffffffff821690639327136890604401600060405180830381600087803b15801561190a57600080fd5b505af115801561191e573d6000803e3d6000fd5b505050505b50509b9a5050505050505050505050565b6004548061199e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330303100000000000000000000000000000000000000000000000000000060448201526064016107d8565b6119aa84848484610966565b50505050565b6060600060035467ffffffffffffffff8111156119cf576119cf6132fa565b6040519080825280602002602001820160405280156119f8578160200160208202803683370190505b506001600090815260026020527fe90b7bceb6e7df5418fb78d8ee546e97c83a08bbccc01a0644d599ccd2a7c2e0549192509073ffffffffffffffffffffffffffffffffffffffff165b73ffffffffffffffffffffffffffffffffffffffff8116600114611ac05780838381518110611a7357611a73613e32565b73ffffffffffffffffffffffffffffffffffffffff928316602091820292909201810191909152918116600090815260029092526040909120541681611ab881613b49565b925050611a42565b509092915050565b600080825160208401855af480600052503d6020523d600060403e60403d016000fd5b611b298a8a808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508c9250612c72915050565b73ffffffffffffffffffffffffffffffffffffffff841615611b6d57611b6d847f6c9a6c4a39284e37ed1cf53d337577d14212a4870fb976a4366c693b939918d555565b611bad8787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061303f92505050565b8115611bc457611bc282600060018685612ae1565b505b3373ffffffffffffffffffffffffffffffffffffffff167f141df868a6331af528e38c83b7aa03edc19be66e37ae67f9285bf4f8e3c6a1a88b8b8b8b89604051611c12959493929190613e61565b60405180910390a250505050505050505050565b6000805a9050611c6f878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525089925050505a612a68565b611c7857600080fd5b60005a611c859083613e1b565b905080604051602001611c9a91815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290527f08c379a00000000000000000000000000000000000000000000000000000000082526107d891600401613587565b606060008267ffffffffffffffff811115611d1557611d156132fa565b604051908082528060200260200182016040528015611d3e578160200160208202803683370190505b5073ffffffffffffffffffffffffffffffffffffffff80861660009081526001602052604081205492945091165b73ffffffffffffffffffffffffffffffffffffffff811615801590611da8575073ffffffffffffffffffffffffffffffffffffffff8116600114155b8015611db357508482105b15611e185780848381518110611dcb57611dcb613e32565b73ffffffffffffffffffffffffffffffffffffffff928316602091820292909201810191909152918116600090815260019092526040909120541681611e1081613b49565b925050611d6c565b908352919491935090915050565b3360009081526002602052604090205473ffffffffffffffffffffffffffffffffffffffff16611eb2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330333000000000000000000000000000000000000000000000000000000060448201526064016107d8565b336000818152600860209081526040808320858452909152808220600190555183917ff2a0eb156472d1440255b0d7c1e19cc07115d1051fe605b0dce69acfec884d9c91a350565b6000611f0f8c8c8c8c8c8c8c8c8c8c8c612504565b8051906020012090509b9a5050505050505050505050565b611f2f6129a5565b73ffffffffffffffffffffffffffffffffffffffff811615801590611f6b575073ffffffffffffffffffffffffffffffffffffffff8116600114155b611fd1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303100000000000000000000000000000000000000000000000000000060448201526064016107d8565b73ffffffffffffffffffffffffffffffffffffffff828116600090815260016020526040902054811690821614612064576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303300000000000000000000000000000000000000000000000000000060448201526064016107d8565b73ffffffffffffffffffffffffffffffffffffffff8181166000818152600160209081526040808320805488871685528285208054919097167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790965592849052825490941690915591519081527faab4fa2b463f581b2b32cb3b7e3b704b9ce37cc209b5fb4d77e593ace405427691015b60405180910390a15050565b61210e6129a5565b7f4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c881815560405173ffffffffffffffffffffffffffffffffffffffff831681527f1151116914515bc0891ff9047a6cb32cf902546f83066499bcf8ba33d2353fa2906020016120fa565b6121806129a5565b73ffffffffffffffffffffffffffffffffffffffff8116158015906121bc575073ffffffffffffffffffffffffffffffffffffffff8116600114155b80156121de575073ffffffffffffffffffffffffffffffffffffffff81163014155b612244576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303300000000000000000000000000000000000000000000000000000060448201526064016107d8565b73ffffffffffffffffffffffffffffffffffffffff81811660009081526002602052604090205416156122d3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303400000000000000000000000000000000000000000000000000000060448201526064016107d8565b73ffffffffffffffffffffffffffffffffffffffff82161580159061230f575073ffffffffffffffffffffffffffffffffffffffff8216600114155b612375576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303300000000000000000000000000000000000000000000000000000060448201526064016107d8565b73ffffffffffffffffffffffffffffffffffffffff838116600090815260026020526040902054811690831614612408576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303500000000000000000000000000000000000000000000000000000060448201526064016107d8565b73ffffffffffffffffffffffffffffffffffffffff8281166000818152600260209081526040808320805487871680865283862080549289167fffffffffffffffffffffffff0000000000000000000000000000000000000000938416179055968a1685528285208054821690971790965592849052825490941690915591519081527ff8d49fc529812e9a7c5c50e69c20f0dccc0db8fa95c98bc58cc9a4f1c1299eaf910160405180910390a160405173ffffffffffffffffffffffffffffffffffffffff821681527f9465fa0c962cc76958e6373a993326400c1c94f8be2fe3a952adfa7f60b2ea269060200160405180910390a1505050565b606060007fbb8310d486368db6bd6f849402fdd73ad53d316b5a4b2644ad6efe0f941286d860001b8d8d8d8d60405161253e929190613ee7565b604051908190038120612564949392918e908e908e908e908e908e908e90602001613ef7565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052805160209091012090507f19000000000000000000000000000000000000000000000000000000000000007f010000000000000000000000000000000000000000000000000000000000000061263860007f47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a794692184660408051602081019390935282015230606082015260800160405160208183030381529060405280519060200120905090565b6040517fff0000000000000000000000000000000000000000000000000000000000000093841660208201529290911660218301526022820152604281018290526062016040516020818303038152906040529150509b9a5050505050505050505050565b6126a56129a5565b6126cd817f6c9a6c4a39284e37ed1cf53d337577d14212a4870fb976a4366c693b939918d555565b60405173ffffffffffffffffffffffffffffffffffffffff821681527f5ac6c46c93c8d0e53714ba3b53db3e7c046da994313d7ed0d192028bc7c228b09060200161141b565b61271b6129a5565b80600160035461272b9190613e1b565b1015612793576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303100000000000000000000000000000000000000000000000000000060448201526064016107d8565b73ffffffffffffffffffffffffffffffffffffffff8216158015906127cf575073ffffffffffffffffffffffffffffffffffffffff8216600114155b612835576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303300000000000000000000000000000000000000000000000000000060448201526064016107d8565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600260205260409020548116908316146128c8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303500000000000000000000000000000000000000000000000000000060448201526064016107d8565b73ffffffffffffffffffffffffffffffffffffffff828116600081815260026020526040808220805488861684529183208054929095167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179094559181528254909116909155600380549161294083613f74565b909155505060405173ffffffffffffffffffffffffffffffffffffffff831681527ff8d49fc529812e9a7c5c50e69c20f0dccc0db8fa95c98bc58cc9a4f1c1299eaf9060200160405180910390a180600454146129a0576129a081611426565b505050565b333014612a0e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330333100000000000000000000000000000000000000000000000000000060448201526064016107d8565b565b600082600003612a225750600061100a565b6000612a2e8385613c0b565b905082612a3b8583613de0565b14612a4557600080fd5b9392505050565b600080612a598385613dc8565b905083811015612a4557600080fd5b60006001836001811115612a7e57612a7e613c48565b03612a96576000808551602087018986f49050612aa6565b600080855160208701888a87f190505b95945050505050565b600081831015612abf5781612a45565b5090919050565b600082821115612ad557600080fd5b60006111708385613e1b565b60008073ffffffffffffffffffffffffffffffffffffffff831615612b065782612b08565b325b905073ffffffffffffffffffffffffffffffffffffffff8416612be757612b473a8610612b35573a612b37565b855b612b418989612a4c565b90612a10565b60405190925073ffffffffffffffffffffffffffffffffffffffff82169083156108fc029084906000818181858888f19350505050612be2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330313100000000000000000000000000000000000000000000000000000060448201526064016107d8565b612c68565b612bf585612b418989612a4c565b9150612c028482846131cf565b612c68576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330313200000000000000000000000000000000000000000000000000000060448201526064016107d8565b5095945050505050565b60045415612cdc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303000000000000000000000000000000000000000000000000000000060448201526064016107d8565b8151811115612d47576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303100000000000000000000000000000000000000000000000000000060448201526064016107d8565b6001811015612db2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303200000000000000000000000000000000000000000000000000000060448201526064016107d8565b600160005b8351811015612fe7576000848281518110612dd457612dd4613e32565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614158015612e32575073ffffffffffffffffffffffffffffffffffffffff8116600114155b8015612e54575073ffffffffffffffffffffffffffffffffffffffff81163014155b8015612e8c57508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614155b612ef2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303300000000000000000000000000000000000000000000000000000060448201526064016107d8565b73ffffffffffffffffffffffffffffffffffffffff8181166000908152600260205260409020541615612f81576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303400000000000000000000000000000000000000000000000000000060448201526064016107d8565b73ffffffffffffffffffffffffffffffffffffffff928316600090815260026020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169382169390931790925580612fdf81613b49565b915050612db7565b5073ffffffffffffffffffffffffffffffffffffffff16600090815260026020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790559051600355600455565b600160008190526020527fcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f5473ffffffffffffffffffffffffffffffffffffffff16156130e8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303000000000000000000000000000000000000000000000000000000060448201526064016107d8565b6001600081905260208190527fcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f80547fffffffffffffffffffffffff000000000000000000000000000000000000000016909117905573ffffffffffffffffffffffffffffffffffffffff821615610962576131698260008360015a612a68565b610962576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330303000000000000000000000000000000000000000000000000000000060448201526064016107d8565b6040805173ffffffffffffffffffffffffffffffffffffffff841660248201526044808201849052825180830390910181526064909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001781528251600093929184919082896127105a03f13d801561327c5760208114613284576000935061328f565b81935061328f565b600051158215171593505b5050509392505050565b73ffffffffffffffffffffffffffffffffffffffff811681146132bb57600080fd5b50565b80356132c981613299565b919050565b600080604083850312156132e157600080fd5b82356132ec81613299565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261333a57600080fd5b813567ffffffffffffffff80821115613355576133556132fa565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561339b5761339b6132fa565b816040528381528660208588010111156133b457600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600080608085870312156133ea57600080fd5b84359350602085013567ffffffffffffffff8082111561340957600080fd5b61341588838901613329565b9450604087013591508082111561342b57600080fd5b5061343887828801613329565b949793965093946060013593505050565b60006020828403121561345b57600080fd5b8135612a4581613299565b8035600281106132c957600080fd5b6000806000806080858703121561348b57600080fd5b843561349681613299565b935060208501359250604085013567ffffffffffffffff8111156134b957600080fd5b6134c587828801613329565b9250506134d460608601613466565b905092959194509250565b6000815180845260005b81811015613505576020818501810151868301820152016134e9565b81811115613517576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b821515815260406020820152600061117060408301846134df565b6000806040838503121561357857600080fd5b50508035926020909101359150565b602081526000612a4560208301846134df565b6000602082840312156135ac57600080fd5b5035919050565b60008083601f8401126135c557600080fd5b50813567ffffffffffffffff8111156135dd57600080fd5b6020830191508360208285010111156135f557600080fd5b9250929050565b60008060008060008060008060008060006101408c8e03121561361e57600080fd5b6136278c6132be565b9a5060208c0135995067ffffffffffffffff8060408e0135111561364a57600080fd5b61365a8e60408f01358f016135b3565b909a50985061366b60608e01613466565b975060808d0135965060a08d0135955060c08d0135945061368e60e08e016132be565b935061369d6101008e016132be565b9250806101208e013511156136b157600080fd5b506136c38d6101208e01358e01613329565b90509295989b509295989b9093969950565b6000806000606084860312156136ea57600080fd5b83359250602084013567ffffffffffffffff8082111561370957600080fd5b61371587838801613329565b9350604086013591508082111561372b57600080fd5b5061373886828701613329565b9150509250925092565b600081518084526020808501945080840160005b8381101561378857815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101613756565b509495945050505050565b602081526000612a456020830184613742565b600080604083850312156137b957600080fd5b82356137c481613299565b9150602083013567ffffffffffffffff8111156137e057600080fd5b6137ec85828601613329565b9150509250929050565b6000806000806000806000806000806101008b8d03121561381657600080fd5b8a3567ffffffffffffffff8082111561382e57600080fd5b818d0191508d601f83011261384257600080fd5b81358181111561385157600080fd5b8e60208260051b850101111561386657600080fd5b60208381019d50909b508d0135995061388160408e016132be565b985060608d013591508082111561389757600080fd5b506138a48d828e016135b3565b90975095506138b7905060808c016132be565b93506138c560a08c016132be565b925060c08b013591506138da60e08c016132be565b90509295989b9194979a5092959850565b60008060008060006080868803121561390357600080fd5b853561390e81613299565b945060208601359350604086013567ffffffffffffffff81111561393157600080fd5b61393d888289016135b3565b9094509250613950905060608701613466565b90509295509295909350565b60408152600061396f6040830185613742565b905073ffffffffffffffffffffffffffffffffffffffff831660208301529392505050565b60008060008060008060008060008060006101408c8e0312156139b657600080fd5b8b356139c181613299565b9a5060208c0135995060408c013567ffffffffffffffff8111156139e457600080fd5b6139f08e828f016135b3565b909a509850613a03905060608d01613466565b965060808c0135955060a08c0135945060c08c0135935060e08c0135613a2881613299565b92506101008c0135613a3981613299565b809250506101208c013590509295989b509295989b9093969950565b60008060408385031215613a6857600080fd5b8235613a7381613299565b91506020830135613a8381613299565b809150509250929050565b600080600060608486031215613aa357600080fd5b8335613aae81613299565b92506020840135613abe81613299565b91506040840135613ace81613299565b809150509250925092565b600080600060608486031215613aee57600080fd5b8335613af981613299565b92506020840135613b0981613299565b929592945050506040919091013590565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613b7a57613b7a613b1a565b5060010190565b604081526000613b9460408301856134df565b8281036020840152612aa681856134df565b600060208284031215613bb857600080fd5b81517fffffffff0000000000000000000000000000000000000000000000000000000081168114612a4557600080fd5b600060ff821660ff841680821015613c0257613c02613b1a565b90039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613c4357613c43613b1a565b500290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60028110613cae577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b600061016073ffffffffffffffffffffffffffffffffffffffff8f1683528d60208401528060408401528b81840152506101808b8d828501376000818d850101527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8d01168301613d28606085018d613c77565b8a60808501528960a08501528860c0850152613d5c60e085018973ffffffffffffffffffffffffffffffffffffffff169052565b73ffffffffffffffffffffffffffffffffffffffff87166101008501528184820301610120850152613d90828201876134df565b92505050613db761014083018473ffffffffffffffffffffffffffffffffffffffff169052565b9d9c50505050505050505050505050565b60008219821115613ddb57613ddb613b1a565b500190565b600082613e16577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b600082821015613e2d57613e2d613b1a565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6080808252810185905260008660a08301825b88811015613eb1578235613e8781613299565b73ffffffffffffffffffffffffffffffffffffffff16825260209283019290910190600101613e74565b506020840196909652505073ffffffffffffffffffffffffffffffffffffffff9283166040820152911660609091015292915050565b8183823760009101908152919050565b6000610160820190508c825273ffffffffffffffffffffffffffffffffffffffff808d1660208401528b60408401528a6060840152613f39608084018b613c77565b60a083019890985260c082019690965260e0810194909452918516610100840152909316610120820152610140019190915295945050505050565b600081613f8357613f83613b1a565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019056fea164736f6c634300080f000a", - "deployedCode": "0x6080604052600436106101dc5760003560e01c8063affed0e011610102578063e19a9dd911610095578063f08a032311610064578063f08a032314610620578063f698da2514610640578063f8dc5dd9146106a7578063ffa1ad74146106c757610218565b8063e19a9dd9146105ab578063e318b52b146105cb578063e75235b8146105eb578063e86637db1461060057610218565b8063cc2f8452116100d1578063cc2f84521461051d578063d4d9bdcd1461054b578063d8d11f781461056b578063e009cfde1461058b57610218565b8063affed0e0146104a7578063b4faba09146104bd578063b63e800d146104dd578063c4ca3a9c146104fd57610218565b80635624b25b1161017a5780636a761202116101495780636a7612021461041a5780637d8329741461042d578063934f3a1114610465578063a0e67e2b1461048557610218565b80635624b25b146103805780635ae6bd37146103ad578063610b5925146103da578063694e80c3146103fa57610218565b80632f54bf6e116101b65780632f54bf6e146102f55780633408e47014610315578063468721a7146103325780635229073f1461035257610218565b80630d582f131461027e57806312fb68e0146102a05780632d9ad53d146102c057610218565b366102185760405134815233907f3d0ce9bfc3ed7d6862dbb28b2dea94561fe714a1b4d019aa8af39730d1ad7c3d9060200160405180910390a2005b34801561022457600080fd5b507f6c9a6c4a39284e37ed1cf53d337577d14212a4870fb976a4366c693b939918d580548061024f57005b36600080373360601b365260008060143601600080855af190503d6000803e80610278573d6000fd5b503d6000f35b34801561028a57600080fd5b5061029e6102993660046132ce565b610710565b005b3480156102ac57600080fd5b5061029e6102bb3660046133d4565b610966565b3480156102cc57600080fd5b506102e06102db366004613449565b610fbb565b60405190151581526020015b60405180910390f35b34801561030157600080fd5b506102e0610310366004613449565b611010565b34801561032157600080fd5b50465b6040519081526020016102ec565b34801561033e57600080fd5b506102e061034d366004613475565b611062565b34801561035e57600080fd5b5061037261036d366004613475565b611178565b6040516102ec92919061354a565b34801561038c57600080fd5b506103a061039b366004613565565b6111ae565b6040516102ec9190613587565b3480156103b957600080fd5b506103246103c836600461359a565b60076020526000908152604090205481565b3480156103e657600080fd5b5061029e6103f5366004613449565b611234565b34801561040657600080fd5b5061029e61041536600461359a565b611426565b6102e06104283660046135fc565b61153a565b34801561043957600080fd5b506103246104483660046132ce565b600860209081526000928352604080842090915290825290205481565b34801561047157600080fd5b5061029e6104803660046136d5565b611934565b34801561049157600080fd5b5061049a6119b0565b6040516102ec9190613793565b3480156104b357600080fd5b5061032460055481565b3480156104c957600080fd5b5061029e6104d83660046137a6565b611ac8565b3480156104e957600080fd5b5061029e6104f83660046137f6565b611aeb565b34801561050957600080fd5b506103246105183660046138eb565b611c26565b34801561052957600080fd5b5061053d6105383660046132ce565b611cf8565b6040516102ec92919061395c565b34801561055757600080fd5b5061029e61056636600461359a565b611e26565b34801561057757600080fd5b50610324610586366004613994565b611efa565b34801561059757600080fd5b5061029e6105a6366004613a55565b611f27565b3480156105b757600080fd5b5061029e6105c6366004613449565b612106565b3480156105d757600080fd5b5061029e6105e6366004613a8e565b612178565b3480156105f757600080fd5b50600454610324565b34801561060c57600080fd5b506103a061061b366004613994565b612504565b34801561062c57600080fd5b5061029e61063b366004613449565b61269d565b34801561064c57600080fd5b5061032460007f47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a794692184660408051602081019390935282015230606082015260800160405160208183030381529060405280519060200120905090565b3480156106b357600080fd5b5061029e6106c2366004613ad9565b612713565b3480156106d357600080fd5b506103a06040518060400160405280600581526020017f312e332e3000000000000000000000000000000000000000000000000000000081525081565b6107186129a5565b73ffffffffffffffffffffffffffffffffffffffff821615801590610754575073ffffffffffffffffffffffffffffffffffffffff8216600114155b8015610776575073ffffffffffffffffffffffffffffffffffffffff82163014155b6107e1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303300000000000000000000000000000000000000000000000000000060448201526064015b60405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8281166000908152600260205260409020541615610870576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303400000000000000000000000000000000000000000000000000000060448201526064016107d8565b60026020527fe90b7bceb6e7df5418fb78d8ee546e97c83a08bbccc01a0644d599ccd2a7c2e0805473ffffffffffffffffffffffffffffffffffffffff8481166000818152604081208054939094167fffffffffffffffffffffffff00000000000000000000000000000000000000009384161790935560018352835490911617909155600380549161090283613b49565b909155505060405173ffffffffffffffffffffffffffffffffffffffff831681527f9465fa0c962cc76958e6373a993326400c1c94f8be2fe3a952adfa7f60b2ea269060200160405180910390a180600454146109625761096281611426565b5050565b610971816041612a10565b825110156109db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323000000000000000000000000000000000000000000000000000000060448201526064016107d8565b6000808060008060005b86811015610faf576041818102890160208101516040820151919092015160ff16955090935091506000849003610cbc579193508391610a26876041612a10565b821015610a8f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323100000000000000000000000000000000000000000000000000000060448201526064016107d8565b8751610a9c836020612a4c565b1115610b04576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323200000000000000000000000000000000000000000000000000000060448201526064016107d8565b602082890181015189519091610b27908390610b21908790612a4c565b90612a4c565b1115610b8f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323300000000000000000000000000000000000000000000000000000060448201526064016107d8565b6040517f20c13b0b000000000000000000000000000000000000000000000000000000008082528a85016020019173ffffffffffffffffffffffffffffffffffffffff8916906320c13b0b90610beb908f908690600401613b81565b602060405180830381865afa158015610c08573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c2c9190613ba6565b7fffffffff000000000000000000000000000000000000000000000000000000001614610cb5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323400000000000000000000000000000000000000000000000000000060448201526064016107d8565b5050610eaf565b8360ff16600103610d8a5791935083913373ffffffffffffffffffffffffffffffffffffffff84161480610d1f575073ffffffffffffffffffffffffffffffffffffffff851660009081526008602090815260408083208d845290915290205415155b610d85576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323500000000000000000000000000000000000000000000000000000060448201526064016107d8565b610eaf565b601e8460ff161115610e4f576040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c81018b9052600190605c0160405160208183030381529060405280519060200120600486610def9190613be8565b6040805160008152602081018083529390935260ff90911690820152606081018590526080810184905260a0016020604051602081039080840390855afa158015610e3e573d6000803e3d6000fd5b505050602060405103519450610eaf565b6040805160008152602081018083528c905260ff861691810191909152606081018490526080810183905260019060a0016020604051602081039080840390855afa158015610ea2573d6000803e3d6000fd5b5050506020604051035194505b8573ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16118015610f10575073ffffffffffffffffffffffffffffffffffffffff8581166000908152600260205260409020541615155b8015610f33575073ffffffffffffffffffffffffffffffffffffffff8516600114155b610f99576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330323600000000000000000000000000000000000000000000000000000060448201526064016107d8565b8495508080610fa790613b49565b9150506109e5565b50505050505050505050565b6000600173ffffffffffffffffffffffffffffffffffffffff83161480159061100a575073ffffffffffffffffffffffffffffffffffffffff8281166000908152600160205260409020541615155b92915050565b600073ffffffffffffffffffffffffffffffffffffffff821660011480159061100a57505073ffffffffffffffffffffffffffffffffffffffff90811660009081526002602052604090205416151590565b60003360011480159061109957503360009081526001602052604090205473ffffffffffffffffffffffffffffffffffffffff1615155b6110ff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303400000000000000000000000000000000000000000000000000000060448201526064016107d8565b61110c858585855a612a68565b905080156111445760405133907f6895c13664aa4f67288b25d7a21d7aaa34916e355fb9b6fae0a139a9085becb890600090a2611170565b60405133907facd2c8702804128fdb0db2bb49f6d127dd0181c13fd45dbfe16de0930e2bd37590600090a25b949350505050565b6000606061118886868686611062565b915060405160203d0181016040523d81523d6000602083013e8091505094509492505050565b606060006111bd836020613c0b565b67ffffffffffffffff8111156111d5576111d56132fa565b6040519080825280601f01601f1916602001820160405280156111ff576020820181803683370190505b50905060005b8381101561122c57848101546020808302840101528061122481613b49565b915050611205565b509392505050565b61123c6129a5565b73ffffffffffffffffffffffffffffffffffffffff811615801590611278575073ffffffffffffffffffffffffffffffffffffffff8116600114155b6112de576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303100000000000000000000000000000000000000000000000000000060448201526064016107d8565b73ffffffffffffffffffffffffffffffffffffffff818116600090815260016020526040902054161561136d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303200000000000000000000000000000000000000000000000000000060448201526064016107d8565b600160208181527fcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f805473ffffffffffffffffffffffffffffffffffffffff858116600081815260408082208054949095167fffffffffffffffffffffffff000000000000000000000000000000000000000094851617909455959095528254168417909155519182527fecdf3a3effea5783a3c4c2140e677577666428d44ed9d474a0b3a4c9943f844091015b60405180910390a150565b61142e6129a5565b60035481111561149a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303100000000000000000000000000000000000000000000000000000060448201526064016107d8565b6001811015611505576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303200000000000000000000000000000000000000000000000000000060448201526064016107d8565b60048190556040518181527f610f7ff2b304ae8903c3de74c60c6ab1f7d6226b3f52c5161905bb5ad4039c939060200161141b565b60008060006115548e8e8e8e8e8e8e8e8e8e600554612504565b60058054919250600061156683613b49565b909155505080516020820120915061157f828286611934565b5060006115aa7f4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c85490565b905073ffffffffffffffffffffffffffffffffffffffff81161561164a578073ffffffffffffffffffffffffffffffffffffffff166375f0bb528f8f8f8f8f8f8f8f8f8f8f336040518d63ffffffff1660e01b81526004016116179c9b9a99989796959493929190613cb2565b600060405180830381600087803b15801561163157600080fd5b505af1158015611645573d6000803e3d6000fd5b505050505b6116766116598a6109c4613dc8565b603f6116668c6040613c0b565b6116709190613de0565b90612aaf565b611682906101f4613dc8565b5a10156116eb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330313000000000000000000000000000000000000000000000000000000060448201526064016107d8565b60005a905061175c8f8f8f8f8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508e8c600014611749578e612a68565b6109c45a6117579190613e1b565b612a68565b93506117695a8290612ac6565b9050838061177657508915155b8061178057508715155b6117e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330313300000000000000000000000000000000000000000000000000000060448201526064016107d8565b600088156117fe576117fb828b8b8b8b612ae1565b90505b84156118425760408051858152602081018390527f442e715f626346e8c54381002da614f62bee8d27386535b2521ec8540898556e910160405180910390a161187c565b60408051858152602081018390527f23428b18acfb3ea64b08dc0c1d296ea9c09702c09083ca5272e64d115b687d23910160405180910390a15b505073ffffffffffffffffffffffffffffffffffffffff811615611923576040517f9327136800000000000000000000000000000000000000000000000000000000815260048101839052831515602482015273ffffffffffffffffffffffffffffffffffffffff821690639327136890604401600060405180830381600087803b15801561190a57600080fd5b505af115801561191e573d6000803e3d6000fd5b505050505b50509b9a5050505050505050505050565b6004548061199e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330303100000000000000000000000000000000000000000000000000000060448201526064016107d8565b6119aa84848484610966565b50505050565b6060600060035467ffffffffffffffff8111156119cf576119cf6132fa565b6040519080825280602002602001820160405280156119f8578160200160208202803683370190505b506001600090815260026020527fe90b7bceb6e7df5418fb78d8ee546e97c83a08bbccc01a0644d599ccd2a7c2e0549192509073ffffffffffffffffffffffffffffffffffffffff165b73ffffffffffffffffffffffffffffffffffffffff8116600114611ac05780838381518110611a7357611a73613e32565b73ffffffffffffffffffffffffffffffffffffffff928316602091820292909201810191909152918116600090815260029092526040909120541681611ab881613b49565b925050611a42565b509092915050565b600080825160208401855af480600052503d6020523d600060403e60403d016000fd5b611b298a8a808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508c9250612c72915050565b73ffffffffffffffffffffffffffffffffffffffff841615611b6d57611b6d847f6c9a6c4a39284e37ed1cf53d337577d14212a4870fb976a4366c693b939918d555565b611bad8787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061303f92505050565b8115611bc457611bc282600060018685612ae1565b505b3373ffffffffffffffffffffffffffffffffffffffff167f141df868a6331af528e38c83b7aa03edc19be66e37ae67f9285bf4f8e3c6a1a88b8b8b8b89604051611c12959493929190613e61565b60405180910390a250505050505050505050565b6000805a9050611c6f878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525089925050505a612a68565b611c7857600080fd5b60005a611c859083613e1b565b905080604051602001611c9a91815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290527f08c379a00000000000000000000000000000000000000000000000000000000082526107d891600401613587565b606060008267ffffffffffffffff811115611d1557611d156132fa565b604051908082528060200260200182016040528015611d3e578160200160208202803683370190505b5073ffffffffffffffffffffffffffffffffffffffff80861660009081526001602052604081205492945091165b73ffffffffffffffffffffffffffffffffffffffff811615801590611da8575073ffffffffffffffffffffffffffffffffffffffff8116600114155b8015611db357508482105b15611e185780848381518110611dcb57611dcb613e32565b73ffffffffffffffffffffffffffffffffffffffff928316602091820292909201810191909152918116600090815260019092526040909120541681611e1081613b49565b925050611d6c565b908352919491935090915050565b3360009081526002602052604090205473ffffffffffffffffffffffffffffffffffffffff16611eb2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330333000000000000000000000000000000000000000000000000000000060448201526064016107d8565b336000818152600860209081526040808320858452909152808220600190555183917ff2a0eb156472d1440255b0d7c1e19cc07115d1051fe605b0dce69acfec884d9c91a350565b6000611f0f8c8c8c8c8c8c8c8c8c8c8c612504565b8051906020012090509b9a5050505050505050505050565b611f2f6129a5565b73ffffffffffffffffffffffffffffffffffffffff811615801590611f6b575073ffffffffffffffffffffffffffffffffffffffff8116600114155b611fd1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303100000000000000000000000000000000000000000000000000000060448201526064016107d8565b73ffffffffffffffffffffffffffffffffffffffff828116600090815260016020526040902054811690821614612064576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303300000000000000000000000000000000000000000000000000000060448201526064016107d8565b73ffffffffffffffffffffffffffffffffffffffff8181166000818152600160209081526040808320805488871685528285208054919097167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790965592849052825490941690915591519081527faab4fa2b463f581b2b32cb3b7e3b704b9ce37cc209b5fb4d77e593ace405427691015b60405180910390a15050565b61210e6129a5565b7f4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c881815560405173ffffffffffffffffffffffffffffffffffffffff831681527f1151116914515bc0891ff9047a6cb32cf902546f83066499bcf8ba33d2353fa2906020016120fa565b6121806129a5565b73ffffffffffffffffffffffffffffffffffffffff8116158015906121bc575073ffffffffffffffffffffffffffffffffffffffff8116600114155b80156121de575073ffffffffffffffffffffffffffffffffffffffff81163014155b612244576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303300000000000000000000000000000000000000000000000000000060448201526064016107d8565b73ffffffffffffffffffffffffffffffffffffffff81811660009081526002602052604090205416156122d3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303400000000000000000000000000000000000000000000000000000060448201526064016107d8565b73ffffffffffffffffffffffffffffffffffffffff82161580159061230f575073ffffffffffffffffffffffffffffffffffffffff8216600114155b612375576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303300000000000000000000000000000000000000000000000000000060448201526064016107d8565b73ffffffffffffffffffffffffffffffffffffffff838116600090815260026020526040902054811690831614612408576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303500000000000000000000000000000000000000000000000000000060448201526064016107d8565b73ffffffffffffffffffffffffffffffffffffffff8281166000818152600260209081526040808320805487871680865283862080549289167fffffffffffffffffffffffff0000000000000000000000000000000000000000938416179055968a1685528285208054821690971790965592849052825490941690915591519081527ff8d49fc529812e9a7c5c50e69c20f0dccc0db8fa95c98bc58cc9a4f1c1299eaf910160405180910390a160405173ffffffffffffffffffffffffffffffffffffffff821681527f9465fa0c962cc76958e6373a993326400c1c94f8be2fe3a952adfa7f60b2ea269060200160405180910390a1505050565b606060007fbb8310d486368db6bd6f849402fdd73ad53d316b5a4b2644ad6efe0f941286d860001b8d8d8d8d60405161253e929190613ee7565b604051908190038120612564949392918e908e908e908e908e908e908e90602001613ef7565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052805160209091012090507f19000000000000000000000000000000000000000000000000000000000000007f010000000000000000000000000000000000000000000000000000000000000061263860007f47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a794692184660408051602081019390935282015230606082015260800160405160208183030381529060405280519060200120905090565b6040517fff0000000000000000000000000000000000000000000000000000000000000093841660208201529290911660218301526022820152604281018290526062016040516020818303038152906040529150509b9a5050505050505050505050565b6126a56129a5565b6126cd817f6c9a6c4a39284e37ed1cf53d337577d14212a4870fb976a4366c693b939918d555565b60405173ffffffffffffffffffffffffffffffffffffffff821681527f5ac6c46c93c8d0e53714ba3b53db3e7c046da994313d7ed0d192028bc7c228b09060200161141b565b61271b6129a5565b80600160035461272b9190613e1b565b1015612793576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303100000000000000000000000000000000000000000000000000000060448201526064016107d8565b73ffffffffffffffffffffffffffffffffffffffff8216158015906127cf575073ffffffffffffffffffffffffffffffffffffffff8216600114155b612835576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303300000000000000000000000000000000000000000000000000000060448201526064016107d8565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600260205260409020548116908316146128c8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303500000000000000000000000000000000000000000000000000000060448201526064016107d8565b73ffffffffffffffffffffffffffffffffffffffff828116600081815260026020526040808220805488861684529183208054929095167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179094559181528254909116909155600380549161294083613f74565b909155505060405173ffffffffffffffffffffffffffffffffffffffff831681527ff8d49fc529812e9a7c5c50e69c20f0dccc0db8fa95c98bc58cc9a4f1c1299eaf9060200160405180910390a180600454146129a0576129a081611426565b505050565b333014612a0e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330333100000000000000000000000000000000000000000000000000000060448201526064016107d8565b565b600082600003612a225750600061100a565b6000612a2e8385613c0b565b905082612a3b8583613de0565b14612a4557600080fd5b9392505050565b600080612a598385613dc8565b905083811015612a4557600080fd5b60006001836001811115612a7e57612a7e613c48565b03612a96576000808551602087018986f49050612aa6565b600080855160208701888a87f190505b95945050505050565b600081831015612abf5781612a45565b5090919050565b600082821115612ad557600080fd5b60006111708385613e1b565b60008073ffffffffffffffffffffffffffffffffffffffff831615612b065782612b08565b325b905073ffffffffffffffffffffffffffffffffffffffff8416612be757612b473a8610612b35573a612b37565b855b612b418989612a4c565b90612a10565b60405190925073ffffffffffffffffffffffffffffffffffffffff82169083156108fc029084906000818181858888f19350505050612be2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330313100000000000000000000000000000000000000000000000000000060448201526064016107d8565b612c68565b612bf585612b418989612a4c565b9150612c028482846131cf565b612c68576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330313200000000000000000000000000000000000000000000000000000060448201526064016107d8565b5095945050505050565b60045415612cdc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303000000000000000000000000000000000000000000000000000000060448201526064016107d8565b8151811115612d47576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303100000000000000000000000000000000000000000000000000000060448201526064016107d8565b6001811015612db2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303200000000000000000000000000000000000000000000000000000060448201526064016107d8565b600160005b8351811015612fe7576000848281518110612dd457612dd4613e32565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614158015612e32575073ffffffffffffffffffffffffffffffffffffffff8116600114155b8015612e54575073ffffffffffffffffffffffffffffffffffffffff81163014155b8015612e8c57508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614155b612ef2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303300000000000000000000000000000000000000000000000000000060448201526064016107d8565b73ffffffffffffffffffffffffffffffffffffffff8181166000908152600260205260409020541615612f81576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475332303400000000000000000000000000000000000000000000000000000060448201526064016107d8565b73ffffffffffffffffffffffffffffffffffffffff928316600090815260026020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169382169390931790925580612fdf81613b49565b915050612db7565b5073ffffffffffffffffffffffffffffffffffffffff16600090815260026020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790559051600355600455565b600160008190526020527fcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f5473ffffffffffffffffffffffffffffffffffffffff16156130e8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475331303000000000000000000000000000000000000000000000000000000060448201526064016107d8565b6001600081905260208190527fcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f80547fffffffffffffffffffffffff000000000000000000000000000000000000000016909117905573ffffffffffffffffffffffffffffffffffffffff821615610962576131698260008360015a612a68565b610962576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600560248201527f475330303000000000000000000000000000000000000000000000000000000060448201526064016107d8565b6040805173ffffffffffffffffffffffffffffffffffffffff841660248201526044808201849052825180830390910181526064909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001781528251600093929184919082896127105a03f13d801561327c5760208114613284576000935061328f565b81935061328f565b600051158215171593505b5050509392505050565b73ffffffffffffffffffffffffffffffffffffffff811681146132bb57600080fd5b50565b80356132c981613299565b919050565b600080604083850312156132e157600080fd5b82356132ec81613299565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261333a57600080fd5b813567ffffffffffffffff80821115613355576133556132fa565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561339b5761339b6132fa565b816040528381528660208588010111156133b457600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600080608085870312156133ea57600080fd5b84359350602085013567ffffffffffffffff8082111561340957600080fd5b61341588838901613329565b9450604087013591508082111561342b57600080fd5b5061343887828801613329565b949793965093946060013593505050565b60006020828403121561345b57600080fd5b8135612a4581613299565b8035600281106132c957600080fd5b6000806000806080858703121561348b57600080fd5b843561349681613299565b935060208501359250604085013567ffffffffffffffff8111156134b957600080fd5b6134c587828801613329565b9250506134d460608601613466565b905092959194509250565b6000815180845260005b81811015613505576020818501810151868301820152016134e9565b81811115613517576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b821515815260406020820152600061117060408301846134df565b6000806040838503121561357857600080fd5b50508035926020909101359150565b602081526000612a4560208301846134df565b6000602082840312156135ac57600080fd5b5035919050565b60008083601f8401126135c557600080fd5b50813567ffffffffffffffff8111156135dd57600080fd5b6020830191508360208285010111156135f557600080fd5b9250929050565b60008060008060008060008060008060006101408c8e03121561361e57600080fd5b6136278c6132be565b9a5060208c0135995067ffffffffffffffff8060408e0135111561364a57600080fd5b61365a8e60408f01358f016135b3565b909a50985061366b60608e01613466565b975060808d0135965060a08d0135955060c08d0135945061368e60e08e016132be565b935061369d6101008e016132be565b9250806101208e013511156136b157600080fd5b506136c38d6101208e01358e01613329565b90509295989b509295989b9093969950565b6000806000606084860312156136ea57600080fd5b83359250602084013567ffffffffffffffff8082111561370957600080fd5b61371587838801613329565b9350604086013591508082111561372b57600080fd5b5061373886828701613329565b9150509250925092565b600081518084526020808501945080840160005b8381101561378857815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101613756565b509495945050505050565b602081526000612a456020830184613742565b600080604083850312156137b957600080fd5b82356137c481613299565b9150602083013567ffffffffffffffff8111156137e057600080fd5b6137ec85828601613329565b9150509250929050565b6000806000806000806000806000806101008b8d03121561381657600080fd5b8a3567ffffffffffffffff8082111561382e57600080fd5b818d0191508d601f83011261384257600080fd5b81358181111561385157600080fd5b8e60208260051b850101111561386657600080fd5b60208381019d50909b508d0135995061388160408e016132be565b985060608d013591508082111561389757600080fd5b506138a48d828e016135b3565b90975095506138b7905060808c016132be565b93506138c560a08c016132be565b925060c08b013591506138da60e08c016132be565b90509295989b9194979a5092959850565b60008060008060006080868803121561390357600080fd5b853561390e81613299565b945060208601359350604086013567ffffffffffffffff81111561393157600080fd5b61393d888289016135b3565b9094509250613950905060608701613466565b90509295509295909350565b60408152600061396f6040830185613742565b905073ffffffffffffffffffffffffffffffffffffffff831660208301529392505050565b60008060008060008060008060008060006101408c8e0312156139b657600080fd5b8b356139c181613299565b9a5060208c0135995060408c013567ffffffffffffffff8111156139e457600080fd5b6139f08e828f016135b3565b909a509850613a03905060608d01613466565b965060808c0135955060a08c0135945060c08c0135935060e08c0135613a2881613299565b92506101008c0135613a3981613299565b809250506101208c013590509295989b509295989b9093969950565b60008060408385031215613a6857600080fd5b8235613a7381613299565b91506020830135613a8381613299565b809150509250929050565b600080600060608486031215613aa357600080fd5b8335613aae81613299565b92506020840135613abe81613299565b91506040840135613ace81613299565b809150509250925092565b600080600060608486031215613aee57600080fd5b8335613af981613299565b92506020840135613b0981613299565b929592945050506040919091013590565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613b7a57613b7a613b1a565b5060010190565b604081526000613b9460408301856134df565b8281036020840152612aa681856134df565b600060208284031215613bb857600080fd5b81517fffffffff0000000000000000000000000000000000000000000000000000000081168114612a4557600080fd5b600060ff821660ff841680821015613c0257613c02613b1a565b90039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613c4357613c43613b1a565b500290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60028110613cae577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b600061016073ffffffffffffffffffffffffffffffffffffffff8f1683528d60208401528060408401528b81840152506101808b8d828501376000818d850101527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8d01168301613d28606085018d613c77565b8a60808501528960a08501528860c0850152613d5c60e085018973ffffffffffffffffffffffffffffffffffffffff169052565b73ffffffffffffffffffffffffffffffffffffffff87166101008501528184820301610120850152613d90828201876134df565b92505050613db761014083018473ffffffffffffffffffffffffffffffffffffffff169052565b9d9c50505050505050505050505050565b60008219821115613ddb57613ddb613b1a565b500190565b600082613e16577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b600082821015613e2d57613e2d613b1a565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6080808252810185905260008660a08301825b88811015613eb1578235613e8781613299565b73ffffffffffffffffffffffffffffffffffffffff16825260209283019290910190600101613e74565b506020840196909652505073ffffffffffffffffffffffffffffffffffffffff9283166040820152911660609091015292915050565b8183823760009101908152919050565b6000610160820190508c825273ffffffffffffffffffffffffffffffffffffffff808d1660208401528b60408401528a6060840152613f39608084018b613c77565b60a083019890985260c082019690965260e0810194909452918516610100840152909316610120820152610140019190915295945050505050565b600081613f8357613f83613b1a565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019056fea164736f6c634300080f000a", - "initialized": true, - "kind": "Create", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3", - "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": "0xA8452Ec99ce0C64f20701dB7dD3abDb607c00496", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x1688f0b9000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3000000000000000000000000000000000000000000000000000000000000006047555c7c5eb40250af82c9713b290d445cad0893c01b18ae084f70d0b7b0d67d0000000000000000000000000000000000000000000000000000000000000164b63e800d0000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [], - "value": 0 - }, - { - "accessor": "0xA8452Ec99ce0C64f20701dB7dD3abDb607c00496", - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x608060405234801561001057600080fd5b5060405161016f38038061016f83398101604081905261002f916100b9565b6001600160a01b0381166100945760405162461bcd60e51b815260206004820152602260248201527f496e76616c69642073696e676c65746f6e20616464726573732070726f766964604482015261195960f21b606482015260840160405180910390fd5b600080546001600160a01b0319166001600160a01b03929092169190911790556100e9565b6000602082840312156100cb57600080fd5b81516001600160a01b03811681146100e257600080fd5b9392505050565b6078806100f76000396000f3fe6080604052600073ffffffffffffffffffffffffffffffffffffffff8154167fa619486e00000000000000000000000000000000000000000000000000000000823503604d57808252602082f35b3682833781823684845af490503d82833e806066573d82fd5b503d81f3fea164736f6c634300080f000a000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", - "deployedCode": "0x6080604052600073ffffffffffffffffffffffffffffffffffffffff8154167fa619486e00000000000000000000000000000000000000000000000000000000823503604d57808252602082f35b3682833781823684845af490503d82833e806066573d82fd5b503d81f3fea164736f6c634300080f000a", - "initialized": true, - "kind": "Create", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": true, - "newValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - ], - "value": 0 - }, - { - "accessor": "0xA8452Ec99ce0C64f20701dB7dD3abDb607c00496", - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xb63e800d0000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f380000000000000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", - "previousValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - ], - "value": 0 - }, - { - "accessor": "0xA8452Ec99ce0C64f20701dB7dD3abDb607c00496", - "account": "0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xb63e800d0000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f380000000000000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0xd1b0d319c6526317dce66989b393dcfb4435c9a65e399a088b63bbf65d7aee32" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0xe90b7bceb6e7df5418fb78d8ee546e97c83a08bbccc01a0644d599ccd2a7c2e0" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": true, - "newValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0xe90b7bceb6e7df5418fb78d8ee546e97c83a08bbccc01a0644d599ccd2a7c2e0" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0xd1b0d319c6526317dce66989b393dcfb4435c9a65e399a088b63bbf65d7aee32" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0xd1b0d319c6526317dce66989b393dcfb4435c9a65e399a088b63bbf65d7aee32" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000003" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0xcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0xcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "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": "0x50EEf481cae4250d252Ae577A09bF514f224C6C4", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x608060405234801561001057600080fd5b5061001a3361001f565b61006f565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6105ef8061007e6000396000f3fe608060405234801561001057600080fd5b50600436106100675760003560e01c80639b2ea4bd116100505780639b2ea4bd146100b9578063bf40fac1146100cc578063f2fde38b146100df57600080fd5b8063715018a61461006c5780638da5cb5b14610076575b600080fd5b6100746100f2565b005b60005473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b6100746100c73660046104fa565b610106565b6100906100da366004610548565b6101d9565b6100746100ed366004610585565b610215565b6100fa6102d1565b6101046000610352565b565b61010e6102d1565b6000610119836103c7565b60008181526001602052604090819020805473ffffffffffffffffffffffffffffffffffffffff8681167fffffffffffffffffffffffff00000000000000000000000000000000000000008316179092559151929350169061017c9085906105a7565b6040805191829003822073ffffffffffffffffffffffffffffffffffffffff808716845284166020840152917f9416a153a346f93d95f94b064ae3f148b6460473c6e82b3f9fc2521b873fcd6c910160405180910390a250505050565b6000600160006101e8846103c7565b815260208101919091526040016000205473ffffffffffffffffffffffffffffffffffffffff1692915050565b61021d6102d1565b73ffffffffffffffffffffffffffffffffffffffff81166102c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6102ce81610352565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314610104576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016102bc565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000816040516020016103da91906105a7565b604051602081830303815290604052805190602001209050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261043757600080fd5b813567ffffffffffffffff80821115610452576104526103f7565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715610498576104986103f7565b816040528381528660208588010111156104b157600080fd5b836020870160208301376000602085830101528094505050505092915050565b803573ffffffffffffffffffffffffffffffffffffffff811681146104f557600080fd5b919050565b6000806040838503121561050d57600080fd5b823567ffffffffffffffff81111561052457600080fd5b61053085828601610426565b92505061053f602084016104d1565b90509250929050565b60006020828403121561055a57600080fd5b813567ffffffffffffffff81111561057157600080fd5b61057d84828501610426565b949350505050565b60006020828403121561059757600080fd5b6105a0826104d1565b9392505050565b6000825160005b818110156105c857602081860181015185830152016105ae565b818111156105d7576000828501525b50919091019291505056fea164736f6c634300080f000a", - "deployedCode": "0x608060405234801561001057600080fd5b50600436106100675760003560e01c80639b2ea4bd116100505780639b2ea4bd146100b9578063bf40fac1146100cc578063f2fde38b146100df57600080fd5b8063715018a61461006c5780638da5cb5b14610076575b600080fd5b6100746100f2565b005b60005473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b6100746100c73660046104fa565b610106565b6100906100da366004610548565b6101d9565b6100746100ed366004610585565b610215565b6100fa6102d1565b6101046000610352565b565b61010e6102d1565b6000610119836103c7565b60008181526001602052604090819020805473ffffffffffffffffffffffffffffffffffffffff8681167fffffffffffffffffffffffff00000000000000000000000000000000000000008316179092559151929350169061017c9085906105a7565b6040805191829003822073ffffffffffffffffffffffffffffffffffffffff808716845284166020840152917f9416a153a346f93d95f94b064ae3f148b6460473c6e82b3f9fc2521b873fcd6c910160405180910390a250505050565b6000600160006101e8846103c7565b815260208101919091526040016000205473ffffffffffffffffffffffffffffffffffffffff1692915050565b61021d6102d1565b73ffffffffffffffffffffffffffffffffffffffff81166102c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6102ce81610352565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314610104576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016102bc565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000816040516020016103da91906105a7565b604051602081830303815290604052805190602001209050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261043757600080fd5b813567ffffffffffffffff80821115610452576104526103f7565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715610498576104986103f7565b816040528381528660208588010111156104b157600080fd5b836020870160208301376000602085830101528094505050505092915050565b803573ffffffffffffffffffffffffffffffffffffffff811681146104f557600080fd5b919050565b6000806040838503121561050d57600080fd5b823567ffffffffffffffff81111561052457600080fd5b61053085828601610426565b92505061053f602084016104d1565b90509250929050565b60006020828403121561055a57600080fd5b813567ffffffffffffffff81111561057157600080fd5b61057d84828501610426565b949350505050565b60006020828403121561059757600080fd5b6105a0826104d1565b9392505050565b6000825160005b818110156105c857602081860181015185830152016105ae565b818111156105d7576000828501525b50919091019291505056fea164736f6c634300080f000a", - "initialized": true, - "kind": "Create", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x50EEf481cae4250d252Ae577A09bF514f224C6C4", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x50EEf481cae4250d252Ae577A09bF514f224C6C4", - "isWrite": true, - "newValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x50EEf481cae4250d252Ae577A09bF514f224C6C4", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x8da5cb5b", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x50EEf481cae4250d252Ae577A09bF514f224C6C4", - "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": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x60806040523480156200001157600080fd5b5060405162001a5f38038062001a5f8339810160408190526200003491620000a1565b6200003f3362000051565b6200004a8162000051565b50620000d3565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600060208284031215620000b457600080fd5b81516001600160a01b0381168114620000cc57600080fd5b9392505050565b61197c80620000e36000396000f3fe60806040526004361061010e5760003560e01c8063860f7cda116100a557806399a88ec411610074578063b794726211610059578063b794726214610329578063f2fde38b14610364578063f3b7dead1461038457600080fd5b806399a88ec4146102e95780639b2ea4bd1461030957600080fd5b8063860f7cda1461026b5780638d52d4a01461028b5780638da5cb5b146102ab5780639623609d146102d657600080fd5b80633ab76e9f116100e15780633ab76e9f146101cc5780636bd9f516146101f9578063715018a6146102365780637eff275e1461024b57600080fd5b80630652b57a1461011357806307c8f7b014610135578063204e1c7a14610155578063238181ae1461019f575b600080fd5b34801561011f57600080fd5b5061013361012e3660046111f9565b6103a4565b005b34801561014157600080fd5b50610133610150366004611216565b6103f3565b34801561016157600080fd5b506101756101703660046111f9565b610445565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156101ab57600080fd5b506101bf6101ba3660046111f9565b61066b565b60405161019691906112ae565b3480156101d857600080fd5b506003546101759073ffffffffffffffffffffffffffffffffffffffff1681565b34801561020557600080fd5b506102296102143660046111f9565b60016020526000908152604090205460ff1681565b60405161019691906112f0565b34801561024257600080fd5b50610133610705565b34801561025757600080fd5b50610133610266366004611331565b610719565b34801561027757600080fd5b5061013361028636600461148c565b6108cc565b34801561029757600080fd5b506101336102a63660046114dc565b610903565b3480156102b757600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16610175565b6101336102e436600461150e565b610977565b3480156102f557600080fd5b50610133610304366004611331565b610b8e565b34801561031557600080fd5b50610133610324366004611584565b610e1e565b34801561033557600080fd5b5060035474010000000000000000000000000000000000000000900460ff166040519015158152602001610196565b34801561037057600080fd5b5061013361037f3660046111f9565b610eb4565b34801561039057600080fd5b5061017561039f3660046111f9565b610f6b565b6103ac6110e1565b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6103fb6110e1565b6003805491151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff909216919091179055565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602052604081205460ff1681816002811115610481576104816112c1565b036104fc578273ffffffffffffffffffffffffffffffffffffffff16635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104f591906115cb565b9392505050565b6001816002811115610510576105106112c1565b03610560578273ffffffffffffffffffffffffffffffffffffffff1663aaf10f426040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b6002816002811115610574576105746112c1565b036105fe5760035473ffffffffffffffffffffffffffffffffffffffff8481166000908152600260205260409081902090517fbf40fac1000000000000000000000000000000000000000000000000000000008152919092169163bf40fac1916105e19190600401611635565b602060405180830381865afa1580156104d1573d6000803e3d6000fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f50726f787941646d696e3a20756e6b6e6f776e2070726f78792074797065000060448201526064015b60405180910390fd5b50919050565b60026020526000908152604090208054610684906115e8565b80601f01602080910402602001604051908101604052809291908181526020018280546106b0906115e8565b80156106fd5780601f106106d2576101008083540402835291602001916106fd565b820191906000526020600020905b8154815290600101906020018083116106e057829003601f168201915b505050505081565b61070d6110e1565b6107176000611162565b565b6107216110e1565b73ffffffffffffffffffffffffffffffffffffffff821660009081526001602052604081205460ff169081600281111561075d5761075d6112c1565b036107e9576040517f8f28397000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152841690638f283970906024015b600060405180830381600087803b1580156107cc57600080fd5b505af11580156107e0573d6000803e3d6000fd5b50505050505050565b60018160028111156107fd576107fd6112c1565b03610856576040517f13af403500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906313af4035906024016107b2565b600281600281111561086a5761086a6112c1565b036105fe576003546040517ff2fde38b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301529091169063f2fde38b906024016107b2565b505050565b6108d46110e1565b73ffffffffffffffffffffffffffffffffffffffff821660009081526002602052604090206108c78282611724565b61090b6110e1565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600160208190526040909120805483927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009091169083600281111561096e5761096e6112c1565b02179055505050565b61097f6110e1565b73ffffffffffffffffffffffffffffffffffffffff831660009081526001602052604081205460ff16908160028111156109bb576109bb6112c1565b03610a81576040517f4f1ef28600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851690634f1ef286903490610a16908790879060040161183e565b60006040518083038185885af1158015610a34573d6000803e3d6000fd5b50505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610a7b9190810190611875565b50610b88565b610a8b8484610b8e565b60008473ffffffffffffffffffffffffffffffffffffffff163484604051610ab391906118ec565b60006040518083038185875af1925050503d8060008114610af0576040519150601f19603f3d011682016040523d82523d6000602084013e610af5565b606091505b5050905080610b86576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f50726f787941646d696e3a2063616c6c20746f2070726f78792061667465722060448201527f75706772616465206661696c6564000000000000000000000000000000000000606482015260840161065c565b505b50505050565b610b966110e1565b73ffffffffffffffffffffffffffffffffffffffff821660009081526001602052604081205460ff1690816002811115610bd257610bd26112c1565b03610c2b576040517f3659cfe600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152841690633659cfe6906024016107b2565b6001816002811115610c3f57610c3f6112c1565b03610cbe576040517f9b0b0fda0000000000000000000000000000000000000000000000000000000081527f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc600482015273ffffffffffffffffffffffffffffffffffffffff8381166024830152841690639b0b0fda906044016107b2565b6002816002811115610cd257610cd26112c1565b03610e165773ffffffffffffffffffffffffffffffffffffffff831660009081526002602052604081208054610d07906115e8565b80601f0160208091040260200160405190810160405280929190818152602001828054610d33906115e8565b8015610d805780601f10610d5557610100808354040283529160200191610d80565b820191906000526020600020905b815481529060010190602001808311610d6357829003601f168201915b50506003546040517f9b2ea4bd00000000000000000000000000000000000000000000000000000000815294955073ffffffffffffffffffffffffffffffffffffffff1693639b2ea4bd9350610dde92508591508790600401611908565b600060405180830381600087803b158015610df857600080fd5b505af1158015610e0c573d6000803e3d6000fd5b5050505050505050565b6108c7611940565b610e266110e1565b6003546040517f9b2ea4bd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911690639b2ea4bd90610e7e9085908590600401611908565b600060405180830381600087803b158015610e9857600080fd5b505af1158015610eac573d6000803e3d6000fd5b505050505050565b610ebc6110e1565b73ffffffffffffffffffffffffffffffffffffffff8116610f5f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161065c565b610f6881611162565b50565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602052604081205460ff1681816002811115610fa757610fa76112c1565b03610ff7578273ffffffffffffffffffffffffffffffffffffffff1663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b600181600281111561100b5761100b6112c1565b0361105b578273ffffffffffffffffffffffffffffffffffffffff1663893d20e86040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b600281600281111561106f5761106f6112c1565b036105fe57600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b60005473ffffffffffffffffffffffffffffffffffffffff163314610717576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161065c565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b73ffffffffffffffffffffffffffffffffffffffff81168114610f6857600080fd5b60006020828403121561120b57600080fd5b81356104f5816111d7565b60006020828403121561122857600080fd5b813580151581146104f557600080fd5b60005b8381101561125357818101518382015260200161123b565b83811115610b885750506000910152565b6000815180845261127c816020860160208601611238565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006104f56020830184611264565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b602081016003831061132b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b6000806040838503121561134457600080fd5b823561134f816111d7565b9150602083013561135f816111d7565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156113e0576113e061136a565b604052919050565b600067ffffffffffffffff8211156114025761140261136a565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600061144161143c846113e8565b611399565b905082815283838301111561145557600080fd5b828260208301376000602084830101529392505050565b600082601f83011261147d57600080fd5b6104f58383356020850161142e565b6000806040838503121561149f57600080fd5b82356114aa816111d7565b9150602083013567ffffffffffffffff8111156114c657600080fd5b6114d28582860161146c565b9150509250929050565b600080604083850312156114ef57600080fd5b82356114fa816111d7565b915060208301356003811061135f57600080fd5b60008060006060848603121561152357600080fd5b833561152e816111d7565b9250602084013561153e816111d7565b9150604084013567ffffffffffffffff81111561155a57600080fd5b8401601f8101861361156b57600080fd5b61157a8682356020840161142e565b9150509250925092565b6000806040838503121561159757600080fd5b823567ffffffffffffffff8111156115ae57600080fd5b6115ba8582860161146c565b925050602083013561135f816111d7565b6000602082840312156115dd57600080fd5b81516104f5816111d7565b600181811c908216806115fc57607f821691505b602082108103610665577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000602080835260008454611649816115e8565b8084870152604060018084166000811461166a57600181146116a2576116d0565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838a01528284151560051b8a010195506116d0565b896000528660002060005b858110156116c85781548b82018601529083019088016116ad565b8a0184019650505b509398975050505050505050565b601f8211156108c757600081815260208120601f850160051c810160208610156117055750805b601f850160051c820191505b81811015610eac57828155600101611711565b815167ffffffffffffffff81111561173e5761173e61136a565b6117528161174c84546115e8565b846116de565b602080601f8311600181146117a5576000841561176f5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610eac565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156117f2578886015182559484019460019091019084016117d3565b508582101561182e57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b73ffffffffffffffffffffffffffffffffffffffff8316815260406020820152600061186d6040830184611264565b949350505050565b60006020828403121561188757600080fd5b815167ffffffffffffffff81111561189e57600080fd5b8201601f810184136118af57600080fd5b80516118bd61143c826113e8565b8181528560208385010111156118d257600080fd5b6118e3826020830160208601611238565b95945050505050565b600082516118fe818460208701611238565b9190910192915050565b60408152600061191b6040830185611264565b905073ffffffffffffffffffffffffffffffffffffffff831660208301529392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fdfea164736f6c634300080f000a0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", - "deployedCode": "0x60806040526004361061010e5760003560e01c8063860f7cda116100a557806399a88ec411610074578063b794726211610059578063b794726214610329578063f2fde38b14610364578063f3b7dead1461038457600080fd5b806399a88ec4146102e95780639b2ea4bd1461030957600080fd5b8063860f7cda1461026b5780638d52d4a01461028b5780638da5cb5b146102ab5780639623609d146102d657600080fd5b80633ab76e9f116100e15780633ab76e9f146101cc5780636bd9f516146101f9578063715018a6146102365780637eff275e1461024b57600080fd5b80630652b57a1461011357806307c8f7b014610135578063204e1c7a14610155578063238181ae1461019f575b600080fd5b34801561011f57600080fd5b5061013361012e3660046111f9565b6103a4565b005b34801561014157600080fd5b50610133610150366004611216565b6103f3565b34801561016157600080fd5b506101756101703660046111f9565b610445565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156101ab57600080fd5b506101bf6101ba3660046111f9565b61066b565b60405161019691906112ae565b3480156101d857600080fd5b506003546101759073ffffffffffffffffffffffffffffffffffffffff1681565b34801561020557600080fd5b506102296102143660046111f9565b60016020526000908152604090205460ff1681565b60405161019691906112f0565b34801561024257600080fd5b50610133610705565b34801561025757600080fd5b50610133610266366004611331565b610719565b34801561027757600080fd5b5061013361028636600461148c565b6108cc565b34801561029757600080fd5b506101336102a63660046114dc565b610903565b3480156102b757600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16610175565b6101336102e436600461150e565b610977565b3480156102f557600080fd5b50610133610304366004611331565b610b8e565b34801561031557600080fd5b50610133610324366004611584565b610e1e565b34801561033557600080fd5b5060035474010000000000000000000000000000000000000000900460ff166040519015158152602001610196565b34801561037057600080fd5b5061013361037f3660046111f9565b610eb4565b34801561039057600080fd5b5061017561039f3660046111f9565b610f6b565b6103ac6110e1565b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6103fb6110e1565b6003805491151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff909216919091179055565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602052604081205460ff1681816002811115610481576104816112c1565b036104fc578273ffffffffffffffffffffffffffffffffffffffff16635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104f591906115cb565b9392505050565b6001816002811115610510576105106112c1565b03610560578273ffffffffffffffffffffffffffffffffffffffff1663aaf10f426040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b6002816002811115610574576105746112c1565b036105fe5760035473ffffffffffffffffffffffffffffffffffffffff8481166000908152600260205260409081902090517fbf40fac1000000000000000000000000000000000000000000000000000000008152919092169163bf40fac1916105e19190600401611635565b602060405180830381865afa1580156104d1573d6000803e3d6000fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f50726f787941646d696e3a20756e6b6e6f776e2070726f78792074797065000060448201526064015b60405180910390fd5b50919050565b60026020526000908152604090208054610684906115e8565b80601f01602080910402602001604051908101604052809291908181526020018280546106b0906115e8565b80156106fd5780601f106106d2576101008083540402835291602001916106fd565b820191906000526020600020905b8154815290600101906020018083116106e057829003601f168201915b505050505081565b61070d6110e1565b6107176000611162565b565b6107216110e1565b73ffffffffffffffffffffffffffffffffffffffff821660009081526001602052604081205460ff169081600281111561075d5761075d6112c1565b036107e9576040517f8f28397000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152841690638f283970906024015b600060405180830381600087803b1580156107cc57600080fd5b505af11580156107e0573d6000803e3d6000fd5b50505050505050565b60018160028111156107fd576107fd6112c1565b03610856576040517f13af403500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906313af4035906024016107b2565b600281600281111561086a5761086a6112c1565b036105fe576003546040517ff2fde38b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301529091169063f2fde38b906024016107b2565b505050565b6108d46110e1565b73ffffffffffffffffffffffffffffffffffffffff821660009081526002602052604090206108c78282611724565b61090b6110e1565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600160208190526040909120805483927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009091169083600281111561096e5761096e6112c1565b02179055505050565b61097f6110e1565b73ffffffffffffffffffffffffffffffffffffffff831660009081526001602052604081205460ff16908160028111156109bb576109bb6112c1565b03610a81576040517f4f1ef28600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851690634f1ef286903490610a16908790879060040161183e565b60006040518083038185885af1158015610a34573d6000803e3d6000fd5b50505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610a7b9190810190611875565b50610b88565b610a8b8484610b8e565b60008473ffffffffffffffffffffffffffffffffffffffff163484604051610ab391906118ec565b60006040518083038185875af1925050503d8060008114610af0576040519150601f19603f3d011682016040523d82523d6000602084013e610af5565b606091505b5050905080610b86576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f50726f787941646d696e3a2063616c6c20746f2070726f78792061667465722060448201527f75706772616465206661696c6564000000000000000000000000000000000000606482015260840161065c565b505b50505050565b610b966110e1565b73ffffffffffffffffffffffffffffffffffffffff821660009081526001602052604081205460ff1690816002811115610bd257610bd26112c1565b03610c2b576040517f3659cfe600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152841690633659cfe6906024016107b2565b6001816002811115610c3f57610c3f6112c1565b03610cbe576040517f9b0b0fda0000000000000000000000000000000000000000000000000000000081527f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc600482015273ffffffffffffffffffffffffffffffffffffffff8381166024830152841690639b0b0fda906044016107b2565b6002816002811115610cd257610cd26112c1565b03610e165773ffffffffffffffffffffffffffffffffffffffff831660009081526002602052604081208054610d07906115e8565b80601f0160208091040260200160405190810160405280929190818152602001828054610d33906115e8565b8015610d805780601f10610d5557610100808354040283529160200191610d80565b820191906000526020600020905b815481529060010190602001808311610d6357829003601f168201915b50506003546040517f9b2ea4bd00000000000000000000000000000000000000000000000000000000815294955073ffffffffffffffffffffffffffffffffffffffff1693639b2ea4bd9350610dde92508591508790600401611908565b600060405180830381600087803b158015610df857600080fd5b505af1158015610e0c573d6000803e3d6000fd5b5050505050505050565b6108c7611940565b610e266110e1565b6003546040517f9b2ea4bd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911690639b2ea4bd90610e7e9085908590600401611908565b600060405180830381600087803b158015610e9857600080fd5b505af1158015610eac573d6000803e3d6000fd5b505050505050565b610ebc6110e1565b73ffffffffffffffffffffffffffffffffffffffff8116610f5f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161065c565b610f6881611162565b50565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602052604081205460ff1681816002811115610fa757610fa76112c1565b03610ff7578273ffffffffffffffffffffffffffffffffffffffff1663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b600181600281111561100b5761100b6112c1565b0361105b578273ffffffffffffffffffffffffffffffffffffffff1663893d20e86040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b600281600281111561106f5761106f6112c1565b036105fe57600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b60005473ffffffffffffffffffffffffffffffffffffffff163314610717576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161065c565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b73ffffffffffffffffffffffffffffffffffffffff81168114610f6857600080fd5b60006020828403121561120b57600080fd5b81356104f5816111d7565b60006020828403121561122857600080fd5b813580151581146104f557600080fd5b60005b8381101561125357818101518382015260200161123b565b83811115610b885750506000910152565b6000815180845261127c816020860160208601611238565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006104f56020830184611264565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b602081016003831061132b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b6000806040838503121561134457600080fd5b823561134f816111d7565b9150602083013561135f816111d7565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156113e0576113e061136a565b604052919050565b600067ffffffffffffffff8211156114025761140261136a565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600061144161143c846113e8565b611399565b905082815283838301111561145557600080fd5b828260208301376000602084830101529392505050565b600082601f83011261147d57600080fd5b6104f58383356020850161142e565b6000806040838503121561149f57600080fd5b82356114aa816111d7565b9150602083013567ffffffffffffffff8111156114c657600080fd5b6114d28582860161146c565b9150509250929050565b600080604083850312156114ef57600080fd5b82356114fa816111d7565b915060208301356003811061135f57600080fd5b60008060006060848603121561152357600080fd5b833561152e816111d7565b9250602084013561153e816111d7565b9150604084013567ffffffffffffffff81111561155a57600080fd5b8401601f8101861361156b57600080fd5b61157a8682356020840161142e565b9150509250925092565b6000806040838503121561159757600080fd5b823567ffffffffffffffff8111156115ae57600080fd5b6115ba8582860161146c565b925050602083013561135f816111d7565b6000602082840312156115dd57600080fd5b81516104f5816111d7565b600181811c908216806115fc57607f821691505b602082108103610665577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000602080835260008454611649816115e8565b8084870152604060018084166000811461166a57600181146116a2576116d0565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838a01528284151560051b8a010195506116d0565b896000528660002060005b858110156116c85781548b82018601529083019088016116ad565b8a0184019650505b509398975050505050505050565b601f8211156108c757600081815260208120601f850160051c810160208610156117055750805b601f850160051c820191505b81811015610eac57828155600101611711565b815167ffffffffffffffff81111561173e5761173e61136a565b6117528161174c84546115e8565b846116de565b602080601f8311600181146117a5576000841561176f5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610eac565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156117f2578886015182559484019460019091019084016117d3565b508582101561182e57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b73ffffffffffffffffffffffffffffffffffffffff8316815260406020820152600061186d6040830184611264565b949350505050565b60006020828403121561188757600080fd5b815167ffffffffffffffff81111561189e57600080fd5b8201601f810184136118af57600080fd5b80516118bd61143c826113e8565b8181528560208385010111156118d257600080fd5b6118e3826020830160208601611238565b95945050505050565b600082516118fe818460208701611238565b9190910192915050565b60408152600061191b6040830185611264565b905073ffffffffffffffffffffffffffffffffffffffff831660208301529392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fdfea164736f6c634300080f000a", - "initialized": true, - "kind": "Create", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": true, - "newValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", - "previousValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": true, - "newValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", - "previousValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x8da5cb5b", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", - "previousValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x3ab76e9f", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000003" - } - ], - "value": 0 - }, - { - "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "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": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x0652b57a00000000000000000000000050eef481cae4250d252ae577a09bf514f224c6c4", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", - "previousValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000003" - }, - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": true, - "newValue": "0x00000000000000000000000050eef481cae4250d252ae577a09bf514f224c6c4", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000003" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x3ab76e9f", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x00000000000000000000000050eef481cae4250d252ae577a09bf514f224c6c4", - "previousValue": "0x00000000000000000000000050eef481cae4250d252ae577a09bf514f224c6c4", - "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": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x8da5cb5b", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", - "previousValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - ], - "value": 0 - }, - { - "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "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": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xf2fde38b0000000000000000000000007c0c8a15773ed7b50e7c738d1af4c5e3a2b210bd", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", - "previousValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", - "previousValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": true, - "newValue": "0x0000000000000000000000007c0c8a15773ed7b50e7c738d1af4c5e3a2b210bd", - "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": "0x4f559F30f5eB88D635FDe1548C4267DB8FaB0351", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x608060405234801561001057600080fd5b5060405161091f38038061091f83398101604081905261002f916100b5565b6100388161003e565b506100e5565b60006100566000805160206108ff8339815191525490565b6000805160206108ff833981519152838155604080516001600160a01b0380851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b6000602082840312156100c757600080fd5b81516001600160a01b03811681146100de57600080fd5b9392505050565b61080b806100f46000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610300000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "deployedCode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a", - "initialized": true, - "kind": "Create", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x4f559F30f5eB88D635FDe1548C4267DB8FaB0351", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" - }, - { - "account": "0x4f559F30f5eB88D635FDe1548C4267DB8FaB0351", - "isWrite": true, - "newValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "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": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x638627e586f5e36fe67a77519503a7c6da22f92b150d3c6055fd40bdcfe9ffd160806040523480156200001157600080fd5b506200001f60008062000025565b62000361565b600054610100900460ff1615808015620000465750600054600160ff909116105b8062000076575062000063306200019460201b620005fd1760201c565b15801562000076575060005460ff166001145b620000de5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840160405180910390fd5b6000805460ff19166001179055801562000102576000805461ff0019166101001790555b6200010d83620001a3565b81156200014857604080518082019091526012815271125b9a5d1a585b1a5e995c881c185d5cd95960721b6020820152620001489062000248565b80156200018f576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b6001600160a01b03163b151590565b620001e9620001d460017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69620002cf565b60001b82620002cb60201b620006191760201c565b6000604080516001600160a01b03841660208201527f7b743789cff01dafdeae47739925425aab5dfd02d0c8229e4a508bcd2b9f42bb910160408051601f19818403018152908290526200023d9162000345565b60405180910390a250565b6200028f6200027960017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7620002cf565b60001b6001620002cb60201b620006191760201c565b7fc32e6d5d6d1de257f64eac19ddb1f700ba13527983849c9486b1ab007ea2838181604051620002c0919062000345565b60405180910390a150565b9055565b600082821015620002f057634e487b7160e01b600052601160045260246000fd5b500390565b6000815180845260005b818110156200031d57602081850181015186830182015201620002ff565b8181111562000330576000602083870101525b50601f01601f19169290920160200192915050565b6020815260006200035a6020830184620002f5565b9392505050565b61096b80620003716000396000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c80635c975abb1161005b5780635c975abb146101255780636da663551461013d5780637fbf7b6a14610150578063c23a451a1461016657600080fd5b80633f4ba83a1461008d578063400ada7514610097578063452a9320146100aa57806354fd4d50146100dc575b600080fd5b61009561016e565b005b6100956100a5366004610746565b610294565b6100b261046d565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6101186040518060400160405280600581526020017f312e312e3000000000000000000000000000000000000000000000000000000081525081565b6040516100d39190610808565b61012d6104a6565b60405190151581526020016100d3565b61009561014b366004610851565b6104d6565b6101586105a4565b6040519081526020016100d3565b6101586105d2565b61017661046d565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610235576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f5375706572636861696e436f6e6669673a206f6e6c7920677561726469616e2060448201527f63616e20756e706175736500000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61026961026360017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b60009055565b6040517fa45f47fdea8a1efdd9029a5691c7f759c32b7c698632b563573e155625d1693390600090a1565b600054610100900460ff16158080156102b45750600054600160ff909116105b806102ce5750303b1580156102ce575060005460ff166001145b61035a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161022c565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156103b857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6103c18361061d565b8115610405576104056040518060400160405280601281526020017f496e697469616c697a65722070617573656400000000000000000000000000008152506106d8565b801561046857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b60006104a161049d60017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69610920565b5490565b905090565b60006104a161049d60017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b6104de61046d565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610598576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f5375706572636861696e436f6e6669673a206f6e6c7920677561726469616e2060448201527f63616e2070617573650000000000000000000000000000000000000000000000606482015260840161022c565b6105a1816106d8565b50565b6105cf60017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b81565b6105cf60017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69610920565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b9055565b61065061064b60017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69610920565b829055565b60006040805173ffffffffffffffffffffffffffffffffffffffff841660208201527f7b743789cff01dafdeae47739925425aab5dfd02d0c8229e4a508bcd2b9f42bb9101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526106cd91610808565b60405180910390a250565b61070c61070660017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b60019055565b7fc32e6d5d6d1de257f64eac19ddb1f700ba13527983849c9486b1ab007ea283818160405161073b9190610808565b60405180910390a150565b6000806040838503121561075957600080fd5b823573ffffffffffffffffffffffffffffffffffffffff8116811461077d57600080fd5b91506020830135801515811461079257600080fd5b809150509250929050565b6000815180845260005b818110156107c3576020818501810151868301820152016107a7565b818111156107d5576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061081b602083018461079d565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561086357600080fd5b813567ffffffffffffffff8082111561087b57600080fd5b818401915084601f83011261088f57600080fd5b8135818111156108a1576108a1610822565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156108e7576108e7610822565b8160405282815287602084870101111561090057600080fd5b826020860160208301376000928101602001929092525095945050505050565b600082821015610959577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50039056fea164736f6c634300080f000a", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "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": "0x000000000000000000000000000000000000000000000000000000000000000f" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x6a76120200000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000000e49623609d0000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab0351000000000000000000000000068e44eb31e111028c41598e4535be7468674d0a00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044400ada750000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", - "previousValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x6a76120200000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000000e49623609d0000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab0351000000000000000000000000068e44eb31e111028c41598e4535be7468674d0a00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044400ada750000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0xd1b0d319c6526317dce66989b393dcfb4435c9a65e399a088b63bbf65d7aee32" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c8" - } - ], - "value": 0 - }, - { - "accessor": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x9623609d0000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab0351000000000000000000000000068e44eb31e111028c41598e4535be7468674d0a00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044400ada750000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x0000000000000000000000007c0c8a15773ed7b50e7c738d1af4c5e3a2b210bd", - "previousValue": "0x0000000000000000000000007c0c8a15773ed7b50e7c738d1af4c5e3a2b210bd", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x6bd95c70b8833b95e56b323d763e7bec801ddd693a6478a9d9eb91508b6b5689" - } - ], - "value": 0 - }, - { - "accessor": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "account": "0x4f559F30f5eB88D635FDe1548C4267DB8FaB0351", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x4f1ef286000000000000000000000000068e44eb31e111028c41598e4535be7468674d0a00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000044400ada750000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x4f559F30f5eB88D635FDe1548C4267DB8FaB0351", - "isWrite": false, - "newValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "previousValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "reverted": false, - "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" - }, - { - "account": "0x4f559F30f5eB88D635FDe1548C4267DB8FaB0351", - "isWrite": true, - "newValue": "0x000000000000000000000000068e44eb31e111028c41598e4535be7468674d0a", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "account": "0x068E44eB31e111028c41598E4535be7468674D0A", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x400ada750000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc0000000000000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x4f559F30f5eB88D635FDe1548C4267DB8FaB0351", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x4f559F30f5eB88D635FDe1548C4267DB8FaB0351", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x4f559F30f5eB88D635FDe1548C4267DB8FaB0351", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x4f559F30f5eB88D635FDe1548C4267DB8FaB0351", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x4f559F30f5eB88D635FDe1548C4267DB8FaB0351", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x4f559F30f5eB88D635FDe1548C4267DB8FaB0351", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x4f559F30f5eB88D635FDe1548C4267DB8FaB0351", - "isWrite": true, - "newValue": "0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0xd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe68" - }, - { - "account": "0x4f559F30f5eB88D635FDe1548C4267DB8FaB0351", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x4f559F30f5eB88D635FDe1548C4267DB8FaB0351", - "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": "0x000000000000000000000000000000000000000000000000000000000000000f" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x4f559F30f5eB88D635FDe1548C4267DB8FaB0351", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x452a9320", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x4f559F30f5eB88D635FDe1548C4267DB8FaB0351", - "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": "0x4f559F30f5eB88D635FDe1548C4267DB8FaB0351", - "isWrite": false, - "newValue": "0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc", - "previousValue": "0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc", - "reverted": false, - "slot": "0xd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe68" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x4f559F30f5eB88D635FDe1548C4267DB8FaB0351", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x5c975abb", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x4f559F30f5eB88D635FDe1548C4267DB8FaB0351", - "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": "0x4f559F30f5eB88D635FDe1548C4267DB8FaB0351", - "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": "0x4C52a6277b1B84121b3072C0c92b6Be0b7CC10F1", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x608060405234801561001057600080fd5b5060405161091f38038061091f83398101604081905261002f916100b5565b6100388161003e565b506100e5565b60006100566000805160206108ff8339815191525490565b6000805160206108ff833981519152838155604080516001600160a01b0380851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b6000602082840312156100c757600080fd5b81516001600160a01b03811681146100de57600080fd5b9392505050565b61080b806100f46000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610300000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "deployedCode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a", - "initialized": true, - "kind": "Create", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x4C52a6277b1B84121b3072C0c92b6Be0b7CC10F1", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" - }, - { - "account": "0x4C52a6277b1B84121b3072C0c92b6Be0b7CC10F1", - "isWrite": true, - "newValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "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": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x638627e586f5e36fe67a77519503a7c6da22f92b150d3c6055fd40bdcfe9ffd160806040523480156200001157600080fd5b506200002261dead60008062000028565b6200051c565b600054610100900460ff1615808015620000495750600054600160ff909116105b8062000079575062000066306200017e60201b6200053f1760201c565b15801562000079575060005460ff166001145b620000e25760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000106576000805461ff0019166101001790555b620001106200018d565b6200011b84620001f5565b620001268362000274565b620001318262000324565b801562000178576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b6001600160a01b03163b151590565b600054610100900460ff16620001e95760405162461bcd60e51b815260206004820152602b602482015260008051602062000f4f83398151915260448201526a6e697469616c697a696e6760a81b6064820152608401620000d9565b620001f362000385565b565b620001ff620003ec565b6001600160a01b038116620002665760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401620000d9565b620002718162000448565b50565b620002ba620002a560017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16200049e565b60001b826200049a60201b6200055b1760201c565b600081604051602001620002d091815260200190565b60408051601f19818403018152919052905060005b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be83604051620003189190620004c4565b60405180910390a35050565b62000355620002a560017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6200049e565b6000816040516020016200036b91815260200190565b60408051601f1981840301815291905290506001620002e5565b600054610100900460ff16620003e15760405162461bcd60e51b815260206004820152602b602482015260008051602062000f4f83398151915260448201526a6e697469616c697a696e6760a81b6064820152608401620000d9565b620001f33362000448565b6033546001600160a01b03163314620001f35760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401620000d9565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b9055565b600082821015620004bf57634e487b7160e01b600052601160045260246000fd5b500390565b600060208083528351808285015260005b81811015620004f357858101830151858201604001528201620004d5565b8181111562000506576000604083870101525b50601f01601f1916929092016040019392505050565b610a23806200052c6000396000f3fe608060405234801561001057600080fd5b50600436106100d45760003560e01c80638da5cb5b11610081578063f2fde38b1161005b578063f2fde38b146101b8578063f7d12760146101cb578063ffa1ad74146101d357600080fd5b80638da5cb5b14610180578063d798b1ac146101a8578063dc8452cd146101b057600080fd5b80635fd579af116100b25780635fd579af14610152578063715018a6146101655780637a1ac61e1461016d57600080fd5b80630457d6f2146100d9578063206a8300146100ee57806354fd4d5014610109575b600080fd5b6100ec6100e73660046108c3565b6101db565b005b6100f66101ef565b6040519081526020015b60405180910390f35b6101456040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516101009190610947565b6100ec6101603660046108c3565b61021d565b6100ec61022e565b6100ec61017b36600461098a565b610242565b60335460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610100565b6100f66103f7565b6100f6610430565b6100ec6101c63660046109bd565b610460565b6100f6610514565b6100f6600081565b6101e361055f565b6101ec816105e0565b50565b61021a60017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16109d8565b81565b61022561055f565b6101ec81610698565b61023661055f565b6102406000610712565b565b600054610100900460ff16158080156102625750600054600160ff909116105b8061027c5750303b15801561027c575060005460ff166001145b61030d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561036b57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610373610789565b61037c84610460565b610385836105e0565b61038e82610698565b80156103f157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b600061042b61042760017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6109d8565b5490565b905090565b600061042b61042760017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16109d8565b61046861055f565b73ffffffffffffffffffffffffffffffffffffffff811661050b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610304565b6101ec81610712565b61021a60017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6109d8565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b9055565b60335473ffffffffffffffffffffffffffffffffffffffff163314610240576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610304565b61061361060e60017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16109d8565b829055565b60008160405160200161062891815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060005b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be8360405161068c9190610947565b60405180910390a35050565b6106c661060e60017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6109d8565b6000816040516020016106db91815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529050600161065b565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16610820576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610304565b610240600054610100900460ff166108ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610304565b61024033610712565b6000602082840312156108d557600080fd5b5035919050565b6000815180845260005b81811015610902576020818501810151868301820152016108e6565b81811115610914576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061095a60208301846108dc565b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461098557600080fd5b919050565b60008060006060848603121561099f57600080fd5b6109a884610961565b95602085013595506040909401359392505050565b6000602082840312156109cf57600080fd5b61095a82610961565b600082821015610a11577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50039056fea164736f6c634300080f000a496e697469616c697a61626c653a20636f6e7472616374206973206e6f742069", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "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": "0x000000000000000000000000000000000000000000000000000000000000000e" - } - ], - "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": "0x000000000000000000000000000000000000000000000000000000000000003f" - } - ], - "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": "0x0000000000000000000000000000000000000000000000000000000000000040" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x6a76120200000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000001049623609d0000000000000000000000004c52a6277b1b84121b3072c0c92b6be0b7cc10f1000000000000000000000000fbfd64a6c0257f613fefce050aa30ecc3e3d7c3f000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000647a1ac61e0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", - "previousValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x6a76120200000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000001049623609d0000000000000000000000004c52a6277b1b84121b3072c0c92b6be0b7cc10f1000000000000000000000000fbfd64a6c0257f613fefce050aa30ecc3e3d7c3f000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000647a1ac61e0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000002", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0xd1b0d319c6526317dce66989b393dcfb4435c9a65e399a088b63bbf65d7aee32" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c8" - } - ], - "value": 0 - }, - { - "accessor": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x9623609d0000000000000000000000004c52a6277b1b84121b3072c0c92b6be0b7cc10f1000000000000000000000000fbfd64a6c0257f613fefce050aa30ecc3e3d7c3f000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000647a1ac61e0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x0000000000000000000000007c0c8a15773ed7b50e7c738d1af4c5e3a2b210bd", - "previousValue": "0x0000000000000000000000007c0c8a15773ed7b50e7c738d1af4c5e3a2b210bd", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x72d7aa813380382c369363d977a28b043ac6e1983f989087faaa96aa4d8d4c12" - } - ], - "value": 0 - }, - { - "accessor": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "account": "0x4C52a6277b1B84121b3072C0c92b6Be0b7CC10F1", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x4f1ef286000000000000000000000000fbfd64a6c0257f613fefce050aa30ecc3e3d7c3f000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000647a1ac61e0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x4C52a6277b1B84121b3072C0c92b6Be0b7CC10F1", - "isWrite": false, - "newValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "previousValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "reverted": false, - "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" - }, - { - "account": "0x4C52a6277b1B84121b3072C0c92b6Be0b7CC10F1", - "isWrite": true, - "newValue": "0x000000000000000000000000fbfd64a6c0257f613fefce050aa30ecc3e3d7c3f", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "account": "0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x7a1ac61e0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x4C52a6277b1B84121b3072C0c92b6Be0b7CC10F1", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x4C52a6277b1B84121b3072C0c92b6Be0b7CC10F1", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x4C52a6277b1B84121b3072C0c92b6Be0b7CC10F1", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x4C52a6277b1B84121b3072C0c92b6Be0b7CC10F1", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x4C52a6277b1B84121b3072C0c92b6Be0b7CC10F1", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x4C52a6277b1B84121b3072C0c92b6Be0b7CC10F1", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x4C52a6277b1B84121b3072C0c92b6Be0b7CC10F1", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x4C52a6277b1B84121b3072C0c92b6Be0b7CC10F1", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x4C52a6277b1B84121b3072C0c92b6Be0b7CC10F1", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - }, - { - "account": "0x4C52a6277b1B84121b3072C0c92b6Be0b7CC10F1", - "isWrite": true, - "newValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - }, - { - "account": "0x4C52a6277b1B84121b3072C0c92b6Be0b7CC10F1", - "isWrite": false, - "newValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "previousValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - }, - { - "account": "0x4C52a6277b1B84121b3072C0c92b6Be0b7CC10F1", - "isWrite": false, - "newValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "previousValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - }, - { - "account": "0x4C52a6277b1B84121b3072C0c92b6Be0b7CC10F1", - "isWrite": true, - "newValue": "0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc", - "previousValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - }, - { - "account": "0x4C52a6277b1B84121b3072C0c92b6Be0b7CC10F1", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace0" - }, - { - "account": "0x4C52a6277b1B84121b3072C0c92b6Be0b7CC10F1", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0xe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1a" - }, - { - "account": "0x4C52a6277b1B84121b3072C0c92b6Be0b7CC10F1", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x4C52a6277b1B84121b3072C0c92b6Be0b7CC10F1", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x4C52a6277b1B84121b3072C0c92b6Be0b7CC10F1", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x54fd4d50", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x4C52a6277b1B84121b3072C0c92b6Be0b7CC10F1", - "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": "0x000000000000000000000000000000000000000000000000000000000000000e" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x4C52a6277b1B84121b3072C0c92b6Be0b7CC10F1", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x8da5cb5b", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x4C52a6277b1B84121b3072C0c92b6Be0b7CC10F1", - "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": "0x4C52a6277b1B84121b3072C0c92b6Be0b7CC10F1", - "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": "0x000000000000000000000000000000000000000000000000000000000000003f" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x4C52a6277b1B84121b3072C0c92b6Be0b7CC10F1", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xdc8452cd", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x4C52a6277b1B84121b3072C0c92b6Be0b7CC10F1", - "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": "0x4C52a6277b1B84121b3072C0c92b6Be0b7CC10F1", - "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": "0x0000000000000000000000000000000000000000000000000000000000000040" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x4C52a6277b1B84121b3072C0c92b6Be0b7CC10F1", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xd798b1ac", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x4C52a6277b1B84121b3072C0c92b6Be0b7CC10F1", - "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": "0x4C52a6277b1B84121b3072C0c92b6Be0b7CC10F1", - "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": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x08e0e2bb", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000044" - } - ], - "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": "0x608060405234801561001057600080fd5b5060405161091f38038061091f83398101604081905261002f916100b5565b6100388161003e565b506100e5565b60006100566000805160206108ff8339815191525490565b6000805160206108ff833981519152838155604080516001600160a01b0380851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b6000602082840312156100c757600080fd5b81516001600160a01b03811681146100de57600080fd5b9392505050565b61080b806100f46000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610300000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "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": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "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": "0x608060405234801561001057600080fd5b5060405161091f38038061091f83398101604081905261002f916100b5565b6100388161003e565b506100e5565b60006100566000805160206108ff8339815191525490565b6000805160206108ff833981519152838155604080516001600160a01b0380851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b6000602082840312156100c757600080fd5b81516001600160a01b03811681146100de57600080fd5b9392505050565b61080b806100f46000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610300000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "deployedCode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a", - "initialized": true, - "kind": "Create", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" - }, - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": true, - "newValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "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": "0x608060405234801561001057600080fd5b50604051610a44380380610a4483398101604081905261002f9161005d565b610057817fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610355565b5061008d565b60006020828403121561006f57600080fd5b81516001600160a01b038116811461008657600080fd5b9392505050565b6109a88061009c6000396000f3fe60806040526004361061005e5760003560e01c8063893d20e811610043578063893d20e8146100b55780639b0b0fda146100f3578063aaf10f42146101135761006d565b806313af4035146100755780636c5d4ad0146100955761006d565b3661006d5761006b610128565b005b61006b610128565b34801561008157600080fd5b5061006b6100903660046107a2565b6103cb565b3480156100a157600080fd5b5061006b6100b036600461080e565b61045c565b3480156100c157600080fd5b506100ca610611565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100ff57600080fd5b5061006b61010e3660046108dd565b6106a8565b34801561011f57600080fd5b506100ca610716565b60006101527fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fb7947262000000000000000000000000000000000000000000000000000000001790529051919250600091829173ffffffffffffffffffffffffffffffffffffffff8516916101d4919061093a565b600060405180830381855afa9150503d806000811461020f576040519150601f19603f3d011682016040523d82523d6000602084013e610214565b606091505b5091509150818015610227575080516020145b156102d9576000818060200190518101906102429190610946565b905080156102d7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c314368756753706c61736850726f78793a2073797374656d2069732063757260448201527f72656e746c79206265696e67207570677261646564000000000000000000000060648201526084015b60405180910390fd5b505b60006103037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff81166103a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4c314368756753706c61736850726f78793a20696d706c656d656e746174696f60448201527f6e206973206e6f7420736574207965740000000000000000000000000000000060648201526084016102ce565b3660008037600080366000845af43d6000803e806103c5573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610424575033155b1561045457610451817fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610355565b50565b610451610128565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806104b5575033155b156104545760006104e47f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b9050803f82516020840120036104f8575050565b60405160009061052e907f600d380380600d6000396000f30000000000000000000000000000000000000090859060200161095f565b604051602081830303815290604052905060008151602083016000f084516020860120909150813f146105e3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4c314368756753706c61736850726f78793a20636f646520776173206e6f742060448201527f636f72726563746c79206465706c6f796564000000000000000000000000000060648201526084016102ce565b61060b817f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55565b50505050565b600061063b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610672575033155b1561069d57507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b6106a5610128565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610701575033155b1561070a579055565b610712610128565b5050565b60006107407fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610777575033155b1561069d57507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000602082840312156107b457600080fd5b813573ffffffffffffffffffffffffffffffffffffffff811681146107d857600080fd5b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561082057600080fd5b813567ffffffffffffffff8082111561083857600080fd5b818401915084601f83011261084c57600080fd5b81358181111561085e5761085e6107df565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156108a4576108a46107df565b816040528281528760208487010111156108bd57600080fd5b826020860160208301376000928101602001929092525095945050505050565b600080604083850312156108f057600080fd5b50508035926020909101359150565b6000815160005b818110156109205760208185018101518683015201610906565b8181111561092f576000828601525b509290920192915050565b60006107d882846108ff565b60006020828403121561095857600080fd5b5051919050565b7fffffffffffffffffffffffffff00000000000000000000000000000000000000831681526000610993600d8301846108ff565b94935050505056fea164736f6c634300080f000a00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "deployedCode": "0x60806040526004361061005e5760003560e01c8063893d20e811610043578063893d20e8146100b55780639b0b0fda146100f3578063aaf10f42146101135761006d565b806313af4035146100755780636c5d4ad0146100955761006d565b3661006d5761006b610128565b005b61006b610128565b34801561008157600080fd5b5061006b6100903660046107a2565b6103cb565b3480156100a157600080fd5b5061006b6100b036600461080e565b61045c565b3480156100c157600080fd5b506100ca610611565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100ff57600080fd5b5061006b61010e3660046108dd565b6106a8565b34801561011f57600080fd5b506100ca610716565b60006101527fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fb7947262000000000000000000000000000000000000000000000000000000001790529051919250600091829173ffffffffffffffffffffffffffffffffffffffff8516916101d4919061093a565b600060405180830381855afa9150503d806000811461020f576040519150601f19603f3d011682016040523d82523d6000602084013e610214565b606091505b5091509150818015610227575080516020145b156102d9576000818060200190518101906102429190610946565b905080156102d7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c314368756753706c61736850726f78793a2073797374656d2069732063757260448201527f72656e746c79206265696e67207570677261646564000000000000000000000060648201526084015b60405180910390fd5b505b60006103037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff81166103a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4c314368756753706c61736850726f78793a20696d706c656d656e746174696f60448201527f6e206973206e6f7420736574207965740000000000000000000000000000000060648201526084016102ce565b3660008037600080366000845af43d6000803e806103c5573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610424575033155b1561045457610451817fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610355565b50565b610451610128565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806104b5575033155b156104545760006104e47f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b9050803f82516020840120036104f8575050565b60405160009061052e907f600d380380600d6000396000f30000000000000000000000000000000000000090859060200161095f565b604051602081830303815290604052905060008151602083016000f084516020860120909150813f146105e3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4c314368756753706c61736850726f78793a20636f646520776173206e6f742060448201527f636f72726563746c79206465706c6f796564000000000000000000000000000060648201526084016102ce565b61060b817f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55565b50505050565b600061063b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610672575033155b1561069d57507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b6106a5610128565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610701575033155b1561070a579055565b610712610128565b5050565b60006107407fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610777575033155b1561069d57507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6000602082840312156107b457600080fd5b813573ffffffffffffffffffffffffffffffffffffffff811681146107d857600080fd5b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561082057600080fd5b813567ffffffffffffffff8082111561083857600080fd5b818401915084601f83011261084c57600080fd5b81358181111561085e5761085e6107df565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156108a4576108a46107df565b816040528281528760208487010111156108bd57600080fd5b826020860160208301376000928101602001929092525095945050505050565b600080604083850312156108f057600080fd5b50508035926020909101359150565b6000815160005b818110156109205760208185018101518683015201610906565b8181111561092f576000828601525b509290920192915050565b60006107d882846108ff565b60006020828403121561095857600080fd5b5051919050565b7fffffffffffffffffffffffffff00000000000000000000000000000000000000831681526000610993600d8301846108ff565b94935050505056fea164736f6c634300080f000a", - "initialized": true, - "kind": "Create", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", - "isWrite": true, - "newValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "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": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x608060405234801561001057600080fd5b506040516105f03803806105f083398101604081905261002f91610088565b30600090815260016020908152604080832080546001600160a01b0319166001600160a01b03871617905590829052902061006a8282610203565b5050506102c2565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561009b57600080fd5b82516001600160a01b03811681146100b257600080fd5b602084810151919350906001600160401b03808211156100d157600080fd5b818601915086601f8301126100e557600080fd5b8151818111156100f7576100f7610072565b604051601f8201601f19908116603f0116810190838211818310171561011f5761011f610072565b81604052828152898684870101111561013757600080fd5b600093505b82841015610159578484018601518185018701529285019261013c565b8284111561016a5760008684830101525b8096505050505050509250929050565b600181811c9082168061018e57607f821691505b6020821081036101ae57634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156101fe57600081815260208120601f850160051c810160208610156101db5750805b601f850160051c820191505b818110156101fa578281556001016101e7565b5050505b505050565b81516001600160401b0381111561021c5761021c610072565b6102308161022a845461017a565b846101b4565b602080601f831160018114610265576000841561024d5750858301515b600019600386901b1c1916600185901b1785556101fa565b600085815260208120601f198616915b8281101561029457888601518255948401946001909101908401610275565b50858210156102b25787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b61031f806102d16000396000f3fe608060408181523060009081526001602090815282822054908290529181207fbf40fac1000000000000000000000000000000000000000000000000000000009093529173ffffffffffffffffffffffffffffffffffffffff9091169063bf40fac19061006d9060846101e2565b602060405180830381865afa15801561008a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100ae91906102c5565b905073ffffffffffffffffffffffffffffffffffffffff8116610157576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f5265736f6c76656444656c656761746550726f78793a2074617267657420616460448201527f6472657373206d75737420626520696e697469616c697a656400000000000000606482015260840160405180910390fd5b6000808273ffffffffffffffffffffffffffffffffffffffff16600036604051610182929190610302565b600060405180830381855af49150503d80600081146101bd576040519150601f19603f3d011682016040523d82523d6000602084013e6101c2565b606091505b5090925090508115156001036101da57805160208201f35b805160208201fd5b600060208083526000845481600182811c91508083168061020457607f831692505b858310810361023a577f4e487b710000000000000000000000000000000000000000000000000000000085526022600452602485fd5b878601838152602001818015610257576001811461028b576102b6565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008616825284151560051b820196506102b6565b60008b81526020902060005b868110156102b057815484820152908501908901610297565b83019750505b50949998505050505050505050565b6000602082840312156102d757600080fd5b815173ffffffffffffffffffffffffffffffffffffffff811681146102fb57600080fd5b9392505050565b818382376000910190815291905056fea164736f6c634300080f000a00000000000000000000000050eef481cae4250d252ae577a09bf514f224c6c40000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001a4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000000", - "deployedCode": "0x608060408181523060009081526001602090815282822054908290529181207fbf40fac1000000000000000000000000000000000000000000000000000000009093529173ffffffffffffffffffffffffffffffffffffffff9091169063bf40fac19061006d9060846101e2565b602060405180830381865afa15801561008a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100ae91906102c5565b905073ffffffffffffffffffffffffffffffffffffffff8116610157576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f5265736f6c76656444656c656761746550726f78793a2074617267657420616460448201527f6472657373206d75737420626520696e697469616c697a656400000000000000606482015260840160405180910390fd5b6000808273ffffffffffffffffffffffffffffffffffffffff16600036604051610182929190610302565b600060405180830381855af49150503d80600081146101bd576040519150601f19603f3d011682016040523d82523d6000602084013e6101c2565b606091505b5090925090508115156001036101da57805160208201f35b805160208201fd5b600060208083526000845481600182811c91508083168061020457607f831692505b858310810361023a577f4e487b710000000000000000000000000000000000000000000000000000000085526022600452602485fd5b878601838152602001818015610257576001811461028b576102b6565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008616825284151560051b820196506102b6565b60008b81526020902060005b868110156102b057815484820152908501908901610297565b83019750505b50949998505050505050505050565b6000602082840312156102d757600080fd5b815173ffffffffffffffffffffffffffffffffffffffff811681146102fb57600080fd5b9392505050565b818382376000910190815291905056fea164736f6c634300080f000a", - "initialized": true, - "kind": "Create", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x191cda7b5a8219e0cc3bb6c2b45be830e3ba520f78e119446a476c4147fcc284" - }, - { - "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", - "isWrite": true, - "newValue": "0x00000000000000000000000050eef481cae4250d252ae577a09bf514f224c6c4", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x191cda7b5a8219e0cc3bb6c2b45be830e3ba520f78e119446a476c4147fcc284" - }, - { - "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x6822ddba83a78589c753bb747cf4919773ec1d36eeb0bb2a09d64b6d87adda0b" - }, - { - "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", - "isWrite": true, - "newValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x6822ddba83a78589c753bb747cf4919773ec1d36eeb0bb2a09d64b6d87adda0b" - } - ], - "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": "0xc7B87b2b892EA5C3CfF47168881FE168C00377FB", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x608060405234801561001057600080fd5b5060405161091f38038061091f83398101604081905261002f916100b5565b6100388161003e565b506100e5565b60006100566000805160206108ff8339815191525490565b6000805160206108ff833981519152838155604080516001600160a01b0380851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b6000602082840312156100c757600080fd5b81516001600160a01b03811681146100de57600080fd5b9392505050565b61080b806100f46000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610300000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "deployedCode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a", - "initialized": true, - "kind": "Create", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xc7B87b2b892EA5C3CfF47168881FE168C00377FB", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" - }, - { - "account": "0xc7B87b2b892EA5C3CfF47168881FE168C00377FB", - "isWrite": true, - "newValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "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": "0xD31598c909d9C935a9e35bA70d9a3DD47d4D5865", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x608060405234801561001057600080fd5b5060405161091f38038061091f83398101604081905261002f916100b5565b6100388161003e565b506100e5565b60006100566000805160206108ff8339815191525490565b6000805160206108ff833981519152838155604080516001600160a01b0380851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b6000602082840312156100c757600080fd5b81516001600160a01b03811681146100de57600080fd5b9392505050565b61080b806100f46000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610300000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "deployedCode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a", - "initialized": true, - "kind": "Create", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xD31598c909d9C935a9e35bA70d9a3DD47d4D5865", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" - }, - { - "account": "0xD31598c909d9C935a9e35bA70d9a3DD47d4D5865", - "isWrite": true, - "newValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "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": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x608060405234801561001057600080fd5b5060405161091f38038061091f83398101604081905261002f916100b5565b6100388161003e565b506100e5565b60006100566000805160206108ff8339815191525490565b6000805160206108ff833981519152838155604080516001600160a01b0380851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b6000602082840312156100c757600080fd5b81516001600160a01b03811681146100de57600080fd5b9392505050565b61080b806100f46000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610300000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "deployedCode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a", - "initialized": true, - "kind": "Create", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" - }, - { - "account": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "isWrite": true, - "newValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "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": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x608060405234801561001057600080fd5b5060405161091f38038061091f83398101604081905261002f916100b5565b6100388161003e565b506100e5565b60006100566000805160206108ff8339815191525490565b6000805160206108ff833981519152838155604080516001600160a01b0380851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b6000602082840312156100c757600080fd5b81516001600160a01b03811681146100de57600080fd5b9392505050565b61080b806100f46000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610300000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "deployedCode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a", - "initialized": true, - "kind": "Create", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" - }, - { - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "isWrite": true, - "newValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "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": "0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x608060405234801561001057600080fd5b5060405161091f38038061091f83398101604081905261002f916100b5565b6100388161003e565b506100e5565b60006100566000805160206108ff8339815191525490565b6000805160206108ff833981519152838155604080516001600160a01b0380851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b6000602082840312156100c757600080fd5b81516001600160a01b03811681146100de57600080fd5b9392505050565b61080b806100f46000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610300000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "deployedCode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a", - "initialized": true, - "kind": "Create", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" - }, - { - "account": "0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92", - "isWrite": true, - "newValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "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": "0xd6EAF4c146261653EE059077B78ED088Add54309", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x608060405234801561001057600080fd5b5060405161091f38038061091f83398101604081905261002f916100b5565b6100388161003e565b506100e5565b60006100566000805160206108ff8339815191525490565b6000805160206108ff833981519152838155604080516001600160a01b0380851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b6000602082840312156100c757600080fd5b81516001600160a01b03811681146100de57600080fd5b9392505050565b61080b806100f46000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610300000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "deployedCode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a", - "initialized": true, - "kind": "Create", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xd6EAF4c146261653EE059077B78ED088Add54309", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" - }, - { - "account": "0xd6EAF4c146261653EE059077B78ED088Add54309", - "isWrite": true, - "newValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "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": "0x970670459734a83899773A0fd45941B5afC1200e", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x608060405234801561001057600080fd5b5060405161091f38038061091f83398101604081905261002f916100b5565b6100388161003e565b506100e5565b60006100566000805160206108ff8339815191525490565b6000805160206108ff833981519152838155604080516001600160a01b0380851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b6000602082840312156100c757600080fd5b81516001600160a01b03811681146100de57600080fd5b9392505050565b61080b806100f46000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610300000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "deployedCode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a", - "initialized": true, - "kind": "Create", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x970670459734a83899773A0fd45941B5afC1200e", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" - }, - { - "account": "0x970670459734a83899773A0fd45941B5afC1200e", - "isWrite": true, - "newValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "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": "0x50EEf481cae4250d252Ae577A09bF514f224C6C4", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x8da5cb5b", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x50EEf481cae4250d252Ae577A09bF514f224C6C4", - "isWrite": false, - "newValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", - "previousValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - ], - "value": 0 - }, - { - "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", - "account": "0x50EEf481cae4250d252Ae577A09bF514f224C6C4", - "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": "0x50EEf481cae4250d252Ae577A09bF514f224C6C4", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xf2fde38b00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x50EEf481cae4250d252Ae577A09bF514f224C6C4", - "isWrite": false, - "newValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", - "previousValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x50EEf481cae4250d252Ae577A09bF514f224C6C4", - "isWrite": false, - "newValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", - "previousValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x50EEf481cae4250d252Ae577A09bF514f224C6C4", - "isWrite": true, - "newValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "previousValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x50EEf481cae4250d252Ae577A09bF514f224C6C4", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x8da5cb5b", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x50EEf481cae4250d252Ae577A09bF514f224C6C4", - "isWrite": false, - "newValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "previousValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "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": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x638627e586f5e36fe67a77519503a7c6da22f92b150d3c6055fd40bdcfe9ffd160806040523480156200001157600080fd5b50620000206000808062000026565b6200028e565b600054600160a81b900460ff16158080156200004f57506000546001600160a01b90910460ff16105b806200008657506200006c30620001c860201b620015b71760201c565b158015620000865750600054600160a01b900460ff166001145b620000ef5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff60a01b1916600160a01b17905580156200011d576000805460ff60a81b1916600160a81b1790555b60fb80546001600160a01b038087166001600160a01b03199283161790925560fc805486841690831617905560fd80549285169290911691909117905562000179734200000000000000000000000000000000000007620001d7565b8015620001c2576000805460ff60a81b19169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b6001600160a01b03163b151590565b600054600160a81b900460ff16620002465760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401620000e6565b60cc546001600160a01b03166200026c5760cc80546001600160a01b03191661dead1790555b60cf80546001600160a01b0319166001600160a01b0392909216919091179055565b6121a1806200029e6000396000f3fe60806040526004361061018b5760003560e01c80636425666b116100d6578063b1b1b2091161007f578063d764ad0b11610059578063d764ad0b1461049b578063db505d80146104ae578063ecc70428146104db57600080fd5b8063b1b1b2091461042b578063b28ade251461045b578063c0c53b8b1461047b57600080fd5b80638cbeeef2116100b05780638cbeeef2146102d05780639fce812c146103d0578063a4e7f8bd146103fb57600080fd5b80636425666b146103775780636e296e45146103a457806383a74074146103b957600080fd5b80633dbb202b1161013857806354fd4d501161011257806354fd4d50146102e65780635644cfdf1461033c5780635c975abb1461035257600080fd5b80633dbb202b146102935780633f827a5a146102a85780634c1d6a69146102d057600080fd5b80632828d7e8116101695780632828d7e81461022457806333d7e2bd1461023957806335e80ab31461026657600080fd5b8063028f85f7146101905780630c568498146101c35780630ff754ea146101d8575b600080fd5b34801561019c57600080fd5b506101a5601081565b60405167ffffffffffffffff90911681526020015b60405180910390f35b3480156101cf57600080fd5b506101a5603f81565b3480156101e457600080fd5b5060fc5473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101ba565b34801561023057600080fd5b506101a5604081565b34801561024557600080fd5b5060fd546101ff9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561027257600080fd5b5060fb546101ff9073ffffffffffffffffffffffffffffffffffffffff1681565b6102a66102a1366004611bdd565b610540565b005b3480156102b457600080fd5b506102bd600181565b60405161ffff90911681526020016101ba565b3480156102dc57600080fd5b506101a5619c4081565b3480156102f257600080fd5b5061032f6040518060400160405280600581526020017f322e342e3000000000000000000000000000000000000000000000000000000081525081565b6040516101ba9190611caf565b34801561034857600080fd5b506101a561138881565b34801561035e57600080fd5b5061036761083d565b60405190151581526020016101ba565b34801561038357600080fd5b5060fc546101ff9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156103b057600080fd5b506101ff6108d6565b3480156103c557600080fd5b506101a562030d4081565b3480156103dc57600080fd5b5060cf5473ffffffffffffffffffffffffffffffffffffffff166101ff565b34801561040757600080fd5b50610367610416366004611cc9565b60ce6020526000908152604090205460ff1681565b34801561043757600080fd5b50610367610446366004611cc9565b60cb6020526000908152604090205460ff1681565b34801561046757600080fd5b506101a5610476366004611ce2565b6109bd565b34801561048757600080fd5b506102a6610496366004611d36565b610a2b565b6102a66104a9366004611d81565b610ca2565b3480156104ba57600080fd5b5060cf546101ff9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156104e757600080fd5b5061053260cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b6040519081526020016101ba565b6105486115d3565b156105e05734156105e0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f43726f7373446f6d61696e4d657373656e6765723a2063616e6e6f742073656e60448201527f642076616c7565207769746820637573746f6d2067617320746f6b656e00000060648201526084015b60405180910390fd5b60cf546107129073ffffffffffffffffffffffffffffffffffffffff166106088585856109bd565b347fd764ad0b0000000000000000000000000000000000000000000000000000000061067460cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b338a34898c8c6040516024016106909796959493929190611e50565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611612565b8373ffffffffffffffffffffffffffffffffffffffff167fcb0f7ffd78f9aee47a248fae8db181db6eee833039123e026dcbff529522e52a33858561079760cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b866040516107a9959493929190611eaf565b60405180910390a260405134815233907f8ebb2ec2465bdb2a06a66fc37a0963af8a2a6a1479d81d56fdb8cbb98096d5469060200160405180910390a2505060cd80547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808216600101167fffff0000000000000000000000000000000000000000000000000000000000009091161790555050565b60fb54604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa1580156108ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108d19190611efd565b905090565b60cc5460009073ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2153016109a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f43726f7373446f6d61696e4d657373656e6765723a2078446f6d61696e4d657360448201527f7361676553656e646572206973206e6f7420736574000000000000000000000060648201526084016105d7565b5060cc5473ffffffffffffffffffffffffffffffffffffffff1690565b6000611388619c4080603f6109d9604063ffffffff8816611f4e565b6109e39190611f7e565b6109ee601088611f4e565b6109fb9062030d40611fcc565b610a059190611fcc565b610a0f9190611fcc565b610a199190611fcc565b610a239190611fcc565b949350505050565b6000547501000000000000000000000000000000000000000000900460ff1615808015610a76575060005460017401000000000000000000000000000000000000000090910460ff16105b80610aa85750303b158015610aa8575060005474010000000000000000000000000000000000000000900460ff166001145b610b34576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016105d7565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790558015610bba57600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000001790555b60fb805473ffffffffffffffffffffffffffffffffffffffff8087167fffffffffffffffffffffffff00000000000000000000000000000000000000009283161790925560fc805486841690831617905560fd805492851692909116919091179055610c397342000000000000000000000000000000000000076116ab565b8015610c9c57600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b610caa61083d565b15610d11576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f43726f7373446f6d61696e4d657373656e6765723a207061757365640000000060448201526064016105d7565b60f087901c60028110610dcc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f43726f7373446f6d61696e4d657373656e6765723a206f6e6c7920766572736960448201527f6f6e2030206f722031206d657373616765732061726520737570706f7274656460648201527f20617420746869732074696d6500000000000000000000000000000000000000608482015260a4016105d7565b8061ffff16600003610ec1576000610e1d878986868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508f92506117e7915050565b600081815260cb602052604090205490915060ff1615610ebf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f43726f7373446f6d61696e4d657373656e6765723a206c65676163792077697460448201527f6864726177616c20616c72656164792072656c6179656400000000000000000060648201526084016105d7565b505b6000610f07898989898989898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061180692505050565b9050610f11611829565b15610f4957853414610f2557610f25611ff8565b600081815260ce602052604090205460ff1615610f4457610f44611ff8565b61109b565b3415610ffd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605060248201527f43726f7373446f6d61696e4d657373656e6765723a2076616c7565206d75737460448201527f206265207a65726f20756e6c657373206d6573736167652069732066726f6d2060648201527f612073797374656d206164647265737300000000000000000000000000000000608482015260a4016105d7565b600081815260ce602052604090205460ff1661109b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520636160448201527f6e6e6f74206265207265706c617965640000000000000000000000000000000060648201526084016105d7565b6110a487611905565b15611157576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f43726f7373446f6d61696e4d657373656e6765723a2063616e6e6f742073656e60448201527f64206d65737361676520746f20626c6f636b65642073797374656d206164647260648201527f6573730000000000000000000000000000000000000000000000000000000000608482015260a4016105d7565b600081815260cb602052604090205460ff16156111f6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520686160448201527f7320616c7265616479206265656e2072656c617965640000000000000000000060648201526084016105d7565b61121785611208611388619c40611fcc565b67ffffffffffffffff1661194b565b158061123d575060cc5473ffffffffffffffffffffffffffffffffffffffff1661dead14155b1561135657600081815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555182917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff320161134f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d6573736167650000000000000000000000000000000000000060648201526084016105d7565b50506115ae565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8a1617905560006113e788619c405a6113aa9190612027565b8988888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061196992505050565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790559050801561149d57600082815260cb602052604090205460ff161561143a5761143a611ff8565b600082815260cb602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f4641df4a962071e12719d8c8c8e5ac7fc4d97b927346a3d7a335b1f7517e133c91a26115aa565b600082815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff32016115aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d6573736167650000000000000000000000000000000000000060648201526084016105d7565b5050505b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6000806115de611981565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b60fc546040517fe9e05c4200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063e9e05c4290849061167390889083908990600090899060040161203e565b6000604051808303818588803b15801561168c57600080fd5b505af11580156116a0573d6000803e3d6000fd5b505050505050505050565b6000547501000000000000000000000000000000000000000000900460ff16611756576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016105d7565b60cc5473ffffffffffffffffffffffffffffffffffffffff166117a05760cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790555b60cf80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60006117f585858585611a1e565b805190602001209050949350505050565b6000611816878787878787611ab7565b8051906020012090509695505050505050565b60fc5460009073ffffffffffffffffffffffffffffffffffffffff16331480156108d1575060cf5460fc54604080517f9bf62d82000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9384169390921691639bf62d82916004808201926020929091908290030181865afa1580156118c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118e99190612096565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b600073ffffffffffffffffffffffffffffffffffffffff8216301480611945575060fc5473ffffffffffffffffffffffffffffffffffffffff8381169116145b92915050565b600080603f83619c4001026040850201603f5a021015949350505050565b6000806000835160208501868989f195945050505050565b60fd54604080517f4397dfef0000000000000000000000000000000000000000000000000000000081528151600093849373ffffffffffffffffffffffffffffffffffffffff90911692634397dfef92600480830193928290030181865afa1580156119f1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a1591906120b3565b90939092509050565b606084848484604051602401611a3794939291906120f3565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fcbd4ece9000000000000000000000000000000000000000000000000000000001790529050949350505050565b6060868686868686604051602401611ad49695949392919061213d565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd764ad0b0000000000000000000000000000000000000000000000000000000017905290509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff81168114611b7857600080fd5b50565b60008083601f840112611b8d57600080fd5b50813567ffffffffffffffff811115611ba557600080fd5b602083019150836020828501011115611bbd57600080fd5b9250929050565b803563ffffffff81168114611bd857600080fd5b919050565b60008060008060608587031215611bf357600080fd5b8435611bfe81611b56565b9350602085013567ffffffffffffffff811115611c1a57600080fd5b611c2687828801611b7b565b9094509250611c39905060408601611bc4565b905092959194509250565b6000815180845260005b81811015611c6a57602081850181015186830182015201611c4e565b81811115611c7c576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611cc26020830184611c44565b9392505050565b600060208284031215611cdb57600080fd5b5035919050565b600080600060408486031215611cf757600080fd5b833567ffffffffffffffff811115611d0e57600080fd5b611d1a86828701611b7b565b9094509250611d2d905060208501611bc4565b90509250925092565b600080600060608486031215611d4b57600080fd5b8335611d5681611b56565b92506020840135611d6681611b56565b91506040840135611d7681611b56565b809150509250925092565b600080600080600080600060c0888a031215611d9c57600080fd5b873596506020880135611dae81611b56565b95506040880135611dbe81611b56565b9450606088013593506080880135925060a088013567ffffffffffffffff811115611de857600080fd5b611df48a828b01611b7b565b989b979a50959850939692959293505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b878152600073ffffffffffffffffffffffffffffffffffffffff808916602084015280881660408401525085606083015263ffffffff8516608083015260c060a0830152611ea260c083018486611e07565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff86168152608060208201526000611edf608083018688611e07565b905083604083015263ffffffff831660608301529695505050505050565b600060208284031215611f0f57600080fd5b81518015158114611cc257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff80831681851681830481118215151615611f7557611f75611f1f565b02949350505050565b600067ffffffffffffffff80841680611fc0577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b92169190910492915050565b600067ffffffffffffffff808316818516808303821115611fef57611fef611f1f565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b60008282101561203957612039611f1f565b500390565b73ffffffffffffffffffffffffffffffffffffffff8616815284602082015267ffffffffffffffff84166040820152821515606082015260a06080820152600061208b60a0830184611c44565b979650505050505050565b6000602082840312156120a857600080fd5b8151611cc281611b56565b600080604083850312156120c657600080fd5b82516120d181611b56565b602084015190925060ff811681146120e857600080fd5b809150509250929050565b600073ffffffffffffffffffffffffffffffffffffffff80871683528086166020840152506080604083015261212c6080830185611c44565b905082606083015295945050505050565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a083015261218860c0830184611c44565b9897505050505050505056fea164736f6c634300080f000a", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [], - "value": 0 - }, - { - "accessor": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "account": "0x094e6508ba9d9bf1ce421fff3dE06aE56e67901b", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x60806040523480156200001157600080fd5b50620000206000808062000026565b6200028e565b600054600160a81b900460ff16158080156200004f57506000546001600160a01b90910460ff16105b806200008657506200006c30620001c860201b620015b71760201c565b158015620000865750600054600160a01b900460ff166001145b620000ef5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff60a01b1916600160a01b17905580156200011d576000805460ff60a81b1916600160a81b1790555b60fb80546001600160a01b038087166001600160a01b03199283161790925560fc805486841690831617905560fd80549285169290911691909117905562000179734200000000000000000000000000000000000007620001d7565b8015620001c2576000805460ff60a81b19169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b6001600160a01b03163b151590565b600054600160a81b900460ff16620002465760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401620000e6565b60cc546001600160a01b03166200026c5760cc80546001600160a01b03191661dead1790555b60cf80546001600160a01b0319166001600160a01b0392909216919091179055565b6121a1806200029e6000396000f3fe60806040526004361061018b5760003560e01c80636425666b116100d6578063b1b1b2091161007f578063d764ad0b11610059578063d764ad0b1461049b578063db505d80146104ae578063ecc70428146104db57600080fd5b8063b1b1b2091461042b578063b28ade251461045b578063c0c53b8b1461047b57600080fd5b80638cbeeef2116100b05780638cbeeef2146102d05780639fce812c146103d0578063a4e7f8bd146103fb57600080fd5b80636425666b146103775780636e296e45146103a457806383a74074146103b957600080fd5b80633dbb202b1161013857806354fd4d501161011257806354fd4d50146102e65780635644cfdf1461033c5780635c975abb1461035257600080fd5b80633dbb202b146102935780633f827a5a146102a85780634c1d6a69146102d057600080fd5b80632828d7e8116101695780632828d7e81461022457806333d7e2bd1461023957806335e80ab31461026657600080fd5b8063028f85f7146101905780630c568498146101c35780630ff754ea146101d8575b600080fd5b34801561019c57600080fd5b506101a5601081565b60405167ffffffffffffffff90911681526020015b60405180910390f35b3480156101cf57600080fd5b506101a5603f81565b3480156101e457600080fd5b5060fc5473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101ba565b34801561023057600080fd5b506101a5604081565b34801561024557600080fd5b5060fd546101ff9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561027257600080fd5b5060fb546101ff9073ffffffffffffffffffffffffffffffffffffffff1681565b6102a66102a1366004611bdd565b610540565b005b3480156102b457600080fd5b506102bd600181565b60405161ffff90911681526020016101ba565b3480156102dc57600080fd5b506101a5619c4081565b3480156102f257600080fd5b5061032f6040518060400160405280600581526020017f322e342e3000000000000000000000000000000000000000000000000000000081525081565b6040516101ba9190611caf565b34801561034857600080fd5b506101a561138881565b34801561035e57600080fd5b5061036761083d565b60405190151581526020016101ba565b34801561038357600080fd5b5060fc546101ff9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156103b057600080fd5b506101ff6108d6565b3480156103c557600080fd5b506101a562030d4081565b3480156103dc57600080fd5b5060cf5473ffffffffffffffffffffffffffffffffffffffff166101ff565b34801561040757600080fd5b50610367610416366004611cc9565b60ce6020526000908152604090205460ff1681565b34801561043757600080fd5b50610367610446366004611cc9565b60cb6020526000908152604090205460ff1681565b34801561046757600080fd5b506101a5610476366004611ce2565b6109bd565b34801561048757600080fd5b506102a6610496366004611d36565b610a2b565b6102a66104a9366004611d81565b610ca2565b3480156104ba57600080fd5b5060cf546101ff9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156104e757600080fd5b5061053260cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b6040519081526020016101ba565b6105486115d3565b156105e05734156105e0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f43726f7373446f6d61696e4d657373656e6765723a2063616e6e6f742073656e60448201527f642076616c7565207769746820637573746f6d2067617320746f6b656e00000060648201526084015b60405180910390fd5b60cf546107129073ffffffffffffffffffffffffffffffffffffffff166106088585856109bd565b347fd764ad0b0000000000000000000000000000000000000000000000000000000061067460cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b338a34898c8c6040516024016106909796959493929190611e50565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611612565b8373ffffffffffffffffffffffffffffffffffffffff167fcb0f7ffd78f9aee47a248fae8db181db6eee833039123e026dcbff529522e52a33858561079760cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b866040516107a9959493929190611eaf565b60405180910390a260405134815233907f8ebb2ec2465bdb2a06a66fc37a0963af8a2a6a1479d81d56fdb8cbb98096d5469060200160405180910390a2505060cd80547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808216600101167fffff0000000000000000000000000000000000000000000000000000000000009091161790555050565b60fb54604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa1580156108ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108d19190611efd565b905090565b60cc5460009073ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2153016109a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f43726f7373446f6d61696e4d657373656e6765723a2078446f6d61696e4d657360448201527f7361676553656e646572206973206e6f7420736574000000000000000000000060648201526084016105d7565b5060cc5473ffffffffffffffffffffffffffffffffffffffff1690565b6000611388619c4080603f6109d9604063ffffffff8816611f4e565b6109e39190611f7e565b6109ee601088611f4e565b6109fb9062030d40611fcc565b610a059190611fcc565b610a0f9190611fcc565b610a199190611fcc565b610a239190611fcc565b949350505050565b6000547501000000000000000000000000000000000000000000900460ff1615808015610a76575060005460017401000000000000000000000000000000000000000090910460ff16105b80610aa85750303b158015610aa8575060005474010000000000000000000000000000000000000000900460ff166001145b610b34576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016105d7565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790558015610bba57600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000001790555b60fb805473ffffffffffffffffffffffffffffffffffffffff8087167fffffffffffffffffffffffff00000000000000000000000000000000000000009283161790925560fc805486841690831617905560fd805492851692909116919091179055610c397342000000000000000000000000000000000000076116ab565b8015610c9c57600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b610caa61083d565b15610d11576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f43726f7373446f6d61696e4d657373656e6765723a207061757365640000000060448201526064016105d7565b60f087901c60028110610dcc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f43726f7373446f6d61696e4d657373656e6765723a206f6e6c7920766572736960448201527f6f6e2030206f722031206d657373616765732061726520737570706f7274656460648201527f20617420746869732074696d6500000000000000000000000000000000000000608482015260a4016105d7565b8061ffff16600003610ec1576000610e1d878986868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508f92506117e7915050565b600081815260cb602052604090205490915060ff1615610ebf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f43726f7373446f6d61696e4d657373656e6765723a206c65676163792077697460448201527f6864726177616c20616c72656164792072656c6179656400000000000000000060648201526084016105d7565b505b6000610f07898989898989898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061180692505050565b9050610f11611829565b15610f4957853414610f2557610f25611ff8565b600081815260ce602052604090205460ff1615610f4457610f44611ff8565b61109b565b3415610ffd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605060248201527f43726f7373446f6d61696e4d657373656e6765723a2076616c7565206d75737460448201527f206265207a65726f20756e6c657373206d6573736167652069732066726f6d2060648201527f612073797374656d206164647265737300000000000000000000000000000000608482015260a4016105d7565b600081815260ce602052604090205460ff1661109b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520636160448201527f6e6e6f74206265207265706c617965640000000000000000000000000000000060648201526084016105d7565b6110a487611905565b15611157576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f43726f7373446f6d61696e4d657373656e6765723a2063616e6e6f742073656e60448201527f64206d65737361676520746f20626c6f636b65642073797374656d206164647260648201527f6573730000000000000000000000000000000000000000000000000000000000608482015260a4016105d7565b600081815260cb602052604090205460ff16156111f6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520686160448201527f7320616c7265616479206265656e2072656c617965640000000000000000000060648201526084016105d7565b61121785611208611388619c40611fcc565b67ffffffffffffffff1661194b565b158061123d575060cc5473ffffffffffffffffffffffffffffffffffffffff1661dead14155b1561135657600081815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555182917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff320161134f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d6573736167650000000000000000000000000000000000000060648201526084016105d7565b50506115ae565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8a1617905560006113e788619c405a6113aa9190612027565b8988888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061196992505050565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790559050801561149d57600082815260cb602052604090205460ff161561143a5761143a611ff8565b600082815260cb602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f4641df4a962071e12719d8c8c8e5ac7fc4d97b927346a3d7a335b1f7517e133c91a26115aa565b600082815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff32016115aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d6573736167650000000000000000000000000000000000000060648201526084016105d7565b5050505b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6000806115de611981565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b60fc546040517fe9e05c4200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063e9e05c4290849061167390889083908990600090899060040161203e565b6000604051808303818588803b15801561168c57600080fd5b505af11580156116a0573d6000803e3d6000fd5b505050505050505050565b6000547501000000000000000000000000000000000000000000900460ff16611756576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016105d7565b60cc5473ffffffffffffffffffffffffffffffffffffffff166117a05760cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790555b60cf80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60006117f585858585611a1e565b805190602001209050949350505050565b6000611816878787878787611ab7565b8051906020012090509695505050505050565b60fc5460009073ffffffffffffffffffffffffffffffffffffffff16331480156108d1575060cf5460fc54604080517f9bf62d82000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9384169390921691639bf62d82916004808201926020929091908290030181865afa1580156118c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118e99190612096565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b600073ffffffffffffffffffffffffffffffffffffffff8216301480611945575060fc5473ffffffffffffffffffffffffffffffffffffffff8381169116145b92915050565b600080603f83619c4001026040850201603f5a021015949350505050565b6000806000835160208501868989f195945050505050565b60fd54604080517f4397dfef0000000000000000000000000000000000000000000000000000000081528151600093849373ffffffffffffffffffffffffffffffffffffffff90911692634397dfef92600480830193928290030181865afa1580156119f1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a1591906120b3565b90939092509050565b606084848484604051602401611a3794939291906120f3565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fcbd4ece9000000000000000000000000000000000000000000000000000000001790529050949350505050565b6060868686868686604051602401611ad49695949392919061213d565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd764ad0b0000000000000000000000000000000000000000000000000000000017905290509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff81168114611b7857600080fd5b50565b60008083601f840112611b8d57600080fd5b50813567ffffffffffffffff811115611ba557600080fd5b602083019150836020828501011115611bbd57600080fd5b9250929050565b803563ffffffff81168114611bd857600080fd5b919050565b60008060008060608587031215611bf357600080fd5b8435611bfe81611b56565b9350602085013567ffffffffffffffff811115611c1a57600080fd5b611c2687828801611b7b565b9094509250611c39905060408601611bc4565b905092959194509250565b6000815180845260005b81811015611c6a57602081850181015186830182015201611c4e565b81811115611c7c576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611cc26020830184611c44565b9392505050565b600060208284031215611cdb57600080fd5b5035919050565b600080600060408486031215611cf757600080fd5b833567ffffffffffffffff811115611d0e57600080fd5b611d1a86828701611b7b565b9094509250611d2d905060208501611bc4565b90509250925092565b600080600060608486031215611d4b57600080fd5b8335611d5681611b56565b92506020840135611d6681611b56565b91506040840135611d7681611b56565b809150509250925092565b600080600080600080600060c0888a031215611d9c57600080fd5b873596506020880135611dae81611b56565b95506040880135611dbe81611b56565b9450606088013593506080880135925060a088013567ffffffffffffffff811115611de857600080fd5b611df48a828b01611b7b565b989b979a50959850939692959293505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b878152600073ffffffffffffffffffffffffffffffffffffffff808916602084015280881660408401525085606083015263ffffffff8516608083015260c060a0830152611ea260c083018486611e07565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff86168152608060208201526000611edf608083018688611e07565b905083604083015263ffffffff831660608301529695505050505050565b600060208284031215611f0f57600080fd5b81518015158114611cc257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff80831681851681830481118215151615611f7557611f75611f1f565b02949350505050565b600067ffffffffffffffff80841680611fc0577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b92169190910492915050565b600067ffffffffffffffff808316818516808303821115611fef57611fef611f1f565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b60008282101561203957612039611f1f565b500390565b73ffffffffffffffffffffffffffffffffffffffff8616815284602082015267ffffffffffffffff84166040820152821515606082015260a06080820152600061208b60a0830184611c44565b979650505050505050565b6000602082840312156120a857600080fd5b8151611cc281611b56565b600080604083850312156120c657600080fd5b82516120d181611b56565b602084015190925060ff811681146120e857600080fd5b809150509250929050565b600073ffffffffffffffffffffffffffffffffffffffff80871683528086166020840152506080604083015261212c6080830185611c44565b905082606083015295945050505050565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a083015261218860c0830184611c44565b9897505050505050505056fea164736f6c634300080f000a", - "deployedCode": "0x60806040526004361061018b5760003560e01c80636425666b116100d6578063b1b1b2091161007f578063d764ad0b11610059578063d764ad0b1461049b578063db505d80146104ae578063ecc70428146104db57600080fd5b8063b1b1b2091461042b578063b28ade251461045b578063c0c53b8b1461047b57600080fd5b80638cbeeef2116100b05780638cbeeef2146102d05780639fce812c146103d0578063a4e7f8bd146103fb57600080fd5b80636425666b146103775780636e296e45146103a457806383a74074146103b957600080fd5b80633dbb202b1161013857806354fd4d501161011257806354fd4d50146102e65780635644cfdf1461033c5780635c975abb1461035257600080fd5b80633dbb202b146102935780633f827a5a146102a85780634c1d6a69146102d057600080fd5b80632828d7e8116101695780632828d7e81461022457806333d7e2bd1461023957806335e80ab31461026657600080fd5b8063028f85f7146101905780630c568498146101c35780630ff754ea146101d8575b600080fd5b34801561019c57600080fd5b506101a5601081565b60405167ffffffffffffffff90911681526020015b60405180910390f35b3480156101cf57600080fd5b506101a5603f81565b3480156101e457600080fd5b5060fc5473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101ba565b34801561023057600080fd5b506101a5604081565b34801561024557600080fd5b5060fd546101ff9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561027257600080fd5b5060fb546101ff9073ffffffffffffffffffffffffffffffffffffffff1681565b6102a66102a1366004611bdd565b610540565b005b3480156102b457600080fd5b506102bd600181565b60405161ffff90911681526020016101ba565b3480156102dc57600080fd5b506101a5619c4081565b3480156102f257600080fd5b5061032f6040518060400160405280600581526020017f322e342e3000000000000000000000000000000000000000000000000000000081525081565b6040516101ba9190611caf565b34801561034857600080fd5b506101a561138881565b34801561035e57600080fd5b5061036761083d565b60405190151581526020016101ba565b34801561038357600080fd5b5060fc546101ff9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156103b057600080fd5b506101ff6108d6565b3480156103c557600080fd5b506101a562030d4081565b3480156103dc57600080fd5b5060cf5473ffffffffffffffffffffffffffffffffffffffff166101ff565b34801561040757600080fd5b50610367610416366004611cc9565b60ce6020526000908152604090205460ff1681565b34801561043757600080fd5b50610367610446366004611cc9565b60cb6020526000908152604090205460ff1681565b34801561046757600080fd5b506101a5610476366004611ce2565b6109bd565b34801561048757600080fd5b506102a6610496366004611d36565b610a2b565b6102a66104a9366004611d81565b610ca2565b3480156104ba57600080fd5b5060cf546101ff9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156104e757600080fd5b5061053260cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b6040519081526020016101ba565b6105486115d3565b156105e05734156105e0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f43726f7373446f6d61696e4d657373656e6765723a2063616e6e6f742073656e60448201527f642076616c7565207769746820637573746f6d2067617320746f6b656e00000060648201526084015b60405180910390fd5b60cf546107129073ffffffffffffffffffffffffffffffffffffffff166106088585856109bd565b347fd764ad0b0000000000000000000000000000000000000000000000000000000061067460cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b338a34898c8c6040516024016106909796959493929190611e50565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611612565b8373ffffffffffffffffffffffffffffffffffffffff167fcb0f7ffd78f9aee47a248fae8db181db6eee833039123e026dcbff529522e52a33858561079760cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b866040516107a9959493929190611eaf565b60405180910390a260405134815233907f8ebb2ec2465bdb2a06a66fc37a0963af8a2a6a1479d81d56fdb8cbb98096d5469060200160405180910390a2505060cd80547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808216600101167fffff0000000000000000000000000000000000000000000000000000000000009091161790555050565b60fb54604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa1580156108ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108d19190611efd565b905090565b60cc5460009073ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2153016109a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f43726f7373446f6d61696e4d657373656e6765723a2078446f6d61696e4d657360448201527f7361676553656e646572206973206e6f7420736574000000000000000000000060648201526084016105d7565b5060cc5473ffffffffffffffffffffffffffffffffffffffff1690565b6000611388619c4080603f6109d9604063ffffffff8816611f4e565b6109e39190611f7e565b6109ee601088611f4e565b6109fb9062030d40611fcc565b610a059190611fcc565b610a0f9190611fcc565b610a199190611fcc565b610a239190611fcc565b949350505050565b6000547501000000000000000000000000000000000000000000900460ff1615808015610a76575060005460017401000000000000000000000000000000000000000090910460ff16105b80610aa85750303b158015610aa8575060005474010000000000000000000000000000000000000000900460ff166001145b610b34576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016105d7565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790558015610bba57600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000001790555b60fb805473ffffffffffffffffffffffffffffffffffffffff8087167fffffffffffffffffffffffff00000000000000000000000000000000000000009283161790925560fc805486841690831617905560fd805492851692909116919091179055610c397342000000000000000000000000000000000000076116ab565b8015610c9c57600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b610caa61083d565b15610d11576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f43726f7373446f6d61696e4d657373656e6765723a207061757365640000000060448201526064016105d7565b60f087901c60028110610dcc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f43726f7373446f6d61696e4d657373656e6765723a206f6e6c7920766572736960448201527f6f6e2030206f722031206d657373616765732061726520737570706f7274656460648201527f20617420746869732074696d6500000000000000000000000000000000000000608482015260a4016105d7565b8061ffff16600003610ec1576000610e1d878986868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508f92506117e7915050565b600081815260cb602052604090205490915060ff1615610ebf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f43726f7373446f6d61696e4d657373656e6765723a206c65676163792077697460448201527f6864726177616c20616c72656164792072656c6179656400000000000000000060648201526084016105d7565b505b6000610f07898989898989898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061180692505050565b9050610f11611829565b15610f4957853414610f2557610f25611ff8565b600081815260ce602052604090205460ff1615610f4457610f44611ff8565b61109b565b3415610ffd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605060248201527f43726f7373446f6d61696e4d657373656e6765723a2076616c7565206d75737460448201527f206265207a65726f20756e6c657373206d6573736167652069732066726f6d2060648201527f612073797374656d206164647265737300000000000000000000000000000000608482015260a4016105d7565b600081815260ce602052604090205460ff1661109b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520636160448201527f6e6e6f74206265207265706c617965640000000000000000000000000000000060648201526084016105d7565b6110a487611905565b15611157576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f43726f7373446f6d61696e4d657373656e6765723a2063616e6e6f742073656e60448201527f64206d65737361676520746f20626c6f636b65642073797374656d206164647260648201527f6573730000000000000000000000000000000000000000000000000000000000608482015260a4016105d7565b600081815260cb602052604090205460ff16156111f6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520686160448201527f7320616c7265616479206265656e2072656c617965640000000000000000000060648201526084016105d7565b61121785611208611388619c40611fcc565b67ffffffffffffffff1661194b565b158061123d575060cc5473ffffffffffffffffffffffffffffffffffffffff1661dead14155b1561135657600081815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555182917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff320161134f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d6573736167650000000000000000000000000000000000000060648201526084016105d7565b50506115ae565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8a1617905560006113e788619c405a6113aa9190612027565b8988888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061196992505050565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790559050801561149d57600082815260cb602052604090205460ff161561143a5761143a611ff8565b600082815260cb602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f4641df4a962071e12719d8c8c8e5ac7fc4d97b927346a3d7a335b1f7517e133c91a26115aa565b600082815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff32016115aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d6573736167650000000000000000000000000000000000000060648201526084016105d7565b5050505b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6000806115de611981565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b60fc546040517fe9e05c4200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063e9e05c4290849061167390889083908990600090899060040161203e565b6000604051808303818588803b15801561168c57600080fd5b505af11580156116a0573d6000803e3d6000fd5b505050505050505050565b6000547501000000000000000000000000000000000000000000900460ff16611756576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016105d7565b60cc5473ffffffffffffffffffffffffffffffffffffffff166117a05760cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790555b60cf80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60006117f585858585611a1e565b805190602001209050949350505050565b6000611816878787878787611ab7565b8051906020012090509695505050505050565b60fc5460009073ffffffffffffffffffffffffffffffffffffffff16331480156108d1575060cf5460fc54604080517f9bf62d82000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9384169390921691639bf62d82916004808201926020929091908290030181865afa1580156118c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118e99190612096565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b600073ffffffffffffffffffffffffffffffffffffffff8216301480611945575060fc5473ffffffffffffffffffffffffffffffffffffffff8381169116145b92915050565b600080603f83619c4001026040850201603f5a021015949350505050565b6000806000835160208501868989f195945050505050565b60fd54604080517f4397dfef0000000000000000000000000000000000000000000000000000000081528151600093849373ffffffffffffffffffffffffffffffffffffffff90911692634397dfef92600480830193928290030181865afa1580156119f1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a1591906120b3565b90939092509050565b606084848484604051602401611a3794939291906120f3565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fcbd4ece9000000000000000000000000000000000000000000000000000000001790529050949350505050565b6060868686868686604051602401611ad49695949392919061213d565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd764ad0b0000000000000000000000000000000000000000000000000000000017905290509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff81168114611b7857600080fd5b50565b60008083601f840112611b8d57600080fd5b50813567ffffffffffffffff811115611ba557600080fd5b602083019150836020828501011115611bbd57600080fd5b9250929050565b803563ffffffff81168114611bd857600080fd5b919050565b60008060008060608587031215611bf357600080fd5b8435611bfe81611b56565b9350602085013567ffffffffffffffff811115611c1a57600080fd5b611c2687828801611b7b565b9094509250611c39905060408601611bc4565b905092959194509250565b6000815180845260005b81811015611c6a57602081850181015186830182015201611c4e565b81811115611c7c576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611cc26020830184611c44565b9392505050565b600060208284031215611cdb57600080fd5b5035919050565b600080600060408486031215611cf757600080fd5b833567ffffffffffffffff811115611d0e57600080fd5b611d1a86828701611b7b565b9094509250611d2d905060208501611bc4565b90509250925092565b600080600060608486031215611d4b57600080fd5b8335611d5681611b56565b92506020840135611d6681611b56565b91506040840135611d7681611b56565b809150509250925092565b600080600080600080600060c0888a031215611d9c57600080fd5b873596506020880135611dae81611b56565b95506040880135611dbe81611b56565b9450606088013593506080880135925060a088013567ffffffffffffffff811115611de857600080fd5b611df48a828b01611b7b565b989b979a50959850939692959293505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b878152600073ffffffffffffffffffffffffffffffffffffffff808916602084015280881660408401525085606083015263ffffffff8516608083015260c060a0830152611ea260c083018486611e07565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff86168152608060208201526000611edf608083018688611e07565b905083604083015263ffffffff831660608301529695505050505050565b600060208284031215611f0f57600080fd5b81518015158114611cc257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff80831681851681830481118215151615611f7557611f75611f1f565b02949350505050565b600067ffffffffffffffff80841680611fc0577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b92169190910492915050565b600067ffffffffffffffff808316818516808303821115611fef57611fef611f1f565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b60008282101561203957612039611f1f565b500390565b73ffffffffffffffffffffffffffffffffffffffff8616815284602082015267ffffffffffffffff84166040820152821515606082015260a06080820152600061208b60a0830184611c44565b979650505050505050565b6000602082840312156120a857600080fd5b8151611cc281611b56565b600080604083850312156120c657600080fd5b82516120d181611b56565b602084015190925060ff811681146120e857600080fd5b809150509250929050565b600073ffffffffffffffffffffffffffffffffffffffff80871683528086166020840152506080604083015261212c6080830185611c44565b905082606083015295945050505050565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a083015261218860c0830184611c44565b9897505050505050505056fea164736f6c634300080f000a", - "initialized": true, - "kind": "Create", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x094e6508ba9d9bf1ce421fff3dE06aE56e67901b", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x094e6508ba9d9bf1ce421fff3dE06aE56e67901b", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x094e6508ba9d9bf1ce421fff3dE06aE56e67901b", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x094e6508ba9d9bf1ce421fff3dE06aE56e67901b", - "isWrite": true, - "newValue": "0x0000000000000000000000010000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x094e6508ba9d9bf1ce421fff3dE06aE56e67901b", - "isWrite": false, - "newValue": "0x0000000000000000000000010000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000010000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x094e6508ba9d9bf1ce421fff3dE06aE56e67901b", - "isWrite": true, - "newValue": "0x0000000000000000000001010000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000010000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x094e6508ba9d9bf1ce421fff3dE06aE56e67901b", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x00000000000000000000000000000000000000000000000000000000000000fb" - }, - { - "account": "0x094e6508ba9d9bf1ce421fff3dE06aE56e67901b", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x00000000000000000000000000000000000000000000000000000000000000fb" - }, - { - "account": "0x094e6508ba9d9bf1ce421fff3dE06aE56e67901b", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x00000000000000000000000000000000000000000000000000000000000000fc" - }, - { - "account": "0x094e6508ba9d9bf1ce421fff3dE06aE56e67901b", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x00000000000000000000000000000000000000000000000000000000000000fc" - }, - { - "account": "0x094e6508ba9d9bf1ce421fff3dE06aE56e67901b", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x00000000000000000000000000000000000000000000000000000000000000fd" - }, - { - "account": "0x094e6508ba9d9bf1ce421fff3dE06aE56e67901b", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x00000000000000000000000000000000000000000000000000000000000000fd" - }, - { - "account": "0x094e6508ba9d9bf1ce421fff3dE06aE56e67901b", - "isWrite": false, - "newValue": "0x0000000000000000000001010000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000001010000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x094e6508ba9d9bf1ce421fff3dE06aE56e67901b", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x00000000000000000000000000000000000000000000000000000000000000cc" - }, - { - "account": "0x094e6508ba9d9bf1ce421fff3dE06aE56e67901b", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x00000000000000000000000000000000000000000000000000000000000000cc" - }, - { - "account": "0x094e6508ba9d9bf1ce421fff3dE06aE56e67901b", - "isWrite": true, - "newValue": "0x000000000000000000000000000000000000000000000000000000000000dead", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x00000000000000000000000000000000000000000000000000000000000000cc" - }, - { - "account": "0x094e6508ba9d9bf1ce421fff3dE06aE56e67901b", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x00000000000000000000000000000000000000000000000000000000000000cf" - }, - { - "account": "0x094e6508ba9d9bf1ce421fff3dE06aE56e67901b", - "isWrite": true, - "newValue": "0x0000000000000000000000004200000000000000000000000000000000000007", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x00000000000000000000000000000000000000000000000000000000000000cf" - }, - { - "account": "0x094e6508ba9d9bf1ce421fff3dE06aE56e67901b", - "isWrite": false, - "newValue": "0x0000000000000000000001010000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000001010000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x094e6508ba9d9bf1ce421fff3dE06aE56e67901b", - "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": "0x094e6508ba9d9bf1ce421fff3dE06aE56e67901b", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x9fce812c", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x094e6508ba9d9bf1ce421fff3dE06aE56e67901b", - "isWrite": false, - "newValue": "0x0000000000000000000000004200000000000000000000000000000000000007", - "previousValue": "0x0000000000000000000000004200000000000000000000000000000000000007", - "reverted": false, - "slot": "0x00000000000000000000000000000000000000000000000000000000000000cf" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x094e6508ba9d9bf1ce421fff3dE06aE56e67901b", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xdb505d80", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x094e6508ba9d9bf1ce421fff3dE06aE56e67901b", - "isWrite": false, - "newValue": "0x0000000000000000000000004200000000000000000000000000000000000007", - "previousValue": "0x0000000000000000000000004200000000000000000000000000000000000007", - "reverted": false, - "slot": "0x00000000000000000000000000000000000000000000000000000000000000cf" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x094e6508ba9d9bf1ce421fff3dE06aE56e67901b", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x0ff754ea", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x094e6508ba9d9bf1ce421fff3dE06aE56e67901b", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x00000000000000000000000000000000000000000000000000000000000000fc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x094e6508ba9d9bf1ce421fff3dE06aE56e67901b", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x6425666b", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x094e6508ba9d9bf1ce421fff3dE06aE56e67901b", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x00000000000000000000000000000000000000000000000000000000000000fc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x094e6508ba9d9bf1ce421fff3dE06aE56e67901b", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x35e80ab3", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x094e6508ba9d9bf1ce421fff3dE06aE56e67901b", - "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": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x638627e586f5e36fe67a77519503a7c6da22f92b150d3c6055fd40bdcfe9ffd1608060405234801561001057600080fd5b5061001b6000610020565b610169565b600054610100900460ff16158080156100405750600054600160ff909116105b8061006b57506100593061015a60201b6105fe1760201c565b15801561006b575060005460ff166001145b6100d25760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840160405180910390fd5b6000805460ff1916600117905580156100f5576000805461ff0019166101001790555b600180546001600160a01b0319166001600160a01b0384161790558015610156576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6001600160a01b03163b151590565b612146806101786000396000f3fe60806040523480156200001157600080fd5b5060043610620000935760003560e01c8063c4d66de81162000062578063c4d66de81462000175578063ce5ac90f146200018e578063e78cea9214620001a5578063ee9a31a214620001c657600080fd5b8063316b3739146200009857806354fd4d5014620000fb578063896f93d114620001475780638cf0629c146200015e575b600080fd5b620000d1620000a936600462000652565b60026020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b620001386040518060400160405280600681526020017f312e31302e30000000000000000000000000000000000000000000000000000081525081565b604051620000f29190620006e5565b620000d162000158366004620007dc565b620001e5565b620000d16200016f36600462000859565b620001fc565b6200018c6200018636600462000652565b6200041b565b005b620000d16200019f366004620007dc565b620005ed565b600154620000d19073ffffffffffffffffffffffffffffffffffffffff1681565b60015473ffffffffffffffffffffffffffffffffffffffff16620000d1565b6000620001f4848484620005ed565b949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8516620002a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d4d696e7461626c654552433230466163746f72793a206d7560448201527f73742070726f766964652072656d6f746520746f6b656e20616464726573730060648201526084015b60405180910390fd5b600085858585604051602001620002c29493929190620008f0565b604051602081830303815290604052805190602001209050600081600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168888888860405162000312906200061a565b620003229594939291906200094a565b8190604051809103906000f590508015801562000343573d6000803e3d6000fd5b5073ffffffffffffffffffffffffffffffffffffffff81811660008181526002602052604080822080547fffffffffffffffffffffffff000000000000000000000000000000000000000016948d1694851790555193945090927fceeb8e7d520d7f3b65fc11a262b91066940193b05d4f93df07cfdced0eb551cf9190a360405133815273ffffffffffffffffffffffffffffffffffffffff80891691908316907f52fe89dd5930f343d25650b62fd367bae47088bcddffd2a88350a6ecdd620cdb9060200160405180910390a39695505050505050565b600054610100900460ff16158080156200043c5750600054600160ff909116105b80620004585750303b15801562000458575060005460ff166001145b620004e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016200029e565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156200054557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84161790558015620005e957600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6000620001f48484846012620001fc565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b61178a80620009b083390190565b803573ffffffffffffffffffffffffffffffffffffffff811681146200064d57600080fd5b919050565b6000602082840312156200066557600080fd5b620006708262000628565b9392505050565b6000815180845260005b818110156200069f5760208185018101518683018201520162000681565b81811115620006b2576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600062000670602083018462000677565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126200073b57600080fd5b813567ffffffffffffffff80821115620007595762000759620006fa565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715620007a257620007a2620006fa565b81604052838152866020858801011115620007bc57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600060608486031215620007f257600080fd5b620007fd8462000628565b9250602084013567ffffffffffffffff808211156200081b57600080fd5b620008298783880162000729565b935060408601359150808211156200084057600080fd5b506200084f8682870162000729565b9150509250925092565b600080600080608085870312156200087057600080fd5b6200087b8562000628565b9350602085013567ffffffffffffffff808211156200089957600080fd5b620008a78883890162000729565b94506040870135915080821115620008be57600080fd5b50620008cd8782880162000729565b925050606085013560ff81168114620008e557600080fd5b939692955090935050565b73ffffffffffffffffffffffffffffffffffffffff8516815260806020820152600062000921608083018662000677565b828103604084015262000935818662000677565b91505060ff8316606083015295945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808816835280871660208401525060a060408301526200098560a083018662000677565b828103606084015262000999818662000677565b91505060ff83166080830152969550505050505056fe60e06040523480156200001157600080fd5b506040516200178a3803806200178a833981016040819052620000349162000163565b828260036200004483826200029e565b5060046200005382826200029e565b5050506001600160a01b039384166080529390921660a052505060ff1660c0526200036a565b80516001600160a01b03811681146200009157600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620000be57600080fd5b81516001600160401b0380821115620000db57620000db62000096565b604051601f8301601f19908116603f0116810190828211818310171562000106576200010662000096565b816040528381526020925086838588010111156200012357600080fd5b600091505b8382101562000147578582018301518183018401529082019062000128565b83821115620001595760008385830101525b9695505050505050565b600080600080600060a086880312156200017c57600080fd5b620001878662000079565b9450620001976020870162000079565b60408701519094506001600160401b0380821115620001b557600080fd5b620001c389838a01620000ac565b94506060880151915080821115620001da57600080fd5b50620001e988828901620000ac565b925050608086015160ff811681146200020157600080fd5b809150509295509295909350565b600181811c908216806200022457607f821691505b6020821081036200024557634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200029957600081815260208120601f850160051c81016020861015620002745750805b601f850160051c820191505b81811015620002955782815560010162000280565b5050505b505050565b81516001600160401b03811115620002ba57620002ba62000096565b620002d281620002cb84546200020f565b846200024b565b602080601f8311600181146200030a5760008415620002f15750858301515b600019600386901b1c1916600185901b17855562000295565b600085815260208120601f198616915b828110156200033b578886015182559484019460019091019084016200031a565b50858210156200035a5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c0516113d4620003b6600039600061024401526000818161034b015281816103e001528181610625015261075c0152600081816101a9015261037101526113d46000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063ae1f6aaf1161008c578063dd62ed3e11610066578063dd62ed3e14610395578063e78cea9214610349578063ee9a31a2146103db57600080fd5b8063ae1f6aaf14610349578063c01e1bd61461036f578063d6c0b2c41461036f57600080fd5b80639dc29fac116100bd5780639dc29fac14610310578063a457c2d714610323578063a9059cbb1461033657600080fd5b806370a08231146102d257806395d89b411461030857600080fd5b806323b872dd1161012f5780633950935111610114578063395093511461026e57806340c10f191461028157806354fd4d501461029657600080fd5b806323b872dd1461022a578063313ce5671461023d57600080fd5b806306fdde031161016057806306fdde03146101f0578063095ea7b31461020557806318160ddd1461021857600080fd5b806301ffc9a71461017c578063033964be146101a4575b600080fd5b61018f61018a36600461117d565b610402565b60405190151581526020015b60405180910390f35b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101f86104f3565b60405161019b91906111c6565b61018f610213366004611262565b610585565b6002545b60405190815260200161019b565b61018f61023836600461128c565b61059d565b60405160ff7f000000000000000000000000000000000000000000000000000000000000000016815260200161019b565b61018f61027c366004611262565b6105c1565b61029461028f366004611262565b61060d565b005b6101f86040518060400160405280600581526020017f312e332e3000000000000000000000000000000000000000000000000000000081525081565b61021c6102e03660046112c8565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101f8610735565b61029461031e366004611262565b610744565b61018f610331366004611262565b61085b565b61018f610344366004611262565b61092c565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b61021c6103a33660046112e3565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f1d1d8b63000000000000000000000000000000000000000000000000000000007fec4fc8e3000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000085168314806104bb57507fffffffff00000000000000000000000000000000000000000000000000000000858116908316145b806104ea57507fffffffff00000000000000000000000000000000000000000000000000000000858116908216145b95945050505050565b60606003805461050290611316565b80601f016020809104026020016040519081016040528092919081815260200182805461052e90611316565b801561057b5780601f106105505761010080835404028352916020019161057b565b820191906000526020600020905b81548152906001019060200180831161055e57829003601f168201915b5050505050905090565b60003361059381858561093a565b5060019392505050565b6000336105ab858285610aee565b6105b6858585610bc5565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906105939082908690610608908790611398565b61093a565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146106d7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084015b60405180910390fd5b6106e18282610e78565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d41213968858260405161072991815260200190565b60405180910390a25050565b60606004805461050290611316565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610809576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084016106ce565b6108138282610f98565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca58260405161072991815260200190565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091908381101561091f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084016106ce565b6105b6828686840361093a565b600033610593818585610bc5565b73ffffffffffffffffffffffffffffffffffffffff83166109dc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f726573730000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216610a7f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f737300000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610bbf5781811015610bb2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016106ce565b610bbf848484840361093a565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610c68576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216610d0b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f657373000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610dc1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e6365000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220858503905591851681529081208054849290610e05908490611398565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610e6b91815260200190565b60405180910390a3610bbf565b73ffffffffffffffffffffffffffffffffffffffff8216610ef5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016106ce565b8060026000828254610f079190611398565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604081208054839290610f41908490611398565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff821661103b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f730000000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260208190526040902054818110156110f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f636500000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260208190526040812083830390556002805484929061112d9084906113b0565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610ae1565b60006020828403121561118f57600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146111bf57600080fd5b9392505050565b600060208083528351808285015260005b818110156111f3578581018301518582016040015282016111d7565b81811115611205576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461125d57600080fd5b919050565b6000806040838503121561127557600080fd5b61127e83611239565b946020939093013593505050565b6000806000606084860312156112a157600080fd5b6112aa84611239565b92506112b860208501611239565b9150604084013590509250925092565b6000602082840312156112da57600080fd5b6111bf82611239565b600080604083850312156112f657600080fd5b6112ff83611239565b915061130d60208401611239565b90509250929050565b600181811c9082168061132a57607f821691505b602082108103611363577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156113ab576113ab611369565b500190565b6000828210156113c2576113c2611369565b50039056fea164736f6c634300080f000aa164736f6c634300080f000a", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [], - "value": 0 - }, - { - "accessor": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "account": "0x7c06d3a0a2f45e39E1798afbd9C3330971332a4F", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x608060405234801561001057600080fd5b5061001b6000610020565b610169565b600054610100900460ff16158080156100405750600054600160ff909116105b8061006b57506100593061015a60201b6105fe1760201c565b15801561006b575060005460ff166001145b6100d25760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840160405180910390fd5b6000805460ff1916600117905580156100f5576000805461ff0019166101001790555b600180546001600160a01b0319166001600160a01b0384161790558015610156576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6001600160a01b03163b151590565b612146806101786000396000f3fe60806040523480156200001157600080fd5b5060043610620000935760003560e01c8063c4d66de81162000062578063c4d66de81462000175578063ce5ac90f146200018e578063e78cea9214620001a5578063ee9a31a214620001c657600080fd5b8063316b3739146200009857806354fd4d5014620000fb578063896f93d114620001475780638cf0629c146200015e575b600080fd5b620000d1620000a936600462000652565b60026020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b620001386040518060400160405280600681526020017f312e31302e30000000000000000000000000000000000000000000000000000081525081565b604051620000f29190620006e5565b620000d162000158366004620007dc565b620001e5565b620000d16200016f36600462000859565b620001fc565b6200018c6200018636600462000652565b6200041b565b005b620000d16200019f366004620007dc565b620005ed565b600154620000d19073ffffffffffffffffffffffffffffffffffffffff1681565b60015473ffffffffffffffffffffffffffffffffffffffff16620000d1565b6000620001f4848484620005ed565b949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8516620002a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d4d696e7461626c654552433230466163746f72793a206d7560448201527f73742070726f766964652072656d6f746520746f6b656e20616464726573730060648201526084015b60405180910390fd5b600085858585604051602001620002c29493929190620008f0565b604051602081830303815290604052805190602001209050600081600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168888888860405162000312906200061a565b620003229594939291906200094a565b8190604051809103906000f590508015801562000343573d6000803e3d6000fd5b5073ffffffffffffffffffffffffffffffffffffffff81811660008181526002602052604080822080547fffffffffffffffffffffffff000000000000000000000000000000000000000016948d1694851790555193945090927fceeb8e7d520d7f3b65fc11a262b91066940193b05d4f93df07cfdced0eb551cf9190a360405133815273ffffffffffffffffffffffffffffffffffffffff80891691908316907f52fe89dd5930f343d25650b62fd367bae47088bcddffd2a88350a6ecdd620cdb9060200160405180910390a39695505050505050565b600054610100900460ff16158080156200043c5750600054600160ff909116105b80620004585750303b15801562000458575060005460ff166001145b620004e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016200029e565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156200054557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84161790558015620005e957600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6000620001f48484846012620001fc565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b61178a80620009b083390190565b803573ffffffffffffffffffffffffffffffffffffffff811681146200064d57600080fd5b919050565b6000602082840312156200066557600080fd5b620006708262000628565b9392505050565b6000815180845260005b818110156200069f5760208185018101518683018201520162000681565b81811115620006b2576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600062000670602083018462000677565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126200073b57600080fd5b813567ffffffffffffffff80821115620007595762000759620006fa565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715620007a257620007a2620006fa565b81604052838152866020858801011115620007bc57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600060608486031215620007f257600080fd5b620007fd8462000628565b9250602084013567ffffffffffffffff808211156200081b57600080fd5b620008298783880162000729565b935060408601359150808211156200084057600080fd5b506200084f8682870162000729565b9150509250925092565b600080600080608085870312156200087057600080fd5b6200087b8562000628565b9350602085013567ffffffffffffffff808211156200089957600080fd5b620008a78883890162000729565b94506040870135915080821115620008be57600080fd5b50620008cd8782880162000729565b925050606085013560ff81168114620008e557600080fd5b939692955090935050565b73ffffffffffffffffffffffffffffffffffffffff8516815260806020820152600062000921608083018662000677565b828103604084015262000935818662000677565b91505060ff8316606083015295945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808816835280871660208401525060a060408301526200098560a083018662000677565b828103606084015262000999818662000677565b91505060ff83166080830152969550505050505056fe60e06040523480156200001157600080fd5b506040516200178a3803806200178a833981016040819052620000349162000163565b828260036200004483826200029e565b5060046200005382826200029e565b5050506001600160a01b039384166080529390921660a052505060ff1660c0526200036a565b80516001600160a01b03811681146200009157600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620000be57600080fd5b81516001600160401b0380821115620000db57620000db62000096565b604051601f8301601f19908116603f0116810190828211818310171562000106576200010662000096565b816040528381526020925086838588010111156200012357600080fd5b600091505b8382101562000147578582018301518183018401529082019062000128565b83821115620001595760008385830101525b9695505050505050565b600080600080600060a086880312156200017c57600080fd5b620001878662000079565b9450620001976020870162000079565b60408701519094506001600160401b0380821115620001b557600080fd5b620001c389838a01620000ac565b94506060880151915080821115620001da57600080fd5b50620001e988828901620000ac565b925050608086015160ff811681146200020157600080fd5b809150509295509295909350565b600181811c908216806200022457607f821691505b6020821081036200024557634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200029957600081815260208120601f850160051c81016020861015620002745750805b601f850160051c820191505b81811015620002955782815560010162000280565b5050505b505050565b81516001600160401b03811115620002ba57620002ba62000096565b620002d281620002cb84546200020f565b846200024b565b602080601f8311600181146200030a5760008415620002f15750858301515b600019600386901b1c1916600185901b17855562000295565b600085815260208120601f198616915b828110156200033b578886015182559484019460019091019084016200031a565b50858210156200035a5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c0516113d4620003b6600039600061024401526000818161034b015281816103e001528181610625015261075c0152600081816101a9015261037101526113d46000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063ae1f6aaf1161008c578063dd62ed3e11610066578063dd62ed3e14610395578063e78cea9214610349578063ee9a31a2146103db57600080fd5b8063ae1f6aaf14610349578063c01e1bd61461036f578063d6c0b2c41461036f57600080fd5b80639dc29fac116100bd5780639dc29fac14610310578063a457c2d714610323578063a9059cbb1461033657600080fd5b806370a08231146102d257806395d89b411461030857600080fd5b806323b872dd1161012f5780633950935111610114578063395093511461026e57806340c10f191461028157806354fd4d501461029657600080fd5b806323b872dd1461022a578063313ce5671461023d57600080fd5b806306fdde031161016057806306fdde03146101f0578063095ea7b31461020557806318160ddd1461021857600080fd5b806301ffc9a71461017c578063033964be146101a4575b600080fd5b61018f61018a36600461117d565b610402565b60405190151581526020015b60405180910390f35b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101f86104f3565b60405161019b91906111c6565b61018f610213366004611262565b610585565b6002545b60405190815260200161019b565b61018f61023836600461128c565b61059d565b60405160ff7f000000000000000000000000000000000000000000000000000000000000000016815260200161019b565b61018f61027c366004611262565b6105c1565b61029461028f366004611262565b61060d565b005b6101f86040518060400160405280600581526020017f312e332e3000000000000000000000000000000000000000000000000000000081525081565b61021c6102e03660046112c8565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101f8610735565b61029461031e366004611262565b610744565b61018f610331366004611262565b61085b565b61018f610344366004611262565b61092c565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b61021c6103a33660046112e3565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f1d1d8b63000000000000000000000000000000000000000000000000000000007fec4fc8e3000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000085168314806104bb57507fffffffff00000000000000000000000000000000000000000000000000000000858116908316145b806104ea57507fffffffff00000000000000000000000000000000000000000000000000000000858116908216145b95945050505050565b60606003805461050290611316565b80601f016020809104026020016040519081016040528092919081815260200182805461052e90611316565b801561057b5780601f106105505761010080835404028352916020019161057b565b820191906000526020600020905b81548152906001019060200180831161055e57829003601f168201915b5050505050905090565b60003361059381858561093a565b5060019392505050565b6000336105ab858285610aee565b6105b6858585610bc5565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906105939082908690610608908790611398565b61093a565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146106d7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084015b60405180910390fd5b6106e18282610e78565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d41213968858260405161072991815260200190565b60405180910390a25050565b60606004805461050290611316565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610809576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084016106ce565b6108138282610f98565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca58260405161072991815260200190565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091908381101561091f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084016106ce565b6105b6828686840361093a565b600033610593818585610bc5565b73ffffffffffffffffffffffffffffffffffffffff83166109dc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f726573730000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216610a7f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f737300000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610bbf5781811015610bb2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016106ce565b610bbf848484840361093a565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610c68576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216610d0b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f657373000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610dc1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e6365000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220858503905591851681529081208054849290610e05908490611398565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610e6b91815260200190565b60405180910390a3610bbf565b73ffffffffffffffffffffffffffffffffffffffff8216610ef5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016106ce565b8060026000828254610f079190611398565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604081208054839290610f41908490611398565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff821661103b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f730000000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260208190526040902054818110156110f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f636500000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260208190526040812083830390556002805484929061112d9084906113b0565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610ae1565b60006020828403121561118f57600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146111bf57600080fd5b9392505050565b600060208083528351808285015260005b818110156111f3578581018301518582016040015282016111d7565b81811115611205576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461125d57600080fd5b919050565b6000806040838503121561127557600080fd5b61127e83611239565b946020939093013593505050565b6000806000606084860312156112a157600080fd5b6112aa84611239565b92506112b860208501611239565b9150604084013590509250925092565b6000602082840312156112da57600080fd5b6111bf82611239565b600080604083850312156112f657600080fd5b6112ff83611239565b915061130d60208401611239565b90509250929050565b600181811c9082168061132a57607f821691505b602082108103611363577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156113ab576113ab611369565b500190565b6000828210156113c2576113c2611369565b50039056fea164736f6c634300080f000aa164736f6c634300080f000a", - "deployedCode": "0x60806040523480156200001157600080fd5b5060043610620000935760003560e01c8063c4d66de81162000062578063c4d66de81462000175578063ce5ac90f146200018e578063e78cea9214620001a5578063ee9a31a214620001c657600080fd5b8063316b3739146200009857806354fd4d5014620000fb578063896f93d114620001475780638cf0629c146200015e575b600080fd5b620000d1620000a936600462000652565b60026020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b620001386040518060400160405280600681526020017f312e31302e30000000000000000000000000000000000000000000000000000081525081565b604051620000f29190620006e5565b620000d162000158366004620007dc565b620001e5565b620000d16200016f36600462000859565b620001fc565b6200018c6200018636600462000652565b6200041b565b005b620000d16200019f366004620007dc565b620005ed565b600154620000d19073ffffffffffffffffffffffffffffffffffffffff1681565b60015473ffffffffffffffffffffffffffffffffffffffff16620000d1565b6000620001f4848484620005ed565b949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8516620002a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d4d696e7461626c654552433230466163746f72793a206d7560448201527f73742070726f766964652072656d6f746520746f6b656e20616464726573730060648201526084015b60405180910390fd5b600085858585604051602001620002c29493929190620008f0565b604051602081830303815290604052805190602001209050600081600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168888888860405162000312906200061a565b620003229594939291906200094a565b8190604051809103906000f590508015801562000343573d6000803e3d6000fd5b5073ffffffffffffffffffffffffffffffffffffffff81811660008181526002602052604080822080547fffffffffffffffffffffffff000000000000000000000000000000000000000016948d1694851790555193945090927fceeb8e7d520d7f3b65fc11a262b91066940193b05d4f93df07cfdced0eb551cf9190a360405133815273ffffffffffffffffffffffffffffffffffffffff80891691908316907f52fe89dd5930f343d25650b62fd367bae47088bcddffd2a88350a6ecdd620cdb9060200160405180910390a39695505050505050565b600054610100900460ff16158080156200043c5750600054600160ff909116105b80620004585750303b15801562000458575060005460ff166001145b620004e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016200029e565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156200054557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84161790558015620005e957600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6000620001f48484846012620001fc565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b61178a80620009b083390190565b803573ffffffffffffffffffffffffffffffffffffffff811681146200064d57600080fd5b919050565b6000602082840312156200066557600080fd5b620006708262000628565b9392505050565b6000815180845260005b818110156200069f5760208185018101518683018201520162000681565b81811115620006b2576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600062000670602083018462000677565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126200073b57600080fd5b813567ffffffffffffffff80821115620007595762000759620006fa565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715620007a257620007a2620006fa565b81604052838152866020858801011115620007bc57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600060608486031215620007f257600080fd5b620007fd8462000628565b9250602084013567ffffffffffffffff808211156200081b57600080fd5b620008298783880162000729565b935060408601359150808211156200084057600080fd5b506200084f8682870162000729565b9150509250925092565b600080600080608085870312156200087057600080fd5b6200087b8562000628565b9350602085013567ffffffffffffffff808211156200089957600080fd5b620008a78883890162000729565b94506040870135915080821115620008be57600080fd5b50620008cd8782880162000729565b925050606085013560ff81168114620008e557600080fd5b939692955090935050565b73ffffffffffffffffffffffffffffffffffffffff8516815260806020820152600062000921608083018662000677565b828103604084015262000935818662000677565b91505060ff8316606083015295945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808816835280871660208401525060a060408301526200098560a083018662000677565b828103606084015262000999818662000677565b91505060ff83166080830152969550505050505056fe60e06040523480156200001157600080fd5b506040516200178a3803806200178a833981016040819052620000349162000163565b828260036200004483826200029e565b5060046200005382826200029e565b5050506001600160a01b039384166080529390921660a052505060ff1660c0526200036a565b80516001600160a01b03811681146200009157600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620000be57600080fd5b81516001600160401b0380821115620000db57620000db62000096565b604051601f8301601f19908116603f0116810190828211818310171562000106576200010662000096565b816040528381526020925086838588010111156200012357600080fd5b600091505b8382101562000147578582018301518183018401529082019062000128565b83821115620001595760008385830101525b9695505050505050565b600080600080600060a086880312156200017c57600080fd5b620001878662000079565b9450620001976020870162000079565b60408701519094506001600160401b0380821115620001b557600080fd5b620001c389838a01620000ac565b94506060880151915080821115620001da57600080fd5b50620001e988828901620000ac565b925050608086015160ff811681146200020157600080fd5b809150509295509295909350565b600181811c908216806200022457607f821691505b6020821081036200024557634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200029957600081815260208120601f850160051c81016020861015620002745750805b601f850160051c820191505b81811015620002955782815560010162000280565b5050505b505050565b81516001600160401b03811115620002ba57620002ba62000096565b620002d281620002cb84546200020f565b846200024b565b602080601f8311600181146200030a5760008415620002f15750858301515b600019600386901b1c1916600185901b17855562000295565b600085815260208120601f198616915b828110156200033b578886015182559484019460019091019084016200031a565b50858210156200035a5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c0516113d4620003b6600039600061024401526000818161034b015281816103e001528181610625015261075c0152600081816101a9015261037101526113d46000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063ae1f6aaf1161008c578063dd62ed3e11610066578063dd62ed3e14610395578063e78cea9214610349578063ee9a31a2146103db57600080fd5b8063ae1f6aaf14610349578063c01e1bd61461036f578063d6c0b2c41461036f57600080fd5b80639dc29fac116100bd5780639dc29fac14610310578063a457c2d714610323578063a9059cbb1461033657600080fd5b806370a08231146102d257806395d89b411461030857600080fd5b806323b872dd1161012f5780633950935111610114578063395093511461026e57806340c10f191461028157806354fd4d501461029657600080fd5b806323b872dd1461022a578063313ce5671461023d57600080fd5b806306fdde031161016057806306fdde03146101f0578063095ea7b31461020557806318160ddd1461021857600080fd5b806301ffc9a71461017c578063033964be146101a4575b600080fd5b61018f61018a36600461117d565b610402565b60405190151581526020015b60405180910390f35b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101f86104f3565b60405161019b91906111c6565b61018f610213366004611262565b610585565b6002545b60405190815260200161019b565b61018f61023836600461128c565b61059d565b60405160ff7f000000000000000000000000000000000000000000000000000000000000000016815260200161019b565b61018f61027c366004611262565b6105c1565b61029461028f366004611262565b61060d565b005b6101f86040518060400160405280600581526020017f312e332e3000000000000000000000000000000000000000000000000000000081525081565b61021c6102e03660046112c8565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101f8610735565b61029461031e366004611262565b610744565b61018f610331366004611262565b61085b565b61018f610344366004611262565b61092c565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b61021c6103a33660046112e3565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f1d1d8b63000000000000000000000000000000000000000000000000000000007fec4fc8e3000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000085168314806104bb57507fffffffff00000000000000000000000000000000000000000000000000000000858116908316145b806104ea57507fffffffff00000000000000000000000000000000000000000000000000000000858116908216145b95945050505050565b60606003805461050290611316565b80601f016020809104026020016040519081016040528092919081815260200182805461052e90611316565b801561057b5780601f106105505761010080835404028352916020019161057b565b820191906000526020600020905b81548152906001019060200180831161055e57829003601f168201915b5050505050905090565b60003361059381858561093a565b5060019392505050565b6000336105ab858285610aee565b6105b6858585610bc5565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906105939082908690610608908790611398565b61093a565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146106d7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084015b60405180910390fd5b6106e18282610e78565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d41213968858260405161072991815260200190565b60405180910390a25050565b60606004805461050290611316565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610809576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084016106ce565b6108138282610f98565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca58260405161072991815260200190565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091908381101561091f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084016106ce565b6105b6828686840361093a565b600033610593818585610bc5565b73ffffffffffffffffffffffffffffffffffffffff83166109dc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f726573730000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216610a7f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f737300000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610bbf5781811015610bb2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016106ce565b610bbf848484840361093a565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610c68576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216610d0b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f657373000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610dc1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e6365000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220858503905591851681529081208054849290610e05908490611398565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610e6b91815260200190565b60405180910390a3610bbf565b73ffffffffffffffffffffffffffffffffffffffff8216610ef5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016106ce565b8060026000828254610f079190611398565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604081208054839290610f41908490611398565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff821661103b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f730000000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260208190526040902054818110156110f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f636500000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260208190526040812083830390556002805484929061112d9084906113b0565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610ae1565b60006020828403121561118f57600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146111bf57600080fd5b9392505050565b600060208083528351808285015260005b818110156111f3578581018301518582016040015282016111d7565b81811115611205576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461125d57600080fd5b919050565b6000806040838503121561127557600080fd5b61127e83611239565b946020939093013593505050565b6000806000606084860312156112a157600080fd5b6112aa84611239565b92506112b860208501611239565b9150604084013590509250925092565b6000602082840312156112da57600080fd5b6111bf82611239565b600080604083850312156112f657600080fd5b6112ff83611239565b915061130d60208401611239565b90509250929050565b600181811c9082168061132a57607f821691505b602082108103611363577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156113ab576113ab611369565b500190565b6000828210156113c2576113c2611369565b50039056fea164736f6c634300080f000aa164736f6c634300080f000a", - "initialized": true, - "kind": "Create", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x7c06d3a0a2f45e39E1798afbd9C3330971332a4F", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x7c06d3a0a2f45e39E1798afbd9C3330971332a4F", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x7c06d3a0a2f45e39E1798afbd9C3330971332a4F", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x7c06d3a0a2f45e39E1798afbd9C3330971332a4F", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x7c06d3a0a2f45e39E1798afbd9C3330971332a4F", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x7c06d3a0a2f45e39E1798afbd9C3330971332a4F", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x7c06d3a0a2f45e39E1798afbd9C3330971332a4F", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000001" - }, - { - "account": "0x7c06d3a0a2f45e39E1798afbd9C3330971332a4F", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000001" - }, - { - "account": "0x7c06d3a0a2f45e39E1798afbd9C3330971332a4F", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x7c06d3a0a2f45e39E1798afbd9C3330971332a4F", - "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": "0x7c06d3a0a2f45e39E1798afbd9C3330971332a4F", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xee9a31a2", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x7c06d3a0a2f45e39E1798afbd9C3330971332a4F", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000001" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x7c06d3a0a2f45e39E1798afbd9C3330971332a4F", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xe78cea92", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x7c06d3a0a2f45e39E1798afbd9C3330971332a4F", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000001" - } - ], - "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": "0x493f862b", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x000000000000000000000000000000000000000000000000000000000000004a" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x638627e586f5e36fe67a77519503a7c6da22f92b150d3c6055fd40bdcfe9ffd160806040523480156200001157600080fd5b506200004962000032600160008051602062003ce683398151915262001203565b60001b600019620000d160201b62000fc61760201c565b6040805160c080820183526001808352602080840182905260028486015260006060808601829052608080870183905260a0808801849052885160e081018a528481529485018490529784018390529083018290528201819052948101859052918201849052620000cb9361dead9390928392839290918391908290620000d5565b6200142c565b9055565b600054610100900460ff1615808015620000f65750600054600160ff909116105b806200012657506200011330620004e660201b62000fca1760201c565b15801562000126575060005460ff166001145b6200018f5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff191660011790558015620001b3576000805461ff0019166101001790555b620001bd620004f5565b620001c88a6200055d565b620001d387620005dc565b620001df89896200062e565b620001ea86620006f5565b620002217f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c0886620000d160201b62000fc61760201c565b620002676200025260017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc59862001203565b60001b84620000d160201b62000fc61760201c565b620002b16200029860017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce958063762001203565b60001b8360000151620000d160201b62000fc61760201c565b620002fb620002e260017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a862001203565b60001b8360200151620000d160201b62000fc61760201c565b620003456200032c60017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad637762001203565b60001b8360400151620000d160201b62000fc61760201c565b6200038f6200037660017f52322a25d9f59ea17656545543306b7aef62bc0cc53a0e65ccfa0c75b97aa90762001203565b60001b8360600151620000d160201b62000fc61760201c565b620003c8620003af600160008051602062003cc683398151915262001203565b60001b8360800151620000d160201b62000fc61760201c565b62000412620003f960017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d62001203565b60001b8360a00151620000d160201b62000fc61760201c565b6200041c620007f1565b60c08201516200042c9062000862565b620004378462000aeb565b6200044162000e2f565b6001600160401b0316866001600160401b03161015620004935760405162461bcd60e51b815260206004820152601f602482015260008051602062003c66833981519152604482015260640162000186565b8015620004da576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050505050565b6001600160a01b03163b151590565b600054610100900460ff16620005515760405162461bcd60e51b815260206004820152602b602482015260008051602062003ca683398151915260448201526a6e697469616c697a696e6760a81b606482015260840162000186565b6200055b62000e5c565b565b6200056762000ec3565b6001600160a01b038116620005ce5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840162000186565b620005d98162000f1f565b50565b60678190556040805160208082018490528251808303909101815290820190915260005b600060008051602062003c86833981519152836040516200062291906200124c565b60405180910390a35050565b60688054600160401b600160801b0319166801000000000000000063ffffffff85811691820263ffffffff60601b1916929092176c010000000000000000000000009285169290920291909117909155600160f81b602083811b67ffffffff0000000016909217176066819055606554604080519384019190915282015260009060600160408051601f1981840301815291905290506001600060008051602062003c8683398151915283604051620006e891906200124c565b60405180910390a3505050565b620006ff62000e2f565b6001600160401b0316816001600160401b03161015620007515760405162461bcd60e51b815260206004820152601f602482015260008051602062003c66833981519152604482015260640162000186565b630bebc2006001600160401b0382161115620007b05760405162461bcd60e51b815260206004820181905260248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f2068696768604482015260640162000186565b606880546001600160401b0319166001600160401b038316908117909155604080516020808201939093528151808203909301835281019052600262000600565b6200082562000811600160008051602062003ce683398151915262001203565b60001b62000f7160201b620007581760201c565b6000036200055b576200055b6200084d600160008051602062003ce683398151915262001203565b60001b43620000d160201b62000fc61760201c565b6001600160a01b038116158015906200089857506001600160a01b03811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14155b8015620008ac5750620008aa62000f75565b155b15620005d957601260ff16816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015620008f6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200091c919062001281565b60ff1614620009855760405162461bcd60e51b815260206004820152602e60248201527f53797374656d436f6e6669673a2062616420646563696d616c73206f6620676160448201526d39903830bcb4b733903a37b5b2b760911b606482015260840162000186565b600062000a05826001600160a01b03166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa158015620009ca573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620009f49190810190620012c3565b62000fa960201b62000fe61760201c565b9050600062000a4c836001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620009ca573d6000803e3d6000fd5b905062000a6883601284846200104160201b620010891760201c565b62000a726200111d565b6040516371cfaa3f60e01b81526001600160a01b03858116600483015260126024830152604482018590526064820184905291909116906371cfaa3f90608401600060405180830381600087803b15801562000acd57600080fd5b505af115801562000ae2573d6000803e3d6000fd5b50505050505050565b8060a001516001600160801b0316816060015163ffffffff16111562000b7a5760405162461bcd60e51b815260206004820152603560248201527f53797374656d436f6e6669673a206d696e206261736520666565206d7573742060448201527f6265206c657373207468616e206d617820626173650000000000000000000000606482015260840162000186565b6001816040015160ff161162000beb5760405162461bcd60e51b815260206004820152602f60248201527f53797374656d436f6e6669673a2064656e6f6d696e61746f72206d757374206260448201526e65206c6172676572207468616e203160881b606482015260840162000186565b606854608082015182516001600160401b039092169162000c0d91906200137b565b63ffffffff16111562000c525760405162461bcd60e51b815260206004820152601f602482015260008051602062003c66833981519152604482015260640162000186565b6000816020015160ff161162000cc35760405162461bcd60e51b815260206004820152602f60248201527f53797374656d436f6e6669673a20656c6173746963697479206d756c7469706c60448201526e06965722063616e6e6f74206265203608c1b606482015260840162000186565b8051602082015163ffffffff82169160ff9091169062000ce5908290620013a6565b62000cf19190620013d8565b63ffffffff161462000d6c5760405162461bcd60e51b815260206004820152603760248201527f53797374656d436f6e6669673a20707265636973696f6e206c6f73732077697460448201527f6820746172676574207265736f75726365206c696d6974000000000000000000606482015260840162000186565b805160698054602084015160408501516060860151608087015160a09097015163ffffffff96871664ffffffffff199095169490941764010000000060ff948516021764ffffffffff60281b191665010000000000939092169290920263ffffffff60301b19161766010000000000009185169190910217600160501b600160f01b0319166a01000000000000000000009390941692909202600160701b600160f01b03191692909217600160701b6001600160801b0390921691909102179055565b60695460009062000e579063ffffffff6a010000000000000000000082048116911662001407565b905090565b600054610100900460ff1662000eb85760405162461bcd60e51b815260206004820152602b602482015260008051602062003ca683398151915260448201526a6e697469616c697a696e6760a81b606482015260840162000186565b6200055b3362000f1f565b6033546001600160a01b031633146200055b5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640162000186565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b5490565b60008062000f826200113f565b506001600160a01b031673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b6000602082511115620010255760405162461bcd60e51b815260206004820152603660248201527f476173506179696e67546f6b656e3a20737472696e672063616e6e6f7420626560448201527f2067726561746572207468616e20333220627974657300000000000000000000606482015260840162000186565b6200103b826200116060201b6200115b1760201c565b92915050565b6200108b62001061600160008051602062003c4683398151915262001203565b60001b856001600160a01b031660a08660ff16901b1760001b620000d160201b62000fc61760201c565b620010d1620010bc60017f657c3582c29b3176614e3a33ddd1ec48352696a04e92b3c0566d72010fa8863d62001203565b60001b83620000d160201b62000fc61760201c565b620011176200110260017fa48b38a4b44951360fbdcbfaaeae5ed6ae92585412e9841b70ec72ed8cd0576462001203565b60001b82620000d160201b62000fc61760201c565b50505050565b600062000e5762000811600160008051602062003cc683398151915262001203565b600080620011576200118a60201b620011841760201c565b90939092509050565b805160218110620011795763ec92f9a36000526004601cfd5b9081015160209190910360031b1b90565b60008080620011ae62000811600160008051602062003c4683398151915262001203565b6001600160a01b0381169350905082620011e1575073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee92601292509050565b60a081901c9150509091565b634e487b7160e01b600052601160045260246000fd5b600082821015620012185762001218620011ed565b500390565b60005b838110156200123a57818101518382015260200162001220565b83811115620011175750506000910152565b60208152600082518060208401526200126d8160408501602087016200121d565b601f01601f19169190910160400192915050565b6000602082840312156200129457600080fd5b815160ff81168114620012a657600080fd5b9392505050565b634e487b7160e01b600052604160045260246000fd5b600060208284031215620012d657600080fd5b81516001600160401b0380821115620012ee57600080fd5b818401915084601f8301126200130357600080fd5b815181811115620013185762001318620012ad565b604051601f8201601f19908116603f01168101908382118183101715620013435762001343620012ad565b816040528281528760208487010111156200135d57600080fd5b620013708360208301602088016200121d565b979650505050505050565b600063ffffffff8083168185168083038211156200139d576200139d620011ed565b01949350505050565b600063ffffffff80841680620013cc57634e487b7160e01b600052601260045260246000fd5b92169190910492915050565b600063ffffffff80831681851681830481118215151615620013fe57620013fe620011ed565b02949350505050565b60006001600160401b038281168482168083038211156200139d576200139d620011ed565b61280a806200143c6000396000f3fe608060405234801561001057600080fd5b50600436106102de5760003560e01c8063a711986911610186578063e0e2016d116100e3578063f2fde38b11610097578063f8c68de011610071578063f8c68de0146106e2578063fd32aa0f146106ea578063ffa1ad74146106f257600080fd5b8063f2fde38b146106b2578063f45e65d8146106c5578063f68016b7146106ce57600080fd5b8063e81b2c6d116100c8578063e81b2c6d14610681578063ec7075171461068a578063f2b4e617146106aa57600080fd5b8063e0e2016d14610671578063e2a3285c1461067957600080fd5b8063c9b26f611161013a578063d84447151161011f578063d84447151461064e578063dac6e63a14610656578063db9040fa1461065e57600080fd5b8063c9b26f6114610507578063cc731b021461051a57600080fd5b8063bc49ce5f1161016b578063bc49ce5f146104c6578063bfb14fb7146104ce578063c4e8ddfa146104ff57600080fd5b8063a7119869146104ab578063b40a817c146104b357600080fd5b80634397dfef1161023f578063550fcdc9116101f35780638da5cb5b116101cd5780638da5cb5b14610472578063935f029e146104905780639b7d7f0a146104a357600080fd5b8063550fcdc91461045a5780635d73369c14610462578063715018a61461046a57600080fd5b80634add321d116102245780634add321d146103e95780634f16540b146103f157806354fd4d501461041857600080fd5b80634397dfef146103ab57806348cd4cb1146103e157600080fd5b806318d13918116102965780631fd19ee11161027b5780631fd19ee114610378578063213268491461038057806321d7fde51461039857600080fd5b806318d139181461035b57806319f5cea81461037057600080fd5b80630a49cb03116102c75780630a49cb031461032b5780630ae14b1b146103335780630c18c1621461035257600080fd5b806306c92657146102e3578063078f29cf146102fe575b600080fd5b6102eb6106fa565b6040519081526020015b60405180910390f35b610306610728565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102f5565b610306610761565b630bebc2005b60405167ffffffffffffffff90911681526020016102f5565b6102eb60655481565b61036e610369366004612241565b610791565b005b6102eb6107a5565b6103066107d0565b6103886107fa565b60405190151581526020016102f5565b61036e6103a6366004612277565b610839565b6103b361084f565b6040805173ffffffffffffffffffffffffffffffffffffffff909316835260ff9091166020830152016102f5565b6102eb610863565b610339610893565b6102eb7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c0881565b60408051808201909152600c81527f322e332e302d626574612e32000000000000000000000000000000000000000060208201525b6040516102f59190612320565b61044d6108b9565b6102eb6108c3565b61036e6108ee565b60335473ffffffffffffffffffffffffffffffffffffffff16610306565b61036e61049e366004612333565b610902565b610306610914565b610306610944565b61036e6104c136600461236d565b610974565b6102eb610985565b6068546104ea9068010000000000000000900463ffffffff1681565b60405163ffffffff90911681526020016102f5565b6103066109b0565b61036e610515366004612388565b6109e0565b6105de6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152506040805160c08101825260695463ffffffff8082168352640100000000820460ff9081166020850152650100000000008304169383019390935266010000000000008104831660608301526a0100000000000000000000810490921660808201526e0100000000000000000000000000009091046fffffffffffffffffffffffffffffffff1660a082015290565b6040516102f59190600060c08201905063ffffffff80845116835260ff602085015116602084015260ff6040850151166040840152806060850151166060840152806080850151166080840152506fffffffffffffffffffffffffffffffff60a08401511660a083015292915050565b61044d6109f1565b6103066109fb565b61036e61066c3660046124bb565b610a2b565b6102eb610e36565b6102eb610e61565b6102eb60675481565b6068546104ea906c01000000000000000000000000900463ffffffff1681565b610306610e8c565b61036e6106c0366004612241565b610ebc565b6102eb60665481565b6068546103399067ffffffffffffffff1681565b6102eb610f70565b6102eb610f9b565b6102eb600081565b61072560017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d61263d565b81565b600061075c61075860017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad637761263d565b5490565b905090565b600061075c61075860017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad61263d565b610799611201565b6107a281611282565b50565b61072560017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a861263d565b600061075c7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c085490565b60008061080561084f565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b610841611201565b61084b828261133f565b5050565b60008061085a611184565b90939092509050565b600061075c61075860017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a061263d565b60695460009061075c9063ffffffff6a0100000000000000000000820481169116612654565b606061075c61147d565b61072560017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce958063761263d565b6108f6611201565b610900600061153e565b565b61090a611201565b61084b82826115b5565b600061075c61075860017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d61263d565b600061075c61075860017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce958063761263d565b61097c611201565b6107a28161168b565b61072560017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc59861263d565b600061075c61075860017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a861263d565b6109e8611201565b6107a2816117e1565b606061075c611809565b600061075c61075860017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc59861263d565b600054610100900460ff1615808015610a4b5750600054600160ff909116105b80610a655750303b158015610a65575060005460ff166001145b610af6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610b5457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610b5c6118bf565b610b658a610ebc565b610b6e876117e1565b610b78898961133f565b610b818661168b565b610baa7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08869055565b610bdd610bd860017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc59861263d565b849055565b610c11610c0b60017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce958063761263d565b83519055565b610c48610c3f60017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a861263d565b60208401519055565b610c7f610c7660017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad637761263d565b60408401519055565b610cb6610cad60017f52322a25d9f59ea17656545543306b7aef62bc0cc53a0e65ccfa0c75b97aa90761263d565b60608401519055565b610ced610ce460017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad61263d565b60808401519055565b610d24610d1b60017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d61263d565b60a08401519055565b610d2c61195e565b610d398260c001516119c6565b610d4284611cd0565b610d4a610893565b67ffffffffffffffff168667ffffffffffffffff161015610dc7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77006044820152606401610aed565b8015610e2a57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050505050565b61072560017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a061263d565b61072560017f52322a25d9f59ea17656545543306b7aef62bc0cc53a0e65ccfa0c75b97aa90761263d565b600061075c61075860017f52322a25d9f59ea17656545543306b7aef62bc0cc53a0e65ccfa0c75b97aa90761263d565b610ec4611201565b73ffffffffffffffffffffffffffffffffffffffff8116610f67576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610aed565b6107a28161153e565b61072560017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad637761263d565b61072560017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad61263d565b9055565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b600060208251111561107a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f476173506179696e67546f6b656e3a20737472696e672063616e6e6f7420626560448201527f2067726561746572207468616e203332206279746573000000000000000000006064820152608401610aed565b6110838261115b565b92915050565b6110ef6110b760017f04adb1412b2ddc16fcc0d4538d5c8f07cf9c83abecc6b41f6f69037b708fbcec61263d565b74ff000000000000000000000000000000000000000060a086901b1673ffffffffffffffffffffffffffffffffffffffff8716179055565b61112261111d60017f657c3582c29b3176614e3a33ddd1ec48352696a04e92b3c0566d72010fa8863d61263d565b839055565b61115561115060017fa48b38a4b44951360fbdcbfaaeae5ed6ae92585412e9841b70ec72ed8cd0576461263d565b829055565b50505050565b8051602181106111735763ec92f9a36000526004601cfd5b9081015160209190910360031b1b90565b600080806111b661075860017f04adb1412b2ddc16fcc0d4538d5c8f07cf9c83abecc6b41f6f69037b708fbcec61263d565b73ffffffffffffffffffffffffffffffffffffffff811693509050826111f5575073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee92601292509050565b60a081901c9150509091565b60335473ffffffffffffffffffffffffffffffffffffffff163314610900576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610aed565b6112ab7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08829055565b6040805173ffffffffffffffffffffffffffffffffffffffff8316602082015260009101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060035b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be836040516113339190612320565b60405180910390a35050565b606880547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000063ffffffff8581169182027fffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffff16929092176c0100000000000000000000000092851692909202919091179091557f0100000000000000000000000000000000000000000000000000000000000000602083811b67ffffffff000000001690921717606681905560655460408051938401919091528201526000906060015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529050600160007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be836040516114709190612320565b60405180910390a3505050565b60606000611489611184565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff82160161150257505060408051808201909152600381527f4554480000000000000000000000000000000000000000000000000000000000602082015290565b61153861153361075860017fa48b38a4b44951360fbdcbfaaeae5ed6ae92585412e9841b70ec72ed8cd0576461263d565b612144565b91505090565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b7fff00000000000000000000000000000000000000000000000000000000000000811615611665576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f53797374656d436f6e6669673a207363616c61722065786365656473206d617860448201527f2e000000000000000000000000000000000000000000000000000000000000006064820152608401610aed565b60658290556066819055604080516020810184905290810182905260009060600161140d565b611693610893565b67ffffffffffffffff168167ffffffffffffffff161015611710576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77006044820152606401610aed565b630bebc20067ffffffffffffffff82161115611788576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f20686967686044820152606401610aed565b606880547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff83169081179091556040805160208082019390935281518082039093018352810190526002611302565b6067819055604080516020808201849052825180830390910181529082019091526000611302565b60606000611815611184565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff82160161188e57505060408051808201909152600581527f4574686572000000000000000000000000000000000000000000000000000000602082015290565b61153861153361075860017f657c3582c29b3176614e3a33ddd1ec48352696a04e92b3c0566d72010fa8863d61263d565b600054610100900460ff16611956576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610aed565b610900612178565b61198c61075860017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a061263d565b600003610900576109006119c160017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a061263d565b439055565b73ffffffffffffffffffffffffffffffffffffffff811615801590611a15575073ffffffffffffffffffffffffffffffffffffffff811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14155b8015611a265750611a246107fa565b155b156107a257601260ff168173ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a9f9190612680565b60ff1614611b2f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f53797374656d436f6e6669673a2062616420646563696d616c73206f6620676160448201527f7320706179696e6720746f6b656e0000000000000000000000000000000000006064820152608401610aed565b6000611bca8273ffffffffffffffffffffffffffffffffffffffff166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa158015611b7f573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611bc5919081019061269d565b610fe6565b90506000611c1c8373ffffffffffffffffffffffffffffffffffffffff166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015611b7f573d6000803e3d6000fd5b9050611c2b8360128484611089565b611c33610761565b6040517f71cfaa3f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015260126024830152604482018590526064820184905291909116906371cfaa3f90608401600060405180830381600087803b158015611cb357600080fd5b505af1158015611cc7573d6000803e3d6000fd5b50505050505050565b8060a001516fffffffffffffffffffffffffffffffff16816060015163ffffffff161115611d80576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f53797374656d436f6e6669673a206d696e206261736520666565206d7573742060448201527f6265206c657373207468616e206d6178206261736500000000000000000000006064820152608401610aed565b6001816040015160ff1611611e17576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f53797374656d436f6e6669673a2064656e6f6d696e61746f72206d757374206260448201527f65206c6172676572207468616e203100000000000000000000000000000000006064820152608401610aed565b6068546080820151825167ffffffffffffffff90921691611e389190612768565b63ffffffff161115611ea6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77006044820152606401610aed565b6000816020015160ff1611611f3d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f53797374656d436f6e6669673a20656c6173746963697479206d756c7469706c60448201527f6965722063616e6e6f74206265203000000000000000000000000000000000006064820152608401610aed565b8051602082015163ffffffff82169160ff90911690611f5d908290612787565b611f6791906127d1565b63ffffffff1614611ffa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f53797374656d436f6e6669673a20707265636973696f6e206c6f73732077697460448201527f6820746172676574207265736f75726365206c696d69740000000000000000006064820152608401610aed565b805160698054602084015160408501516060860151608087015160a09097015163ffffffff9687167fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009095169490941764010000000060ff94851602177fffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffff166501000000000093909216929092027fffffffffffffffffffffffffffffffffffffffffffff00000000ffffffffffff1617660100000000000091851691909102177fffff0000000000000000000000000000000000000000ffffffffffffffffffff166a010000000000000000000093909416929092027fffff00000000000000000000000000000000ffffffffffffffffffffffffffff16929092176e0100000000000000000000000000006fffffffffffffffffffffffffffffffff90921691909102179055565b60405160005b82811a1561215a5760010161214a565b80825260208201838152600082820152505060408101604052919050565b600054610100900460ff1661220f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610aed565b6109003361153e565b803573ffffffffffffffffffffffffffffffffffffffff8116811461223c57600080fd5b919050565b60006020828403121561225357600080fd5b61225c82612218565b9392505050565b803563ffffffff8116811461223c57600080fd5b6000806040838503121561228a57600080fd5b61229383612263565b91506122a160208401612263565b90509250929050565b60005b838110156122c55781810151838201526020016122ad565b838111156111555750506000910152565b600081518084526122ee8160208601602086016122aa565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061225c60208301846122d6565b6000806040838503121561234657600080fd5b50508035926020909101359150565b803567ffffffffffffffff8116811461223c57600080fd5b60006020828403121561237f57600080fd5b61225c82612355565b60006020828403121561239a57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160c0810167ffffffffffffffff811182821017156123f3576123f36123a1565b60405290565b60ff811681146107a257600080fd5b600060e0828403121561241a57600080fd5b60405160e0810181811067ffffffffffffffff8211171561243d5761243d6123a1565b60405290508061244c83612218565b815261245a60208401612218565b602082015261246b60408401612218565b604082015261247c60608401612218565b606082015261248d60808401612218565b608082015261249e60a08401612218565b60a08201526124af60c08401612218565b60c08201525092915050565b6000806000806000806000806000898b036102808112156124db57600080fd5b6124e48b612218565b99506124f260208c01612263565b985061250060408c01612263565b975060608b0135965061251560808c01612355565b955061252360a08c01612218565b945060c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff408201121561255557600080fd5b5061255e6123d0565b61256a60c08c01612263565b815260e08b013561257a816123f9565b60208201526101008b013561258e816123f9565b60408201526125a06101208c01612263565b60608201526125b26101408c01612263565b60808201526101608b01356fffffffffffffffffffffffffffffffff811681146125db57600080fd5b60a082015292506125ef6101808b01612218565b91506125ff8b6101a08c01612408565b90509295985092959850929598565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561264f5761264f61260e565b500390565b600067ffffffffffffffff8083168185168083038211156126775761267761260e565b01949350505050565b60006020828403121561269257600080fd5b815161225c816123f9565b6000602082840312156126af57600080fd5b815167ffffffffffffffff808211156126c757600080fd5b818401915084601f8301126126db57600080fd5b8151818111156126ed576126ed6123a1565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715612733576127336123a1565b8160405282815287602084870101111561274c57600080fd5b61275d8360208301602088016122aa565b979650505050505050565b600063ffffffff8083168185168083038211156126775761267761260e565b600063ffffffff808416806127c5577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b92169190910492915050565b600063ffffffff808316818516818304811182151516156127f4576127f461260e565b0294935050505056fea164736f6c634300080f000a04adb1412b2ddc16fcc0d4538d5c8f07cf9c83abecc6b41f6f69037b708fbcec53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77001d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be496e697469616c697a61626c653a20636f6e7472616374206973206e6f7420694b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ada11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a0", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [], - "value": 0 - }, - { - "accessor": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x60806040523480156200001157600080fd5b506200004962000032600160008051602062003ce683398151915262001203565b60001b600019620000d160201b62000fc61760201c565b6040805160c080820183526001808352602080840182905260028486015260006060808601829052608080870183905260a0808801849052885160e081018a528481529485018490529784018390529083018290528201819052948101859052918201849052620000cb9361dead9390928392839290918391908290620000d5565b6200142c565b9055565b600054610100900460ff1615808015620000f65750600054600160ff909116105b806200012657506200011330620004e660201b62000fca1760201c565b15801562000126575060005460ff166001145b6200018f5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff191660011790558015620001b3576000805461ff0019166101001790555b620001bd620004f5565b620001c88a6200055d565b620001d387620005dc565b620001df89896200062e565b620001ea86620006f5565b620002217f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c0886620000d160201b62000fc61760201c565b620002676200025260017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc59862001203565b60001b84620000d160201b62000fc61760201c565b620002b16200029860017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce958063762001203565b60001b8360000151620000d160201b62000fc61760201c565b620002fb620002e260017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a862001203565b60001b8360200151620000d160201b62000fc61760201c565b620003456200032c60017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad637762001203565b60001b8360400151620000d160201b62000fc61760201c565b6200038f6200037660017f52322a25d9f59ea17656545543306b7aef62bc0cc53a0e65ccfa0c75b97aa90762001203565b60001b8360600151620000d160201b62000fc61760201c565b620003c8620003af600160008051602062003cc683398151915262001203565b60001b8360800151620000d160201b62000fc61760201c565b62000412620003f960017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d62001203565b60001b8360a00151620000d160201b62000fc61760201c565b6200041c620007f1565b60c08201516200042c9062000862565b620004378462000aeb565b6200044162000e2f565b6001600160401b0316866001600160401b03161015620004935760405162461bcd60e51b815260206004820152601f602482015260008051602062003c66833981519152604482015260640162000186565b8015620004da576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050505050565b6001600160a01b03163b151590565b600054610100900460ff16620005515760405162461bcd60e51b815260206004820152602b602482015260008051602062003ca683398151915260448201526a6e697469616c697a696e6760a81b606482015260840162000186565b6200055b62000e5c565b565b6200056762000ec3565b6001600160a01b038116620005ce5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840162000186565b620005d98162000f1f565b50565b60678190556040805160208082018490528251808303909101815290820190915260005b600060008051602062003c86833981519152836040516200062291906200124c565b60405180910390a35050565b60688054600160401b600160801b0319166801000000000000000063ffffffff85811691820263ffffffff60601b1916929092176c010000000000000000000000009285169290920291909117909155600160f81b602083811b67ffffffff0000000016909217176066819055606554604080519384019190915282015260009060600160408051601f1981840301815291905290506001600060008051602062003c8683398151915283604051620006e891906200124c565b60405180910390a3505050565b620006ff62000e2f565b6001600160401b0316816001600160401b03161015620007515760405162461bcd60e51b815260206004820152601f602482015260008051602062003c66833981519152604482015260640162000186565b630bebc2006001600160401b0382161115620007b05760405162461bcd60e51b815260206004820181905260248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f2068696768604482015260640162000186565b606880546001600160401b0319166001600160401b038316908117909155604080516020808201939093528151808203909301835281019052600262000600565b6200082562000811600160008051602062003ce683398151915262001203565b60001b62000f7160201b620007581760201c565b6000036200055b576200055b6200084d600160008051602062003ce683398151915262001203565b60001b43620000d160201b62000fc61760201c565b6001600160a01b038116158015906200089857506001600160a01b03811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14155b8015620008ac5750620008aa62000f75565b155b15620005d957601260ff16816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015620008f6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200091c919062001281565b60ff1614620009855760405162461bcd60e51b815260206004820152602e60248201527f53797374656d436f6e6669673a2062616420646563696d616c73206f6620676160448201526d39903830bcb4b733903a37b5b2b760911b606482015260840162000186565b600062000a05826001600160a01b03166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa158015620009ca573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620009f49190810190620012c3565b62000fa960201b62000fe61760201c565b9050600062000a4c836001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015620009ca573d6000803e3d6000fd5b905062000a6883601284846200104160201b620010891760201c565b62000a726200111d565b6040516371cfaa3f60e01b81526001600160a01b03858116600483015260126024830152604482018590526064820184905291909116906371cfaa3f90608401600060405180830381600087803b15801562000acd57600080fd5b505af115801562000ae2573d6000803e3d6000fd5b50505050505050565b8060a001516001600160801b0316816060015163ffffffff16111562000b7a5760405162461bcd60e51b815260206004820152603560248201527f53797374656d436f6e6669673a206d696e206261736520666565206d7573742060448201527f6265206c657373207468616e206d617820626173650000000000000000000000606482015260840162000186565b6001816040015160ff161162000beb5760405162461bcd60e51b815260206004820152602f60248201527f53797374656d436f6e6669673a2064656e6f6d696e61746f72206d757374206260448201526e65206c6172676572207468616e203160881b606482015260840162000186565b606854608082015182516001600160401b039092169162000c0d91906200137b565b63ffffffff16111562000c525760405162461bcd60e51b815260206004820152601f602482015260008051602062003c66833981519152604482015260640162000186565b6000816020015160ff161162000cc35760405162461bcd60e51b815260206004820152602f60248201527f53797374656d436f6e6669673a20656c6173746963697479206d756c7469706c60448201526e06965722063616e6e6f74206265203608c1b606482015260840162000186565b8051602082015163ffffffff82169160ff9091169062000ce5908290620013a6565b62000cf19190620013d8565b63ffffffff161462000d6c5760405162461bcd60e51b815260206004820152603760248201527f53797374656d436f6e6669673a20707265636973696f6e206c6f73732077697460448201527f6820746172676574207265736f75726365206c696d6974000000000000000000606482015260840162000186565b805160698054602084015160408501516060860151608087015160a09097015163ffffffff96871664ffffffffff199095169490941764010000000060ff948516021764ffffffffff60281b191665010000000000939092169290920263ffffffff60301b19161766010000000000009185169190910217600160501b600160f01b0319166a01000000000000000000009390941692909202600160701b600160f01b03191692909217600160701b6001600160801b0390921691909102179055565b60695460009062000e579063ffffffff6a010000000000000000000082048116911662001407565b905090565b600054610100900460ff1662000eb85760405162461bcd60e51b815260206004820152602b602482015260008051602062003ca683398151915260448201526a6e697469616c697a696e6760a81b606482015260840162000186565b6200055b3362000f1f565b6033546001600160a01b031633146200055b5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640162000186565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b5490565b60008062000f826200113f565b506001600160a01b031673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b6000602082511115620010255760405162461bcd60e51b815260206004820152603660248201527f476173506179696e67546f6b656e3a20737472696e672063616e6e6f7420626560448201527f2067726561746572207468616e20333220627974657300000000000000000000606482015260840162000186565b6200103b826200116060201b6200115b1760201c565b92915050565b6200108b62001061600160008051602062003c4683398151915262001203565b60001b856001600160a01b031660a08660ff16901b1760001b620000d160201b62000fc61760201c565b620010d1620010bc60017f657c3582c29b3176614e3a33ddd1ec48352696a04e92b3c0566d72010fa8863d62001203565b60001b83620000d160201b62000fc61760201c565b620011176200110260017fa48b38a4b44951360fbdcbfaaeae5ed6ae92585412e9841b70ec72ed8cd0576462001203565b60001b82620000d160201b62000fc61760201c565b50505050565b600062000e5762000811600160008051602062003cc683398151915262001203565b600080620011576200118a60201b620011841760201c565b90939092509050565b805160218110620011795763ec92f9a36000526004601cfd5b9081015160209190910360031b1b90565b60008080620011ae62000811600160008051602062003c4683398151915262001203565b6001600160a01b0381169350905082620011e1575073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee92601292509050565b60a081901c9150509091565b634e487b7160e01b600052601160045260246000fd5b600082821015620012185762001218620011ed565b500390565b60005b838110156200123a57818101518382015260200162001220565b83811115620011175750506000910152565b60208152600082518060208401526200126d8160408501602087016200121d565b601f01601f19169190910160400192915050565b6000602082840312156200129457600080fd5b815160ff81168114620012a657600080fd5b9392505050565b634e487b7160e01b600052604160045260246000fd5b600060208284031215620012d657600080fd5b81516001600160401b0380821115620012ee57600080fd5b818401915084601f8301126200130357600080fd5b815181811115620013185762001318620012ad565b604051601f8201601f19908116603f01168101908382118183101715620013435762001343620012ad565b816040528281528760208487010111156200135d57600080fd5b620013708360208301602088016200121d565b979650505050505050565b600063ffffffff8083168185168083038211156200139d576200139d620011ed565b01949350505050565b600063ffffffff80841680620013cc57634e487b7160e01b600052601260045260246000fd5b92169190910492915050565b600063ffffffff80831681851681830481118215151615620013fe57620013fe620011ed565b02949350505050565b60006001600160401b038281168482168083038211156200139d576200139d620011ed565b61280a806200143c6000396000f3fe608060405234801561001057600080fd5b50600436106102de5760003560e01c8063a711986911610186578063e0e2016d116100e3578063f2fde38b11610097578063f8c68de011610071578063f8c68de0146106e2578063fd32aa0f146106ea578063ffa1ad74146106f257600080fd5b8063f2fde38b146106b2578063f45e65d8146106c5578063f68016b7146106ce57600080fd5b8063e81b2c6d116100c8578063e81b2c6d14610681578063ec7075171461068a578063f2b4e617146106aa57600080fd5b8063e0e2016d14610671578063e2a3285c1461067957600080fd5b8063c9b26f611161013a578063d84447151161011f578063d84447151461064e578063dac6e63a14610656578063db9040fa1461065e57600080fd5b8063c9b26f6114610507578063cc731b021461051a57600080fd5b8063bc49ce5f1161016b578063bc49ce5f146104c6578063bfb14fb7146104ce578063c4e8ddfa146104ff57600080fd5b8063a7119869146104ab578063b40a817c146104b357600080fd5b80634397dfef1161023f578063550fcdc9116101f35780638da5cb5b116101cd5780638da5cb5b14610472578063935f029e146104905780639b7d7f0a146104a357600080fd5b8063550fcdc91461045a5780635d73369c14610462578063715018a61461046a57600080fd5b80634add321d116102245780634add321d146103e95780634f16540b146103f157806354fd4d501461041857600080fd5b80634397dfef146103ab57806348cd4cb1146103e157600080fd5b806318d13918116102965780631fd19ee11161027b5780631fd19ee114610378578063213268491461038057806321d7fde51461039857600080fd5b806318d139181461035b57806319f5cea81461037057600080fd5b80630a49cb03116102c75780630a49cb031461032b5780630ae14b1b146103335780630c18c1621461035257600080fd5b806306c92657146102e3578063078f29cf146102fe575b600080fd5b6102eb6106fa565b6040519081526020015b60405180910390f35b610306610728565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102f5565b610306610761565b630bebc2005b60405167ffffffffffffffff90911681526020016102f5565b6102eb60655481565b61036e610369366004612241565b610791565b005b6102eb6107a5565b6103066107d0565b6103886107fa565b60405190151581526020016102f5565b61036e6103a6366004612277565b610839565b6103b361084f565b6040805173ffffffffffffffffffffffffffffffffffffffff909316835260ff9091166020830152016102f5565b6102eb610863565b610339610893565b6102eb7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c0881565b60408051808201909152600c81527f322e332e302d626574612e32000000000000000000000000000000000000000060208201525b6040516102f59190612320565b61044d6108b9565b6102eb6108c3565b61036e6108ee565b60335473ffffffffffffffffffffffffffffffffffffffff16610306565b61036e61049e366004612333565b610902565b610306610914565b610306610944565b61036e6104c136600461236d565b610974565b6102eb610985565b6068546104ea9068010000000000000000900463ffffffff1681565b60405163ffffffff90911681526020016102f5565b6103066109b0565b61036e610515366004612388565b6109e0565b6105de6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152506040805160c08101825260695463ffffffff8082168352640100000000820460ff9081166020850152650100000000008304169383019390935266010000000000008104831660608301526a0100000000000000000000810490921660808201526e0100000000000000000000000000009091046fffffffffffffffffffffffffffffffff1660a082015290565b6040516102f59190600060c08201905063ffffffff80845116835260ff602085015116602084015260ff6040850151166040840152806060850151166060840152806080850151166080840152506fffffffffffffffffffffffffffffffff60a08401511660a083015292915050565b61044d6109f1565b6103066109fb565b61036e61066c3660046124bb565b610a2b565b6102eb610e36565b6102eb610e61565b6102eb60675481565b6068546104ea906c01000000000000000000000000900463ffffffff1681565b610306610e8c565b61036e6106c0366004612241565b610ebc565b6102eb60665481565b6068546103399067ffffffffffffffff1681565b6102eb610f70565b6102eb610f9b565b6102eb600081565b61072560017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d61263d565b81565b600061075c61075860017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad637761263d565b5490565b905090565b600061075c61075860017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad61263d565b610799611201565b6107a281611282565b50565b61072560017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a861263d565b600061075c7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c085490565b60008061080561084f565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b610841611201565b61084b828261133f565b5050565b60008061085a611184565b90939092509050565b600061075c61075860017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a061263d565b60695460009061075c9063ffffffff6a0100000000000000000000820481169116612654565b606061075c61147d565b61072560017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce958063761263d565b6108f6611201565b610900600061153e565b565b61090a611201565b61084b82826115b5565b600061075c61075860017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d61263d565b600061075c61075860017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce958063761263d565b61097c611201565b6107a28161168b565b61072560017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc59861263d565b600061075c61075860017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a861263d565b6109e8611201565b6107a2816117e1565b606061075c611809565b600061075c61075860017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc59861263d565b600054610100900460ff1615808015610a4b5750600054600160ff909116105b80610a655750303b158015610a65575060005460ff166001145b610af6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610b5457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610b5c6118bf565b610b658a610ebc565b610b6e876117e1565b610b78898961133f565b610b818661168b565b610baa7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08869055565b610bdd610bd860017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc59861263d565b849055565b610c11610c0b60017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce958063761263d565b83519055565b610c48610c3f60017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a861263d565b60208401519055565b610c7f610c7660017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad637761263d565b60408401519055565b610cb6610cad60017f52322a25d9f59ea17656545543306b7aef62bc0cc53a0e65ccfa0c75b97aa90761263d565b60608401519055565b610ced610ce460017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad61263d565b60808401519055565b610d24610d1b60017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d61263d565b60a08401519055565b610d2c61195e565b610d398260c001516119c6565b610d4284611cd0565b610d4a610893565b67ffffffffffffffff168667ffffffffffffffff161015610dc7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77006044820152606401610aed565b8015610e2a57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050505050565b61072560017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a061263d565b61072560017f52322a25d9f59ea17656545543306b7aef62bc0cc53a0e65ccfa0c75b97aa90761263d565b600061075c61075860017f52322a25d9f59ea17656545543306b7aef62bc0cc53a0e65ccfa0c75b97aa90761263d565b610ec4611201565b73ffffffffffffffffffffffffffffffffffffffff8116610f67576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610aed565b6107a28161153e565b61072560017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad637761263d565b61072560017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad61263d565b9055565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b600060208251111561107a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f476173506179696e67546f6b656e3a20737472696e672063616e6e6f7420626560448201527f2067726561746572207468616e203332206279746573000000000000000000006064820152608401610aed565b6110838261115b565b92915050565b6110ef6110b760017f04adb1412b2ddc16fcc0d4538d5c8f07cf9c83abecc6b41f6f69037b708fbcec61263d565b74ff000000000000000000000000000000000000000060a086901b1673ffffffffffffffffffffffffffffffffffffffff8716179055565b61112261111d60017f657c3582c29b3176614e3a33ddd1ec48352696a04e92b3c0566d72010fa8863d61263d565b839055565b61115561115060017fa48b38a4b44951360fbdcbfaaeae5ed6ae92585412e9841b70ec72ed8cd0576461263d565b829055565b50505050565b8051602181106111735763ec92f9a36000526004601cfd5b9081015160209190910360031b1b90565b600080806111b661075860017f04adb1412b2ddc16fcc0d4538d5c8f07cf9c83abecc6b41f6f69037b708fbcec61263d565b73ffffffffffffffffffffffffffffffffffffffff811693509050826111f5575073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee92601292509050565b60a081901c9150509091565b60335473ffffffffffffffffffffffffffffffffffffffff163314610900576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610aed565b6112ab7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08829055565b6040805173ffffffffffffffffffffffffffffffffffffffff8316602082015260009101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060035b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be836040516113339190612320565b60405180910390a35050565b606880547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000063ffffffff8581169182027fffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffff16929092176c0100000000000000000000000092851692909202919091179091557f0100000000000000000000000000000000000000000000000000000000000000602083811b67ffffffff000000001690921717606681905560655460408051938401919091528201526000906060015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529050600160007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be836040516114709190612320565b60405180910390a3505050565b60606000611489611184565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff82160161150257505060408051808201909152600381527f4554480000000000000000000000000000000000000000000000000000000000602082015290565b61153861153361075860017fa48b38a4b44951360fbdcbfaaeae5ed6ae92585412e9841b70ec72ed8cd0576461263d565b612144565b91505090565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b7fff00000000000000000000000000000000000000000000000000000000000000811615611665576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f53797374656d436f6e6669673a207363616c61722065786365656473206d617860448201527f2e000000000000000000000000000000000000000000000000000000000000006064820152608401610aed565b60658290556066819055604080516020810184905290810182905260009060600161140d565b611693610893565b67ffffffffffffffff168167ffffffffffffffff161015611710576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77006044820152606401610aed565b630bebc20067ffffffffffffffff82161115611788576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f20686967686044820152606401610aed565b606880547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff83169081179091556040805160208082019390935281518082039093018352810190526002611302565b6067819055604080516020808201849052825180830390910181529082019091526000611302565b60606000611815611184565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff82160161188e57505060408051808201909152600581527f4574686572000000000000000000000000000000000000000000000000000000602082015290565b61153861153361075860017f657c3582c29b3176614e3a33ddd1ec48352696a04e92b3c0566d72010fa8863d61263d565b600054610100900460ff16611956576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610aed565b610900612178565b61198c61075860017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a061263d565b600003610900576109006119c160017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a061263d565b439055565b73ffffffffffffffffffffffffffffffffffffffff811615801590611a15575073ffffffffffffffffffffffffffffffffffffffff811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14155b8015611a265750611a246107fa565b155b156107a257601260ff168173ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a9f9190612680565b60ff1614611b2f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f53797374656d436f6e6669673a2062616420646563696d616c73206f6620676160448201527f7320706179696e6720746f6b656e0000000000000000000000000000000000006064820152608401610aed565b6000611bca8273ffffffffffffffffffffffffffffffffffffffff166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa158015611b7f573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611bc5919081019061269d565b610fe6565b90506000611c1c8373ffffffffffffffffffffffffffffffffffffffff166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015611b7f573d6000803e3d6000fd5b9050611c2b8360128484611089565b611c33610761565b6040517f71cfaa3f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015260126024830152604482018590526064820184905291909116906371cfaa3f90608401600060405180830381600087803b158015611cb357600080fd5b505af1158015611cc7573d6000803e3d6000fd5b50505050505050565b8060a001516fffffffffffffffffffffffffffffffff16816060015163ffffffff161115611d80576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f53797374656d436f6e6669673a206d696e206261736520666565206d7573742060448201527f6265206c657373207468616e206d6178206261736500000000000000000000006064820152608401610aed565b6001816040015160ff1611611e17576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f53797374656d436f6e6669673a2064656e6f6d696e61746f72206d757374206260448201527f65206c6172676572207468616e203100000000000000000000000000000000006064820152608401610aed565b6068546080820151825167ffffffffffffffff90921691611e389190612768565b63ffffffff161115611ea6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77006044820152606401610aed565b6000816020015160ff1611611f3d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f53797374656d436f6e6669673a20656c6173746963697479206d756c7469706c60448201527f6965722063616e6e6f74206265203000000000000000000000000000000000006064820152608401610aed565b8051602082015163ffffffff82169160ff90911690611f5d908290612787565b611f6791906127d1565b63ffffffff1614611ffa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f53797374656d436f6e6669673a20707265636973696f6e206c6f73732077697460448201527f6820746172676574207265736f75726365206c696d69740000000000000000006064820152608401610aed565b805160698054602084015160408501516060860151608087015160a09097015163ffffffff9687167fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009095169490941764010000000060ff94851602177fffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffff166501000000000093909216929092027fffffffffffffffffffffffffffffffffffffffffffff00000000ffffffffffff1617660100000000000091851691909102177fffff0000000000000000000000000000000000000000ffffffffffffffffffff166a010000000000000000000093909416929092027fffff00000000000000000000000000000000ffffffffffffffffffffffffffff16929092176e0100000000000000000000000000006fffffffffffffffffffffffffffffffff90921691909102179055565b60405160005b82811a1561215a5760010161214a565b80825260208201838152600082820152505060408101604052919050565b600054610100900460ff1661220f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610aed565b6109003361153e565b803573ffffffffffffffffffffffffffffffffffffffff8116811461223c57600080fd5b919050565b60006020828403121561225357600080fd5b61225c82612218565b9392505050565b803563ffffffff8116811461223c57600080fd5b6000806040838503121561228a57600080fd5b61229383612263565b91506122a160208401612263565b90509250929050565b60005b838110156122c55781810151838201526020016122ad565b838111156111555750506000910152565b600081518084526122ee8160208601602086016122aa565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061225c60208301846122d6565b6000806040838503121561234657600080fd5b50508035926020909101359150565b803567ffffffffffffffff8116811461223c57600080fd5b60006020828403121561237f57600080fd5b61225c82612355565b60006020828403121561239a57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160c0810167ffffffffffffffff811182821017156123f3576123f36123a1565b60405290565b60ff811681146107a257600080fd5b600060e0828403121561241a57600080fd5b60405160e0810181811067ffffffffffffffff8211171561243d5761243d6123a1565b60405290508061244c83612218565b815261245a60208401612218565b602082015261246b60408401612218565b604082015261247c60608401612218565b606082015261248d60808401612218565b608082015261249e60a08401612218565b60a08201526124af60c08401612218565b60c08201525092915050565b6000806000806000806000806000898b036102808112156124db57600080fd5b6124e48b612218565b99506124f260208c01612263565b985061250060408c01612263565b975060608b0135965061251560808c01612355565b955061252360a08c01612218565b945060c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff408201121561255557600080fd5b5061255e6123d0565b61256a60c08c01612263565b815260e08b013561257a816123f9565b60208201526101008b013561258e816123f9565b60408201526125a06101208c01612263565b60608201526125b26101408c01612263565b60808201526101608b01356fffffffffffffffffffffffffffffffff811681146125db57600080fd5b60a082015292506125ef6101808b01612218565b91506125ff8b6101a08c01612408565b90509295985092959850929598565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561264f5761264f61260e565b500390565b600067ffffffffffffffff8083168185168083038211156126775761267761260e565b01949350505050565b60006020828403121561269257600080fd5b815161225c816123f9565b6000602082840312156126af57600080fd5b815167ffffffffffffffff808211156126c757600080fd5b818401915084601f8301126126db57600080fd5b8151818111156126ed576126ed6123a1565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715612733576127336123a1565b8160405282815287602084870101111561274c57600080fd5b61275d8360208301602088016122aa565b979650505050505050565b600063ffffffff8083168185168083038211156126775761267761260e565b600063ffffffff808416806127c5577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b92169190910492915050565b600063ffffffff808316818516818304811182151516156127f4576127f461260e565b0294935050505056fea164736f6c634300080f000a04adb1412b2ddc16fcc0d4538d5c8f07cf9c83abecc6b41f6f69037b708fbcec53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77001d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be496e697469616c697a61626c653a20636f6e7472616374206973206e6f7420694b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ada11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a0", - "deployedCode": "0x608060405234801561001057600080fd5b50600436106102de5760003560e01c8063a711986911610186578063e0e2016d116100e3578063f2fde38b11610097578063f8c68de011610071578063f8c68de0146106e2578063fd32aa0f146106ea578063ffa1ad74146106f257600080fd5b8063f2fde38b146106b2578063f45e65d8146106c5578063f68016b7146106ce57600080fd5b8063e81b2c6d116100c8578063e81b2c6d14610681578063ec7075171461068a578063f2b4e617146106aa57600080fd5b8063e0e2016d14610671578063e2a3285c1461067957600080fd5b8063c9b26f611161013a578063d84447151161011f578063d84447151461064e578063dac6e63a14610656578063db9040fa1461065e57600080fd5b8063c9b26f6114610507578063cc731b021461051a57600080fd5b8063bc49ce5f1161016b578063bc49ce5f146104c6578063bfb14fb7146104ce578063c4e8ddfa146104ff57600080fd5b8063a7119869146104ab578063b40a817c146104b357600080fd5b80634397dfef1161023f578063550fcdc9116101f35780638da5cb5b116101cd5780638da5cb5b14610472578063935f029e146104905780639b7d7f0a146104a357600080fd5b8063550fcdc91461045a5780635d73369c14610462578063715018a61461046a57600080fd5b80634add321d116102245780634add321d146103e95780634f16540b146103f157806354fd4d501461041857600080fd5b80634397dfef146103ab57806348cd4cb1146103e157600080fd5b806318d13918116102965780631fd19ee11161027b5780631fd19ee114610378578063213268491461038057806321d7fde51461039857600080fd5b806318d139181461035b57806319f5cea81461037057600080fd5b80630a49cb03116102c75780630a49cb031461032b5780630ae14b1b146103335780630c18c1621461035257600080fd5b806306c92657146102e3578063078f29cf146102fe575b600080fd5b6102eb6106fa565b6040519081526020015b60405180910390f35b610306610728565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102f5565b610306610761565b630bebc2005b60405167ffffffffffffffff90911681526020016102f5565b6102eb60655481565b61036e610369366004612241565b610791565b005b6102eb6107a5565b6103066107d0565b6103886107fa565b60405190151581526020016102f5565b61036e6103a6366004612277565b610839565b6103b361084f565b6040805173ffffffffffffffffffffffffffffffffffffffff909316835260ff9091166020830152016102f5565b6102eb610863565b610339610893565b6102eb7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c0881565b60408051808201909152600c81527f322e332e302d626574612e32000000000000000000000000000000000000000060208201525b6040516102f59190612320565b61044d6108b9565b6102eb6108c3565b61036e6108ee565b60335473ffffffffffffffffffffffffffffffffffffffff16610306565b61036e61049e366004612333565b610902565b610306610914565b610306610944565b61036e6104c136600461236d565b610974565b6102eb610985565b6068546104ea9068010000000000000000900463ffffffff1681565b60405163ffffffff90911681526020016102f5565b6103066109b0565b61036e610515366004612388565b6109e0565b6105de6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152506040805160c08101825260695463ffffffff8082168352640100000000820460ff9081166020850152650100000000008304169383019390935266010000000000008104831660608301526a0100000000000000000000810490921660808201526e0100000000000000000000000000009091046fffffffffffffffffffffffffffffffff1660a082015290565b6040516102f59190600060c08201905063ffffffff80845116835260ff602085015116602084015260ff6040850151166040840152806060850151166060840152806080850151166080840152506fffffffffffffffffffffffffffffffff60a08401511660a083015292915050565b61044d6109f1565b6103066109fb565b61036e61066c3660046124bb565b610a2b565b6102eb610e36565b6102eb610e61565b6102eb60675481565b6068546104ea906c01000000000000000000000000900463ffffffff1681565b610306610e8c565b61036e6106c0366004612241565b610ebc565b6102eb60665481565b6068546103399067ffffffffffffffff1681565b6102eb610f70565b6102eb610f9b565b6102eb600081565b61072560017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d61263d565b81565b600061075c61075860017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad637761263d565b5490565b905090565b600061075c61075860017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad61263d565b610799611201565b6107a281611282565b50565b61072560017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a861263d565b600061075c7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c085490565b60008061080561084f565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b610841611201565b61084b828261133f565b5050565b60008061085a611184565b90939092509050565b600061075c61075860017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a061263d565b60695460009061075c9063ffffffff6a0100000000000000000000820481169116612654565b606061075c61147d565b61072560017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce958063761263d565b6108f6611201565b610900600061153e565b565b61090a611201565b61084b82826115b5565b600061075c61075860017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d61263d565b600061075c61075860017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce958063761263d565b61097c611201565b6107a28161168b565b61072560017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc59861263d565b600061075c61075860017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a861263d565b6109e8611201565b6107a2816117e1565b606061075c611809565b600061075c61075860017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc59861263d565b600054610100900460ff1615808015610a4b5750600054600160ff909116105b80610a655750303b158015610a65575060005460ff166001145b610af6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610b5457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610b5c6118bf565b610b658a610ebc565b610b6e876117e1565b610b78898961133f565b610b818661168b565b610baa7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08869055565b610bdd610bd860017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc59861263d565b849055565b610c11610c0b60017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce958063761263d565b83519055565b610c48610c3f60017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a861263d565b60208401519055565b610c7f610c7660017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad637761263d565b60408401519055565b610cb6610cad60017f52322a25d9f59ea17656545543306b7aef62bc0cc53a0e65ccfa0c75b97aa90761263d565b60608401519055565b610ced610ce460017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad61263d565b60808401519055565b610d24610d1b60017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d61263d565b60a08401519055565b610d2c61195e565b610d398260c001516119c6565b610d4284611cd0565b610d4a610893565b67ffffffffffffffff168667ffffffffffffffff161015610dc7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77006044820152606401610aed565b8015610e2a57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050505050565b61072560017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a061263d565b61072560017f52322a25d9f59ea17656545543306b7aef62bc0cc53a0e65ccfa0c75b97aa90761263d565b600061075c61075860017f52322a25d9f59ea17656545543306b7aef62bc0cc53a0e65ccfa0c75b97aa90761263d565b610ec4611201565b73ffffffffffffffffffffffffffffffffffffffff8116610f67576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610aed565b6107a28161153e565b61072560017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad637761263d565b61072560017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad61263d565b9055565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b600060208251111561107a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f476173506179696e67546f6b656e3a20737472696e672063616e6e6f7420626560448201527f2067726561746572207468616e203332206279746573000000000000000000006064820152608401610aed565b6110838261115b565b92915050565b6110ef6110b760017f04adb1412b2ddc16fcc0d4538d5c8f07cf9c83abecc6b41f6f69037b708fbcec61263d565b74ff000000000000000000000000000000000000000060a086901b1673ffffffffffffffffffffffffffffffffffffffff8716179055565b61112261111d60017f657c3582c29b3176614e3a33ddd1ec48352696a04e92b3c0566d72010fa8863d61263d565b839055565b61115561115060017fa48b38a4b44951360fbdcbfaaeae5ed6ae92585412e9841b70ec72ed8cd0576461263d565b829055565b50505050565b8051602181106111735763ec92f9a36000526004601cfd5b9081015160209190910360031b1b90565b600080806111b661075860017f04adb1412b2ddc16fcc0d4538d5c8f07cf9c83abecc6b41f6f69037b708fbcec61263d565b73ffffffffffffffffffffffffffffffffffffffff811693509050826111f5575073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee92601292509050565b60a081901c9150509091565b60335473ffffffffffffffffffffffffffffffffffffffff163314610900576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610aed565b6112ab7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08829055565b6040805173ffffffffffffffffffffffffffffffffffffffff8316602082015260009101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060035b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be836040516113339190612320565b60405180910390a35050565b606880547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000063ffffffff8581169182027fffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffff16929092176c0100000000000000000000000092851692909202919091179091557f0100000000000000000000000000000000000000000000000000000000000000602083811b67ffffffff000000001690921717606681905560655460408051938401919091528201526000906060015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529050600160007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be836040516114709190612320565b60405180910390a3505050565b60606000611489611184565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff82160161150257505060408051808201909152600381527f4554480000000000000000000000000000000000000000000000000000000000602082015290565b61153861153361075860017fa48b38a4b44951360fbdcbfaaeae5ed6ae92585412e9841b70ec72ed8cd0576461263d565b612144565b91505090565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b7fff00000000000000000000000000000000000000000000000000000000000000811615611665576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f53797374656d436f6e6669673a207363616c61722065786365656473206d617860448201527f2e000000000000000000000000000000000000000000000000000000000000006064820152608401610aed565b60658290556066819055604080516020810184905290810182905260009060600161140d565b611693610893565b67ffffffffffffffff168167ffffffffffffffff161015611710576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77006044820152606401610aed565b630bebc20067ffffffffffffffff82161115611788576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f20686967686044820152606401610aed565b606880547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff83169081179091556040805160208082019390935281518082039093018352810190526002611302565b6067819055604080516020808201849052825180830390910181529082019091526000611302565b60606000611815611184565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff82160161188e57505060408051808201909152600581527f4574686572000000000000000000000000000000000000000000000000000000602082015290565b61153861153361075860017f657c3582c29b3176614e3a33ddd1ec48352696a04e92b3c0566d72010fa8863d61263d565b600054610100900460ff16611956576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610aed565b610900612178565b61198c61075860017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a061263d565b600003610900576109006119c160017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a061263d565b439055565b73ffffffffffffffffffffffffffffffffffffffff811615801590611a15575073ffffffffffffffffffffffffffffffffffffffff811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14155b8015611a265750611a246107fa565b155b156107a257601260ff168173ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a9f9190612680565b60ff1614611b2f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f53797374656d436f6e6669673a2062616420646563696d616c73206f6620676160448201527f7320706179696e6720746f6b656e0000000000000000000000000000000000006064820152608401610aed565b6000611bca8273ffffffffffffffffffffffffffffffffffffffff166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa158015611b7f573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611bc5919081019061269d565b610fe6565b90506000611c1c8373ffffffffffffffffffffffffffffffffffffffff166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015611b7f573d6000803e3d6000fd5b9050611c2b8360128484611089565b611c33610761565b6040517f71cfaa3f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015260126024830152604482018590526064820184905291909116906371cfaa3f90608401600060405180830381600087803b158015611cb357600080fd5b505af1158015611cc7573d6000803e3d6000fd5b50505050505050565b8060a001516fffffffffffffffffffffffffffffffff16816060015163ffffffff161115611d80576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f53797374656d436f6e6669673a206d696e206261736520666565206d7573742060448201527f6265206c657373207468616e206d6178206261736500000000000000000000006064820152608401610aed565b6001816040015160ff1611611e17576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f53797374656d436f6e6669673a2064656e6f6d696e61746f72206d757374206260448201527f65206c6172676572207468616e203100000000000000000000000000000000006064820152608401610aed565b6068546080820151825167ffffffffffffffff90921691611e389190612768565b63ffffffff161115611ea6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77006044820152606401610aed565b6000816020015160ff1611611f3d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f53797374656d436f6e6669673a20656c6173746963697479206d756c7469706c60448201527f6965722063616e6e6f74206265203000000000000000000000000000000000006064820152608401610aed565b8051602082015163ffffffff82169160ff90911690611f5d908290612787565b611f6791906127d1565b63ffffffff1614611ffa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f53797374656d436f6e6669673a20707265636973696f6e206c6f73732077697460448201527f6820746172676574207265736f75726365206c696d69740000000000000000006064820152608401610aed565b805160698054602084015160408501516060860151608087015160a09097015163ffffffff9687167fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009095169490941764010000000060ff94851602177fffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffff166501000000000093909216929092027fffffffffffffffffffffffffffffffffffffffffffff00000000ffffffffffff1617660100000000000091851691909102177fffff0000000000000000000000000000000000000000ffffffffffffffffffff166a010000000000000000000093909416929092027fffff00000000000000000000000000000000ffffffffffffffffffffffffffff16929092176e0100000000000000000000000000006fffffffffffffffffffffffffffffffff90921691909102179055565b60405160005b82811a1561215a5760010161214a565b80825260208201838152600082820152505060408101604052919050565b600054610100900460ff1661220f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610aed565b6109003361153e565b803573ffffffffffffffffffffffffffffffffffffffff8116811461223c57600080fd5b919050565b60006020828403121561225357600080fd5b61225c82612218565b9392505050565b803563ffffffff8116811461223c57600080fd5b6000806040838503121561228a57600080fd5b61229383612263565b91506122a160208401612263565b90509250929050565b60005b838110156122c55781810151838201526020016122ad565b838111156111555750506000910152565b600081518084526122ee8160208601602086016122aa565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061225c60208301846122d6565b6000806040838503121561234657600080fd5b50508035926020909101359150565b803567ffffffffffffffff8116811461223c57600080fd5b60006020828403121561237f57600080fd5b61225c82612355565b60006020828403121561239a57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160c0810167ffffffffffffffff811182821017156123f3576123f36123a1565b60405290565b60ff811681146107a257600080fd5b600060e0828403121561241a57600080fd5b60405160e0810181811067ffffffffffffffff8211171561243d5761243d6123a1565b60405290508061244c83612218565b815261245a60208401612218565b602082015261246b60408401612218565b604082015261247c60608401612218565b606082015261248d60808401612218565b608082015261249e60a08401612218565b60a08201526124af60c08401612218565b60c08201525092915050565b6000806000806000806000806000898b036102808112156124db57600080fd5b6124e48b612218565b99506124f260208c01612263565b985061250060408c01612263565b975060608b0135965061251560808c01612355565b955061252360a08c01612218565b945060c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff408201121561255557600080fd5b5061255e6123d0565b61256a60c08c01612263565b815260e08b013561257a816123f9565b60208201526101008b013561258e816123f9565b60408201526125a06101208c01612263565b60608201526125b26101408c01612263565b60808201526101608b01356fffffffffffffffffffffffffffffffff811681146125db57600080fd5b60a082015292506125ef6101808b01612218565b91506125ff8b6101a08c01612408565b90509295985092959850929598565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561264f5761264f61260e565b500390565b600067ffffffffffffffff8083168185168083038211156126775761267761260e565b01949350505050565b60006020828403121561269257600080fd5b815161225c816123f9565b6000602082840312156126af57600080fd5b815167ffffffffffffffff808211156126c757600080fd5b818401915084601f8301126126db57600080fd5b8151818111156126ed576126ed6123a1565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715612733576127336123a1565b8160405282815287602084870101111561274c57600080fd5b61275d8360208301602088016122aa565b979650505050505050565b600063ffffffff8083168185168083038211156126775761267761260e565b600063ffffffff808416806127c5577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b92169190910492915050565b600063ffffffff808316818516818304811182151516156127f4576127f461260e565b0294935050505056fea164736f6c634300080f000a", - "initialized": true, - "kind": "Create", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "isWrite": true, - "newValue": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0xa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb19f" - }, - { - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - }, - { - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "isWrite": true, - "newValue": "0x0000000000000000000000004e59b44847b379578588920ca78fbf26c0b4956c", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - }, - { - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "isWrite": false, - "newValue": "0x0000000000000000000000004e59b44847b379578588920ca78fbf26c0b4956c", - "previousValue": "0x0000000000000000000000004e59b44847b379578588920ca78fbf26c0b4956c", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - }, - { - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "isWrite": false, - "newValue": "0x0000000000000000000000004e59b44847b379578588920ca78fbf26c0b4956c", - "previousValue": "0x0000000000000000000000004e59b44847b379578588920ca78fbf26c0b4956c", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - }, - { - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "isWrite": true, - "newValue": "0x000000000000000000000000000000000000000000000000000000000000dead", - "previousValue": "0x0000000000000000000000004e59b44847b379578588920ca78fbf26c0b4956c", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - }, - { - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000067" - }, - { - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000068" - }, - { - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000068" - }, - { - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "isWrite": true, - "newValue": "0x0100000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000066" - }, - { - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000065" - }, - { - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000069" - }, - { - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000068" - }, - { - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000068" - }, - { - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08" - }, - { - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc597" - }, - { - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce9580636" - }, - { - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a7" - }, - { - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad6376" - }, - { - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x52322a25d9f59ea17656545543306b7aef62bc0cc53a0e65ccfa0c75b97aa906" - }, - { - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ac" - }, - { - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0xa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320c" - }, - { - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "isWrite": false, - "newValue": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "previousValue": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "reverted": false, - "slot": "0xa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb19f" - }, - { - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000068" - }, - { - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000069" - }, - { - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000020100000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000069" - }, - { - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000020100000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000020100000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000069" - }, - { - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "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": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xcc731b02", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000020100000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000020100000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000069" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x8da5cb5b", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "isWrite": false, - "newValue": "0x000000000000000000000000000000000000000000000000000000000000dead", - "previousValue": "0x000000000000000000000000000000000000000000000000000000000000dead", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x0c18c162", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000065" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xf45e65d8", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "isWrite": false, - "newValue": "0x0100000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0100000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000066" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xbfb14fb7", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000068" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xec707517", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000068" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xe81b2c6d", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000067" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xf68016b7", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000068" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x1fd19ee1", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x48cd4cb1", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "isWrite": false, - "newValue": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "previousValue": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "reverted": false, - "slot": "0xa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb19f" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xdac6e63a", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc597" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xa7119869", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce9580636" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xc4e8ddfa", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a7" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x078f29cf", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad6376" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xf2b4e617", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x52322a25d9f59ea17656545543306b7aef62bc0cc53a0e65ccfa0c75b97aa906" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x0a49cb03", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ac" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x9b7d7f0a", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "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": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x638627e586f5e36fe67a77519503a7c6da22f92b150d3c6055fd40bdcfe9ffd160806040523480156200001157600080fd5b50620000206000808062000026565b6200024b565b600054610100900460ff1615808015620000475750600054600160ff909116105b806200007757506200006430620001a160201b620005891760201c565b15801562000077575060005460ff166001145b620000e05760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000104576000805461ff0019166101001790555b603280546001600160a01b038086166001600160a01b03199283161790925560338054928516929091169190911790556200015484734200000000000000000000000000000000000010620001b0565b80156200019b576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b6001600160a01b03163b151590565b600054610100900460ff166200021d5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401620000d7565b600380546001600160a01b039384166001600160a01b03199182161790915560048054929093169116179055565b612fad806200025b6000396000f3fe6080604052600436106101845760003560e01c80637f46ddb2116100d65780639a2ac6d51161007f578063c0c53b8b11610059578063c0c53b8b14610529578063c89701a214610549578063e11013dd1461057657600080fd5b80639a2ac6d5146104e3578063a9f9e675146104f6578063b1a1a8821461051657600080fd5b80638f601f66116100b05780638f601f661461047257806391c49bf814610407578063927ede2d146104b857600080fd5b80637f46ddb214610407578063838b252014610432578063870876231461045257600080fd5b806335e80ab31161013857806354fd4d501161011257806354fd4d501461036c57806358a997f6146103c25780635c975abb146103e257600080fd5b806335e80ab3146102f25780633cb747bf1461031f578063540abf731461034c57600080fd5b80631532ec34116101695780631532ec34146102755780631635f5fd1461028857806333d7e2bd1461029b57600080fd5b80630166a07a1461024257806309fc88431461026257600080fd5b3661023d57333b1561021d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084015b60405180910390fd5b61023b333362030d40604051806020016040528060008152506105a5565b005b600080fd5b34801561024e57600080fd5b5061023b61025d366004612991565b6105b8565b61023b610270366004612a42565b6109d2565b61023b610283366004612a95565b610aa9565b61023b610296366004612a95565b610abd565b3480156102a757600080fd5b506033546102c89073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156102fe57600080fd5b506032546102c89073ffffffffffffffffffffffffffffffffffffffff1681565b34801561032b57600080fd5b506003546102c89073ffffffffffffffffffffffffffffffffffffffff1681565b34801561035857600080fd5b5061023b610367366004612b08565b61101b565b34801561037857600080fd5b506103b56040518060400160405280600581526020017f322e322e3000000000000000000000000000000000000000000000000000000081525081565b6040516102e99190612bf5565b3480156103ce57600080fd5b5061023b6103dd366004612c08565b611060565b3480156103ee57600080fd5b506103f7611134565b60405190151581526020016102e9565b34801561041357600080fd5b5060045473ffffffffffffffffffffffffffffffffffffffff166102c8565b34801561043e57600080fd5b5061023b61044d366004612b08565b6111cd565b34801561045e57600080fd5b5061023b61046d366004612c08565b611212565b34801561047e57600080fd5b506104aa61048d366004612c8b565b600260209081526000928352604080842090915290825290205481565b6040519081526020016102e9565b3480156104c457600080fd5b5060035473ffffffffffffffffffffffffffffffffffffffff166102c8565b61023b6104f1366004612cc4565b6112e6565b34801561050257600080fd5b5061023b610511366004612991565b611328565b61023b610524366004612a42565b611337565b34801561053557600080fd5b5061023b610544366004612d27565b611408565b34801561055557600080fd5b506004546102c89073ffffffffffffffffffffffffffffffffffffffff1681565b61023b610584366004612cc4565b611607565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6105b2848434858561164a565b50505050565b60035473ffffffffffffffffffffffffffffffffffffffff163314801561068b575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa15801561064f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106739190612d72565b73ffffffffffffffffffffffffffffffffffffffff16145b61073d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a401610214565b610745611134565b156107ac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616e646172644272696467653a20706175736564000000000000000000006044820152606401610214565b6107b5876118a9565b15610903576107c4878761190b565b610876576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a401610214565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b1580156108e657600080fd5b505af11580156108fa573d6000803e3d6000fd5b50505050610985565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054610941908490612dbe565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c1683529390529190912091909155610985908585611a2b565b6109c9878787878787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611aff92505050565b50505050505050565b333b15610a61576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610214565b610aa43333348686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061164a92505050565b505050565b610ab68585858585610abd565b5050505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610b90575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa158015610b54573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b789190612d72565b73ffffffffffffffffffffffffffffffffffffffff16145b610c42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a401610214565b610c4a611134565b15610cb1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616e646172644272696467653a20706175736564000000000000000000006044820152606401610214565b610cb9611b8d565b15610d46576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e0000000000000000006064820152608401610214565b823414610dd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e742072657175697265640000000000006064820152608401610214565b3073ffffffffffffffffffffffffffffffffffffffff851603610e7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c6600000000000000000000000000000000000000000000000000000000006064820152608401610214565b60035473ffffffffffffffffffffffffffffffffffffffff90811690851603610f25576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e6765720000000000000000000000000000000000000000000000006064820152608401610214565b610f6785858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611bcc92505050565b6000610f84855a8660405180602001604052806000815250611c3f565b905080611013576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c656400000000000000000000000000000000000000000000000000000000006064820152608401610214565b505050505050565b6109c987873388888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611c5792505050565b333b156110ef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610214565b61101386863333888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061201092505050565b603254604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa1580156111a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111c89190612dd5565b905090565b6109c987873388888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061201092505050565b333b156112a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610214565b61101386863333888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611c5792505050565b6105b233858585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506105a592505050565b6109c9878787878787876105b8565b333b156113c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610214565b610aa433338585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506105a592505050565b600054610100900460ff16158080156114285750600054600160ff909116105b806114425750303b158015611442575060005460ff166001145b6114ce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610214565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561152c57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6032805473ffffffffffffffffffffffffffffffffffffffff8086167fffffffffffffffffffffffff000000000000000000000000000000000000000092831617909255603380549285169290911691909117905561159f8473420000000000000000000000000000000000001061201f565b80156105b257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150505050565b6105b23385348686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061164a92505050565b611652611b8d565b156116df576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e0000000000000000006064820152608401610214565b82341461176e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c756500006064820152608401610214565b61177a85858584612109565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9287929116907f1635f5fd00000000000000000000000000000000000000000000000000000000906117dd908b908b9086908a90602401612df7565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b909216825261187092918890600401612e40565b6000604051808303818588803b15801561188957600080fd5b505af115801561189d573d6000803e3d6000fd5b50505050505050505050565b60006118d5827f1d1d8b630000000000000000000000000000000000000000000000000000000061217c565b806119055750611905827fec4fc8e30000000000000000000000000000000000000000000000000000000061217c565b92915050565b6000611937837f1d1d8b630000000000000000000000000000000000000000000000000000000061217c565b156119e0578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015611987573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ab9190612d72565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050611905565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611987573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052610aa49084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915261219f565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f3ceee06c1e37648fcbb6ed52e17b3e1f275a1f8c7b22a84b2b84732431e046b3868686604051611b7793929190612e85565b60405180910390a46110138686868686866122ab565b600080611b98612333565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2ac69ee804d9a7a0984249f508dfab7cb2534b465b6ce1580f99a38ba9c5e6318484604051611c2b929190612ec3565b60405180910390a36105b2848484846123d0565b6000806000835160208501868989f195945050505050565b3415611ce5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5374616e646172644272696467653a2063616e6e6f742073656e642076616c7560448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610214565b611cee876118a9565b15611e3c57611cfd878761190b565b611daf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a401610214565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b158015611e1f57600080fd5b505af1158015611e33573d6000803e3d6000fd5b50505050611ed0565b611e5e73ffffffffffffffffffffffffffffffffffffffff881686308661243d565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054611e9c908490612edc565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b611ede87878787878661249b565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9216907f0166a07a0000000000000000000000000000000000000000000000000000000090611f42908b908d908c908c908c908b90602401612ef4565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b9092168252611fd592918790600401612e40565b600060405180830381600087803b158015611fef57600080fd5b505af1158015612003573d6000803e3d6000fd5b5050505050505050505050565b6109c987878787878787611c57565b600054610100900460ff166120b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610214565b6003805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560048054929093169116179055565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f35d79ab81f2b2017e19afb5c5571778877782d7a8786f5907f93b0f4702f4f238484604051612168929190612ec3565b60405180910390a36105b284848484612529565b600061218783612588565b8015612198575061219883836125ec565b9392505050565b6000612201826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166126bb9092919063ffffffff16565b805190915015610aa4578080602001905181019061221f9190612dd5565b610aa4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610214565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd86868660405161232393929190612e85565b60405180910390a4505050505050565b603354604080517f4397dfef0000000000000000000000000000000000000000000000000000000081528151600093849373ffffffffffffffffffffffffffffffffffffffff90911692634397dfef92600480830193928290030181865afa1580156123a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123c79190612f4f565b90939092509050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d848460405161242f929190612ec3565b60405180910390a350505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526105b29085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611a7d565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f718594027abd4eaed59f95162563e0cc6d0e8d5b86b1c7be8b1b0ac3343d039686868660405161251393929190612e85565b60405180910390a46110138686868686866126d2565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af5848460405161242f929190612ec3565b60006125b4827f01ffc9a7000000000000000000000000000000000000000000000000000000006125ec565b801561190557506125e5827fffffffff000000000000000000000000000000000000000000000000000000006125ec565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d915060005190508280156126a4575060208210155b80156126b05750600081115b979650505050505050565b60606126ca848460008561274a565b949350505050565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf86868660405161232393929190612e85565b6060824710156127dc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610214565b73ffffffffffffffffffffffffffffffffffffffff85163b61285a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610214565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516128839190612f84565b60006040518083038185875af1925050503d80600081146128c0576040519150601f19603f3d011682016040523d82523d6000602084013e6128c5565b606091505b50915091506126b0828286606083156128df575081612198565b8251156128ef5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102149190612bf5565b73ffffffffffffffffffffffffffffffffffffffff8116811461294557600080fd5b50565b60008083601f84011261295a57600080fd5b50813567ffffffffffffffff81111561297257600080fd5b60208301915083602082850101111561298a57600080fd5b9250929050565b600080600080600080600060c0888a0312156129ac57600080fd5b87356129b781612923565b965060208801356129c781612923565b955060408801356129d781612923565b945060608801356129e781612923565b93506080880135925060a088013567ffffffffffffffff811115612a0a57600080fd5b612a168a828b01612948565b989b979a50959850939692959293505050565b803563ffffffff81168114612a3d57600080fd5b919050565b600080600060408486031215612a5757600080fd5b612a6084612a29565b9250602084013567ffffffffffffffff811115612a7c57600080fd5b612a8886828701612948565b9497909650939450505050565b600080600080600060808688031215612aad57600080fd5b8535612ab881612923565b94506020860135612ac881612923565b935060408601359250606086013567ffffffffffffffff811115612aeb57600080fd5b612af788828901612948565b969995985093965092949392505050565b600080600080600080600060c0888a031215612b2357600080fd5b8735612b2e81612923565b96506020880135612b3e81612923565b95506040880135612b4e81612923565b945060608801359350612b6360808901612a29565b925060a088013567ffffffffffffffff811115612a0a57600080fd5b60005b83811015612b9a578181015183820152602001612b82565b838111156105b25750506000910152565b60008151808452612bc3816020860160208601612b7f565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006121986020830184612bab565b60008060008060008060a08789031215612c2157600080fd5b8635612c2c81612923565b95506020870135612c3c81612923565b945060408701359350612c5160608801612a29565b9250608087013567ffffffffffffffff811115612c6d57600080fd5b612c7989828a01612948565b979a9699509497509295939492505050565b60008060408385031215612c9e57600080fd5b8235612ca981612923565b91506020830135612cb981612923565b809150509250929050565b60008060008060608587031215612cda57600080fd5b8435612ce581612923565b9350612cf360208601612a29565b9250604085013567ffffffffffffffff811115612d0f57600080fd5b612d1b87828801612948565b95989497509550505050565b600080600060608486031215612d3c57600080fd5b8335612d4781612923565b92506020840135612d5781612923565b91506040840135612d6781612923565b809150509250925092565b600060208284031215612d8457600080fd5b815161219881612923565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015612dd057612dd0612d8f565b500390565b600060208284031215612de757600080fd5b8151801515811461219857600080fd5b600073ffffffffffffffffffffffffffffffffffffffff808716835280861660208401525083604083015260806060830152612e366080830184612bab565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff84168152606060208201526000612e6f6060830185612bab565b905063ffffffff83166040830152949350505050565b73ffffffffffffffffffffffffffffffffffffffff84168152826020820152606060408201526000612eba6060830184612bab565b95945050505050565b8281526040602082015260006126ca6040830184612bab565b60008219821115612eef57612eef612d8f565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a0830152612f4360c0830184612bab565b98975050505050505050565b60008060408385031215612f6257600080fd5b8251612f6d81612923565b602084015190925060ff81168114612cb957600080fd5b60008251612f96818460208701612b7f565b919091019291505056fea164736f6c634300080f000a", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [], - "value": 0 - }, - { - "accessor": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "account": "0xb7900B27Be8f0E0fF65d1C3A4671e1220437dd2b", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x60806040523480156200001157600080fd5b50620000206000808062000026565b6200024b565b600054610100900460ff1615808015620000475750600054600160ff909116105b806200007757506200006430620001a160201b620005891760201c565b15801562000077575060005460ff166001145b620000e05760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000104576000805461ff0019166101001790555b603280546001600160a01b038086166001600160a01b03199283161790925560338054928516929091169190911790556200015484734200000000000000000000000000000000000010620001b0565b80156200019b576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b6001600160a01b03163b151590565b600054610100900460ff166200021d5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401620000d7565b600380546001600160a01b039384166001600160a01b03199182161790915560048054929093169116179055565b612fad806200025b6000396000f3fe6080604052600436106101845760003560e01c80637f46ddb2116100d65780639a2ac6d51161007f578063c0c53b8b11610059578063c0c53b8b14610529578063c89701a214610549578063e11013dd1461057657600080fd5b80639a2ac6d5146104e3578063a9f9e675146104f6578063b1a1a8821461051657600080fd5b80638f601f66116100b05780638f601f661461047257806391c49bf814610407578063927ede2d146104b857600080fd5b80637f46ddb214610407578063838b252014610432578063870876231461045257600080fd5b806335e80ab31161013857806354fd4d501161011257806354fd4d501461036c57806358a997f6146103c25780635c975abb146103e257600080fd5b806335e80ab3146102f25780633cb747bf1461031f578063540abf731461034c57600080fd5b80631532ec34116101695780631532ec34146102755780631635f5fd1461028857806333d7e2bd1461029b57600080fd5b80630166a07a1461024257806309fc88431461026257600080fd5b3661023d57333b1561021d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084015b60405180910390fd5b61023b333362030d40604051806020016040528060008152506105a5565b005b600080fd5b34801561024e57600080fd5b5061023b61025d366004612991565b6105b8565b61023b610270366004612a42565b6109d2565b61023b610283366004612a95565b610aa9565b61023b610296366004612a95565b610abd565b3480156102a757600080fd5b506033546102c89073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156102fe57600080fd5b506032546102c89073ffffffffffffffffffffffffffffffffffffffff1681565b34801561032b57600080fd5b506003546102c89073ffffffffffffffffffffffffffffffffffffffff1681565b34801561035857600080fd5b5061023b610367366004612b08565b61101b565b34801561037857600080fd5b506103b56040518060400160405280600581526020017f322e322e3000000000000000000000000000000000000000000000000000000081525081565b6040516102e99190612bf5565b3480156103ce57600080fd5b5061023b6103dd366004612c08565b611060565b3480156103ee57600080fd5b506103f7611134565b60405190151581526020016102e9565b34801561041357600080fd5b5060045473ffffffffffffffffffffffffffffffffffffffff166102c8565b34801561043e57600080fd5b5061023b61044d366004612b08565b6111cd565b34801561045e57600080fd5b5061023b61046d366004612c08565b611212565b34801561047e57600080fd5b506104aa61048d366004612c8b565b600260209081526000928352604080842090915290825290205481565b6040519081526020016102e9565b3480156104c457600080fd5b5060035473ffffffffffffffffffffffffffffffffffffffff166102c8565b61023b6104f1366004612cc4565b6112e6565b34801561050257600080fd5b5061023b610511366004612991565b611328565b61023b610524366004612a42565b611337565b34801561053557600080fd5b5061023b610544366004612d27565b611408565b34801561055557600080fd5b506004546102c89073ffffffffffffffffffffffffffffffffffffffff1681565b61023b610584366004612cc4565b611607565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6105b2848434858561164a565b50505050565b60035473ffffffffffffffffffffffffffffffffffffffff163314801561068b575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa15801561064f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106739190612d72565b73ffffffffffffffffffffffffffffffffffffffff16145b61073d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a401610214565b610745611134565b156107ac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616e646172644272696467653a20706175736564000000000000000000006044820152606401610214565b6107b5876118a9565b15610903576107c4878761190b565b610876576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a401610214565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b1580156108e657600080fd5b505af11580156108fa573d6000803e3d6000fd5b50505050610985565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054610941908490612dbe565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c1683529390529190912091909155610985908585611a2b565b6109c9878787878787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611aff92505050565b50505050505050565b333b15610a61576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610214565b610aa43333348686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061164a92505050565b505050565b610ab68585858585610abd565b5050505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610b90575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa158015610b54573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b789190612d72565b73ffffffffffffffffffffffffffffffffffffffff16145b610c42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a401610214565b610c4a611134565b15610cb1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616e646172644272696467653a20706175736564000000000000000000006044820152606401610214565b610cb9611b8d565b15610d46576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e0000000000000000006064820152608401610214565b823414610dd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e742072657175697265640000000000006064820152608401610214565b3073ffffffffffffffffffffffffffffffffffffffff851603610e7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c6600000000000000000000000000000000000000000000000000000000006064820152608401610214565b60035473ffffffffffffffffffffffffffffffffffffffff90811690851603610f25576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e6765720000000000000000000000000000000000000000000000006064820152608401610214565b610f6785858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611bcc92505050565b6000610f84855a8660405180602001604052806000815250611c3f565b905080611013576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c656400000000000000000000000000000000000000000000000000000000006064820152608401610214565b505050505050565b6109c987873388888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611c5792505050565b333b156110ef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610214565b61101386863333888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061201092505050565b603254604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa1580156111a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111c89190612dd5565b905090565b6109c987873388888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061201092505050565b333b156112a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610214565b61101386863333888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611c5792505050565b6105b233858585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506105a592505050565b6109c9878787878787876105b8565b333b156113c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610214565b610aa433338585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506105a592505050565b600054610100900460ff16158080156114285750600054600160ff909116105b806114425750303b158015611442575060005460ff166001145b6114ce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610214565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561152c57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6032805473ffffffffffffffffffffffffffffffffffffffff8086167fffffffffffffffffffffffff000000000000000000000000000000000000000092831617909255603380549285169290911691909117905561159f8473420000000000000000000000000000000000001061201f565b80156105b257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150505050565b6105b23385348686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061164a92505050565b611652611b8d565b156116df576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e0000000000000000006064820152608401610214565b82341461176e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c756500006064820152608401610214565b61177a85858584612109565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9287929116907f1635f5fd00000000000000000000000000000000000000000000000000000000906117dd908b908b9086908a90602401612df7565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b909216825261187092918890600401612e40565b6000604051808303818588803b15801561188957600080fd5b505af115801561189d573d6000803e3d6000fd5b50505050505050505050565b60006118d5827f1d1d8b630000000000000000000000000000000000000000000000000000000061217c565b806119055750611905827fec4fc8e30000000000000000000000000000000000000000000000000000000061217c565b92915050565b6000611937837f1d1d8b630000000000000000000000000000000000000000000000000000000061217c565b156119e0578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015611987573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ab9190612d72565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050611905565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611987573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052610aa49084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915261219f565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f3ceee06c1e37648fcbb6ed52e17b3e1f275a1f8c7b22a84b2b84732431e046b3868686604051611b7793929190612e85565b60405180910390a46110138686868686866122ab565b600080611b98612333565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2ac69ee804d9a7a0984249f508dfab7cb2534b465b6ce1580f99a38ba9c5e6318484604051611c2b929190612ec3565b60405180910390a36105b2848484846123d0565b6000806000835160208501868989f195945050505050565b3415611ce5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5374616e646172644272696467653a2063616e6e6f742073656e642076616c7560448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610214565b611cee876118a9565b15611e3c57611cfd878761190b565b611daf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a401610214565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b158015611e1f57600080fd5b505af1158015611e33573d6000803e3d6000fd5b50505050611ed0565b611e5e73ffffffffffffffffffffffffffffffffffffffff881686308661243d565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054611e9c908490612edc565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b611ede87878787878661249b565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9216907f0166a07a0000000000000000000000000000000000000000000000000000000090611f42908b908d908c908c908c908b90602401612ef4565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b9092168252611fd592918790600401612e40565b600060405180830381600087803b158015611fef57600080fd5b505af1158015612003573d6000803e3d6000fd5b5050505050505050505050565b6109c987878787878787611c57565b600054610100900460ff166120b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610214565b6003805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560048054929093169116179055565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f35d79ab81f2b2017e19afb5c5571778877782d7a8786f5907f93b0f4702f4f238484604051612168929190612ec3565b60405180910390a36105b284848484612529565b600061218783612588565b8015612198575061219883836125ec565b9392505050565b6000612201826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166126bb9092919063ffffffff16565b805190915015610aa4578080602001905181019061221f9190612dd5565b610aa4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610214565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd86868660405161232393929190612e85565b60405180910390a4505050505050565b603354604080517f4397dfef0000000000000000000000000000000000000000000000000000000081528151600093849373ffffffffffffffffffffffffffffffffffffffff90911692634397dfef92600480830193928290030181865afa1580156123a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123c79190612f4f565b90939092509050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d848460405161242f929190612ec3565b60405180910390a350505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526105b29085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611a7d565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f718594027abd4eaed59f95162563e0cc6d0e8d5b86b1c7be8b1b0ac3343d039686868660405161251393929190612e85565b60405180910390a46110138686868686866126d2565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af5848460405161242f929190612ec3565b60006125b4827f01ffc9a7000000000000000000000000000000000000000000000000000000006125ec565b801561190557506125e5827fffffffff000000000000000000000000000000000000000000000000000000006125ec565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d915060005190508280156126a4575060208210155b80156126b05750600081115b979650505050505050565b60606126ca848460008561274a565b949350505050565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf86868660405161232393929190612e85565b6060824710156127dc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610214565b73ffffffffffffffffffffffffffffffffffffffff85163b61285a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610214565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516128839190612f84565b60006040518083038185875af1925050503d80600081146128c0576040519150601f19603f3d011682016040523d82523d6000602084013e6128c5565b606091505b50915091506126b0828286606083156128df575081612198565b8251156128ef5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102149190612bf5565b73ffffffffffffffffffffffffffffffffffffffff8116811461294557600080fd5b50565b60008083601f84011261295a57600080fd5b50813567ffffffffffffffff81111561297257600080fd5b60208301915083602082850101111561298a57600080fd5b9250929050565b600080600080600080600060c0888a0312156129ac57600080fd5b87356129b781612923565b965060208801356129c781612923565b955060408801356129d781612923565b945060608801356129e781612923565b93506080880135925060a088013567ffffffffffffffff811115612a0a57600080fd5b612a168a828b01612948565b989b979a50959850939692959293505050565b803563ffffffff81168114612a3d57600080fd5b919050565b600080600060408486031215612a5757600080fd5b612a6084612a29565b9250602084013567ffffffffffffffff811115612a7c57600080fd5b612a8886828701612948565b9497909650939450505050565b600080600080600060808688031215612aad57600080fd5b8535612ab881612923565b94506020860135612ac881612923565b935060408601359250606086013567ffffffffffffffff811115612aeb57600080fd5b612af788828901612948565b969995985093965092949392505050565b600080600080600080600060c0888a031215612b2357600080fd5b8735612b2e81612923565b96506020880135612b3e81612923565b95506040880135612b4e81612923565b945060608801359350612b6360808901612a29565b925060a088013567ffffffffffffffff811115612a0a57600080fd5b60005b83811015612b9a578181015183820152602001612b82565b838111156105b25750506000910152565b60008151808452612bc3816020860160208601612b7f565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006121986020830184612bab565b60008060008060008060a08789031215612c2157600080fd5b8635612c2c81612923565b95506020870135612c3c81612923565b945060408701359350612c5160608801612a29565b9250608087013567ffffffffffffffff811115612c6d57600080fd5b612c7989828a01612948565b979a9699509497509295939492505050565b60008060408385031215612c9e57600080fd5b8235612ca981612923565b91506020830135612cb981612923565b809150509250929050565b60008060008060608587031215612cda57600080fd5b8435612ce581612923565b9350612cf360208601612a29565b9250604085013567ffffffffffffffff811115612d0f57600080fd5b612d1b87828801612948565b95989497509550505050565b600080600060608486031215612d3c57600080fd5b8335612d4781612923565b92506020840135612d5781612923565b91506040840135612d6781612923565b809150509250925092565b600060208284031215612d8457600080fd5b815161219881612923565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015612dd057612dd0612d8f565b500390565b600060208284031215612de757600080fd5b8151801515811461219857600080fd5b600073ffffffffffffffffffffffffffffffffffffffff808716835280861660208401525083604083015260806060830152612e366080830184612bab565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff84168152606060208201526000612e6f6060830185612bab565b905063ffffffff83166040830152949350505050565b73ffffffffffffffffffffffffffffffffffffffff84168152826020820152606060408201526000612eba6060830184612bab565b95945050505050565b8281526040602082015260006126ca6040830184612bab565b60008219821115612eef57612eef612d8f565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a0830152612f4360c0830184612bab565b98975050505050505050565b60008060408385031215612f6257600080fd5b8251612f6d81612923565b602084015190925060ff81168114612cb957600080fd5b60008251612f96818460208701612b7f565b919091019291505056fea164736f6c634300080f000a", - "deployedCode": "0x6080604052600436106101845760003560e01c80637f46ddb2116100d65780639a2ac6d51161007f578063c0c53b8b11610059578063c0c53b8b14610529578063c89701a214610549578063e11013dd1461057657600080fd5b80639a2ac6d5146104e3578063a9f9e675146104f6578063b1a1a8821461051657600080fd5b80638f601f66116100b05780638f601f661461047257806391c49bf814610407578063927ede2d146104b857600080fd5b80637f46ddb214610407578063838b252014610432578063870876231461045257600080fd5b806335e80ab31161013857806354fd4d501161011257806354fd4d501461036c57806358a997f6146103c25780635c975abb146103e257600080fd5b806335e80ab3146102f25780633cb747bf1461031f578063540abf731461034c57600080fd5b80631532ec34116101695780631532ec34146102755780631635f5fd1461028857806333d7e2bd1461029b57600080fd5b80630166a07a1461024257806309fc88431461026257600080fd5b3661023d57333b1561021d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084015b60405180910390fd5b61023b333362030d40604051806020016040528060008152506105a5565b005b600080fd5b34801561024e57600080fd5b5061023b61025d366004612991565b6105b8565b61023b610270366004612a42565b6109d2565b61023b610283366004612a95565b610aa9565b61023b610296366004612a95565b610abd565b3480156102a757600080fd5b506033546102c89073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156102fe57600080fd5b506032546102c89073ffffffffffffffffffffffffffffffffffffffff1681565b34801561032b57600080fd5b506003546102c89073ffffffffffffffffffffffffffffffffffffffff1681565b34801561035857600080fd5b5061023b610367366004612b08565b61101b565b34801561037857600080fd5b506103b56040518060400160405280600581526020017f322e322e3000000000000000000000000000000000000000000000000000000081525081565b6040516102e99190612bf5565b3480156103ce57600080fd5b5061023b6103dd366004612c08565b611060565b3480156103ee57600080fd5b506103f7611134565b60405190151581526020016102e9565b34801561041357600080fd5b5060045473ffffffffffffffffffffffffffffffffffffffff166102c8565b34801561043e57600080fd5b5061023b61044d366004612b08565b6111cd565b34801561045e57600080fd5b5061023b61046d366004612c08565b611212565b34801561047e57600080fd5b506104aa61048d366004612c8b565b600260209081526000928352604080842090915290825290205481565b6040519081526020016102e9565b3480156104c457600080fd5b5060035473ffffffffffffffffffffffffffffffffffffffff166102c8565b61023b6104f1366004612cc4565b6112e6565b34801561050257600080fd5b5061023b610511366004612991565b611328565b61023b610524366004612a42565b611337565b34801561053557600080fd5b5061023b610544366004612d27565b611408565b34801561055557600080fd5b506004546102c89073ffffffffffffffffffffffffffffffffffffffff1681565b61023b610584366004612cc4565b611607565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6105b2848434858561164a565b50505050565b60035473ffffffffffffffffffffffffffffffffffffffff163314801561068b575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa15801561064f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106739190612d72565b73ffffffffffffffffffffffffffffffffffffffff16145b61073d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a401610214565b610745611134565b156107ac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616e646172644272696467653a20706175736564000000000000000000006044820152606401610214565b6107b5876118a9565b15610903576107c4878761190b565b610876576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a401610214565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b1580156108e657600080fd5b505af11580156108fa573d6000803e3d6000fd5b50505050610985565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054610941908490612dbe565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c1683529390529190912091909155610985908585611a2b565b6109c9878787878787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611aff92505050565b50505050505050565b333b15610a61576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610214565b610aa43333348686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061164a92505050565b505050565b610ab68585858585610abd565b5050505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610b90575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa158015610b54573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b789190612d72565b73ffffffffffffffffffffffffffffffffffffffff16145b610c42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a401610214565b610c4a611134565b15610cb1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616e646172644272696467653a20706175736564000000000000000000006044820152606401610214565b610cb9611b8d565b15610d46576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e0000000000000000006064820152608401610214565b823414610dd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e742072657175697265640000000000006064820152608401610214565b3073ffffffffffffffffffffffffffffffffffffffff851603610e7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c6600000000000000000000000000000000000000000000000000000000006064820152608401610214565b60035473ffffffffffffffffffffffffffffffffffffffff90811690851603610f25576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e6765720000000000000000000000000000000000000000000000006064820152608401610214565b610f6785858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611bcc92505050565b6000610f84855a8660405180602001604052806000815250611c3f565b905080611013576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c656400000000000000000000000000000000000000000000000000000000006064820152608401610214565b505050505050565b6109c987873388888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611c5792505050565b333b156110ef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610214565b61101386863333888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061201092505050565b603254604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa1580156111a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111c89190612dd5565b905090565b6109c987873388888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061201092505050565b333b156112a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610214565b61101386863333888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611c5792505050565b6105b233858585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506105a592505050565b6109c9878787878787876105b8565b333b156113c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610214565b610aa433338585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506105a592505050565b600054610100900460ff16158080156114285750600054600160ff909116105b806114425750303b158015611442575060005460ff166001145b6114ce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610214565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561152c57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6032805473ffffffffffffffffffffffffffffffffffffffff8086167fffffffffffffffffffffffff000000000000000000000000000000000000000092831617909255603380549285169290911691909117905561159f8473420000000000000000000000000000000000001061201f565b80156105b257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150505050565b6105b23385348686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061164a92505050565b611652611b8d565b156116df576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e0000000000000000006064820152608401610214565b82341461176e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c756500006064820152608401610214565b61177a85858584612109565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9287929116907f1635f5fd00000000000000000000000000000000000000000000000000000000906117dd908b908b9086908a90602401612df7565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b909216825261187092918890600401612e40565b6000604051808303818588803b15801561188957600080fd5b505af115801561189d573d6000803e3d6000fd5b50505050505050505050565b60006118d5827f1d1d8b630000000000000000000000000000000000000000000000000000000061217c565b806119055750611905827fec4fc8e30000000000000000000000000000000000000000000000000000000061217c565b92915050565b6000611937837f1d1d8b630000000000000000000000000000000000000000000000000000000061217c565b156119e0578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015611987573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ab9190612d72565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050611905565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611987573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052610aa49084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915261219f565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f3ceee06c1e37648fcbb6ed52e17b3e1f275a1f8c7b22a84b2b84732431e046b3868686604051611b7793929190612e85565b60405180910390a46110138686868686866122ab565b600080611b98612333565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2ac69ee804d9a7a0984249f508dfab7cb2534b465b6ce1580f99a38ba9c5e6318484604051611c2b929190612ec3565b60405180910390a36105b2848484846123d0565b6000806000835160208501868989f195945050505050565b3415611ce5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5374616e646172644272696467653a2063616e6e6f742073656e642076616c7560448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610214565b611cee876118a9565b15611e3c57611cfd878761190b565b611daf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a401610214565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b158015611e1f57600080fd5b505af1158015611e33573d6000803e3d6000fd5b50505050611ed0565b611e5e73ffffffffffffffffffffffffffffffffffffffff881686308661243d565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054611e9c908490612edc565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b611ede87878787878661249b565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9216907f0166a07a0000000000000000000000000000000000000000000000000000000090611f42908b908d908c908c908c908b90602401612ef4565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b9092168252611fd592918790600401612e40565b600060405180830381600087803b158015611fef57600080fd5b505af1158015612003573d6000803e3d6000fd5b5050505050505050505050565b6109c987878787878787611c57565b600054610100900460ff166120b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610214565b6003805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560048054929093169116179055565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f35d79ab81f2b2017e19afb5c5571778877782d7a8786f5907f93b0f4702f4f238484604051612168929190612ec3565b60405180910390a36105b284848484612529565b600061218783612588565b8015612198575061219883836125ec565b9392505050565b6000612201826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166126bb9092919063ffffffff16565b805190915015610aa4578080602001905181019061221f9190612dd5565b610aa4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610214565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd86868660405161232393929190612e85565b60405180910390a4505050505050565b603354604080517f4397dfef0000000000000000000000000000000000000000000000000000000081528151600093849373ffffffffffffffffffffffffffffffffffffffff90911692634397dfef92600480830193928290030181865afa1580156123a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123c79190612f4f565b90939092509050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d848460405161242f929190612ec3565b60405180910390a350505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526105b29085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611a7d565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f718594027abd4eaed59f95162563e0cc6d0e8d5b86b1c7be8b1b0ac3343d039686868660405161251393929190612e85565b60405180910390a46110138686868686866126d2565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af5848460405161242f929190612ec3565b60006125b4827f01ffc9a7000000000000000000000000000000000000000000000000000000006125ec565b801561190557506125e5827fffffffff000000000000000000000000000000000000000000000000000000006125ec565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d915060005190508280156126a4575060208210155b80156126b05750600081115b979650505050505050565b60606126ca848460008561274a565b949350505050565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf86868660405161232393929190612e85565b6060824710156127dc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610214565b73ffffffffffffffffffffffffffffffffffffffff85163b61285a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610214565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516128839190612f84565b60006040518083038185875af1925050503d80600081146128c0576040519150601f19603f3d011682016040523d82523d6000602084013e6128c5565b606091505b50915091506126b0828286606083156128df575081612198565b8251156128ef5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102149190612bf5565b73ffffffffffffffffffffffffffffffffffffffff8116811461294557600080fd5b50565b60008083601f84011261295a57600080fd5b50813567ffffffffffffffff81111561297257600080fd5b60208301915083602082850101111561298a57600080fd5b9250929050565b600080600080600080600060c0888a0312156129ac57600080fd5b87356129b781612923565b965060208801356129c781612923565b955060408801356129d781612923565b945060608801356129e781612923565b93506080880135925060a088013567ffffffffffffffff811115612a0a57600080fd5b612a168a828b01612948565b989b979a50959850939692959293505050565b803563ffffffff81168114612a3d57600080fd5b919050565b600080600060408486031215612a5757600080fd5b612a6084612a29565b9250602084013567ffffffffffffffff811115612a7c57600080fd5b612a8886828701612948565b9497909650939450505050565b600080600080600060808688031215612aad57600080fd5b8535612ab881612923565b94506020860135612ac881612923565b935060408601359250606086013567ffffffffffffffff811115612aeb57600080fd5b612af788828901612948565b969995985093965092949392505050565b600080600080600080600060c0888a031215612b2357600080fd5b8735612b2e81612923565b96506020880135612b3e81612923565b95506040880135612b4e81612923565b945060608801359350612b6360808901612a29565b925060a088013567ffffffffffffffff811115612a0a57600080fd5b60005b83811015612b9a578181015183820152602001612b82565b838111156105b25750506000910152565b60008151808452612bc3816020860160208601612b7f565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006121986020830184612bab565b60008060008060008060a08789031215612c2157600080fd5b8635612c2c81612923565b95506020870135612c3c81612923565b945060408701359350612c5160608801612a29565b9250608087013567ffffffffffffffff811115612c6d57600080fd5b612c7989828a01612948565b979a9699509497509295939492505050565b60008060408385031215612c9e57600080fd5b8235612ca981612923565b91506020830135612cb981612923565b809150509250929050565b60008060008060608587031215612cda57600080fd5b8435612ce581612923565b9350612cf360208601612a29565b9250604085013567ffffffffffffffff811115612d0f57600080fd5b612d1b87828801612948565b95989497509550505050565b600080600060608486031215612d3c57600080fd5b8335612d4781612923565b92506020840135612d5781612923565b91506040840135612d6781612923565b809150509250925092565b600060208284031215612d8457600080fd5b815161219881612923565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015612dd057612dd0612d8f565b500390565b600060208284031215612de757600080fd5b8151801515811461219857600080fd5b600073ffffffffffffffffffffffffffffffffffffffff808716835280861660208401525083604083015260806060830152612e366080830184612bab565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff84168152606060208201526000612e6f6060830185612bab565b905063ffffffff83166040830152949350505050565b73ffffffffffffffffffffffffffffffffffffffff84168152826020820152606060408201526000612eba6060830184612bab565b95945050505050565b8281526040602082015260006126ca6040830184612bab565b60008219821115612eef57612eef612d8f565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a0830152612f4360c0830184612bab565b98975050505050505050565b60008060408385031215612f6257600080fd5b8251612f6d81612923565b602084015190925060ff81168114612cb957600080fd5b60008251612f96818460208701612b7f565b919091019291505056fea164736f6c634300080f000a", - "initialized": true, - "kind": "Create", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xb7900B27Be8f0E0fF65d1C3A4671e1220437dd2b", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xb7900B27Be8f0E0fF65d1C3A4671e1220437dd2b", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xb7900B27Be8f0E0fF65d1C3A4671e1220437dd2b", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xb7900B27Be8f0E0fF65d1C3A4671e1220437dd2b", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xb7900B27Be8f0E0fF65d1C3A4671e1220437dd2b", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xb7900B27Be8f0E0fF65d1C3A4671e1220437dd2b", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xb7900B27Be8f0E0fF65d1C3A4671e1220437dd2b", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000032" - }, - { - "account": "0xb7900B27Be8f0E0fF65d1C3A4671e1220437dd2b", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000032" - }, - { - "account": "0xb7900B27Be8f0E0fF65d1C3A4671e1220437dd2b", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - }, - { - "account": "0xb7900B27Be8f0E0fF65d1C3A4671e1220437dd2b", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - }, - { - "account": "0xb7900B27Be8f0E0fF65d1C3A4671e1220437dd2b", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xb7900B27Be8f0E0fF65d1C3A4671e1220437dd2b", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000003" - }, - { - "account": "0xb7900B27Be8f0E0fF65d1C3A4671e1220437dd2b", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000003" - }, - { - "account": "0xb7900B27Be8f0E0fF65d1C3A4671e1220437dd2b", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" - }, - { - "account": "0xb7900B27Be8f0E0fF65d1C3A4671e1220437dd2b", - "isWrite": true, - "newValue": "0x0000000000000000000000004200000000000000000000000000000000000010", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" - }, - { - "account": "0xb7900B27Be8f0E0fF65d1C3A4671e1220437dd2b", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xb7900B27Be8f0E0fF65d1C3A4671e1220437dd2b", - "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": "0xb7900B27Be8f0E0fF65d1C3A4671e1220437dd2b", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x927ede2d", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xb7900B27Be8f0E0fF65d1C3A4671e1220437dd2b", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000003" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xb7900B27Be8f0E0fF65d1C3A4671e1220437dd2b", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x3cb747bf", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xb7900B27Be8f0E0fF65d1C3A4671e1220437dd2b", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000003" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xb7900B27Be8f0E0fF65d1C3A4671e1220437dd2b", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x7f46ddb2", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xb7900B27Be8f0E0fF65d1C3A4671e1220437dd2b", - "isWrite": false, - "newValue": "0x0000000000000000000000004200000000000000000000000000000000000010", - "previousValue": "0x0000000000000000000000004200000000000000000000000000000000000010", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xb7900B27Be8f0E0fF65d1C3A4671e1220437dd2b", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xc89701a2", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xb7900B27Be8f0E0fF65d1C3A4671e1220437dd2b", - "isWrite": false, - "newValue": "0x0000000000000000000000004200000000000000000000000000000000000010", - "previousValue": "0x0000000000000000000000004200000000000000000000000000000000000010", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xb7900B27Be8f0E0fF65d1C3A4671e1220437dd2b", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x35e80ab3", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xb7900B27Be8f0E0fF65d1C3A4671e1220437dd2b", - "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": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x638627e586f5e36fe67a77519503a7c6da22f92b150d3c6055fd40bdcfe9ffd160806040523480156200001157600080fd5b506200001f60008062000025565b62000234565b600054610100900460ff1615808015620000465750600054600160ff909116105b8062000076575062000063306200018a60201b62000b141760201c565b15801562000076575060005460ff166001145b620000df5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000103576000805461ff0019166101001790555b603280546001600160a01b0319166001600160a01b0384161790556200013e8373420000000000000000000000000000000000001462000199565b801562000185576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b6001600160a01b03163b151590565b600054610100900460ff16620002065760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401620000d6565b600180546001600160a01b039384166001600160a01b03199182161790915560028054929093169116179055565b6113e980620002446000396000f3fe608060405234801561001057600080fd5b50600436106100d45760003560e01c80635d93a3fc11610081578063927ede2d1161005b578063927ede2d14610231578063aa5574521461024f578063c89701a21461026257600080fd5b80635d93a3fc146101cc578063761f4493146102005780637f46ddb21461021357600080fd5b8063485cc955116100b2578063485cc9551461015857806354fd4d501461016b5780635c975abb146101b457600080fd5b806335e80ab3146100d95780633687011a146101235780633cb747bf14610138575b600080fd5b6032546100f99073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b610136610131366004610fe1565b610282565b005b6001546100f99073ffffffffffffffffffffffffffffffffffffffff1681565b610136610166366004611064565b61032e565b6101a76040518060400160405280600c81526020017f322e312e312b626574612e31000000000000000000000000000000000000000081525081565b60405161011a9190611108565b6101bc610518565b604051901515815260200161011a565b6101bc6101da366004611122565b603160209081526000938452604080852082529284528284209052825290205460ff1681565b61013661020e366004611163565b6105b1565b60025473ffffffffffffffffffffffffffffffffffffffff166100f9565b60015473ffffffffffffffffffffffffffffffffffffffff166100f9565b61013661025d3660046111fb565b610a58565b6002546100f99073ffffffffffffffffffffffffffffffffffffffff1681565b333b15610316576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4552433732314272696467653a206163636f756e74206973206e6f742065787460448201527f65726e616c6c79206f776e65640000000000000000000000000000000000000060648201526084015b60405180910390fd5b6103268686333388888888610b30565b505050505050565b600054610100900460ff161580801561034e5750600054600160ff909116105b806103685750303b158015610368575060005460ff166001145b6103f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161030d565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561045257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84161790556104b083734200000000000000000000000000000000000014610e70565b801561051357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b603254604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa158015610588573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ac9190611272565b905090565b60015473ffffffffffffffffffffffffffffffffffffffff16331480156106865750600254600154604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9384169390921691636e296e45916004808201926020929091908290030181865afa15801561064a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061066e9190611294565b73ffffffffffffffffffffffffffffffffffffffff16145b610712576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4552433732314272696467653a2066756e6374696f6e2063616e206f6e6c792060448201527f62652063616c6c65642066726f6d20746865206f746865722062726964676500606482015260840161030d565b61071a610518565b15610781576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4c314552433732314272696467653a2070617573656400000000000000000000604482015260640161030d565b3073ffffffffffffffffffffffffffffffffffffffff881603610826576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4c314552433732314272696467653a206c6f63616c20746f6b656e2063616e6e60448201527f6f742062652073656c6600000000000000000000000000000000000000000000606482015260840161030d565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152603160209081526040808320938a1683529281528282208683529052205460ff1615156001146108f5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4c314552433732314272696467653a20546f6b656e204944206973206e6f742060448201527f657363726f77656420696e20746865204c312042726964676500000000000000606482015260840161030d565b73ffffffffffffffffffffffffffffffffffffffff87811660008181526031602090815260408083208b8616845282528083208884529091529081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517f42842e0e000000000000000000000000000000000000000000000000000000008152306004820152918616602483015260448201859052906342842e0e90606401600060405180830381600087803b1580156109b557600080fd5b505af11580156109c9573d6000803e3d6000fd5b505050508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167f1f39bf6707b5d608453e0ae4c067b562bcc4c85c0f562ef5d2c774d2e7f131ac87878787604051610a4794939291906112fa565b60405180910390a450505050505050565b73ffffffffffffffffffffffffffffffffffffffff8516610afb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4552433732314272696467653a206e667420726563697069656e742063616e6e60448201527f6f74206265206164647265737328302900000000000000000000000000000000606482015260840161030d565b610b0b8787338888888888610b30565b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b73ffffffffffffffffffffffffffffffffffffffff8716610bd3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f4c314552433732314272696467653a2072656d6f746520746f6b656e2063616e60448201527f6e6f742062652061646472657373283029000000000000000000000000000000606482015260840161030d565b600063761f449360e01b888a8989898888604051602401610bfa979695949392919061133a565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000959095169490941790935273ffffffffffffffffffffffffffffffffffffffff8c81166000818152603186528381208e8416825286528381208b82529095529382902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905590517f23b872dd000000000000000000000000000000000000000000000000000000008152908a166004820152306024820152604481018890529092506323b872dd90606401600060405180830381600087803b158015610d3a57600080fd5b505af1158015610d4e573d6000803e3d6000fd5b50506001546002546040517f3dbb202b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9283169450633dbb202b9350610db1929091169085908990600401611397565b600060405180830381600087803b158015610dcb57600080fd5b505af1158015610ddf573d6000803e3d6000fd5b505050508673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff167fb7460e2a880f256ebef3406116ff3eee0cee51ebccdc2a40698f87ebb2e9c1a589898888604051610e5d94939291906112fa565b60405180910390a4505050505050505050565b600054610100900460ff16610f07576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161030d565b6001805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560028054929093169116179055565b73ffffffffffffffffffffffffffffffffffffffff81168114610f7c57600080fd5b50565b803563ffffffff81168114610f9357600080fd5b919050565b60008083601f840112610faa57600080fd5b50813567ffffffffffffffff811115610fc257600080fd5b602083019150836020828501011115610fda57600080fd5b9250929050565b60008060008060008060a08789031215610ffa57600080fd5b863561100581610f5a565b9550602087013561101581610f5a565b94506040870135935061102a60608801610f7f565b9250608087013567ffffffffffffffff81111561104657600080fd5b61105289828a01610f98565b979a9699509497509295939492505050565b6000806040838503121561107757600080fd5b823561108281610f5a565b9150602083013561109281610f5a565b809150509250929050565b6000815180845260005b818110156110c3576020818501810151868301820152016110a7565b818111156110d5576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061111b602083018461109d565b9392505050565b60008060006060848603121561113757600080fd5b833561114281610f5a565b9250602084013561115281610f5a565b929592945050506040919091013590565b600080600080600080600060c0888a03121561117e57600080fd5b873561118981610f5a565b9650602088013561119981610f5a565b955060408801356111a981610f5a565b945060608801356111b981610f5a565b93506080880135925060a088013567ffffffffffffffff8111156111dc57600080fd5b6111e88a828b01610f98565b989b979a50959850939692959293505050565b600080600080600080600060c0888a03121561121657600080fd5b873561122181610f5a565b9650602088013561123181610f5a565b9550604088013561124181610f5a565b94506060880135935061125660808901610f7f565b925060a088013567ffffffffffffffff8111156111dc57600080fd5b60006020828403121561128457600080fd5b8151801515811461111b57600080fd5b6000602082840312156112a657600080fd5b815161111b81610f5a565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff851681528360208201526060604082015260006113306060830184866112b1565b9695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff808a1683528089166020840152808816604084015280871660608401525084608083015260c060a083015261138a60c0830184866112b1565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006113c6606083018561109d565b905063ffffffff8316604083015294935050505056fea164736f6c634300080f000a", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [], - "value": 0 - }, - { - "accessor": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "account": "0x5C4F5e749A61a9503c4AAE8a9393e89609a0e804", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x60806040523480156200001157600080fd5b506200001f60008062000025565b62000234565b600054610100900460ff1615808015620000465750600054600160ff909116105b8062000076575062000063306200018a60201b62000b141760201c565b15801562000076575060005460ff166001145b620000df5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000103576000805461ff0019166101001790555b603280546001600160a01b0319166001600160a01b0384161790556200013e8373420000000000000000000000000000000000001462000199565b801562000185576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b6001600160a01b03163b151590565b600054610100900460ff16620002065760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401620000d6565b600180546001600160a01b039384166001600160a01b03199182161790915560028054929093169116179055565b6113e980620002446000396000f3fe608060405234801561001057600080fd5b50600436106100d45760003560e01c80635d93a3fc11610081578063927ede2d1161005b578063927ede2d14610231578063aa5574521461024f578063c89701a21461026257600080fd5b80635d93a3fc146101cc578063761f4493146102005780637f46ddb21461021357600080fd5b8063485cc955116100b2578063485cc9551461015857806354fd4d501461016b5780635c975abb146101b457600080fd5b806335e80ab3146100d95780633687011a146101235780633cb747bf14610138575b600080fd5b6032546100f99073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b610136610131366004610fe1565b610282565b005b6001546100f99073ffffffffffffffffffffffffffffffffffffffff1681565b610136610166366004611064565b61032e565b6101a76040518060400160405280600c81526020017f322e312e312b626574612e31000000000000000000000000000000000000000081525081565b60405161011a9190611108565b6101bc610518565b604051901515815260200161011a565b6101bc6101da366004611122565b603160209081526000938452604080852082529284528284209052825290205460ff1681565b61013661020e366004611163565b6105b1565b60025473ffffffffffffffffffffffffffffffffffffffff166100f9565b60015473ffffffffffffffffffffffffffffffffffffffff166100f9565b61013661025d3660046111fb565b610a58565b6002546100f99073ffffffffffffffffffffffffffffffffffffffff1681565b333b15610316576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4552433732314272696467653a206163636f756e74206973206e6f742065787460448201527f65726e616c6c79206f776e65640000000000000000000000000000000000000060648201526084015b60405180910390fd5b6103268686333388888888610b30565b505050505050565b600054610100900460ff161580801561034e5750600054600160ff909116105b806103685750303b158015610368575060005460ff166001145b6103f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161030d565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561045257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84161790556104b083734200000000000000000000000000000000000014610e70565b801561051357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b603254604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa158015610588573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ac9190611272565b905090565b60015473ffffffffffffffffffffffffffffffffffffffff16331480156106865750600254600154604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9384169390921691636e296e45916004808201926020929091908290030181865afa15801561064a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061066e9190611294565b73ffffffffffffffffffffffffffffffffffffffff16145b610712576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4552433732314272696467653a2066756e6374696f6e2063616e206f6e6c792060448201527f62652063616c6c65642066726f6d20746865206f746865722062726964676500606482015260840161030d565b61071a610518565b15610781576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4c314552433732314272696467653a2070617573656400000000000000000000604482015260640161030d565b3073ffffffffffffffffffffffffffffffffffffffff881603610826576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4c314552433732314272696467653a206c6f63616c20746f6b656e2063616e6e60448201527f6f742062652073656c6600000000000000000000000000000000000000000000606482015260840161030d565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152603160209081526040808320938a1683529281528282208683529052205460ff1615156001146108f5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4c314552433732314272696467653a20546f6b656e204944206973206e6f742060448201527f657363726f77656420696e20746865204c312042726964676500000000000000606482015260840161030d565b73ffffffffffffffffffffffffffffffffffffffff87811660008181526031602090815260408083208b8616845282528083208884529091529081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517f42842e0e000000000000000000000000000000000000000000000000000000008152306004820152918616602483015260448201859052906342842e0e90606401600060405180830381600087803b1580156109b557600080fd5b505af11580156109c9573d6000803e3d6000fd5b505050508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167f1f39bf6707b5d608453e0ae4c067b562bcc4c85c0f562ef5d2c774d2e7f131ac87878787604051610a4794939291906112fa565b60405180910390a450505050505050565b73ffffffffffffffffffffffffffffffffffffffff8516610afb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4552433732314272696467653a206e667420726563697069656e742063616e6e60448201527f6f74206265206164647265737328302900000000000000000000000000000000606482015260840161030d565b610b0b8787338888888888610b30565b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b73ffffffffffffffffffffffffffffffffffffffff8716610bd3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f4c314552433732314272696467653a2072656d6f746520746f6b656e2063616e60448201527f6e6f742062652061646472657373283029000000000000000000000000000000606482015260840161030d565b600063761f449360e01b888a8989898888604051602401610bfa979695949392919061133a565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000959095169490941790935273ffffffffffffffffffffffffffffffffffffffff8c81166000818152603186528381208e8416825286528381208b82529095529382902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905590517f23b872dd000000000000000000000000000000000000000000000000000000008152908a166004820152306024820152604481018890529092506323b872dd90606401600060405180830381600087803b158015610d3a57600080fd5b505af1158015610d4e573d6000803e3d6000fd5b50506001546002546040517f3dbb202b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9283169450633dbb202b9350610db1929091169085908990600401611397565b600060405180830381600087803b158015610dcb57600080fd5b505af1158015610ddf573d6000803e3d6000fd5b505050508673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff167fb7460e2a880f256ebef3406116ff3eee0cee51ebccdc2a40698f87ebb2e9c1a589898888604051610e5d94939291906112fa565b60405180910390a4505050505050505050565b600054610100900460ff16610f07576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161030d565b6001805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560028054929093169116179055565b73ffffffffffffffffffffffffffffffffffffffff81168114610f7c57600080fd5b50565b803563ffffffff81168114610f9357600080fd5b919050565b60008083601f840112610faa57600080fd5b50813567ffffffffffffffff811115610fc257600080fd5b602083019150836020828501011115610fda57600080fd5b9250929050565b60008060008060008060a08789031215610ffa57600080fd5b863561100581610f5a565b9550602087013561101581610f5a565b94506040870135935061102a60608801610f7f565b9250608087013567ffffffffffffffff81111561104657600080fd5b61105289828a01610f98565b979a9699509497509295939492505050565b6000806040838503121561107757600080fd5b823561108281610f5a565b9150602083013561109281610f5a565b809150509250929050565b6000815180845260005b818110156110c3576020818501810151868301820152016110a7565b818111156110d5576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061111b602083018461109d565b9392505050565b60008060006060848603121561113757600080fd5b833561114281610f5a565b9250602084013561115281610f5a565b929592945050506040919091013590565b600080600080600080600060c0888a03121561117e57600080fd5b873561118981610f5a565b9650602088013561119981610f5a565b955060408801356111a981610f5a565b945060608801356111b981610f5a565b93506080880135925060a088013567ffffffffffffffff8111156111dc57600080fd5b6111e88a828b01610f98565b989b979a50959850939692959293505050565b600080600080600080600060c0888a03121561121657600080fd5b873561122181610f5a565b9650602088013561123181610f5a565b9550604088013561124181610f5a565b94506060880135935061125660808901610f7f565b925060a088013567ffffffffffffffff8111156111dc57600080fd5b60006020828403121561128457600080fd5b8151801515811461111b57600080fd5b6000602082840312156112a657600080fd5b815161111b81610f5a565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff851681528360208201526060604082015260006113306060830184866112b1565b9695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff808a1683528089166020840152808816604084015280871660608401525084608083015260c060a083015261138a60c0830184866112b1565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006113c6606083018561109d565b905063ffffffff8316604083015294935050505056fea164736f6c634300080f000a", - "deployedCode": "0x608060405234801561001057600080fd5b50600436106100d45760003560e01c80635d93a3fc11610081578063927ede2d1161005b578063927ede2d14610231578063aa5574521461024f578063c89701a21461026257600080fd5b80635d93a3fc146101cc578063761f4493146102005780637f46ddb21461021357600080fd5b8063485cc955116100b2578063485cc9551461015857806354fd4d501461016b5780635c975abb146101b457600080fd5b806335e80ab3146100d95780633687011a146101235780633cb747bf14610138575b600080fd5b6032546100f99073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b610136610131366004610fe1565b610282565b005b6001546100f99073ffffffffffffffffffffffffffffffffffffffff1681565b610136610166366004611064565b61032e565b6101a76040518060400160405280600c81526020017f322e312e312b626574612e31000000000000000000000000000000000000000081525081565b60405161011a9190611108565b6101bc610518565b604051901515815260200161011a565b6101bc6101da366004611122565b603160209081526000938452604080852082529284528284209052825290205460ff1681565b61013661020e366004611163565b6105b1565b60025473ffffffffffffffffffffffffffffffffffffffff166100f9565b60015473ffffffffffffffffffffffffffffffffffffffff166100f9565b61013661025d3660046111fb565b610a58565b6002546100f99073ffffffffffffffffffffffffffffffffffffffff1681565b333b15610316576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4552433732314272696467653a206163636f756e74206973206e6f742065787460448201527f65726e616c6c79206f776e65640000000000000000000000000000000000000060648201526084015b60405180910390fd5b6103268686333388888888610b30565b505050505050565b600054610100900460ff161580801561034e5750600054600160ff909116105b806103685750303b158015610368575060005460ff166001145b6103f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161030d565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561045257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84161790556104b083734200000000000000000000000000000000000014610e70565b801561051357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b603254604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa158015610588573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ac9190611272565b905090565b60015473ffffffffffffffffffffffffffffffffffffffff16331480156106865750600254600154604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9384169390921691636e296e45916004808201926020929091908290030181865afa15801561064a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061066e9190611294565b73ffffffffffffffffffffffffffffffffffffffff16145b610712576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4552433732314272696467653a2066756e6374696f6e2063616e206f6e6c792060448201527f62652063616c6c65642066726f6d20746865206f746865722062726964676500606482015260840161030d565b61071a610518565b15610781576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4c314552433732314272696467653a2070617573656400000000000000000000604482015260640161030d565b3073ffffffffffffffffffffffffffffffffffffffff881603610826576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4c314552433732314272696467653a206c6f63616c20746f6b656e2063616e6e60448201527f6f742062652073656c6600000000000000000000000000000000000000000000606482015260840161030d565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152603160209081526040808320938a1683529281528282208683529052205460ff1615156001146108f5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4c314552433732314272696467653a20546f6b656e204944206973206e6f742060448201527f657363726f77656420696e20746865204c312042726964676500000000000000606482015260840161030d565b73ffffffffffffffffffffffffffffffffffffffff87811660008181526031602090815260408083208b8616845282528083208884529091529081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517f42842e0e000000000000000000000000000000000000000000000000000000008152306004820152918616602483015260448201859052906342842e0e90606401600060405180830381600087803b1580156109b557600080fd5b505af11580156109c9573d6000803e3d6000fd5b505050508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167f1f39bf6707b5d608453e0ae4c067b562bcc4c85c0f562ef5d2c774d2e7f131ac87878787604051610a4794939291906112fa565b60405180910390a450505050505050565b73ffffffffffffffffffffffffffffffffffffffff8516610afb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4552433732314272696467653a206e667420726563697069656e742063616e6e60448201527f6f74206265206164647265737328302900000000000000000000000000000000606482015260840161030d565b610b0b8787338888888888610b30565b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b73ffffffffffffffffffffffffffffffffffffffff8716610bd3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f4c314552433732314272696467653a2072656d6f746520746f6b656e2063616e60448201527f6e6f742062652061646472657373283029000000000000000000000000000000606482015260840161030d565b600063761f449360e01b888a8989898888604051602401610bfa979695949392919061133a565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000959095169490941790935273ffffffffffffffffffffffffffffffffffffffff8c81166000818152603186528381208e8416825286528381208b82529095529382902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905590517f23b872dd000000000000000000000000000000000000000000000000000000008152908a166004820152306024820152604481018890529092506323b872dd90606401600060405180830381600087803b158015610d3a57600080fd5b505af1158015610d4e573d6000803e3d6000fd5b50506001546002546040517f3dbb202b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9283169450633dbb202b9350610db1929091169085908990600401611397565b600060405180830381600087803b158015610dcb57600080fd5b505af1158015610ddf573d6000803e3d6000fd5b505050508673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff167fb7460e2a880f256ebef3406116ff3eee0cee51ebccdc2a40698f87ebb2e9c1a589898888604051610e5d94939291906112fa565b60405180910390a4505050505050505050565b600054610100900460ff16610f07576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161030d565b6001805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560028054929093169116179055565b73ffffffffffffffffffffffffffffffffffffffff81168114610f7c57600080fd5b50565b803563ffffffff81168114610f9357600080fd5b919050565b60008083601f840112610faa57600080fd5b50813567ffffffffffffffff811115610fc257600080fd5b602083019150836020828501011115610fda57600080fd5b9250929050565b60008060008060008060a08789031215610ffa57600080fd5b863561100581610f5a565b9550602087013561101581610f5a565b94506040870135935061102a60608801610f7f565b9250608087013567ffffffffffffffff81111561104657600080fd5b61105289828a01610f98565b979a9699509497509295939492505050565b6000806040838503121561107757600080fd5b823561108281610f5a565b9150602083013561109281610f5a565b809150509250929050565b6000815180845260005b818110156110c3576020818501810151868301820152016110a7565b818111156110d5576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061111b602083018461109d565b9392505050565b60008060006060848603121561113757600080fd5b833561114281610f5a565b9250602084013561115281610f5a565b929592945050506040919091013590565b600080600080600080600060c0888a03121561117e57600080fd5b873561118981610f5a565b9650602088013561119981610f5a565b955060408801356111a981610f5a565b945060608801356111b981610f5a565b93506080880135925060a088013567ffffffffffffffff8111156111dc57600080fd5b6111e88a828b01610f98565b989b979a50959850939692959293505050565b600080600080600080600060c0888a03121561121657600080fd5b873561122181610f5a565b9650602088013561123181610f5a565b9550604088013561124181610f5a565b94506060880135935061125660808901610f7f565b925060a088013567ffffffffffffffff8111156111dc57600080fd5b60006020828403121561128457600080fd5b8151801515811461111b57600080fd5b6000602082840312156112a657600080fd5b815161111b81610f5a565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff851681528360208201526060604082015260006113306060830184866112b1565b9695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff808a1683528089166020840152808816604084015280871660608401525084608083015260c060a083015261138a60c0830184866112b1565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006113c6606083018561109d565b905063ffffffff8316604083015294935050505056fea164736f6c634300080f000a", - "initialized": true, - "kind": "Create", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x5C4F5e749A61a9503c4AAE8a9393e89609a0e804", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x5C4F5e749A61a9503c4AAE8a9393e89609a0e804", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x5C4F5e749A61a9503c4AAE8a9393e89609a0e804", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x5C4F5e749A61a9503c4AAE8a9393e89609a0e804", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x5C4F5e749A61a9503c4AAE8a9393e89609a0e804", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x5C4F5e749A61a9503c4AAE8a9393e89609a0e804", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x5C4F5e749A61a9503c4AAE8a9393e89609a0e804", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000032" - }, - { - "account": "0x5C4F5e749A61a9503c4AAE8a9393e89609a0e804", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000032" - }, - { - "account": "0x5C4F5e749A61a9503c4AAE8a9393e89609a0e804", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x5C4F5e749A61a9503c4AAE8a9393e89609a0e804", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000001" - }, - { - "account": "0x5C4F5e749A61a9503c4AAE8a9393e89609a0e804", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000001" - }, - { - "account": "0x5C4F5e749A61a9503c4AAE8a9393e89609a0e804", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000002" - }, - { - "account": "0x5C4F5e749A61a9503c4AAE8a9393e89609a0e804", - "isWrite": true, - "newValue": "0x0000000000000000000000004200000000000000000000000000000000000014", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000002" - }, - { - "account": "0x5C4F5e749A61a9503c4AAE8a9393e89609a0e804", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x5C4F5e749A61a9503c4AAE8a9393e89609a0e804", - "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": "0x5C4F5e749A61a9503c4AAE8a9393e89609a0e804", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x7f46ddb2", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x5C4F5e749A61a9503c4AAE8a9393e89609a0e804", - "isWrite": false, - "newValue": "0x0000000000000000000000004200000000000000000000000000000000000014", - "previousValue": "0x0000000000000000000000004200000000000000000000000000000000000014", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000002" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x5C4F5e749A61a9503c4AAE8a9393e89609a0e804", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xc89701a2", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x5C4F5e749A61a9503c4AAE8a9393e89609a0e804", - "isWrite": false, - "newValue": "0x0000000000000000000000004200000000000000000000000000000000000014", - "previousValue": "0x0000000000000000000000004200000000000000000000000000000000000014", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000002" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x5C4F5e749A61a9503c4AAE8a9393e89609a0e804", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x927ede2d", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x5C4F5e749A61a9503c4AAE8a9393e89609a0e804", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000001" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x5C4F5e749A61a9503c4AAE8a9393e89609a0e804", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x3cb747bf", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x5C4F5e749A61a9503c4AAE8a9393e89609a0e804", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000001" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x5C4F5e749A61a9503c4AAE8a9393e89609a0e804", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x35e80ab3", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x5C4F5e749A61a9503c4AAE8a9393e89609a0e804", - "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": "0x493f862b", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x000000000000000000000000000000000000000000000000000000000000004a" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x638627e586f5e36fe67a77519503a7c6da22f92b150d3c6055fd40bdcfe9ffd160806040523480156200001157600080fd5b50620000206000808062000026565b6200028f565b600054610100900460ff1615808015620000475750600054600160ff909116105b806200007757506200006430620001c160201b62001efd1760201c565b15801562000077575060005460ff166001145b620000e05760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000104576000805461ff0019166101001790555b603680546001600160a01b03199081166001600160a01b03878116919091179092556037805490911685831617905560358054610100600160a81b03191661010085841602179055603254166200016a57603280546001600160a01b03191661dead1790555b62000174620001d0565b8015620001bb576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b6001600160a01b03163b151590565b600054610100900460ff166200023d5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401620000d7565b600154600160c01b90046001600160401b03166000036200028d5760408051606081018252633b9aca0080825260006020830152436001600160401b031691909201819052600160c01b02176001555b565b615777806200029f6000396000f3fe6080604052600436106101635760003560e01c80638c3152e9116100c0578063b69ef8a811610074578063cff0ab9611610059578063cff0ab9614610444578063e965084c146104e5578063e9e05c421461057157600080fd5b8063b69ef8a814610401578063c0c53b8b1461042457600080fd5b80639bf62d82116100a55780639bf62d821461036b578063a14238e714610398578063a35d99df146103c857600080fd5b80638c3152e91461031e5780639b5f694a1461033e57600080fd5b806354fd4d50116101175780636dbffb78116100fc5780636dbffb78146102de57806371cfaa3f146102fe5780638b4c40b01461018857600080fd5b806354fd4d501461026d5780635c975abb146102b957600080fd5b806335e80ab31161014857806335e80ab314610206578063452a9320146102385780634870496f1461024d57600080fd5b8063149f2f221461018f57806333d7e2bd146101af57600080fd5b3661018a576101883334620186a060006040518060200160405280600081525061057f565b005b600080fd5b34801561019b57600080fd5b506101886101aa366004614b97565b610624565b3480156101bb57600080fd5b506037546101dc9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561021257600080fd5b506035546101dc90610100900473ffffffffffffffffffffffffffffffffffffffff1681565b34801561024457600080fd5b506101dc610865565b34801561025957600080fd5b50610188610268366004614ccb565b6108fd565b34801561027957600080fd5b50604080518082018252600c81527f322e382e312d626574612e310000000000000000000000000000000000000000602082015290516101fd9190614e1d565b3480156102c557600080fd5b506102ce610eaa565b60405190151581526020016101fd565b3480156102ea57600080fd5b506102ce6102f9366004614e30565b610f3d565b34801561030a57600080fd5b50610188610319366004614e58565b610ff8565b34801561032a57600080fd5b50610188610339366004614e9e565b6111ba565b34801561034a57600080fd5b506036546101dc9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561037757600080fd5b506032546101dc9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156103a457600080fd5b506102ce6103b3366004614e30565b60336020526000908152604090205460ff1681565b3480156103d457600080fd5b506103e86103e3366004614edb565b611c3c565b60405167ffffffffffffffff90911681526020016101fd565b34801561040d57600080fd5b50610416611c55565b6040519081526020016101fd565b34801561043057600080fd5b5061018861043f366004614ef6565b611caf565b34801561045057600080fd5b506001546104ac906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff92831660208501529116908201526060016101fd565b3480156104f157600080fd5b50610543610500366004614e30565b603460205260009081526040902080546001909101546fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041683565b604080519384526fffffffffffffffffffffffffffffffff92831660208501529116908201526060016101fd565b61018861057f366004614f41565b8260005a9050600061058f611f19565b50905073ffffffffffffffffffffffffffffffffffffffff811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee148015906105cb57503415155b15610602576040517ff2365b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610610883489898989611fb6565b5061061b8282612162565b50505050505050565b8260005a90506000610634611f19565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8216016106a6576040517f0eaf3c0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87603d60008282546106b89190614fed565b90915550506040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa15801561072a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061074e9190615005565b905061077273ffffffffffffffffffffffffffffffffffffffff831633308c61242f565b61077c8982614fed565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa1580156107e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061080a9190615005565b14610841576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61084f8a8a8a8a8a8a611fb6565b505061085b8282612162565b5050505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f8919061501e565b905090565b610905610eaa565b1561093c576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff16036109a5576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6036546040517fa25ae5570000000000000000000000000000000000000000000000000000000081526004810186905260009173ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa158015610a15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a39919061505b565b519050610a53610a4e368690038601866150c0565b61250b565b8114610ae6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f7074696d69736d506f7274616c3a20696e76616c6964206f7574707574207260448201527f6f6f742070726f6f66000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000610af187612567565b6000818152603460209081526040918290208251606081018452815481526001909101546fffffffffffffffffffffffffffffffff8082169383018490527001000000000000000000000000000000009091041692810192909252919250901580610c075750805160365460408084015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff909116600482015273ffffffffffffffffffffffffffffffffffffffff9091169063a25ae55790602401606060405180830381865afa158015610bdf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c03919061505b565b5114155b610c93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173682060448201527f68617320616c7265616479206265656e2070726f76656e0000000000000000006064820152608401610add565b60408051602081018490526000918101829052606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201209083018190529250610d5c9101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f0100000000000000000000000000000000000000000000000000000000000000602083015290610d52888a615126565b8a60400135612597565b610de8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a20696e76616c696420776974686472617760448201527f616c20696e636c7573696f6e2070726f6f6600000000000000000000000000006064820152608401610add565b604080516060810182528581526fffffffffffffffffffffffffffffffff42811660208084019182528c831684860190815260008981526034835286812095518655925190518416700100000000000000000000000000000000029316929092176001909301929092558b830151908c0151925173ffffffffffffffffffffffffffffffffffffffff918216939091169186917f67a6208cfcc0801d50f6cbe764733f4fddf66ac0b04442061a8a8c0cb6b63f629190a4505050505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f19573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f891906151aa565b6036546040517fa25ae55700000000000000000000000000000000000000000000000000000000815260048101839052600091610ff29173ffffffffffffffffffffffffffffffffffffffff9091169063a25ae55790602401606060405180830381865afa158015610fb3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fd7919061505b565b602001516fffffffffffffffffffffffffffffffff166125bb565b92915050565b60375473ffffffffffffffffffffffffffffffffffffffff163314611049576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61105562030d40612661565b60405173ffffffffffffffffffffffffffffffffffffffff8516602482015260ff8416604482015260648101839052608481018290526000907342000000000000000000000000000000000000159073deaddeaddeaddeaddeaddeaddeaddeaddead0001907fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32908490819062030d4090829060a401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f71cfaa3f000000000000000000000000000000000000000000000000000000001790529051611172969594939291016151c7565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526111aa91614e1d565b60405180910390a450505050565b565b6111c2610eaa565b156111f9576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60325473ffffffffffffffffffffffffffffffffffffffff1661dead1461124c576040517f9396d15600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061125782612567565b60008181526034602090815260408083208151606081018352815481526001909101546fffffffffffffffffffffffffffffffff80821694830185905270010000000000000000000000000000000090910416918101919091529293509003611342576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206e60448201527f6f74206265656e2070726f76656e2079657400000000000000000000000000006064820152608401610add565b603660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663887862726040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113d39190615005565b81602001516fffffffffffffffffffffffffffffffff16101561149e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604b60248201527f4f7074696d69736d506f7274616c3a207769746864726177616c2074696d657360448201527f74616d70206c657373207468616e204c32204f7261636c65207374617274696e60648201527f672074696d657374616d70000000000000000000000000000000000000000000608482015260a401610add565b6114bd81602001516fffffffffffffffffffffffffffffffff166125bb565b61156f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604560248201527f4f7074696d69736d506f7274616c3a2070726f76656e2077697468647261776160448201527f6c2066696e616c697a6174696f6e20706572696f6420686173206e6f7420656c60648201527f6170736564000000000000000000000000000000000000000000000000000000608482015260a401610add565b60365460408281015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff909116600482015260009173ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa1580156115f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061161a919061505b565b82518151919250146116d4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4f7074696d69736d506f7274616c3a206f757470757420726f6f742070726f7660448201527f656e206973206e6f74207468652073616d652061732063757272656e74206f7560648201527f7470757420726f6f740000000000000000000000000000000000000000000000608482015260a401610add565b6116f381602001516fffffffffffffffffffffffffffffffff166125bb565b6117a5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4f7074696d69736d506f7274616c3a206f75747075742070726f706f73616c2060448201527f66696e616c697a6174696f6e20706572696f6420686173206e6f7420656c617060648201527f7365640000000000000000000000000000000000000000000000000000000000608482015260a401610add565b60008381526033602052604090205460ff1615611844576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206160448201527f6c7265616479206265656e2066696e616c697a656400000000000000000000006064820152608401610add565b6000838152603360209081526040822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558501516032805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff0000000000000000000000000000000000000000909216919091179055806118cf611f19565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8216016119325761192b8660400151876080015188606001518960a001516126c3565b9150611b85565b8073ffffffffffffffffffffffffffffffffffffffff16866040015173ffffffffffffffffffffffffffffffffffffffff160361199b576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606086015115611b5c578560600151603d60008282546119bb919061522c565b90915550506040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015611a2d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a519190615005565b9050611a86876040015188606001518473ffffffffffffffffffffffffffffffffffffffff166127219092919063ffffffff16565b6060870151611a95908261522c565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015611aff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b239190615005565b14611b5a576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60a08601515115611b805761192b8660400151876080015160008960a001516126c3565b600191505b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405185907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b90611be790851515815260200190565b60405180910390a281158015611bfd5750326001145b15611c34576040517feeae4ed300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000611c49826010615243565b610ff290615208615273565b600080611c60611f19565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff821601611ca7574791505090565b5050603d5490565b600054610100900460ff1615808015611ccf5750600054600160ff909116105b80611ce95750303b158015611ce9575060005460ff166001145b611d75576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610add565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015611dd357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603680547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff8781169190911790925560378054909116858316179055603580547fffffffffffffffffffffff0000000000000000000000000000000000000000ff166101008584160217905560325416611e8c57603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790555b611e9461277c565b8015611ef757600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b603754604080517f4397dfef0000000000000000000000000000000000000000000000000000000081528151600093849373ffffffffffffffffffffffffffffffffffffffff90911692634397dfef92600480830193928290030181865afa158015611f89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fad919061529f565b90939092509050565b818015611fd8575073ffffffffffffffffffffffffffffffffffffffff861615155b1561200f576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6120198151611c3c565b67ffffffffffffffff168367ffffffffffffffff161015612066576040517f4929b80800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6201d4c0815111156120a4576040517f73052b0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b333281146120c5575033731111000000000000000000000000000000001111015b600086868686866040516020016120e09594939291906151c7565b604051602081830303815290604052905060008873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32846040516121509190614e1d565b60405180910390a45050505050505050565b600154600090612198907801000000000000000000000000000000000000000000000000900467ffffffffffffffff164361522c565b905060006121a461288f565b90506000816020015160ff16826000015163ffffffff166121c59190615308565b905082156122fc576001546000906121fc908390700100000000000000000000000000000000900467ffffffffffffffff16615370565b90506000836040015160ff168361221391906153e4565b6001546122339084906fffffffffffffffffffffffffffffffff166153e4565b61223d9190615308565b60015490915060009061228e906122679084906fffffffffffffffffffffffffffffffff166154a0565b866060015163ffffffff168760a001516fffffffffffffffffffffffffffffffff16612950565b905060018611156122bd576122ba61226782876040015160ff1660018a6122b5919061522c565b61296f565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b6001805486919060109061232f908490700100000000000000000000000000000000900467ffffffffffffffff16615273565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550816000015163ffffffff16600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff1613156123bc576040517f77ebef4d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001546000906123e8906fffffffffffffffffffffffffffffffff1667ffffffffffffffff8816615514565b905060006123fa48633b9aca006129c4565b6124049083615551565b905060005a612413908861522c565b90508082111561085b5761085b61242a828461522c565b6129db565b60405173ffffffffffffffffffffffffffffffffffffffff80851660248301528316604482015260648101829052611ef79085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612a04565b6000816000015182602001518360400151846060015160405160200161254a949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b80516020808301516040808501516060860151608087015160a0880151935160009761254a979096959101615565565b6000806125a386612b10565b90506125b181868686612b42565b9695505050505050565b603654604080517ff4daa291000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163f4daa2919160048083019260209291908290030181865afa15801561262b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061264f9190615005565b6126599083614fed565b421192915050565b6001805463ffffffff8316919060109061269a908490700100000000000000000000000000000000900467ffffffffffffffff16615273565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555050565b60008060006126d3866000612b72565b905080612709576308c379a06000526020805278185361666543616c6c3a204e6f7420656e6f756768206761736058526064601cfd5b600080855160208701888b5af1979650505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526127779084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401612489565b505050565b600054610100900460ff16612813576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610add565b6001547801000000000000000000000000000000000000000000000000900467ffffffffffffffff166000036111b85760408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b6040805160c08082018352600080835260208301819052828401819052606083018190526080830181905260a083015260375483517fcc731b020000000000000000000000000000000000000000000000000000000081529351929373ffffffffffffffffffffffffffffffffffffffff9091169263cc731b02926004808401939192918290030181865afa15801561292c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f891906155d0565b600061296561295f8585612b90565b83612ba0565b90505b9392505050565b6000670de0b6b3a76400006129b06129878583615308565b61299990670de0b6b3a7640000615370565b6129ab85670de0b6b3a76400006153e4565b612baf565b6129ba90866153e4565b6129659190615308565b6000818310156129d45781612968565b5090919050565b6000805a90505b825a6129ee908361522c565b1015612777576129fd82615673565b91506129e2565b6000612a66826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612be09092919063ffffffff16565b8051909150156127775780806020019051810190612a8491906151aa565b612777576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610add565b60608180519060200120604051602001612b2c91815260200190565b6040516020818303038152906040529050919050565b6000612b6984612b53878686612bef565b8051602091820120825192909101919091201490565b95945050505050565b600080603f83619c4001026040850201603f5a021015949350505050565b6000818312156129d45781612968565b60008183126129d45781612968565b6000612968670de0b6b3a764000083612bc78661366d565b612bd191906153e4565b612bdb9190615308565b6138b1565b60606129658484600085613af0565b60606000845111612c5c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4d65726b6c65547269653a20656d707479206b657900000000000000000000006044820152606401610add565b6000612c6784613c86565b90506000612c7486613d72565b9050600084604051602001612c8b91815260200190565b60405160208183030381529060405290506000805b84518110156135e4576000858281518110612cbd57612cbd6156ab565b602002602001015190508451831115612d58576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4d65726b6c65547269653a206b657920696e646578206578636565647320746f60448201527f74616c206b6579206c656e6774680000000000000000000000000000000000006064820152608401610add565b82600003612e115780518051602091820120604051612da692612d8092910190815260200190565b604051602081830303815290604052858051602091820120825192909101919091201490565b612e0c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4d65726b6c65547269653a20696e76616c696420726f6f7420686173680000006044820152606401610add565b612f68565b805151602011612ec75780518051602091820120604051612e3b92612d8092910190815260200190565b612e0c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d65726b6c65547269653a20696e76616c6964206c6172676520696e7465726e60448201527f616c2068617368000000000000000000000000000000000000000000000000006064820152608401610add565b805184516020808701919091208251919092012014612f68576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4d65726b6c65547269653a20696e76616c696420696e7465726e616c206e6f6460448201527f65206861736800000000000000000000000000000000000000000000000000006064820152608401610add565b612f7460106001614fed565b8160200151510361315057845183036130e857612fae8160200151601081518110612fa157612fa16156ab565b6020026020010151613dd5565b96506000875111613041576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603b60248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286272616e63682900000000006064820152608401610add565b6001865161304f919061522c565b82146130dd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286272616e6368290000000000006064820152608401610add565b505050505050612968565b60008584815181106130fc576130fc6156ab565b602001015160f81c60f81b60f81c9050600082602001518260ff1681518110613127576131276156ab565b6020026020010151905061313a81613e89565b9550613147600186614fed565b945050506135d1565b60028160200151510361354957600061316882613eae565b905060008160008151811061317f5761317f6156ab565b016020015160f81c905060006131966002836156da565b6131a19060026156fc565b905060006131b2848360ff16613ed2565b905060006131c08a89613ed2565b905060006131ce8383613f08565b905080835114613260576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a20706174682072656d61696e646572206d7573742060448201527f736861726520616c6c206e6962626c65732077697468206b65790000000000006064820152608401610add565b60ff851660021480613275575060ff85166003145b15613464578082511461330a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f4d65726b6c65547269653a206b65792072656d61696e646572206d757374206260448201527f65206964656e746963616c20746f20706174682072656d61696e6465720000006064820152608401610add565b6133248760200151600181518110612fa157612fa16156ab565b9c5060008d51116133b7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286c65616629000000000000006064820152608401610add565b60018c516133c5919061522c565b8814613453576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286c6561662900000000000000006064820152608401610add565b505050505050505050505050612968565b60ff85161580613477575060ff85166001145b156134b6576134a38760200151600181518110613496576134966156ab565b6020026020010151613e89565b99506134af818a614fed565b985061353e565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4d65726b6c65547269653a2072656365697665642061206e6f6465207769746860448201527f20616e20756e6b6e6f776e2070726566697800000000000000000000000000006064820152608401610add565b5050505050506135d1565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4d65726b6c65547269653a20726563656976656420616e20756e70617273656160448201527f626c65206e6f64650000000000000000000000000000000000000000000000006064820152608401610add565b50806135dc81615673565b915050612ca0565b506040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4d65726b6c65547269653a2072616e206f7574206f662070726f6f6620656c6560448201527f6d656e74730000000000000000000000000000000000000000000000000000006064820152608401610add565b60008082136136d8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610add565b600060606136e584613fbc565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c182136138e257506000919050565b680755bf798b4a1bf1e58212613954576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4558505f4f564552464c4f5700000000000000000000000000000000000000006044820152606401610add565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b606082471015613b82576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610add565b73ffffffffffffffffffffffffffffffffffffffff85163b613c00576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610add565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051613c29919061571f565b60006040518083038185875af1925050503d8060008114613c66576040519150601f19603f3d011682016040523d82523d6000602084013e613c6b565b606091505b5091509150613c7b828286614092565b979650505050505050565b80516060908067ffffffffffffffff811115613ca457613ca4614a8b565b604051908082528060200260200182016040528015613ce957816020015b6040805180820190915260608082526020820152815260200190600190039081613cc25790505b50915060005b81811015613d6b576040518060400160405280858381518110613d1457613d146156ab565b60200260200101518152602001613d43868481518110613d3657613d366156ab565b60200260200101516140e5565b815250838281518110613d5857613d586156ab565b6020908102919091010152600101613cef565b5050919050565b606080604051905082518060011b603f8101601f1916830160405280835250602084016020830160005b83811015613dca578060011b82018184015160001a8060041c8253600f811660018301535050600101613d9c565b509295945050505050565b60606000806000613de5856140f8565b919450925090506000816001811115613e0057613e0061573b565b14613e37576040517f1ff9b2e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613e418284614fed565b855114613e7a576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612b6985602001518484614596565b60606020826000015110613ea557613ea082613dd5565b610ff2565b610ff28261462a565b6060610ff2613ecd8360200151600081518110612fa157612fa16156ab565b613d72565b606082518210613ef15750604080516020810190915260008152610ff2565b6129688383848651613f03919061522c565b614640565b6000808251845110613f1b578251613f1e565b83515b90505b8082108015613fa55750828281518110613f3d57613f3d6156ab565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916848381518110613f7c57613f7c6156ab565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b15613fb557816001019150613f21565b5092915050565b6000808211614027576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610add565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b606083156140a1575081612968565b8251156140b15782518084602001fd5b816040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610add9190614e1d565b6060610ff26140f383614818565b614885565b6000806000836000015160000361413b576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020840151805160001a607f811161416057600060016000945094509450505061458f565b60b7811161427657600061417560808361522c565b9050808760000151116141b4576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001838101517fff0000000000000000000000000000000000000000000000000000000000000016908214801561422c57507f80000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008216105b15614263576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506001955093506000925061458f915050565b60bf81116143d457600061428b60b78361522c565b9050808760000151116142ca576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff0000000000000000000000000000000000000000000000000000000000000016600081900361432c576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c60378111614374576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61437e8184614fed565b8951116143b7576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6143c2836001614fed565b975095506000945061458f9350505050565b60f781116144395760006143e960c08361522c565b905080876000015111614428576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60019550935084925061458f915050565b600061444660f78361522c565b905080876000015111614485576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff000000000000000000000000000000000000000000000000000000000000001660008190036144e7576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c6037811161452f576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6145398184614fed565b895111614572576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61457d836001614fed565b975095506001945061458f9350505050565b9193909250565b60608167ffffffffffffffff8111156145b1576145b1614a8b565b6040519080825280601f01601f1916602001820160405280156145db576020820181803683370190505b50905081156129685760006145f08486614fed565b90506020820160005b848110156146115782810151828201526020016145f9565b84811115614620576000858301525b5050509392505050565b6060610ff2826020015160008460000151614596565b60608182601f0110156146af576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610add565b82828401101561471b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610add565b81830184511015614788576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401610add565b6060821580156147a7576040519150600082526020820160405261480f565b6040519150601f8416801560200281840101858101878315602002848b0101015b818310156147e05780518352602092830192016147c8565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b60408051808201909152600080825260208201528151600003614867576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50604080518082019091528151815260209182019181019190915290565b60606000806000614895856140f8565b9194509250905060018160018111156148b0576148b061573b565b146148e7576040517f4b9c6abe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84516148f38385614fed565b1461492a576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808252610420820190925290816020015b60408051808201909152600080825260208201528152602001906001900390816149415790505093506000835b8651811015614a2f576000806149b46040518060400160405280858c60000151614998919061522c565b8152602001858c602001516149ad9190614fed565b90526140f8565b5091509150604051806040016040528083836149d09190614fed565b8152602001848b602001516149e59190614fed565b8152508885815181106149fa576149fa6156ab565b6020908102919091010152614a10600185614fed565b9350614a1c8183614fed565b614a269084614fed565b9250505061496e565b50845250919392505050565b73ffffffffffffffffffffffffffffffffffffffff81168114614a5d57600080fd5b50565b803567ffffffffffffffff81168114614a7857600080fd5b919050565b8015158114614a5d57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614b0157614b01614a8b565b604052919050565b600082601f830112614b1a57600080fd5b813567ffffffffffffffff811115614b3457614b34614a8b565b614b6560207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614aba565b818152846020838601011115614b7a57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060008060c08789031215614bb057600080fd5b8635614bbb81614a3b565b95506020870135945060408701359350614bd760608801614a60565b92506080870135614be781614a7d565b915060a087013567ffffffffffffffff811115614c0357600080fd5b614c0f89828a01614b09565b9150509295509295509295565b600060c08284031215614c2e57600080fd5b60405160c0810167ffffffffffffffff8282108183111715614c5257614c52614a8b565b816040528293508435835260208501359150614c6d82614a3b565b81602084015260408501359150614c8382614a3b565b816040840152606085013560608401526080850135608084015260a0850135915080821115614cb157600080fd5b50614cbe85828601614b09565b60a0830152505092915050565b600080600080600085870360e0811215614ce457600080fd5b863567ffffffffffffffff80821115614cfc57600080fd5b614d088a838b01614c1c565b97506020890135965060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc084011215614d4157600080fd5b60408901955060c0890135925080831115614d5b57600080fd5b828901925089601f840112614d6f57600080fd5b8235915080821115614d8057600080fd5b508860208260051b8401011115614d9657600080fd5b959894975092955050506020019190565b60005b83811015614dc2578181015183820152602001614daa565b83811115611ef75750506000910152565b60008151808452614deb816020860160208601614da7565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006129686020830184614dd3565b600060208284031215614e4257600080fd5b5035919050565b60ff81168114614a5d57600080fd5b60008060008060808587031215614e6e57600080fd5b8435614e7981614a3b565b93506020850135614e8981614e49565b93969395505050506040820135916060013590565b600060208284031215614eb057600080fd5b813567ffffffffffffffff811115614ec757600080fd5b614ed384828501614c1c565b949350505050565b600060208284031215614eed57600080fd5b61296882614a60565b600080600060608486031215614f0b57600080fd5b8335614f1681614a3b565b92506020840135614f2681614a3b565b91506040840135614f3681614a3b565b809150509250925092565b600080600080600060a08688031215614f5957600080fd5b8535614f6481614a3b565b945060208601359350614f7960408701614a60565b92506060860135614f8981614a7d565b9150608086013567ffffffffffffffff811115614fa557600080fd5b614fb188828901614b09565b9150509295509295909350565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561500057615000614fbe565b500190565b60006020828403121561501757600080fd5b5051919050565b60006020828403121561503057600080fd5b815161296881614a3b565b80516fffffffffffffffffffffffffffffffff81168114614a7857600080fd5b60006060828403121561506d57600080fd5b6040516060810181811067ffffffffffffffff8211171561509057615090614a8b565b604052825181526150a36020840161503b565b60208201526150b46040840161503b565b60408201529392505050565b6000608082840312156150d257600080fd5b6040516080810181811067ffffffffffffffff821117156150f5576150f5614a8b565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b600067ffffffffffffffff8084111561514157615141614a8b565b8360051b6020615152818301614aba565b86815291850191818101903684111561516a57600080fd5b865b8481101561519e578035868111156151845760008081fd5b61519036828b01614b09565b84525091830191830161516c565b50979650505050505050565b6000602082840312156151bc57600080fd5b815161296881614a7d565b8581528460208201527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b16604082015282151560f81b60488201526000825161521b816049850160208701614da7565b919091016049019695505050505050565b60008282101561523e5761523e614fbe565b500390565b600067ffffffffffffffff8083168185168183048111821515161561526a5761526a614fbe565b02949350505050565b600067ffffffffffffffff80831681851680830382111561529657615296614fbe565b01949350505050565b600080604083850312156152b257600080fd5b82516152bd81614a3b565b60208401519092506152ce81614e49565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082615317576153176152d9565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f80000000000000000000000000000000000000000000000000000000000000008314161561536b5761536b614fbe565b500590565b6000808312837f8000000000000000000000000000000000000000000000000000000000000000018312811516156153aa576153aa614fbe565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0183138116156153de576153de614fbe565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60008413600084138583048511828216161561542557615425614fbe565b7f8000000000000000000000000000000000000000000000000000000000000000600087128682058812818416161561546057615460614fbe565b6000871292508782058712848416161561547c5761547c614fbe565b8785058712818416161561549257615492614fbe565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038413811516156154da576154da614fbe565b827f800000000000000000000000000000000000000000000000000000000000000003841281161561550e5761550e614fbe565b50500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561554c5761554c614fbe565b500290565b600082615560576155606152d9565b500490565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a08301526155b060c0830184614dd3565b98975050505050505050565b805163ffffffff81168114614a7857600080fd5b600060c082840312156155e257600080fd5b60405160c0810181811067ffffffffffffffff8211171561560557615605614a8b565b604052615611836155bc565b8152602083015161562181614e49565b6020820152604083015161563481614e49565b6040820152615645606084016155bc565b6060820152615656608084016155bc565b608082015261566760a0840161503b565b60a08201529392505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036156a4576156a4614fbe565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060ff8316806156ed576156ed6152d9565b8060ff84160691505092915050565b600060ff821660ff84168082101561571657615716614fbe565b90039392505050565b60008251615731818460208701614da7565b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea164736f6c634300080f000a", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [], - "value": 0 - }, - { - "accessor": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "account": "0xbdD90485FCbcac869D5b5752179815a3103d8131", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x60806040523480156200001157600080fd5b50620000206000808062000026565b6200028f565b600054610100900460ff1615808015620000475750600054600160ff909116105b806200007757506200006430620001c160201b62001efd1760201c565b15801562000077575060005460ff166001145b620000e05760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000104576000805461ff0019166101001790555b603680546001600160a01b03199081166001600160a01b03878116919091179092556037805490911685831617905560358054610100600160a81b03191661010085841602179055603254166200016a57603280546001600160a01b03191661dead1790555b62000174620001d0565b8015620001bb576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b6001600160a01b03163b151590565b600054610100900460ff166200023d5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401620000d7565b600154600160c01b90046001600160401b03166000036200028d5760408051606081018252633b9aca0080825260006020830152436001600160401b031691909201819052600160c01b02176001555b565b615777806200029f6000396000f3fe6080604052600436106101635760003560e01c80638c3152e9116100c0578063b69ef8a811610074578063cff0ab9611610059578063cff0ab9614610444578063e965084c146104e5578063e9e05c421461057157600080fd5b8063b69ef8a814610401578063c0c53b8b1461042457600080fd5b80639bf62d82116100a55780639bf62d821461036b578063a14238e714610398578063a35d99df146103c857600080fd5b80638c3152e91461031e5780639b5f694a1461033e57600080fd5b806354fd4d50116101175780636dbffb78116100fc5780636dbffb78146102de57806371cfaa3f146102fe5780638b4c40b01461018857600080fd5b806354fd4d501461026d5780635c975abb146102b957600080fd5b806335e80ab31161014857806335e80ab314610206578063452a9320146102385780634870496f1461024d57600080fd5b8063149f2f221461018f57806333d7e2bd146101af57600080fd5b3661018a576101883334620186a060006040518060200160405280600081525061057f565b005b600080fd5b34801561019b57600080fd5b506101886101aa366004614b97565b610624565b3480156101bb57600080fd5b506037546101dc9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561021257600080fd5b506035546101dc90610100900473ffffffffffffffffffffffffffffffffffffffff1681565b34801561024457600080fd5b506101dc610865565b34801561025957600080fd5b50610188610268366004614ccb565b6108fd565b34801561027957600080fd5b50604080518082018252600c81527f322e382e312d626574612e310000000000000000000000000000000000000000602082015290516101fd9190614e1d565b3480156102c557600080fd5b506102ce610eaa565b60405190151581526020016101fd565b3480156102ea57600080fd5b506102ce6102f9366004614e30565b610f3d565b34801561030a57600080fd5b50610188610319366004614e58565b610ff8565b34801561032a57600080fd5b50610188610339366004614e9e565b6111ba565b34801561034a57600080fd5b506036546101dc9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561037757600080fd5b506032546101dc9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156103a457600080fd5b506102ce6103b3366004614e30565b60336020526000908152604090205460ff1681565b3480156103d457600080fd5b506103e86103e3366004614edb565b611c3c565b60405167ffffffffffffffff90911681526020016101fd565b34801561040d57600080fd5b50610416611c55565b6040519081526020016101fd565b34801561043057600080fd5b5061018861043f366004614ef6565b611caf565b34801561045057600080fd5b506001546104ac906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff92831660208501529116908201526060016101fd565b3480156104f157600080fd5b50610543610500366004614e30565b603460205260009081526040902080546001909101546fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041683565b604080519384526fffffffffffffffffffffffffffffffff92831660208501529116908201526060016101fd565b61018861057f366004614f41565b8260005a9050600061058f611f19565b50905073ffffffffffffffffffffffffffffffffffffffff811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee148015906105cb57503415155b15610602576040517ff2365b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610610883489898989611fb6565b5061061b8282612162565b50505050505050565b8260005a90506000610634611f19565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8216016106a6576040517f0eaf3c0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87603d60008282546106b89190614fed565b90915550506040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa15801561072a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061074e9190615005565b905061077273ffffffffffffffffffffffffffffffffffffffff831633308c61242f565b61077c8982614fed565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa1580156107e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061080a9190615005565b14610841576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61084f8a8a8a8a8a8a611fb6565b505061085b8282612162565b5050505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f8919061501e565b905090565b610905610eaa565b1561093c576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff16036109a5576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6036546040517fa25ae5570000000000000000000000000000000000000000000000000000000081526004810186905260009173ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa158015610a15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a39919061505b565b519050610a53610a4e368690038601866150c0565b61250b565b8114610ae6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f7074696d69736d506f7274616c3a20696e76616c6964206f7574707574207260448201527f6f6f742070726f6f66000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000610af187612567565b6000818152603460209081526040918290208251606081018452815481526001909101546fffffffffffffffffffffffffffffffff8082169383018490527001000000000000000000000000000000009091041692810192909252919250901580610c075750805160365460408084015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff909116600482015273ffffffffffffffffffffffffffffffffffffffff9091169063a25ae55790602401606060405180830381865afa158015610bdf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c03919061505b565b5114155b610c93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173682060448201527f68617320616c7265616479206265656e2070726f76656e0000000000000000006064820152608401610add565b60408051602081018490526000918101829052606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201209083018190529250610d5c9101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f0100000000000000000000000000000000000000000000000000000000000000602083015290610d52888a615126565b8a60400135612597565b610de8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a20696e76616c696420776974686472617760448201527f616c20696e636c7573696f6e2070726f6f6600000000000000000000000000006064820152608401610add565b604080516060810182528581526fffffffffffffffffffffffffffffffff42811660208084019182528c831684860190815260008981526034835286812095518655925190518416700100000000000000000000000000000000029316929092176001909301929092558b830151908c0151925173ffffffffffffffffffffffffffffffffffffffff918216939091169186917f67a6208cfcc0801d50f6cbe764733f4fddf66ac0b04442061a8a8c0cb6b63f629190a4505050505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f19573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f891906151aa565b6036546040517fa25ae55700000000000000000000000000000000000000000000000000000000815260048101839052600091610ff29173ffffffffffffffffffffffffffffffffffffffff9091169063a25ae55790602401606060405180830381865afa158015610fb3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fd7919061505b565b602001516fffffffffffffffffffffffffffffffff166125bb565b92915050565b60375473ffffffffffffffffffffffffffffffffffffffff163314611049576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61105562030d40612661565b60405173ffffffffffffffffffffffffffffffffffffffff8516602482015260ff8416604482015260648101839052608481018290526000907342000000000000000000000000000000000000159073deaddeaddeaddeaddeaddeaddeaddeaddead0001907fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32908490819062030d4090829060a401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f71cfaa3f000000000000000000000000000000000000000000000000000000001790529051611172969594939291016151c7565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526111aa91614e1d565b60405180910390a450505050565b565b6111c2610eaa565b156111f9576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60325473ffffffffffffffffffffffffffffffffffffffff1661dead1461124c576040517f9396d15600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061125782612567565b60008181526034602090815260408083208151606081018352815481526001909101546fffffffffffffffffffffffffffffffff80821694830185905270010000000000000000000000000000000090910416918101919091529293509003611342576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206e60448201527f6f74206265656e2070726f76656e2079657400000000000000000000000000006064820152608401610add565b603660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663887862726040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113d39190615005565b81602001516fffffffffffffffffffffffffffffffff16101561149e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604b60248201527f4f7074696d69736d506f7274616c3a207769746864726177616c2074696d657360448201527f74616d70206c657373207468616e204c32204f7261636c65207374617274696e60648201527f672074696d657374616d70000000000000000000000000000000000000000000608482015260a401610add565b6114bd81602001516fffffffffffffffffffffffffffffffff166125bb565b61156f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604560248201527f4f7074696d69736d506f7274616c3a2070726f76656e2077697468647261776160448201527f6c2066696e616c697a6174696f6e20706572696f6420686173206e6f7420656c60648201527f6170736564000000000000000000000000000000000000000000000000000000608482015260a401610add565b60365460408281015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff909116600482015260009173ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa1580156115f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061161a919061505b565b82518151919250146116d4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4f7074696d69736d506f7274616c3a206f757470757420726f6f742070726f7660448201527f656e206973206e6f74207468652073616d652061732063757272656e74206f7560648201527f7470757420726f6f740000000000000000000000000000000000000000000000608482015260a401610add565b6116f381602001516fffffffffffffffffffffffffffffffff166125bb565b6117a5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4f7074696d69736d506f7274616c3a206f75747075742070726f706f73616c2060448201527f66696e616c697a6174696f6e20706572696f6420686173206e6f7420656c617060648201527f7365640000000000000000000000000000000000000000000000000000000000608482015260a401610add565b60008381526033602052604090205460ff1615611844576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206160448201527f6c7265616479206265656e2066696e616c697a656400000000000000000000006064820152608401610add565b6000838152603360209081526040822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558501516032805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff0000000000000000000000000000000000000000909216919091179055806118cf611f19565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8216016119325761192b8660400151876080015188606001518960a001516126c3565b9150611b85565b8073ffffffffffffffffffffffffffffffffffffffff16866040015173ffffffffffffffffffffffffffffffffffffffff160361199b576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606086015115611b5c578560600151603d60008282546119bb919061522c565b90915550506040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015611a2d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a519190615005565b9050611a86876040015188606001518473ffffffffffffffffffffffffffffffffffffffff166127219092919063ffffffff16565b6060870151611a95908261522c565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015611aff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b239190615005565b14611b5a576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60a08601515115611b805761192b8660400151876080015160008960a001516126c3565b600191505b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405185907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b90611be790851515815260200190565b60405180910390a281158015611bfd5750326001145b15611c34576040517feeae4ed300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000611c49826010615243565b610ff290615208615273565b600080611c60611f19565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff821601611ca7574791505090565b5050603d5490565b600054610100900460ff1615808015611ccf5750600054600160ff909116105b80611ce95750303b158015611ce9575060005460ff166001145b611d75576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610add565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015611dd357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603680547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff8781169190911790925560378054909116858316179055603580547fffffffffffffffffffffff0000000000000000000000000000000000000000ff166101008584160217905560325416611e8c57603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790555b611e9461277c565b8015611ef757600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b603754604080517f4397dfef0000000000000000000000000000000000000000000000000000000081528151600093849373ffffffffffffffffffffffffffffffffffffffff90911692634397dfef92600480830193928290030181865afa158015611f89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fad919061529f565b90939092509050565b818015611fd8575073ffffffffffffffffffffffffffffffffffffffff861615155b1561200f576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6120198151611c3c565b67ffffffffffffffff168367ffffffffffffffff161015612066576040517f4929b80800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6201d4c0815111156120a4576040517f73052b0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b333281146120c5575033731111000000000000000000000000000000001111015b600086868686866040516020016120e09594939291906151c7565b604051602081830303815290604052905060008873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32846040516121509190614e1d565b60405180910390a45050505050505050565b600154600090612198907801000000000000000000000000000000000000000000000000900467ffffffffffffffff164361522c565b905060006121a461288f565b90506000816020015160ff16826000015163ffffffff166121c59190615308565b905082156122fc576001546000906121fc908390700100000000000000000000000000000000900467ffffffffffffffff16615370565b90506000836040015160ff168361221391906153e4565b6001546122339084906fffffffffffffffffffffffffffffffff166153e4565b61223d9190615308565b60015490915060009061228e906122679084906fffffffffffffffffffffffffffffffff166154a0565b866060015163ffffffff168760a001516fffffffffffffffffffffffffffffffff16612950565b905060018611156122bd576122ba61226782876040015160ff1660018a6122b5919061522c565b61296f565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b6001805486919060109061232f908490700100000000000000000000000000000000900467ffffffffffffffff16615273565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550816000015163ffffffff16600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff1613156123bc576040517f77ebef4d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001546000906123e8906fffffffffffffffffffffffffffffffff1667ffffffffffffffff8816615514565b905060006123fa48633b9aca006129c4565b6124049083615551565b905060005a612413908861522c565b90508082111561085b5761085b61242a828461522c565b6129db565b60405173ffffffffffffffffffffffffffffffffffffffff80851660248301528316604482015260648101829052611ef79085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612a04565b6000816000015182602001518360400151846060015160405160200161254a949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b80516020808301516040808501516060860151608087015160a0880151935160009761254a979096959101615565565b6000806125a386612b10565b90506125b181868686612b42565b9695505050505050565b603654604080517ff4daa291000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163f4daa2919160048083019260209291908290030181865afa15801561262b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061264f9190615005565b6126599083614fed565b421192915050565b6001805463ffffffff8316919060109061269a908490700100000000000000000000000000000000900467ffffffffffffffff16615273565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555050565b60008060006126d3866000612b72565b905080612709576308c379a06000526020805278185361666543616c6c3a204e6f7420656e6f756768206761736058526064601cfd5b600080855160208701888b5af1979650505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526127779084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401612489565b505050565b600054610100900460ff16612813576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610add565b6001547801000000000000000000000000000000000000000000000000900467ffffffffffffffff166000036111b85760408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b6040805160c08082018352600080835260208301819052828401819052606083018190526080830181905260a083015260375483517fcc731b020000000000000000000000000000000000000000000000000000000081529351929373ffffffffffffffffffffffffffffffffffffffff9091169263cc731b02926004808401939192918290030181865afa15801561292c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f891906155d0565b600061296561295f8585612b90565b83612ba0565b90505b9392505050565b6000670de0b6b3a76400006129b06129878583615308565b61299990670de0b6b3a7640000615370565b6129ab85670de0b6b3a76400006153e4565b612baf565b6129ba90866153e4565b6129659190615308565b6000818310156129d45781612968565b5090919050565b6000805a90505b825a6129ee908361522c565b1015612777576129fd82615673565b91506129e2565b6000612a66826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612be09092919063ffffffff16565b8051909150156127775780806020019051810190612a8491906151aa565b612777576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610add565b60608180519060200120604051602001612b2c91815260200190565b6040516020818303038152906040529050919050565b6000612b6984612b53878686612bef565b8051602091820120825192909101919091201490565b95945050505050565b600080603f83619c4001026040850201603f5a021015949350505050565b6000818312156129d45781612968565b60008183126129d45781612968565b6000612968670de0b6b3a764000083612bc78661366d565b612bd191906153e4565b612bdb9190615308565b6138b1565b60606129658484600085613af0565b60606000845111612c5c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4d65726b6c65547269653a20656d707479206b657900000000000000000000006044820152606401610add565b6000612c6784613c86565b90506000612c7486613d72565b9050600084604051602001612c8b91815260200190565b60405160208183030381529060405290506000805b84518110156135e4576000858281518110612cbd57612cbd6156ab565b602002602001015190508451831115612d58576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4d65726b6c65547269653a206b657920696e646578206578636565647320746f60448201527f74616c206b6579206c656e6774680000000000000000000000000000000000006064820152608401610add565b82600003612e115780518051602091820120604051612da692612d8092910190815260200190565b604051602081830303815290604052858051602091820120825192909101919091201490565b612e0c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4d65726b6c65547269653a20696e76616c696420726f6f7420686173680000006044820152606401610add565b612f68565b805151602011612ec75780518051602091820120604051612e3b92612d8092910190815260200190565b612e0c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d65726b6c65547269653a20696e76616c6964206c6172676520696e7465726e60448201527f616c2068617368000000000000000000000000000000000000000000000000006064820152608401610add565b805184516020808701919091208251919092012014612f68576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4d65726b6c65547269653a20696e76616c696420696e7465726e616c206e6f6460448201527f65206861736800000000000000000000000000000000000000000000000000006064820152608401610add565b612f7460106001614fed565b8160200151510361315057845183036130e857612fae8160200151601081518110612fa157612fa16156ab565b6020026020010151613dd5565b96506000875111613041576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603b60248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286272616e63682900000000006064820152608401610add565b6001865161304f919061522c565b82146130dd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286272616e6368290000000000006064820152608401610add565b505050505050612968565b60008584815181106130fc576130fc6156ab565b602001015160f81c60f81b60f81c9050600082602001518260ff1681518110613127576131276156ab565b6020026020010151905061313a81613e89565b9550613147600186614fed565b945050506135d1565b60028160200151510361354957600061316882613eae565b905060008160008151811061317f5761317f6156ab565b016020015160f81c905060006131966002836156da565b6131a19060026156fc565b905060006131b2848360ff16613ed2565b905060006131c08a89613ed2565b905060006131ce8383613f08565b905080835114613260576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a20706174682072656d61696e646572206d7573742060448201527f736861726520616c6c206e6962626c65732077697468206b65790000000000006064820152608401610add565b60ff851660021480613275575060ff85166003145b15613464578082511461330a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f4d65726b6c65547269653a206b65792072656d61696e646572206d757374206260448201527f65206964656e746963616c20746f20706174682072656d61696e6465720000006064820152608401610add565b6133248760200151600181518110612fa157612fa16156ab565b9c5060008d51116133b7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286c65616629000000000000006064820152608401610add565b60018c516133c5919061522c565b8814613453576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286c6561662900000000000000006064820152608401610add565b505050505050505050505050612968565b60ff85161580613477575060ff85166001145b156134b6576134a38760200151600181518110613496576134966156ab565b6020026020010151613e89565b99506134af818a614fed565b985061353e565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4d65726b6c65547269653a2072656365697665642061206e6f6465207769746860448201527f20616e20756e6b6e6f776e2070726566697800000000000000000000000000006064820152608401610add565b5050505050506135d1565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4d65726b6c65547269653a20726563656976656420616e20756e70617273656160448201527f626c65206e6f64650000000000000000000000000000000000000000000000006064820152608401610add565b50806135dc81615673565b915050612ca0565b506040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4d65726b6c65547269653a2072616e206f7574206f662070726f6f6620656c6560448201527f6d656e74730000000000000000000000000000000000000000000000000000006064820152608401610add565b60008082136136d8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610add565b600060606136e584613fbc565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c182136138e257506000919050565b680755bf798b4a1bf1e58212613954576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4558505f4f564552464c4f5700000000000000000000000000000000000000006044820152606401610add565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b606082471015613b82576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610add565b73ffffffffffffffffffffffffffffffffffffffff85163b613c00576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610add565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051613c29919061571f565b60006040518083038185875af1925050503d8060008114613c66576040519150601f19603f3d011682016040523d82523d6000602084013e613c6b565b606091505b5091509150613c7b828286614092565b979650505050505050565b80516060908067ffffffffffffffff811115613ca457613ca4614a8b565b604051908082528060200260200182016040528015613ce957816020015b6040805180820190915260608082526020820152815260200190600190039081613cc25790505b50915060005b81811015613d6b576040518060400160405280858381518110613d1457613d146156ab565b60200260200101518152602001613d43868481518110613d3657613d366156ab565b60200260200101516140e5565b815250838281518110613d5857613d586156ab565b6020908102919091010152600101613cef565b5050919050565b606080604051905082518060011b603f8101601f1916830160405280835250602084016020830160005b83811015613dca578060011b82018184015160001a8060041c8253600f811660018301535050600101613d9c565b509295945050505050565b60606000806000613de5856140f8565b919450925090506000816001811115613e0057613e0061573b565b14613e37576040517f1ff9b2e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613e418284614fed565b855114613e7a576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612b6985602001518484614596565b60606020826000015110613ea557613ea082613dd5565b610ff2565b610ff28261462a565b6060610ff2613ecd8360200151600081518110612fa157612fa16156ab565b613d72565b606082518210613ef15750604080516020810190915260008152610ff2565b6129688383848651613f03919061522c565b614640565b6000808251845110613f1b578251613f1e565b83515b90505b8082108015613fa55750828281518110613f3d57613f3d6156ab565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916848381518110613f7c57613f7c6156ab565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b15613fb557816001019150613f21565b5092915050565b6000808211614027576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610add565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b606083156140a1575081612968565b8251156140b15782518084602001fd5b816040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610add9190614e1d565b6060610ff26140f383614818565b614885565b6000806000836000015160000361413b576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020840151805160001a607f811161416057600060016000945094509450505061458f565b60b7811161427657600061417560808361522c565b9050808760000151116141b4576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001838101517fff0000000000000000000000000000000000000000000000000000000000000016908214801561422c57507f80000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008216105b15614263576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506001955093506000925061458f915050565b60bf81116143d457600061428b60b78361522c565b9050808760000151116142ca576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff0000000000000000000000000000000000000000000000000000000000000016600081900361432c576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c60378111614374576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61437e8184614fed565b8951116143b7576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6143c2836001614fed565b975095506000945061458f9350505050565b60f781116144395760006143e960c08361522c565b905080876000015111614428576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60019550935084925061458f915050565b600061444660f78361522c565b905080876000015111614485576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff000000000000000000000000000000000000000000000000000000000000001660008190036144e7576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c6037811161452f576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6145398184614fed565b895111614572576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61457d836001614fed565b975095506001945061458f9350505050565b9193909250565b60608167ffffffffffffffff8111156145b1576145b1614a8b565b6040519080825280601f01601f1916602001820160405280156145db576020820181803683370190505b50905081156129685760006145f08486614fed565b90506020820160005b848110156146115782810151828201526020016145f9565b84811115614620576000858301525b5050509392505050565b6060610ff2826020015160008460000151614596565b60608182601f0110156146af576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610add565b82828401101561471b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610add565b81830184511015614788576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401610add565b6060821580156147a7576040519150600082526020820160405261480f565b6040519150601f8416801560200281840101858101878315602002848b0101015b818310156147e05780518352602092830192016147c8565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b60408051808201909152600080825260208201528151600003614867576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50604080518082019091528151815260209182019181019190915290565b60606000806000614895856140f8565b9194509250905060018160018111156148b0576148b061573b565b146148e7576040517f4b9c6abe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84516148f38385614fed565b1461492a576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808252610420820190925290816020015b60408051808201909152600080825260208201528152602001906001900390816149415790505093506000835b8651811015614a2f576000806149b46040518060400160405280858c60000151614998919061522c565b8152602001858c602001516149ad9190614fed565b90526140f8565b5091509150604051806040016040528083836149d09190614fed565b8152602001848b602001516149e59190614fed565b8152508885815181106149fa576149fa6156ab565b6020908102919091010152614a10600185614fed565b9350614a1c8183614fed565b614a269084614fed565b9250505061496e565b50845250919392505050565b73ffffffffffffffffffffffffffffffffffffffff81168114614a5d57600080fd5b50565b803567ffffffffffffffff81168114614a7857600080fd5b919050565b8015158114614a5d57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614b0157614b01614a8b565b604052919050565b600082601f830112614b1a57600080fd5b813567ffffffffffffffff811115614b3457614b34614a8b565b614b6560207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614aba565b818152846020838601011115614b7a57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060008060c08789031215614bb057600080fd5b8635614bbb81614a3b565b95506020870135945060408701359350614bd760608801614a60565b92506080870135614be781614a7d565b915060a087013567ffffffffffffffff811115614c0357600080fd5b614c0f89828a01614b09565b9150509295509295509295565b600060c08284031215614c2e57600080fd5b60405160c0810167ffffffffffffffff8282108183111715614c5257614c52614a8b565b816040528293508435835260208501359150614c6d82614a3b565b81602084015260408501359150614c8382614a3b565b816040840152606085013560608401526080850135608084015260a0850135915080821115614cb157600080fd5b50614cbe85828601614b09565b60a0830152505092915050565b600080600080600085870360e0811215614ce457600080fd5b863567ffffffffffffffff80821115614cfc57600080fd5b614d088a838b01614c1c565b97506020890135965060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc084011215614d4157600080fd5b60408901955060c0890135925080831115614d5b57600080fd5b828901925089601f840112614d6f57600080fd5b8235915080821115614d8057600080fd5b508860208260051b8401011115614d9657600080fd5b959894975092955050506020019190565b60005b83811015614dc2578181015183820152602001614daa565b83811115611ef75750506000910152565b60008151808452614deb816020860160208601614da7565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006129686020830184614dd3565b600060208284031215614e4257600080fd5b5035919050565b60ff81168114614a5d57600080fd5b60008060008060808587031215614e6e57600080fd5b8435614e7981614a3b565b93506020850135614e8981614e49565b93969395505050506040820135916060013590565b600060208284031215614eb057600080fd5b813567ffffffffffffffff811115614ec757600080fd5b614ed384828501614c1c565b949350505050565b600060208284031215614eed57600080fd5b61296882614a60565b600080600060608486031215614f0b57600080fd5b8335614f1681614a3b565b92506020840135614f2681614a3b565b91506040840135614f3681614a3b565b809150509250925092565b600080600080600060a08688031215614f5957600080fd5b8535614f6481614a3b565b945060208601359350614f7960408701614a60565b92506060860135614f8981614a7d565b9150608086013567ffffffffffffffff811115614fa557600080fd5b614fb188828901614b09565b9150509295509295909350565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561500057615000614fbe565b500190565b60006020828403121561501757600080fd5b5051919050565b60006020828403121561503057600080fd5b815161296881614a3b565b80516fffffffffffffffffffffffffffffffff81168114614a7857600080fd5b60006060828403121561506d57600080fd5b6040516060810181811067ffffffffffffffff8211171561509057615090614a8b565b604052825181526150a36020840161503b565b60208201526150b46040840161503b565b60408201529392505050565b6000608082840312156150d257600080fd5b6040516080810181811067ffffffffffffffff821117156150f5576150f5614a8b565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b600067ffffffffffffffff8084111561514157615141614a8b565b8360051b6020615152818301614aba565b86815291850191818101903684111561516a57600080fd5b865b8481101561519e578035868111156151845760008081fd5b61519036828b01614b09565b84525091830191830161516c565b50979650505050505050565b6000602082840312156151bc57600080fd5b815161296881614a7d565b8581528460208201527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b16604082015282151560f81b60488201526000825161521b816049850160208701614da7565b919091016049019695505050505050565b60008282101561523e5761523e614fbe565b500390565b600067ffffffffffffffff8083168185168183048111821515161561526a5761526a614fbe565b02949350505050565b600067ffffffffffffffff80831681851680830382111561529657615296614fbe565b01949350505050565b600080604083850312156152b257600080fd5b82516152bd81614a3b565b60208401519092506152ce81614e49565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082615317576153176152d9565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f80000000000000000000000000000000000000000000000000000000000000008314161561536b5761536b614fbe565b500590565b6000808312837f8000000000000000000000000000000000000000000000000000000000000000018312811516156153aa576153aa614fbe565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0183138116156153de576153de614fbe565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60008413600084138583048511828216161561542557615425614fbe565b7f8000000000000000000000000000000000000000000000000000000000000000600087128682058812818416161561546057615460614fbe565b6000871292508782058712848416161561547c5761547c614fbe565b8785058712818416161561549257615492614fbe565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038413811516156154da576154da614fbe565b827f800000000000000000000000000000000000000000000000000000000000000003841281161561550e5761550e614fbe565b50500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561554c5761554c614fbe565b500290565b600082615560576155606152d9565b500490565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a08301526155b060c0830184614dd3565b98975050505050505050565b805163ffffffff81168114614a7857600080fd5b600060c082840312156155e257600080fd5b60405160c0810181811067ffffffffffffffff8211171561560557615605614a8b565b604052615611836155bc565b8152602083015161562181614e49565b6020820152604083015161563481614e49565b6040820152615645606084016155bc565b6060820152615656608084016155bc565b608082015261566760a0840161503b565b60a08201529392505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036156a4576156a4614fbe565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060ff8316806156ed576156ed6152d9565b8060ff84160691505092915050565b600060ff821660ff84168082101561571657615716614fbe565b90039392505050565b60008251615731818460208701614da7565b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea164736f6c634300080f000a", - "deployedCode": "0x6080604052600436106101635760003560e01c80638c3152e9116100c0578063b69ef8a811610074578063cff0ab9611610059578063cff0ab9614610444578063e965084c146104e5578063e9e05c421461057157600080fd5b8063b69ef8a814610401578063c0c53b8b1461042457600080fd5b80639bf62d82116100a55780639bf62d821461036b578063a14238e714610398578063a35d99df146103c857600080fd5b80638c3152e91461031e5780639b5f694a1461033e57600080fd5b806354fd4d50116101175780636dbffb78116100fc5780636dbffb78146102de57806371cfaa3f146102fe5780638b4c40b01461018857600080fd5b806354fd4d501461026d5780635c975abb146102b957600080fd5b806335e80ab31161014857806335e80ab314610206578063452a9320146102385780634870496f1461024d57600080fd5b8063149f2f221461018f57806333d7e2bd146101af57600080fd5b3661018a576101883334620186a060006040518060200160405280600081525061057f565b005b600080fd5b34801561019b57600080fd5b506101886101aa366004614b97565b610624565b3480156101bb57600080fd5b506037546101dc9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561021257600080fd5b506035546101dc90610100900473ffffffffffffffffffffffffffffffffffffffff1681565b34801561024457600080fd5b506101dc610865565b34801561025957600080fd5b50610188610268366004614ccb565b6108fd565b34801561027957600080fd5b50604080518082018252600c81527f322e382e312d626574612e310000000000000000000000000000000000000000602082015290516101fd9190614e1d565b3480156102c557600080fd5b506102ce610eaa565b60405190151581526020016101fd565b3480156102ea57600080fd5b506102ce6102f9366004614e30565b610f3d565b34801561030a57600080fd5b50610188610319366004614e58565b610ff8565b34801561032a57600080fd5b50610188610339366004614e9e565b6111ba565b34801561034a57600080fd5b506036546101dc9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561037757600080fd5b506032546101dc9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156103a457600080fd5b506102ce6103b3366004614e30565b60336020526000908152604090205460ff1681565b3480156103d457600080fd5b506103e86103e3366004614edb565b611c3c565b60405167ffffffffffffffff90911681526020016101fd565b34801561040d57600080fd5b50610416611c55565b6040519081526020016101fd565b34801561043057600080fd5b5061018861043f366004614ef6565b611caf565b34801561045057600080fd5b506001546104ac906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff92831660208501529116908201526060016101fd565b3480156104f157600080fd5b50610543610500366004614e30565b603460205260009081526040902080546001909101546fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041683565b604080519384526fffffffffffffffffffffffffffffffff92831660208501529116908201526060016101fd565b61018861057f366004614f41565b8260005a9050600061058f611f19565b50905073ffffffffffffffffffffffffffffffffffffffff811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee148015906105cb57503415155b15610602576040517ff2365b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610610883489898989611fb6565b5061061b8282612162565b50505050505050565b8260005a90506000610634611f19565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8216016106a6576040517f0eaf3c0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87603d60008282546106b89190614fed565b90915550506040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa15801561072a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061074e9190615005565b905061077273ffffffffffffffffffffffffffffffffffffffff831633308c61242f565b61077c8982614fed565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa1580156107e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061080a9190615005565b14610841576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61084f8a8a8a8a8a8a611fb6565b505061085b8282612162565b5050505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f8919061501e565b905090565b610905610eaa565b1561093c576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff16036109a5576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6036546040517fa25ae5570000000000000000000000000000000000000000000000000000000081526004810186905260009173ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa158015610a15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a39919061505b565b519050610a53610a4e368690038601866150c0565b61250b565b8114610ae6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f7074696d69736d506f7274616c3a20696e76616c6964206f7574707574207260448201527f6f6f742070726f6f66000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000610af187612567565b6000818152603460209081526040918290208251606081018452815481526001909101546fffffffffffffffffffffffffffffffff8082169383018490527001000000000000000000000000000000009091041692810192909252919250901580610c075750805160365460408084015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff909116600482015273ffffffffffffffffffffffffffffffffffffffff9091169063a25ae55790602401606060405180830381865afa158015610bdf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c03919061505b565b5114155b610c93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173682060448201527f68617320616c7265616479206265656e2070726f76656e0000000000000000006064820152608401610add565b60408051602081018490526000918101829052606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201209083018190529250610d5c9101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f0100000000000000000000000000000000000000000000000000000000000000602083015290610d52888a615126565b8a60400135612597565b610de8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a20696e76616c696420776974686472617760448201527f616c20696e636c7573696f6e2070726f6f6600000000000000000000000000006064820152608401610add565b604080516060810182528581526fffffffffffffffffffffffffffffffff42811660208084019182528c831684860190815260008981526034835286812095518655925190518416700100000000000000000000000000000000029316929092176001909301929092558b830151908c0151925173ffffffffffffffffffffffffffffffffffffffff918216939091169186917f67a6208cfcc0801d50f6cbe764733f4fddf66ac0b04442061a8a8c0cb6b63f629190a4505050505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f19573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f891906151aa565b6036546040517fa25ae55700000000000000000000000000000000000000000000000000000000815260048101839052600091610ff29173ffffffffffffffffffffffffffffffffffffffff9091169063a25ae55790602401606060405180830381865afa158015610fb3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fd7919061505b565b602001516fffffffffffffffffffffffffffffffff166125bb565b92915050565b60375473ffffffffffffffffffffffffffffffffffffffff163314611049576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61105562030d40612661565b60405173ffffffffffffffffffffffffffffffffffffffff8516602482015260ff8416604482015260648101839052608481018290526000907342000000000000000000000000000000000000159073deaddeaddeaddeaddeaddeaddeaddeaddead0001907fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32908490819062030d4090829060a401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f71cfaa3f000000000000000000000000000000000000000000000000000000001790529051611172969594939291016151c7565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526111aa91614e1d565b60405180910390a450505050565b565b6111c2610eaa565b156111f9576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60325473ffffffffffffffffffffffffffffffffffffffff1661dead1461124c576040517f9396d15600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061125782612567565b60008181526034602090815260408083208151606081018352815481526001909101546fffffffffffffffffffffffffffffffff80821694830185905270010000000000000000000000000000000090910416918101919091529293509003611342576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206e60448201527f6f74206265656e2070726f76656e2079657400000000000000000000000000006064820152608401610add565b603660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663887862726040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113d39190615005565b81602001516fffffffffffffffffffffffffffffffff16101561149e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604b60248201527f4f7074696d69736d506f7274616c3a207769746864726177616c2074696d657360448201527f74616d70206c657373207468616e204c32204f7261636c65207374617274696e60648201527f672074696d657374616d70000000000000000000000000000000000000000000608482015260a401610add565b6114bd81602001516fffffffffffffffffffffffffffffffff166125bb565b61156f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604560248201527f4f7074696d69736d506f7274616c3a2070726f76656e2077697468647261776160448201527f6c2066696e616c697a6174696f6e20706572696f6420686173206e6f7420656c60648201527f6170736564000000000000000000000000000000000000000000000000000000608482015260a401610add565b60365460408281015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff909116600482015260009173ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa1580156115f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061161a919061505b565b82518151919250146116d4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4f7074696d69736d506f7274616c3a206f757470757420726f6f742070726f7660448201527f656e206973206e6f74207468652073616d652061732063757272656e74206f7560648201527f7470757420726f6f740000000000000000000000000000000000000000000000608482015260a401610add565b6116f381602001516fffffffffffffffffffffffffffffffff166125bb565b6117a5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4f7074696d69736d506f7274616c3a206f75747075742070726f706f73616c2060448201527f66696e616c697a6174696f6e20706572696f6420686173206e6f7420656c617060648201527f7365640000000000000000000000000000000000000000000000000000000000608482015260a401610add565b60008381526033602052604090205460ff1615611844576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206160448201527f6c7265616479206265656e2066696e616c697a656400000000000000000000006064820152608401610add565b6000838152603360209081526040822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558501516032805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff0000000000000000000000000000000000000000909216919091179055806118cf611f19565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8216016119325761192b8660400151876080015188606001518960a001516126c3565b9150611b85565b8073ffffffffffffffffffffffffffffffffffffffff16866040015173ffffffffffffffffffffffffffffffffffffffff160361199b576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606086015115611b5c578560600151603d60008282546119bb919061522c565b90915550506040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015611a2d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a519190615005565b9050611a86876040015188606001518473ffffffffffffffffffffffffffffffffffffffff166127219092919063ffffffff16565b6060870151611a95908261522c565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015611aff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b239190615005565b14611b5a576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60a08601515115611b805761192b8660400151876080015160008960a001516126c3565b600191505b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405185907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b90611be790851515815260200190565b60405180910390a281158015611bfd5750326001145b15611c34576040517feeae4ed300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000611c49826010615243565b610ff290615208615273565b600080611c60611f19565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff821601611ca7574791505090565b5050603d5490565b600054610100900460ff1615808015611ccf5750600054600160ff909116105b80611ce95750303b158015611ce9575060005460ff166001145b611d75576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610add565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015611dd357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603680547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff8781169190911790925560378054909116858316179055603580547fffffffffffffffffffffff0000000000000000000000000000000000000000ff166101008584160217905560325416611e8c57603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790555b611e9461277c565b8015611ef757600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b603754604080517f4397dfef0000000000000000000000000000000000000000000000000000000081528151600093849373ffffffffffffffffffffffffffffffffffffffff90911692634397dfef92600480830193928290030181865afa158015611f89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fad919061529f565b90939092509050565b818015611fd8575073ffffffffffffffffffffffffffffffffffffffff861615155b1561200f576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6120198151611c3c565b67ffffffffffffffff168367ffffffffffffffff161015612066576040517f4929b80800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6201d4c0815111156120a4576040517f73052b0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b333281146120c5575033731111000000000000000000000000000000001111015b600086868686866040516020016120e09594939291906151c7565b604051602081830303815290604052905060008873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32846040516121509190614e1d565b60405180910390a45050505050505050565b600154600090612198907801000000000000000000000000000000000000000000000000900467ffffffffffffffff164361522c565b905060006121a461288f565b90506000816020015160ff16826000015163ffffffff166121c59190615308565b905082156122fc576001546000906121fc908390700100000000000000000000000000000000900467ffffffffffffffff16615370565b90506000836040015160ff168361221391906153e4565b6001546122339084906fffffffffffffffffffffffffffffffff166153e4565b61223d9190615308565b60015490915060009061228e906122679084906fffffffffffffffffffffffffffffffff166154a0565b866060015163ffffffff168760a001516fffffffffffffffffffffffffffffffff16612950565b905060018611156122bd576122ba61226782876040015160ff1660018a6122b5919061522c565b61296f565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b6001805486919060109061232f908490700100000000000000000000000000000000900467ffffffffffffffff16615273565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550816000015163ffffffff16600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff1613156123bc576040517f77ebef4d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001546000906123e8906fffffffffffffffffffffffffffffffff1667ffffffffffffffff8816615514565b905060006123fa48633b9aca006129c4565b6124049083615551565b905060005a612413908861522c565b90508082111561085b5761085b61242a828461522c565b6129db565b60405173ffffffffffffffffffffffffffffffffffffffff80851660248301528316604482015260648101829052611ef79085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612a04565b6000816000015182602001518360400151846060015160405160200161254a949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b80516020808301516040808501516060860151608087015160a0880151935160009761254a979096959101615565565b6000806125a386612b10565b90506125b181868686612b42565b9695505050505050565b603654604080517ff4daa291000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163f4daa2919160048083019260209291908290030181865afa15801561262b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061264f9190615005565b6126599083614fed565b421192915050565b6001805463ffffffff8316919060109061269a908490700100000000000000000000000000000000900467ffffffffffffffff16615273565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555050565b60008060006126d3866000612b72565b905080612709576308c379a06000526020805278185361666543616c6c3a204e6f7420656e6f756768206761736058526064601cfd5b600080855160208701888b5af1979650505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526127779084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401612489565b505050565b600054610100900460ff16612813576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610add565b6001547801000000000000000000000000000000000000000000000000900467ffffffffffffffff166000036111b85760408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b6040805160c08082018352600080835260208301819052828401819052606083018190526080830181905260a083015260375483517fcc731b020000000000000000000000000000000000000000000000000000000081529351929373ffffffffffffffffffffffffffffffffffffffff9091169263cc731b02926004808401939192918290030181865afa15801561292c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f891906155d0565b600061296561295f8585612b90565b83612ba0565b90505b9392505050565b6000670de0b6b3a76400006129b06129878583615308565b61299990670de0b6b3a7640000615370565b6129ab85670de0b6b3a76400006153e4565b612baf565b6129ba90866153e4565b6129659190615308565b6000818310156129d45781612968565b5090919050565b6000805a90505b825a6129ee908361522c565b1015612777576129fd82615673565b91506129e2565b6000612a66826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612be09092919063ffffffff16565b8051909150156127775780806020019051810190612a8491906151aa565b612777576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610add565b60608180519060200120604051602001612b2c91815260200190565b6040516020818303038152906040529050919050565b6000612b6984612b53878686612bef565b8051602091820120825192909101919091201490565b95945050505050565b600080603f83619c4001026040850201603f5a021015949350505050565b6000818312156129d45781612968565b60008183126129d45781612968565b6000612968670de0b6b3a764000083612bc78661366d565b612bd191906153e4565b612bdb9190615308565b6138b1565b60606129658484600085613af0565b60606000845111612c5c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4d65726b6c65547269653a20656d707479206b657900000000000000000000006044820152606401610add565b6000612c6784613c86565b90506000612c7486613d72565b9050600084604051602001612c8b91815260200190565b60405160208183030381529060405290506000805b84518110156135e4576000858281518110612cbd57612cbd6156ab565b602002602001015190508451831115612d58576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4d65726b6c65547269653a206b657920696e646578206578636565647320746f60448201527f74616c206b6579206c656e6774680000000000000000000000000000000000006064820152608401610add565b82600003612e115780518051602091820120604051612da692612d8092910190815260200190565b604051602081830303815290604052858051602091820120825192909101919091201490565b612e0c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4d65726b6c65547269653a20696e76616c696420726f6f7420686173680000006044820152606401610add565b612f68565b805151602011612ec75780518051602091820120604051612e3b92612d8092910190815260200190565b612e0c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d65726b6c65547269653a20696e76616c6964206c6172676520696e7465726e60448201527f616c2068617368000000000000000000000000000000000000000000000000006064820152608401610add565b805184516020808701919091208251919092012014612f68576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4d65726b6c65547269653a20696e76616c696420696e7465726e616c206e6f6460448201527f65206861736800000000000000000000000000000000000000000000000000006064820152608401610add565b612f7460106001614fed565b8160200151510361315057845183036130e857612fae8160200151601081518110612fa157612fa16156ab565b6020026020010151613dd5565b96506000875111613041576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603b60248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286272616e63682900000000006064820152608401610add565b6001865161304f919061522c565b82146130dd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286272616e6368290000000000006064820152608401610add565b505050505050612968565b60008584815181106130fc576130fc6156ab565b602001015160f81c60f81b60f81c9050600082602001518260ff1681518110613127576131276156ab565b6020026020010151905061313a81613e89565b9550613147600186614fed565b945050506135d1565b60028160200151510361354957600061316882613eae565b905060008160008151811061317f5761317f6156ab565b016020015160f81c905060006131966002836156da565b6131a19060026156fc565b905060006131b2848360ff16613ed2565b905060006131c08a89613ed2565b905060006131ce8383613f08565b905080835114613260576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a20706174682072656d61696e646572206d7573742060448201527f736861726520616c6c206e6962626c65732077697468206b65790000000000006064820152608401610add565b60ff851660021480613275575060ff85166003145b15613464578082511461330a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f4d65726b6c65547269653a206b65792072656d61696e646572206d757374206260448201527f65206964656e746963616c20746f20706174682072656d61696e6465720000006064820152608401610add565b6133248760200151600181518110612fa157612fa16156ab565b9c5060008d51116133b7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286c65616629000000000000006064820152608401610add565b60018c516133c5919061522c565b8814613453576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286c6561662900000000000000006064820152608401610add565b505050505050505050505050612968565b60ff85161580613477575060ff85166001145b156134b6576134a38760200151600181518110613496576134966156ab565b6020026020010151613e89565b99506134af818a614fed565b985061353e565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4d65726b6c65547269653a2072656365697665642061206e6f6465207769746860448201527f20616e20756e6b6e6f776e2070726566697800000000000000000000000000006064820152608401610add565b5050505050506135d1565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4d65726b6c65547269653a20726563656976656420616e20756e70617273656160448201527f626c65206e6f64650000000000000000000000000000000000000000000000006064820152608401610add565b50806135dc81615673565b915050612ca0565b506040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4d65726b6c65547269653a2072616e206f7574206f662070726f6f6620656c6560448201527f6d656e74730000000000000000000000000000000000000000000000000000006064820152608401610add565b60008082136136d8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610add565b600060606136e584613fbc565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c182136138e257506000919050565b680755bf798b4a1bf1e58212613954576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4558505f4f564552464c4f5700000000000000000000000000000000000000006044820152606401610add565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b606082471015613b82576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610add565b73ffffffffffffffffffffffffffffffffffffffff85163b613c00576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610add565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051613c29919061571f565b60006040518083038185875af1925050503d8060008114613c66576040519150601f19603f3d011682016040523d82523d6000602084013e613c6b565b606091505b5091509150613c7b828286614092565b979650505050505050565b80516060908067ffffffffffffffff811115613ca457613ca4614a8b565b604051908082528060200260200182016040528015613ce957816020015b6040805180820190915260608082526020820152815260200190600190039081613cc25790505b50915060005b81811015613d6b576040518060400160405280858381518110613d1457613d146156ab565b60200260200101518152602001613d43868481518110613d3657613d366156ab565b60200260200101516140e5565b815250838281518110613d5857613d586156ab565b6020908102919091010152600101613cef565b5050919050565b606080604051905082518060011b603f8101601f1916830160405280835250602084016020830160005b83811015613dca578060011b82018184015160001a8060041c8253600f811660018301535050600101613d9c565b509295945050505050565b60606000806000613de5856140f8565b919450925090506000816001811115613e0057613e0061573b565b14613e37576040517f1ff9b2e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613e418284614fed565b855114613e7a576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612b6985602001518484614596565b60606020826000015110613ea557613ea082613dd5565b610ff2565b610ff28261462a565b6060610ff2613ecd8360200151600081518110612fa157612fa16156ab565b613d72565b606082518210613ef15750604080516020810190915260008152610ff2565b6129688383848651613f03919061522c565b614640565b6000808251845110613f1b578251613f1e565b83515b90505b8082108015613fa55750828281518110613f3d57613f3d6156ab565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916848381518110613f7c57613f7c6156ab565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b15613fb557816001019150613f21565b5092915050565b6000808211614027576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610add565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b606083156140a1575081612968565b8251156140b15782518084602001fd5b816040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610add9190614e1d565b6060610ff26140f383614818565b614885565b6000806000836000015160000361413b576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020840151805160001a607f811161416057600060016000945094509450505061458f565b60b7811161427657600061417560808361522c565b9050808760000151116141b4576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001838101517fff0000000000000000000000000000000000000000000000000000000000000016908214801561422c57507f80000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008216105b15614263576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506001955093506000925061458f915050565b60bf81116143d457600061428b60b78361522c565b9050808760000151116142ca576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff0000000000000000000000000000000000000000000000000000000000000016600081900361432c576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c60378111614374576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61437e8184614fed565b8951116143b7576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6143c2836001614fed565b975095506000945061458f9350505050565b60f781116144395760006143e960c08361522c565b905080876000015111614428576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60019550935084925061458f915050565b600061444660f78361522c565b905080876000015111614485576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff000000000000000000000000000000000000000000000000000000000000001660008190036144e7576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c6037811161452f576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6145398184614fed565b895111614572576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61457d836001614fed565b975095506001945061458f9350505050565b9193909250565b60608167ffffffffffffffff8111156145b1576145b1614a8b565b6040519080825280601f01601f1916602001820160405280156145db576020820181803683370190505b50905081156129685760006145f08486614fed565b90506020820160005b848110156146115782810151828201526020016145f9565b84811115614620576000858301525b5050509392505050565b6060610ff2826020015160008460000151614596565b60608182601f0110156146af576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610add565b82828401101561471b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610add565b81830184511015614788576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401610add565b6060821580156147a7576040519150600082526020820160405261480f565b6040519150601f8416801560200281840101858101878315602002848b0101015b818310156147e05780518352602092830192016147c8565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b60408051808201909152600080825260208201528151600003614867576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50604080518082019091528151815260209182019181019190915290565b60606000806000614895856140f8565b9194509250905060018160018111156148b0576148b061573b565b146148e7576040517f4b9c6abe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84516148f38385614fed565b1461492a576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808252610420820190925290816020015b60408051808201909152600080825260208201528152602001906001900390816149415790505093506000835b8651811015614a2f576000806149b46040518060400160405280858c60000151614998919061522c565b8152602001858c602001516149ad9190614fed565b90526140f8565b5091509150604051806040016040528083836149d09190614fed565b8152602001848b602001516149e59190614fed565b8152508885815181106149fa576149fa6156ab565b6020908102919091010152614a10600185614fed565b9350614a1c8183614fed565b614a269084614fed565b9250505061496e565b50845250919392505050565b73ffffffffffffffffffffffffffffffffffffffff81168114614a5d57600080fd5b50565b803567ffffffffffffffff81168114614a7857600080fd5b919050565b8015158114614a5d57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614b0157614b01614a8b565b604052919050565b600082601f830112614b1a57600080fd5b813567ffffffffffffffff811115614b3457614b34614a8b565b614b6560207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614aba565b818152846020838601011115614b7a57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060008060c08789031215614bb057600080fd5b8635614bbb81614a3b565b95506020870135945060408701359350614bd760608801614a60565b92506080870135614be781614a7d565b915060a087013567ffffffffffffffff811115614c0357600080fd5b614c0f89828a01614b09565b9150509295509295509295565b600060c08284031215614c2e57600080fd5b60405160c0810167ffffffffffffffff8282108183111715614c5257614c52614a8b565b816040528293508435835260208501359150614c6d82614a3b565b81602084015260408501359150614c8382614a3b565b816040840152606085013560608401526080850135608084015260a0850135915080821115614cb157600080fd5b50614cbe85828601614b09565b60a0830152505092915050565b600080600080600085870360e0811215614ce457600080fd5b863567ffffffffffffffff80821115614cfc57600080fd5b614d088a838b01614c1c565b97506020890135965060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc084011215614d4157600080fd5b60408901955060c0890135925080831115614d5b57600080fd5b828901925089601f840112614d6f57600080fd5b8235915080821115614d8057600080fd5b508860208260051b8401011115614d9657600080fd5b959894975092955050506020019190565b60005b83811015614dc2578181015183820152602001614daa565b83811115611ef75750506000910152565b60008151808452614deb816020860160208601614da7565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006129686020830184614dd3565b600060208284031215614e4257600080fd5b5035919050565b60ff81168114614a5d57600080fd5b60008060008060808587031215614e6e57600080fd5b8435614e7981614a3b565b93506020850135614e8981614e49565b93969395505050506040820135916060013590565b600060208284031215614eb057600080fd5b813567ffffffffffffffff811115614ec757600080fd5b614ed384828501614c1c565b949350505050565b600060208284031215614eed57600080fd5b61296882614a60565b600080600060608486031215614f0b57600080fd5b8335614f1681614a3b565b92506020840135614f2681614a3b565b91506040840135614f3681614a3b565b809150509250925092565b600080600080600060a08688031215614f5957600080fd5b8535614f6481614a3b565b945060208601359350614f7960408701614a60565b92506060860135614f8981614a7d565b9150608086013567ffffffffffffffff811115614fa557600080fd5b614fb188828901614b09565b9150509295509295909350565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561500057615000614fbe565b500190565b60006020828403121561501757600080fd5b5051919050565b60006020828403121561503057600080fd5b815161296881614a3b565b80516fffffffffffffffffffffffffffffffff81168114614a7857600080fd5b60006060828403121561506d57600080fd5b6040516060810181811067ffffffffffffffff8211171561509057615090614a8b565b604052825181526150a36020840161503b565b60208201526150b46040840161503b565b60408201529392505050565b6000608082840312156150d257600080fd5b6040516080810181811067ffffffffffffffff821117156150f5576150f5614a8b565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b600067ffffffffffffffff8084111561514157615141614a8b565b8360051b6020615152818301614aba565b86815291850191818101903684111561516a57600080fd5b865b8481101561519e578035868111156151845760008081fd5b61519036828b01614b09565b84525091830191830161516c565b50979650505050505050565b6000602082840312156151bc57600080fd5b815161296881614a7d565b8581528460208201527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b16604082015282151560f81b60488201526000825161521b816049850160208701614da7565b919091016049019695505050505050565b60008282101561523e5761523e614fbe565b500390565b600067ffffffffffffffff8083168185168183048111821515161561526a5761526a614fbe565b02949350505050565b600067ffffffffffffffff80831681851680830382111561529657615296614fbe565b01949350505050565b600080604083850312156152b257600080fd5b82516152bd81614a3b565b60208401519092506152ce81614e49565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082615317576153176152d9565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f80000000000000000000000000000000000000000000000000000000000000008314161561536b5761536b614fbe565b500590565b6000808312837f8000000000000000000000000000000000000000000000000000000000000000018312811516156153aa576153aa614fbe565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0183138116156153de576153de614fbe565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60008413600084138583048511828216161561542557615425614fbe565b7f8000000000000000000000000000000000000000000000000000000000000000600087128682058812818416161561546057615460614fbe565b6000871292508782058712848416161561547c5761547c614fbe565b8785058712818416161561549257615492614fbe565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038413811516156154da576154da614fbe565b827f800000000000000000000000000000000000000000000000000000000000000003841281161561550e5761550e614fbe565b50500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561554c5761554c614fbe565b500290565b600082615560576155606152d9565b500490565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a08301526155b060c0830184614dd3565b98975050505050505050565b805163ffffffff81168114614a7857600080fd5b600060c082840312156155e257600080fd5b60405160c0810181811067ffffffffffffffff8211171561560557615605614a8b565b604052615611836155bc565b8152602083015161562181614e49565b6020820152604083015161563481614e49565b6040820152615645606084016155bc565b6060820152615656608084016155bc565b608082015261566760a0840161503b565b60a08201529392505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036156a4576156a4614fbe565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060ff8316806156ed576156ed6152d9565b8060ff84160691505092915050565b600060ff821660ff84168082101561571657615716614fbe565b90039392505050565b60008251615731818460208701614da7565b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea164736f6c634300080f000a", - "initialized": true, - "kind": "Create", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xbdD90485FCbcac869D5b5752179815a3103d8131", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xbdD90485FCbcac869D5b5752179815a3103d8131", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xbdD90485FCbcac869D5b5752179815a3103d8131", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xbdD90485FCbcac869D5b5752179815a3103d8131", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xbdD90485FCbcac869D5b5752179815a3103d8131", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xbdD90485FCbcac869D5b5752179815a3103d8131", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xbdD90485FCbcac869D5b5752179815a3103d8131", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000036" - }, - { - "account": "0xbdD90485FCbcac869D5b5752179815a3103d8131", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000036" - }, - { - "account": "0xbdD90485FCbcac869D5b5752179815a3103d8131", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000037" - }, - { - "account": "0xbdD90485FCbcac869D5b5752179815a3103d8131", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000037" - }, - { - "account": "0xbdD90485FCbcac869D5b5752179815a3103d8131", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000035" - }, - { - "account": "0xbdD90485FCbcac869D5b5752179815a3103d8131", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000035" - }, - { - "account": "0xbdD90485FCbcac869D5b5752179815a3103d8131", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000032" - }, - { - "account": "0xbdD90485FCbcac869D5b5752179815a3103d8131", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000032" - }, - { - "account": "0xbdD90485FCbcac869D5b5752179815a3103d8131", - "isWrite": true, - "newValue": "0x000000000000000000000000000000000000000000000000000000000000dead", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000032" - }, - { - "account": "0xbdD90485FCbcac869D5b5752179815a3103d8131", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xbdD90485FCbcac869D5b5752179815a3103d8131", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000001" - }, - { - "account": "0xbdD90485FCbcac869D5b5752179815a3103d8131", - "isWrite": true, - "newValue": "0x000000000000000100000000000000000000000000000000000000003b9aca00", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000001" - }, - { - "account": "0xbdD90485FCbcac869D5b5752179815a3103d8131", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xbdD90485FCbcac869D5b5752179815a3103d8131", - "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": "0x000000000000000000000000000000000000000000000000000000000000000f" - } - ], - "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": "0xbdD90485FCbcac869D5b5752179815a3103d8131", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x9b5f694a", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xbdD90485FCbcac869D5b5752179815a3103d8131", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000036" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xbdD90485FCbcac869D5b5752179815a3103d8131", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x33d7e2bd", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xbdD90485FCbcac869D5b5752179815a3103d8131", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000037" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xbdD90485FCbcac869D5b5752179815a3103d8131", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x35e80ab3", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xbdD90485FCbcac869D5b5752179815a3103d8131", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000035" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xbdD90485FCbcac869D5b5752179815a3103d8131", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x9bf62d82", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xbdD90485FCbcac869D5b5752179815a3103d8131", - "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": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x638627e586f5e36fe67a77519503a7c6da22f92b150d3c6055fd40bdcfe9ffd160806040523480156200001157600080fd5b50620000256001806000808080806200002b565b62000328565b600054610100900460ff16158080156200004c5750600054600160ff909116105b806200007c575062000069306200031960201b6200135d1760201c565b1580156200007c575060005460ff166001145b620000e55760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000109576000805461ff0019166101001790555b60008811620001815760405162461bcd60e51b815260206004820152603a60248201527f4c324f75747075744f7261636c653a207375626d697373696f6e20696e74657260448201527f76616c206d7573742062652067726561746572207468616e20300000000000006064820152608401620000dc565b60008711620001f95760405162461bcd60e51b815260206004820152603460248201527f4c324f75747075744f7261636c653a204c3220626c6f636b2074696d65206d7560448201527f73742062652067726561746572207468616e20300000000000000000000000006064820152608401620000dc565b428511156200027f5760405162461bcd60e51b8152602060048201526044602482018190527f4c324f75747075744f7261636c653a207374617274696e67204c322074696d65908201527f7374616d70206d757374206265206c657373207468616e2063757272656e742060648201526374696d6560e01b608482015260a401620000dc565b6004889055600587905560018690556002859055600780546001600160a01b038087166001600160a01b0319928316179092556006805492861692909116919091179055600882905580156200030f576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b6001600160a01b03163b151590565b6115d580620003386000396000f3fe60806040526004361061018a5760003560e01c806389c44cbb116100d6578063ce5db8d61161007f578063dcec334811610059578063dcec33481461049b578063e1a41bcf146104b0578063f4daa291146104c657600080fd5b8063ce5db8d614610445578063cf8e5cf01461045b578063d1de856c1461047b57600080fd5b8063a25ae557116100b0578063a25ae55714610391578063a8e4fb90146103ed578063bffa7f0f1461041a57600080fd5b806389c44cbb1461034857806393991af3146103685780639aaab6481461037e57600080fd5b806369f16eec1161013857806370872aa51161011257806370872aa5146102fc5780637f00642014610312578063887862721461033257600080fd5b806369f16eec146102a75780636abcf563146102bc5780636b4d98dd146102d157600080fd5b8063529933df11610169578063529933df146101ea578063534db0e2146101ff57806354fd4d501461025157600080fd5b80622134cc1461018f5780631c89c97d146101b35780634599c788146101d5575b600080fd5b34801561019b57600080fd5b506005545b6040519081526020015b60405180910390f35b3480156101bf57600080fd5b506101d36101ce3660046113a2565b6104db565b005b3480156101e157600080fd5b506101a06108b6565b3480156101f657600080fd5b506004546101a0565b34801561020b57600080fd5b5060065461022c9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101aa565b34801561025d57600080fd5b5061029a6040518060400160405280600581526020017f312e382e3000000000000000000000000000000000000000000000000000000081525081565b6040516101aa9190611405565b3480156102b357600080fd5b506101a0610929565b3480156102c857600080fd5b506003546101a0565b3480156102dd57600080fd5b5060065473ffffffffffffffffffffffffffffffffffffffff1661022c565b34801561030857600080fd5b506101a060015481565b34801561031e57600080fd5b506101a061032d366004611478565b61093b565b34801561033e57600080fd5b506101a060025481565b34801561035457600080fd5b506101d3610363366004611478565b610b4f565b34801561037457600080fd5b506101a060055481565b6101d361038c366004611491565b610de9565b34801561039d57600080fd5b506103b16103ac366004611478565b61124a565b60408051825181526020808401516fffffffffffffffffffffffffffffffff9081169183019190915292820151909216908201526060016101aa565b3480156103f957600080fd5b5060075461022c9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561042657600080fd5b5060075473ffffffffffffffffffffffffffffffffffffffff1661022c565b34801561045157600080fd5b506101a060085481565b34801561046757600080fd5b506103b1610476366004611478565b6112de565b34801561048757600080fd5b506101a0610496366004611478565b611316565b3480156104a757600080fd5b506101a0611346565b3480156104bc57600080fd5b506101a060045481565b3480156104d257600080fd5b506008546101a0565b600054610100900460ff16158080156104fb5750600054600160ff909116105b806105155750303b158015610515575060005460ff166001145b6105a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561060457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b60008811610694576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4c324f75747075744f7261636c653a207375626d697373696f6e20696e74657260448201527f76616c206d7573742062652067726561746572207468616e2030000000000000606482015260840161059d565b60008711610724576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4c324f75747075744f7261636c653a204c3220626c6f636b2074696d65206d7560448201527f73742062652067726561746572207468616e2030000000000000000000000000606482015260840161059d565b428511156107db576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526044602482018190527f4c324f75747075744f7261636c653a207374617274696e67204c322074696d65908201527f7374616d70206d757374206265206c657373207468616e2063757272656e742060648201527f74696d6500000000000000000000000000000000000000000000000000000000608482015260a40161059d565b60048890556005879055600186905560028590556007805473ffffffffffffffffffffffffffffffffffffffff8087167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179092556006805492861692909116919091179055600882905580156108ac57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b6003546000901561092057600380546108d1906001906114f2565b815481106108e1576108e1611509565b600091825260209091206002909102016001015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16919050565b6001545b905090565b600354600090610924906001906114f2565b60006109456108b6565b8211156109fa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a2063616e6e6f7420676574206f7574707560448201527f7420666f72206120626c6f636b207468617420686173206e6f74206265656e2060648201527f70726f706f736564000000000000000000000000000000000000000000000000608482015260a40161059d565b600354610aaf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f4c324f75747075744f7261636c653a2063616e6e6f7420676574206f7574707560448201527f74206173206e6f206f7574707574732068617665206265656e2070726f706f7360648201527f6564207965740000000000000000000000000000000000000000000000000000608482015260a40161059d565b6003546000905b80821015610b485760006002610acc8385611538565b610ad69190611550565b90508460038281548110610aec57610aec611509565b600091825260209091206002909102016001015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff161015610b3e57610b37816001611538565b9250610b42565b8091505b50610ab6565b5092915050565b60065473ffffffffffffffffffffffffffffffffffffffff163314610bf6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f4c324f75747075744f7261636c653a206f6e6c7920746865206368616c6c656e60448201527f67657220616464726573732063616e2064656c657465206f7574707574730000606482015260840161059d565b6003548110610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4c324f75747075744f7261636c653a2063616e6e6f742064656c657465206f7560448201527f747075747320616674657220746865206c6174657374206f757470757420696e60648201527f6465780000000000000000000000000000000000000000000000000000000000608482015260a40161059d565b60085460038281548110610cc357610cc3611509565b6000918252602090912060016002909202010154610cf3906fffffffffffffffffffffffffffffffff16426114f2565b10610da6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f4c324f75747075744f7261636c653a2063616e6e6f742064656c657465206f7560448201527f74707574732074686174206861766520616c7265616479206265656e2066696e60648201527f616c697a65640000000000000000000000000000000000000000000000000000608482015260a40161059d565b6000610db160035490565b90508160035581817f4ee37ac2c786ec85e87592d3c5c8a1dd66f8496dda3f125d9ea8ca5f657629b660405160405180910390a35050565b60075473ffffffffffffffffffffffffffffffffffffffff163314610eb6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f4c324f75747075744f7261636c653a206f6e6c79207468652070726f706f736560448201527f7220616464726573732063616e2070726f706f7365206e6577206f757470757460648201527f7300000000000000000000000000000000000000000000000000000000000000608482015260a40161059d565b610ebe611346565b8314610f72576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a20626c6f636b206e756d626572206d757360448201527f7420626520657175616c20746f206e65787420657870656374656420626c6f6360648201527f6b206e756d626572000000000000000000000000000000000000000000000000608482015260a40161059d565b42610f7c84611316565b10611009576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f4c324f75747075744f7261636c653a2063616e6e6f742070726f706f7365204c60448201527f32206f757470757420696e207468652066757475726500000000000000000000606482015260840161059d565b83611096576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4c324f75747075744f7261636c653a204c32206f75747075742070726f706f7360448201527f616c2063616e6e6f7420626520746865207a65726f2068617368000000000000606482015260840161059d565b81156111525781814014611152576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4c324f75747075744f7261636c653a20626c6f636b206861736820646f65732060448201527f6e6f74206d61746368207468652068617368206174207468652065787065637460648201527f6564206865696768740000000000000000000000000000000000000000000000608482015260a40161059d565b8261115c60035490565b857fa7aaf2512769da4e444e3de247be2564225c2e7a8f74cfe528e46e17d24868e24260405161118e91815260200190565b60405180910390a45050604080516060810182529283526fffffffffffffffffffffffffffffffff4281166020850190815292811691840191825260038054600181018255600091909152935160029094027fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b810194909455915190518216700100000000000000000000000000000000029116177fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85c90910155565b60408051606081018252600080825260208201819052918101919091526003828154811061127a5761127a611509565b600091825260209182902060408051606081018252600290930290910180548352600101546fffffffffffffffffffffffffffffffff8082169484019490945270010000000000000000000000000000000090049092169181019190915292915050565b604080516060810182526000808252602082018190529181019190915260036113068361093b565b8154811061127a5761127a611509565b60006005546001548361132991906114f2565b611333919061158b565b6002546113409190611538565b92915050565b60006004546113536108b6565b6109249190611538565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b803573ffffffffffffffffffffffffffffffffffffffff8116811461139d57600080fd5b919050565b600080600080600080600060e0888a0312156113bd57600080fd5b873596506020880135955060408801359450606088013593506113e260808901611379565b92506113f060a08901611379565b915060c0880135905092959891949750929550565b600060208083528351808285015260005b8181101561143257858101830151858201604001528201611416565b81811115611444576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b60006020828403121561148a57600080fd5b5035919050565b600080600080608085870312156114a757600080fd5b5050823594602084013594506040840135936060013592509050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015611504576115046114c3565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000821982111561154b5761154b6114c3565b500190565b600082611586577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156115c3576115c36114c3565b50029056fea164736f6c634300080f000a", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "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": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x3c9f397c", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000043" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x3c9f397c", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000043" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x493f862b", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x000000000000000000000000000000000000000000000000000000000000004a" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xbf653a5c", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x000000000000000000000000000000000000000000000000000000000000000c", - "previousValue": "0x000000000000000000000000000000000000000000000000000000000000000c", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000041" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x952b2797", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000006", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000006", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000042" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x638627e586f5e36fe67a77519503a7c6da22f92b150d3c6055fd40bdcfe9ffd160c06040523480156200001157600080fd5b5060405162006010380380620060108339810160408190526200003491620002f2565b608082905260a08190526200004d600080808062000055565b505062000317565b600054610100900460ff1615808015620000765750600054600160ff909116105b80620000a6575062000093306200022460201b620023cd1760201c565b158015620000a6575060005460ff166001145b6200010f5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000133576000805461ff0019166101001790555b603880546001600160a01b03199081166001600160a01b03888116919091179092556037805490911686831617905560358054610100600160a81b0319166101008684160217905560325416620001cc576032805461dead6001600160a01b0319909116179055603b80546001600160601b031916640100000000426001600160401b03160263ffffffff19161763ffffffff84161790555b620001d662000233565b80156200021d576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b6001600160a01b03163b151590565b600054610100900460ff16620002a05760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b606482015260840162000106565b600154600160c01b90046001600160401b0316600003620002f05760408051606081018252633b9aca0080825260006020830152436001600160401b031691909201819052600160c01b02176001555b565b600080604083850312156200030657600080fd5b505080516020909101519092909150565b60805160a051615cc56200034b6000396000818161051a0152611b280152600081816106a601526118120152615cc56000f3fe6080604052600436106101d15760003560e01c80637fc48504116100f7578063a35d99df11610095578063bf653a5c11610064578063bf653a5c14610697578063cff0ab96146106ca578063e9e05c421461076b578063f2b4e6171461077e57600080fd5b8063a35d99df1461059b578063a3860f48146105bb578063b69ef8a8146105db578063bb2c727e146105f057600080fd5b80638e819e54116100d15780638e819e54146104eb578063952b27971461050b5780639bf62d821461053e578063a14238e71461056b57600080fd5b80637fc48504146104ab5780638b4c40b0146101f65780638c3152e9146104cb57600080fd5b80634870496f1161016f5780635c975abb1161013e5780635c975abb1461043657806371c1566e1461044b57806371cfaa3f1461046b5780637d6be8dc1461048b57600080fd5b80634870496f1461034d5780634fd0434c1461036d578063513747ab146103af57806354fd4d50146103ea57600080fd5b80633c9f397c116101ab5780633c9f397c146102a657806343ca1c50146102d8578063452a9320146102f857806345884d321461030d57600080fd5b8063149f2f22146101fd57806333d7e2bd1461021d57806335e80ab31461027457600080fd5b366101f8576101f63334620186a06000604051806020016040528060008152506107ab565b005b600080fd5b34801561020957600080fd5b506101f6610218366004614fe6565b610850565b34801561022957600080fd5b5060375461024a9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561028057600080fd5b5060355461024a90610100900473ffffffffffffffffffffffffffffffffffffffff1681565b3480156102b257600080fd5b50603b546102c39063ffffffff1681565b60405163ffffffff909116815260200161026b565b3480156102e457600080fd5b506101f66102f336600461511c565b610a91565b34801561030457600080fd5b5061024a610f31565b34801561031957600080fd5b5061033d61032836600461516e565b603a6020526000908152604090205460ff1681565b604051901515815260200161026b565b34801561035957600080fd5b506101f661036836600461518b565b610fc9565b34801561037957600080fd5b50603b5461039690640100000000900467ffffffffffffffff1681565b60405167ffffffffffffffff909116815260200161026b565b3480156103bb57600080fd5b506103dc6103ca366004615267565b6000908152603c602052604090205490565b60405190815260200161026b565b3480156103f657600080fd5b50604080518082018252600d81527f332e31312e302d626574612e32000000000000000000000000000000000000006020820152905161026b91906152f6565b34801561044257600080fd5b5061033d611531565b34801561045757600080fd5b506101f6610466366004615309565b6115c4565b34801561047757600080fd5b506101f661048636600461533d565b611c7f565b34801561049757600080fd5b506101f66104a636600461516e565b611e3f565b3480156104b757600080fd5b506101f66104c6366004615395565b611f22565b3480156104d757600080fd5b506101f66104e63660046153b2565b61200e565b3480156104f757600080fd5b506101f66105063660046153ef565b61205a565b34801561051757600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006103dc565b34801561054a57600080fd5b5060325461024a9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561057757600080fd5b5061033d610586366004615267565b60336020526000908152604090205460ff1681565b3480156105a757600080fd5b506103966105b636600461544b565b61230f565b3480156105c757600080fd5b5061024a6105d6366004615468565b61232e565b3480156105e757600080fd5b506103dc612373565b3480156105fc57600080fd5b5061066261060b366004615309565b603960209081526000928352604080842090915290825290205473ffffffffffffffffffffffffffffffffffffffff81169074010000000000000000000000000000000000000000900467ffffffffffffffff1682565b6040805173ffffffffffffffffffffffffffffffffffffffff909316835267ffffffffffffffff90911660208301520161026b565b3480156106a357600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006103dc565b3480156106d657600080fd5b50600154610732906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff928316602085015291169082015260600161026b565b6101f661077936600461548a565b6107ab565b34801561078a57600080fd5b5060385461024a9073ffffffffffffffffffffffffffffffffffffffff1681565b8260005a905060006107bb6123e9565b50905073ffffffffffffffffffffffffffffffffffffffff811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee148015906107f757503415155b1561082e576040517ff2365b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61083c883489898989612486565b506108478282612632565b50505050505050565b8260005a905060006108606123e9565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8216016108d2576040517f0eaf3c0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87603d60008282546108e49190615538565b90915550506040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610956573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097a9190615550565b905061099e73ffffffffffffffffffffffffffffffffffffffff831633308c6128ff565b6109a88982615538565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015610a12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a369190615550565b14610a6d576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a7b8a8a8a8a8a8a612486565b5050610a878282612632565b5050505050505050565b610a99611531565b15610ad0576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60325473ffffffffffffffffffffffffffffffffffffffff1661dead14610b23576040517f9396d15600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610b2e836129e1565b9050610b3a81836115c4565b6000818152603360209081526040822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558401516032805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff000000000000000000000000000000000000000090921691909117905580610bc56123e9565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff821601610c2857610c218560400151866080015187606001518860a00151612a2e565b9150610e7b565b8073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff1603610c91576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606085015115610e52578460600151603d6000828254610cb19190615569565b90915550506040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610d23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d479190615550565b9050610d7c866040015187606001518473ffffffffffffffffffffffffffffffffffffffff16612a8c9092919063ffffffff16565b6060860151610d8b9082615569565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015610df5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e199190615550565b14610e50576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60a08501515115610e7657610c218560400151866080015160008860a00151612a2e565b600191505b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405183907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b90610edd90851515815260200190565b60405180910390a281158015610ef35750326001145b15610f2a576040517feeae4ed300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa158015610fa0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc49190615580565b905090565b610fd1611531565b15611008576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff1603611071576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6038546040517fbb8aa1fc00000000000000000000000000000000000000000000000000000000815260048101869052600091829173ffffffffffffffffffffffffffffffffffffffff9091169063bb8aa1fc90602401606060405180830381865afa1580156110e5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611109919061559d565b925050915060008173ffffffffffffffffffffffffffffffffffffffff1663bcef3b556040518163ffffffff1660e01b8152600401602060405180830381865afa15801561115b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061117f9190615550565b603b5490915063ffffffff8481169116146111c6576040517f27a10cc200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111dd6111d8368890038801886155ea565b612ae7565b8114611215576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611220896129e1565b905060018373ffffffffffffffffffffffffffffffffffffffff1663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa15801561126f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611293919061567f565b60028111156112a4576112a4615650565b036112db576040517fd357347400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051602081018390526000918101829052606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012090830181905292506113a49101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f010000000000000000000000000000000000000000000000000000000000000060208301529061139a898b6156a0565b8b60400135612b26565b15156000036113df576040517fb05e92fa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051808201825273ffffffffffffffffffffffffffffffffffffffff808716825267ffffffffffffffff4281166020808501918252600088815260398252868120338252825286812095518654935190941674010000000000000000000000000000000000000000027fffffffff0000000000000000000000000000000000000000000000000000000090931693851693909317919091179093558d840151928e01519351928216939091169185917f67a6208cfcc0801d50f6cbe764733f4fddf66ac0b04442061a8a8c0cb6b63f6291a4604051339083907f798f9f13695f8f045aa5f80ed8efebb695f3c7fe65da381969f2f28bf3c60b9790600090a3506000908152603c602090815260408220805460018101825590835291200180547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790555050505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115a0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc49190615724565b600082815260396020908152604080832073ffffffffffffffffffffffffffffffffffffffff85811685529083528184208251808401845290549182168082527401000000000000000000000000000000000000000090920467ffffffffffffffff1681850152818552603a90935292205490919060ff1615611673576040517f09550c7700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b816020015167ffffffffffffffff166000036116bb576040517f94efd49b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061173c8273ffffffffffffffffffffffffffffffffffffffff1663cf09e0d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561170b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061172f9190615741565b67ffffffffffffffff1690565b90508067ffffffffffffffff16836020015167ffffffffffffffff1611611810576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604e60248201527f4f7074696d69736d506f7274616c3a207769746864726177616c2074696d657360448201527f74616d70206c657373207468616e20646973707574652067616d65206372656160648201527f74696f6e2074696d657374616d70000000000000000000000000000000000000608482015260a4015b60405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000000836020015167ffffffffffffffff164261184b9190615569565b116118d8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a2070726f76656e2077697468647261776160448201527f6c20686173206e6f74206d6174757265642079657400000000000000000000006064820152608401611807565b60028273ffffffffffffffffffffffffffffffffffffffff1663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611925573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611949919061567f565b600281111561195a5761195a615650565b14611991576040517fa080a3c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603b5463ffffffff1663ffffffff16611a1b8373ffffffffffffffffffffffffffffffffffffffff1663bbdc02db6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119ee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a12919061575e565b63ffffffff1690565b63ffffffff1614611a58576040517f27a10cc200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603b5467ffffffffffffffff64010000000090910481169082161015611b26576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604b60248201527f4f7074696d69736d506f7274616c3a20646973707574652067616d652063726560448201527f61746564206265666f7265207265737065637465642067616d6520747970652060648201527f7761732075706461746564000000000000000000000000000000000000000000608482015260a401611807565b7f0000000000000000000000000000000000000000000000000000000000000000611b958373ffffffffffffffffffffffffffffffffffffffff166319effeb46040518163ffffffff1660e01b8152600401602060405180830381865afa15801561170b573d6000803e3d6000fd5b611ba99067ffffffffffffffff1642615569565b11611c36576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4f7074696d69736d506f7274616c3a206f75747075742070726f706f73616c2060448201527f696e206169722d676170000000000000000000000000000000000000000000006064820152608401611807565b60008581526033602052604090205460ff1615610f2a576040517f475a253500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60375473ffffffffffffffffffffffffffffffffffffffff163314611cd0576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611cdc62030d40612b4a565b60405173ffffffffffffffffffffffffffffffffffffffff8516602482015260ff8416604482015260648101839052608481018290526000907342000000000000000000000000000000000000159073deaddeaddeaddeaddeaddeaddeaddeaddead0001907fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32908490819062030d4090829060a401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f71cfaa3f000000000000000000000000000000000000000000000000000000001790529051611df99695949392910161577b565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815290829052611e31916152f6565b60405180910390a450505050565b611e47610f31565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611eab576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81166000818152603a602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055517f192c289026d59a41a27f5aea08f3969b57931b0589202d14f4368cded95d3cda9190a250565b611f2a610f31565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611f8e576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603b805463ffffffff83167fffffffffffffffffffffffffffffffffffffffff00000000000000000000000090911681176401000000004267ffffffffffffffff90811682029290921793849055604051930416917f049fe9dd413cdf037cce27011cc1790c753118272f3630e6e8bdfa5e8208176090600090a350565b565b612016611531565b1561204d576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6120578133610a91565b50565b600054610100900460ff161580801561207a5750600054600160ff909116105b806120945750303b158015612094575060005460ff166001145b612120576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401611807565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561217e57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603880547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff8881169190911790925560378054909116868316179055603580547fffffffffffffffffffffff0000000000000000000000000000000000000000ff16610100868416021790556032541661229e576032805461dead7fffffffffffffffffffffffff0000000000000000000000000000000000000000909116179055603b80547fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166401000000004267ffffffffffffffff16027fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000161763ffffffff84161790555b6122a6612bac565b8015610f2a57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050565b600061231c8260106157e0565b61232890615208615810565b92915050565b603c602052816000526040600020818154811061234a57600080fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff169150829050565b60008061237e6123e9565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8216016123c5574791505090565b5050603d5490565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b603754604080517f4397dfef0000000000000000000000000000000000000000000000000000000081528151600093849373ffffffffffffffffffffffffffffffffffffffff90911692634397dfef92600480830193928290030181865afa158015612459573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061247d919061583c565b90939092509050565b8180156124a8575073ffffffffffffffffffffffffffffffffffffffff861615155b156124df576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6124e9815161230f565b67ffffffffffffffff168367ffffffffffffffff161015612536576040517f4929b80800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6201d4c081511115612574576040517f73052b0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b33328114612595575033731111000000000000000000000000000000001111015b600086868686866040516020016125b095949392919061577b565b604051602081830303815290604052905060008873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c328460405161262091906152f6565b60405180910390a45050505050505050565b600154600090612668907801000000000000000000000000000000000000000000000000900467ffffffffffffffff1643615569565b90506000612674612cbf565b90506000816020015160ff16826000015163ffffffff16612695919061589a565b905082156127cc576001546000906126cc908390700100000000000000000000000000000000900467ffffffffffffffff16615902565b90506000836040015160ff16836126e39190615976565b6001546127039084906fffffffffffffffffffffffffffffffff16615976565b61270d919061589a565b60015490915060009061275e906127379084906fffffffffffffffffffffffffffffffff16615a32565b866060015163ffffffff168760a001516fffffffffffffffffffffffffffffffff16612d80565b9050600186111561278d5761278a61273782876040015160ff1660018a6127859190615569565b612d9f565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b600180548691906010906127ff908490700100000000000000000000000000000000900467ffffffffffffffff16615810565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550816000015163ffffffff16600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff16131561288c576040517f77ebef4d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001546000906128b8906fffffffffffffffffffffffffffffffff1667ffffffffffffffff8816615aa6565b905060006128ca48633b9aca00612df4565b6128d49083615ae3565b905060005a6128e39088615569565b905080821115610a8757610a876128fa8284615569565b612e0b565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526129db9085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612e34565b50505050565b80516020808301516040808501516060860151608087015160a08801519351600097612a11979096959101615af7565b604051602081830303815290604052805190602001209050919050565b6000806000612a3e866000612f40565b905080612a74576308c379a06000526020805278185361666543616c6c3a204e6f7420656e6f756768206761736058526064601cfd5b600080855160208701888b5af1979650505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052612ae29084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401612959565b505050565b60008160000151826020015183604001518460600151604051602001612a11949392919093845260208401929092526040830152606082015260800190565b600080612b3286612f5e565b9050612b4081868686612f90565b9695505050505050565b6001805463ffffffff83169190601090612b83908490700100000000000000000000000000000000900467ffffffffffffffff16615810565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555050565b600054610100900460ff16612c43576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401611807565b6001547801000000000000000000000000000000000000000000000000900467ffffffffffffffff1660000361200c5760408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b6040805160c08082018352600080835260208301819052828401819052606083018190526080830181905260a083015260375483517fcc731b020000000000000000000000000000000000000000000000000000000081529351929373ffffffffffffffffffffffffffffffffffffffff9091169263cc731b02926004808401939192918290030181865afa158015612d5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc49190615b4e565b6000612d95612d8f8585612fc0565b83612fd0565b90505b9392505050565b6000670de0b6b3a7640000612de0612db7858361589a565b612dc990670de0b6b3a7640000615902565b612ddb85670de0b6b3a7640000615976565b612fdf565b612dea9086615976565b612d95919061589a565b600081831015612e045781612d98565b5090919050565b6000805a90505b825a612e1e9083615569565b1015612ae257612e2d82615bf0565b9150612e12565b6000612e96826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166130109092919063ffffffff16565b805190915015612ae25780806020019051810190612eb49190615724565b612ae2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401611807565b600080603f83619c4001026040850201603f5a021015949350505050565b60608180519060200120604051602001612f7a91815260200190565b6040516020818303038152906040529050919050565b6000612fb784612fa187868661301f565b8051602091820120825192909101919091201490565b95945050505050565b600081831215612e045781612d98565b6000818312612e045781612d98565b6000612d98670de0b6b3a764000083612ff786613a9d565b6130019190615976565b61300b919061589a565b613ce1565b6060612d958484600085613f20565b6060600084511161308c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4d65726b6c65547269653a20656d707479206b657900000000000000000000006044820152606401611807565b6000613097846140b6565b905060006130a4866141a2565b90506000846040516020016130bb91815260200190565b60405160208183030381529060405290506000805b8451811015613a145760008582815181106130ed576130ed615c28565b602002602001015190508451831115613188576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4d65726b6c65547269653a206b657920696e646578206578636565647320746f60448201527f74616c206b6579206c656e6774680000000000000000000000000000000000006064820152608401611807565b8260000361324157805180516020918201206040516131d6926131b092910190815260200190565b604051602081830303815290604052858051602091820120825192909101919091201490565b61323c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4d65726b6c65547269653a20696e76616c696420726f6f7420686173680000006044820152606401611807565b613398565b8051516020116132f7578051805160209182012060405161326b926131b092910190815260200190565b61323c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d65726b6c65547269653a20696e76616c6964206c6172676520696e7465726e60448201527f616c2068617368000000000000000000000000000000000000000000000000006064820152608401611807565b805184516020808701919091208251919092012014613398576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4d65726b6c65547269653a20696e76616c696420696e7465726e616c206e6f6460448201527f65206861736800000000000000000000000000000000000000000000000000006064820152608401611807565b6133a460106001615538565b816020015151036135805784518303613518576133de81602001516010815181106133d1576133d1615c28565b6020026020010151614205565b96506000875111613471576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603b60248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286272616e63682900000000006064820152608401611807565b6001865161347f9190615569565b821461350d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286272616e6368290000000000006064820152608401611807565b505050505050612d98565b600085848151811061352c5761352c615c28565b602001015160f81c60f81b60f81c9050600082602001518260ff168151811061355757613557615c28565b6020026020010151905061356a816142b9565b9550613577600186615538565b94505050613a01565b600281602001515103613979576000613598826142de565b90506000816000815181106135af576135af615c28565b016020015160f81c905060006135c6600283615c57565b6135d1906002615c79565b905060006135e2848360ff16614302565b905060006135f08a89614302565b905060006135fe8383614338565b905080835114613690576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a20706174682072656d61696e646572206d7573742060448201527f736861726520616c6c206e6962626c65732077697468206b65790000000000006064820152608401611807565b60ff8516600214806136a5575060ff85166003145b15613894578082511461373a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f4d65726b6c65547269653a206b65792072656d61696e646572206d757374206260448201527f65206964656e746963616c20746f20706174682072656d61696e6465720000006064820152608401611807565b61375487602001516001815181106133d1576133d1615c28565b9c5060008d51116137e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286c65616629000000000000006064820152608401611807565b60018c516137f59190615569565b8814613883576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286c6561662900000000000000006064820152608401611807565b505050505050505050505050612d98565b60ff851615806138a7575060ff85166001145b156138e6576138d387602001516001815181106138c6576138c6615c28565b60200260200101516142b9565b99506138df818a615538565b985061396e565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4d65726b6c65547269653a2072656365697665642061206e6f6465207769746860448201527f20616e20756e6b6e6f776e2070726566697800000000000000000000000000006064820152608401611807565b505050505050613a01565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4d65726b6c65547269653a20726563656976656420616e20756e70617273656160448201527f626c65206e6f64650000000000000000000000000000000000000000000000006064820152608401611807565b5080613a0c81615bf0565b9150506130d0565b506040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4d65726b6c65547269653a2072616e206f7574206f662070726f6f6620656c6560448201527f6d656e74730000000000000000000000000000000000000000000000000000006064820152608401611807565b6000808213613b08576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401611807565b60006060613b15846143ec565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c18213613d1257506000919050565b680755bf798b4a1bf1e58212613d84576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4558505f4f564552464c4f5700000000000000000000000000000000000000006044820152606401611807565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b606082471015613fb2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401611807565b73ffffffffffffffffffffffffffffffffffffffff85163b614030576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401611807565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516140599190615c9c565b60006040518083038185875af1925050503d8060008114614096576040519150601f19603f3d011682016040523d82523d6000602084013e61409b565b606091505b50915091506140ab8282866144c2565b979650505050505050565b80516060908067ffffffffffffffff8111156140d4576140d4614eb1565b60405190808252806020026020018201604052801561411957816020015b60408051808201909152606080825260208201528152602001906001900390816140f25790505b50915060005b8181101561419b57604051806040016040528085838151811061414457614144615c28565b6020026020010151815260200161417386848151811061416657614166615c28565b6020026020010151614515565b81525083828151811061418857614188615c28565b602090810291909101015260010161411f565b5050919050565b606080604051905082518060011b603f8101601f1916830160405280835250602084016020830160005b838110156141fa578060011b82018184015160001a8060041c8253600f8116600183015350506001016141cc565b509295945050505050565b6060600080600061421585614528565b91945092509050600081600181111561423057614230615650565b14614267576040517f1ff9b2e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6142718284615538565b8551146142aa576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612fb7856020015184846149c6565b606060208260000151106142d5576142d082614205565b612328565b61232882614a5a565b60606123286142fd83602001516000815181106133d1576133d1615c28565b6141a2565b6060825182106143215750604080516020810190915260008152612328565b612d9883838486516143339190615569565b614a70565b600080825184511061434b57825161434e565b83515b90505b80821080156143d5575082828151811061436d5761436d615c28565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168483815181106143ac576143ac615c28565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b156143e557816001019150614351565b5092915050565b6000808211614457576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401611807565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b606083156144d1575081612d98565b8251156144e15782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161180791906152f6565b606061232861452383614c48565b614cb5565b6000806000836000015160000361456b576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020840151805160001a607f81116145905760006001600094509450945050506149bf565b60b781116146a65760006145a5608083615569565b9050808760000151116145e4576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001838101517fff0000000000000000000000000000000000000000000000000000000000000016908214801561465c57507f80000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008216105b15614693576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50600195509350600092506149bf915050565b60bf81116148045760006146bb60b783615569565b9050808760000151116146fa576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff0000000000000000000000000000000000000000000000000000000000000016600081900361475c576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c603781116147a4576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6147ae8184615538565b8951116147e7576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6147f2836001615538565b97509550600094506149bf9350505050565b60f7811161486957600061481960c083615569565b905080876000015111614858576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001955093508492506149bf915050565b600061487660f783615569565b9050808760000151116148b5576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614917576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c6037811161495f576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6149698184615538565b8951116149a2576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6149ad836001615538565b97509550600194506149bf9350505050565b9193909250565b60608167ffffffffffffffff8111156149e1576149e1614eb1565b6040519080825280601f01601f191660200182016040528015614a0b576020820181803683370190505b5090508115612d98576000614a208486615538565b90506020820160005b84811015614a41578281015182820152602001614a29565b84811115614a50576000858301525b5050509392505050565b60606123288260200151600084600001516149c6565b60608182601f011015614adf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401611807565b828284011015614b4b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401611807565b81830184511015614bb8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401611807565b606082158015614bd75760405191506000825260208201604052614c3f565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015614c10578051835260209283019201614bf8565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b60408051808201909152600080825260208201528151600003614c97576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50604080518082019091528151815260209182019181019190915290565b60606000806000614cc585614528565b919450925090506001816001811115614ce057614ce0615650565b14614d17576040517f4b9c6abe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8451614d238385615538565b14614d5a576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808252610420820190925290816020015b6040805180820190915260008082526020820152815260200190600190039081614d715790505093506000835b8651811015614e5f57600080614de46040518060400160405280858c60000151614dc89190615569565b8152602001858c60200151614ddd9190615538565b9052614528565b509150915060405180604001604052808383614e009190615538565b8152602001848b60200151614e159190615538565b815250888581518110614e2a57614e2a615c28565b6020908102919091010152614e40600185615538565b9350614e4c8183615538565b614e569084615538565b92505050614d9e565b50845250919392505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461205757600080fd5b67ffffffffffffffff8116811461205757600080fd5b801515811461205757600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160c0810167ffffffffffffffff81118282101715614f0357614f03614eb1565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614f5057614f50614eb1565b604052919050565b600082601f830112614f6957600080fd5b813567ffffffffffffffff811115614f8357614f83614eb1565b614fb460207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614f09565b818152846020838601011115614fc957600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060008060c08789031215614fff57600080fd5b863561500a81614e6b565b95506020870135945060408701359350606087013561502881614e8d565b9250608087013561503881614ea3565b915060a087013567ffffffffffffffff81111561505457600080fd5b61506089828a01614f58565b9150509295509295509295565b600060c0828403121561507f57600080fd5b60405160c0810167ffffffffffffffff82821081831117156150a3576150a3614eb1565b8160405282935084358352602085013591506150be82614e6b565b816020840152604085013591506150d482614e6b565b816040840152606085013560608401526080850135608084015260a085013591508082111561510257600080fd5b5061510f85828601614f58565b60a0830152505092915050565b6000806040838503121561512f57600080fd5b823567ffffffffffffffff81111561514657600080fd5b6151528582860161506d565b925050602083013561516381614e6b565b809150509250929050565b60006020828403121561518057600080fd5b8135612d9881614e6b565b600080600080600085870360e08112156151a457600080fd5b863567ffffffffffffffff808211156151bc57600080fd5b6151c88a838b0161506d565b97506020890135965060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08401121561520157600080fd5b60408901955060c089013592508083111561521b57600080fd5b828901925089601f84011261522f57600080fd5b823591508082111561524057600080fd5b508860208260051b840101111561525657600080fd5b959894975092955050506020019190565b60006020828403121561527957600080fd5b5035919050565b60005b8381101561529b578181015183820152602001615283565b838111156129db5750506000910152565b600081518084526152c4816020860160208601615280565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000612d9860208301846152ac565b6000806040838503121561531c57600080fd5b82359150602083013561516381614e6b565b60ff8116811461205757600080fd5b6000806000806080858703121561535357600080fd5b843561535e81614e6b565b9350602085013561536e8161532e565b93969395505050506040820135916060013590565b63ffffffff8116811461205757600080fd5b6000602082840312156153a757600080fd5b8135612d9881615383565b6000602082840312156153c457600080fd5b813567ffffffffffffffff8111156153db57600080fd5b6153e78482850161506d565b949350505050565b6000806000806080858703121561540557600080fd5b843561541081614e6b565b9350602085013561542081614e6b565b9250604085013561543081614e6b565b9150606085013561544081615383565b939692955090935050565b60006020828403121561545d57600080fd5b8135612d9881614e8d565b6000806040838503121561547b57600080fd5b50508035926020909101359150565b600080600080600060a086880312156154a257600080fd5b85356154ad81614e6b565b94506020860135935060408601356154c481614e8d565b925060608601356154d481614ea3565b9150608086013567ffffffffffffffff8111156154f057600080fd5b6154fc88828901614f58565b9150509295509295909350565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561554b5761554b615509565b500190565b60006020828403121561556257600080fd5b5051919050565b60008282101561557b5761557b615509565b500390565b60006020828403121561559257600080fd5b8151612d9881614e6b565b6000806000606084860312156155b257600080fd5b83516155bd81615383565b60208501519093506155ce81614e8d565b60408501519092506155df81614e6b565b809150509250925092565b6000608082840312156155fc57600080fd5b6040516080810181811067ffffffffffffffff8211171561561f5761561f614eb1565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60006020828403121561569157600080fd5b815160038110612d9857600080fd5b600067ffffffffffffffff808411156156bb576156bb614eb1565b8360051b60206156cc818301614f09565b8681529185019181810190368411156156e457600080fd5b865b84811015615718578035868111156156fe5760008081fd5b61570a36828b01614f58565b8452509183019183016156e6565b50979650505050505050565b60006020828403121561573657600080fd5b8151612d9881614ea3565b60006020828403121561575357600080fd5b8151612d9881614e8d565b60006020828403121561577057600080fd5b8151612d9881615383565b8581528460208201527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b16604082015282151560f81b6048820152600082516157cf816049850160208701615280565b919091016049019695505050505050565b600067ffffffffffffffff8083168185168183048111821515161561580757615807615509565b02949350505050565b600067ffffffffffffffff80831681851680830382111561583357615833615509565b01949350505050565b6000806040838503121561584f57600080fd5b825161585a81614e6b565b60208401519092506151638161532e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826158a9576158a961586b565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f8000000000000000000000000000000000000000000000000000000000000000831416156158fd576158fd615509565b500590565b6000808312837f80000000000000000000000000000000000000000000000000000000000000000183128115161561593c5761593c615509565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01831381161561597057615970615509565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000841360008413858304851182821616156159b7576159b7615509565b7f800000000000000000000000000000000000000000000000000000000000000060008712868205881281841616156159f2576159f2615509565b60008712925087820587128484161615615a0e57615a0e615509565b87850587128184161615615a2457615a24615509565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03841381151615615a6c57615a6c615509565b827f8000000000000000000000000000000000000000000000000000000000000000038412811615615aa057615aa0615509565b50500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615ade57615ade615509565b500290565b600082615af257615af261586b565b500490565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a0830152615b4260c08301846152ac565b98975050505050505050565b600060c08284031215615b6057600080fd5b615b68614ee0565b8251615b7381615383565b81526020830151615b838161532e565b60208201526040830151615b968161532e565b60408201526060830151615ba981615383565b60608201526080830151615bbc81615383565b608082015260a08301516fffffffffffffffffffffffffffffffff81168114615be457600080fd5b60a08201529392505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203615c2157615c21615509565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060ff831680615c6a57615c6a61586b565b8060ff84160691505092915050565b600060ff821660ff841680821015615c9357615c93615509565b90039392505050565b60008251615cae818460208701615280565b919091019291505056fea164736f6c634300080f000a000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000006", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [], - "value": 0 - }, - { - "accessor": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "account": "0xae5DadFc48928543f706a9E6Ce25c682aaD2b63b", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x60c06040523480156200001157600080fd5b5060405162006010380380620060108339810160408190526200003491620002f2565b608082905260a08190526200004d600080808062000055565b505062000317565b600054610100900460ff1615808015620000765750600054600160ff909116105b80620000a6575062000093306200022460201b620023cd1760201c565b158015620000a6575060005460ff166001145b6200010f5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000133576000805461ff0019166101001790555b603880546001600160a01b03199081166001600160a01b03888116919091179092556037805490911686831617905560358054610100600160a81b0319166101008684160217905560325416620001cc576032805461dead6001600160a01b0319909116179055603b80546001600160601b031916640100000000426001600160401b03160263ffffffff19161763ffffffff84161790555b620001d662000233565b80156200021d576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b6001600160a01b03163b151590565b600054610100900460ff16620002a05760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b606482015260840162000106565b600154600160c01b90046001600160401b0316600003620002f05760408051606081018252633b9aca0080825260006020830152436001600160401b031691909201819052600160c01b02176001555b565b600080604083850312156200030657600080fd5b505080516020909101519092909150565b60805160a051615cc56200034b6000396000818161051a0152611b280152600081816106a601526118120152615cc56000f3fe6080604052600436106101d15760003560e01c80637fc48504116100f7578063a35d99df11610095578063bf653a5c11610064578063bf653a5c14610697578063cff0ab96146106ca578063e9e05c421461076b578063f2b4e6171461077e57600080fd5b8063a35d99df1461059b578063a3860f48146105bb578063b69ef8a8146105db578063bb2c727e146105f057600080fd5b80638e819e54116100d15780638e819e54146104eb578063952b27971461050b5780639bf62d821461053e578063a14238e71461056b57600080fd5b80637fc48504146104ab5780638b4c40b0146101f65780638c3152e9146104cb57600080fd5b80634870496f1161016f5780635c975abb1161013e5780635c975abb1461043657806371c1566e1461044b57806371cfaa3f1461046b5780637d6be8dc1461048b57600080fd5b80634870496f1461034d5780634fd0434c1461036d578063513747ab146103af57806354fd4d50146103ea57600080fd5b80633c9f397c116101ab5780633c9f397c146102a657806343ca1c50146102d8578063452a9320146102f857806345884d321461030d57600080fd5b8063149f2f22146101fd57806333d7e2bd1461021d57806335e80ab31461027457600080fd5b366101f8576101f63334620186a06000604051806020016040528060008152506107ab565b005b600080fd5b34801561020957600080fd5b506101f6610218366004614fe6565b610850565b34801561022957600080fd5b5060375461024a9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561028057600080fd5b5060355461024a90610100900473ffffffffffffffffffffffffffffffffffffffff1681565b3480156102b257600080fd5b50603b546102c39063ffffffff1681565b60405163ffffffff909116815260200161026b565b3480156102e457600080fd5b506101f66102f336600461511c565b610a91565b34801561030457600080fd5b5061024a610f31565b34801561031957600080fd5b5061033d61032836600461516e565b603a6020526000908152604090205460ff1681565b604051901515815260200161026b565b34801561035957600080fd5b506101f661036836600461518b565b610fc9565b34801561037957600080fd5b50603b5461039690640100000000900467ffffffffffffffff1681565b60405167ffffffffffffffff909116815260200161026b565b3480156103bb57600080fd5b506103dc6103ca366004615267565b6000908152603c602052604090205490565b60405190815260200161026b565b3480156103f657600080fd5b50604080518082018252600d81527f332e31312e302d626574612e32000000000000000000000000000000000000006020820152905161026b91906152f6565b34801561044257600080fd5b5061033d611531565b34801561045757600080fd5b506101f6610466366004615309565b6115c4565b34801561047757600080fd5b506101f661048636600461533d565b611c7f565b34801561049757600080fd5b506101f66104a636600461516e565b611e3f565b3480156104b757600080fd5b506101f66104c6366004615395565b611f22565b3480156104d757600080fd5b506101f66104e63660046153b2565b61200e565b3480156104f757600080fd5b506101f66105063660046153ef565b61205a565b34801561051757600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006103dc565b34801561054a57600080fd5b5060325461024a9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561057757600080fd5b5061033d610586366004615267565b60336020526000908152604090205460ff1681565b3480156105a757600080fd5b506103966105b636600461544b565b61230f565b3480156105c757600080fd5b5061024a6105d6366004615468565b61232e565b3480156105e757600080fd5b506103dc612373565b3480156105fc57600080fd5b5061066261060b366004615309565b603960209081526000928352604080842090915290825290205473ffffffffffffffffffffffffffffffffffffffff81169074010000000000000000000000000000000000000000900467ffffffffffffffff1682565b6040805173ffffffffffffffffffffffffffffffffffffffff909316835267ffffffffffffffff90911660208301520161026b565b3480156106a357600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006103dc565b3480156106d657600080fd5b50600154610732906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff928316602085015291169082015260600161026b565b6101f661077936600461548a565b6107ab565b34801561078a57600080fd5b5060385461024a9073ffffffffffffffffffffffffffffffffffffffff1681565b8260005a905060006107bb6123e9565b50905073ffffffffffffffffffffffffffffffffffffffff811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee148015906107f757503415155b1561082e576040517ff2365b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61083c883489898989612486565b506108478282612632565b50505050505050565b8260005a905060006108606123e9565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8216016108d2576040517f0eaf3c0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87603d60008282546108e49190615538565b90915550506040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610956573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097a9190615550565b905061099e73ffffffffffffffffffffffffffffffffffffffff831633308c6128ff565b6109a88982615538565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015610a12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a369190615550565b14610a6d576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a7b8a8a8a8a8a8a612486565b5050610a878282612632565b5050505050505050565b610a99611531565b15610ad0576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60325473ffffffffffffffffffffffffffffffffffffffff1661dead14610b23576040517f9396d15600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610b2e836129e1565b9050610b3a81836115c4565b6000818152603360209081526040822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558401516032805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff000000000000000000000000000000000000000090921691909117905580610bc56123e9565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff821601610c2857610c218560400151866080015187606001518860a00151612a2e565b9150610e7b565b8073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff1603610c91576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606085015115610e52578460600151603d6000828254610cb19190615569565b90915550506040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610d23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d479190615550565b9050610d7c866040015187606001518473ffffffffffffffffffffffffffffffffffffffff16612a8c9092919063ffffffff16565b6060860151610d8b9082615569565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015610df5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e199190615550565b14610e50576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60a08501515115610e7657610c218560400151866080015160008860a00151612a2e565b600191505b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405183907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b90610edd90851515815260200190565b60405180910390a281158015610ef35750326001145b15610f2a576040517feeae4ed300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa158015610fa0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc49190615580565b905090565b610fd1611531565b15611008576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff1603611071576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6038546040517fbb8aa1fc00000000000000000000000000000000000000000000000000000000815260048101869052600091829173ffffffffffffffffffffffffffffffffffffffff9091169063bb8aa1fc90602401606060405180830381865afa1580156110e5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611109919061559d565b925050915060008173ffffffffffffffffffffffffffffffffffffffff1663bcef3b556040518163ffffffff1660e01b8152600401602060405180830381865afa15801561115b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061117f9190615550565b603b5490915063ffffffff8481169116146111c6576040517f27a10cc200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111dd6111d8368890038801886155ea565b612ae7565b8114611215576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611220896129e1565b905060018373ffffffffffffffffffffffffffffffffffffffff1663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa15801561126f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611293919061567f565b60028111156112a4576112a4615650565b036112db576040517fd357347400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051602081018390526000918101829052606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012090830181905292506113a49101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f010000000000000000000000000000000000000000000000000000000000000060208301529061139a898b6156a0565b8b60400135612b26565b15156000036113df576040517fb05e92fa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051808201825273ffffffffffffffffffffffffffffffffffffffff808716825267ffffffffffffffff4281166020808501918252600088815260398252868120338252825286812095518654935190941674010000000000000000000000000000000000000000027fffffffff0000000000000000000000000000000000000000000000000000000090931693851693909317919091179093558d840151928e01519351928216939091169185917f67a6208cfcc0801d50f6cbe764733f4fddf66ac0b04442061a8a8c0cb6b63f6291a4604051339083907f798f9f13695f8f045aa5f80ed8efebb695f3c7fe65da381969f2f28bf3c60b9790600090a3506000908152603c602090815260408220805460018101825590835291200180547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790555050505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115a0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc49190615724565b600082815260396020908152604080832073ffffffffffffffffffffffffffffffffffffffff85811685529083528184208251808401845290549182168082527401000000000000000000000000000000000000000090920467ffffffffffffffff1681850152818552603a90935292205490919060ff1615611673576040517f09550c7700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b816020015167ffffffffffffffff166000036116bb576040517f94efd49b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061173c8273ffffffffffffffffffffffffffffffffffffffff1663cf09e0d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561170b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061172f9190615741565b67ffffffffffffffff1690565b90508067ffffffffffffffff16836020015167ffffffffffffffff1611611810576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604e60248201527f4f7074696d69736d506f7274616c3a207769746864726177616c2074696d657360448201527f74616d70206c657373207468616e20646973707574652067616d65206372656160648201527f74696f6e2074696d657374616d70000000000000000000000000000000000000608482015260a4015b60405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000000836020015167ffffffffffffffff164261184b9190615569565b116118d8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a2070726f76656e2077697468647261776160448201527f6c20686173206e6f74206d6174757265642079657400000000000000000000006064820152608401611807565b60028273ffffffffffffffffffffffffffffffffffffffff1663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611925573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611949919061567f565b600281111561195a5761195a615650565b14611991576040517fa080a3c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603b5463ffffffff1663ffffffff16611a1b8373ffffffffffffffffffffffffffffffffffffffff1663bbdc02db6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119ee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a12919061575e565b63ffffffff1690565b63ffffffff1614611a58576040517f27a10cc200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603b5467ffffffffffffffff64010000000090910481169082161015611b26576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604b60248201527f4f7074696d69736d506f7274616c3a20646973707574652067616d652063726560448201527f61746564206265666f7265207265737065637465642067616d6520747970652060648201527f7761732075706461746564000000000000000000000000000000000000000000608482015260a401611807565b7f0000000000000000000000000000000000000000000000000000000000000000611b958373ffffffffffffffffffffffffffffffffffffffff166319effeb46040518163ffffffff1660e01b8152600401602060405180830381865afa15801561170b573d6000803e3d6000fd5b611ba99067ffffffffffffffff1642615569565b11611c36576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4f7074696d69736d506f7274616c3a206f75747075742070726f706f73616c2060448201527f696e206169722d676170000000000000000000000000000000000000000000006064820152608401611807565b60008581526033602052604090205460ff1615610f2a576040517f475a253500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60375473ffffffffffffffffffffffffffffffffffffffff163314611cd0576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611cdc62030d40612b4a565b60405173ffffffffffffffffffffffffffffffffffffffff8516602482015260ff8416604482015260648101839052608481018290526000907342000000000000000000000000000000000000159073deaddeaddeaddeaddeaddeaddeaddeaddead0001907fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32908490819062030d4090829060a401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f71cfaa3f000000000000000000000000000000000000000000000000000000001790529051611df99695949392910161577b565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815290829052611e31916152f6565b60405180910390a450505050565b611e47610f31565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611eab576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81166000818152603a602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055517f192c289026d59a41a27f5aea08f3969b57931b0589202d14f4368cded95d3cda9190a250565b611f2a610f31565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611f8e576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603b805463ffffffff83167fffffffffffffffffffffffffffffffffffffffff00000000000000000000000090911681176401000000004267ffffffffffffffff90811682029290921793849055604051930416917f049fe9dd413cdf037cce27011cc1790c753118272f3630e6e8bdfa5e8208176090600090a350565b565b612016611531565b1561204d576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6120578133610a91565b50565b600054610100900460ff161580801561207a5750600054600160ff909116105b806120945750303b158015612094575060005460ff166001145b612120576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401611807565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561217e57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603880547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff8881169190911790925560378054909116868316179055603580547fffffffffffffffffffffff0000000000000000000000000000000000000000ff16610100868416021790556032541661229e576032805461dead7fffffffffffffffffffffffff0000000000000000000000000000000000000000909116179055603b80547fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166401000000004267ffffffffffffffff16027fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000161763ffffffff84161790555b6122a6612bac565b8015610f2a57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050565b600061231c8260106157e0565b61232890615208615810565b92915050565b603c602052816000526040600020818154811061234a57600080fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff169150829050565b60008061237e6123e9565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8216016123c5574791505090565b5050603d5490565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b603754604080517f4397dfef0000000000000000000000000000000000000000000000000000000081528151600093849373ffffffffffffffffffffffffffffffffffffffff90911692634397dfef92600480830193928290030181865afa158015612459573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061247d919061583c565b90939092509050565b8180156124a8575073ffffffffffffffffffffffffffffffffffffffff861615155b156124df576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6124e9815161230f565b67ffffffffffffffff168367ffffffffffffffff161015612536576040517f4929b80800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6201d4c081511115612574576040517f73052b0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b33328114612595575033731111000000000000000000000000000000001111015b600086868686866040516020016125b095949392919061577b565b604051602081830303815290604052905060008873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c328460405161262091906152f6565b60405180910390a45050505050505050565b600154600090612668907801000000000000000000000000000000000000000000000000900467ffffffffffffffff1643615569565b90506000612674612cbf565b90506000816020015160ff16826000015163ffffffff16612695919061589a565b905082156127cc576001546000906126cc908390700100000000000000000000000000000000900467ffffffffffffffff16615902565b90506000836040015160ff16836126e39190615976565b6001546127039084906fffffffffffffffffffffffffffffffff16615976565b61270d919061589a565b60015490915060009061275e906127379084906fffffffffffffffffffffffffffffffff16615a32565b866060015163ffffffff168760a001516fffffffffffffffffffffffffffffffff16612d80565b9050600186111561278d5761278a61273782876040015160ff1660018a6127859190615569565b612d9f565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b600180548691906010906127ff908490700100000000000000000000000000000000900467ffffffffffffffff16615810565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550816000015163ffffffff16600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff16131561288c576040517f77ebef4d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001546000906128b8906fffffffffffffffffffffffffffffffff1667ffffffffffffffff8816615aa6565b905060006128ca48633b9aca00612df4565b6128d49083615ae3565b905060005a6128e39088615569565b905080821115610a8757610a876128fa8284615569565b612e0b565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526129db9085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612e34565b50505050565b80516020808301516040808501516060860151608087015160a08801519351600097612a11979096959101615af7565b604051602081830303815290604052805190602001209050919050565b6000806000612a3e866000612f40565b905080612a74576308c379a06000526020805278185361666543616c6c3a204e6f7420656e6f756768206761736058526064601cfd5b600080855160208701888b5af1979650505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052612ae29084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401612959565b505050565b60008160000151826020015183604001518460600151604051602001612a11949392919093845260208401929092526040830152606082015260800190565b600080612b3286612f5e565b9050612b4081868686612f90565b9695505050505050565b6001805463ffffffff83169190601090612b83908490700100000000000000000000000000000000900467ffffffffffffffff16615810565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555050565b600054610100900460ff16612c43576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401611807565b6001547801000000000000000000000000000000000000000000000000900467ffffffffffffffff1660000361200c5760408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b6040805160c08082018352600080835260208301819052828401819052606083018190526080830181905260a083015260375483517fcc731b020000000000000000000000000000000000000000000000000000000081529351929373ffffffffffffffffffffffffffffffffffffffff9091169263cc731b02926004808401939192918290030181865afa158015612d5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc49190615b4e565b6000612d95612d8f8585612fc0565b83612fd0565b90505b9392505050565b6000670de0b6b3a7640000612de0612db7858361589a565b612dc990670de0b6b3a7640000615902565b612ddb85670de0b6b3a7640000615976565b612fdf565b612dea9086615976565b612d95919061589a565b600081831015612e045781612d98565b5090919050565b6000805a90505b825a612e1e9083615569565b1015612ae257612e2d82615bf0565b9150612e12565b6000612e96826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166130109092919063ffffffff16565b805190915015612ae25780806020019051810190612eb49190615724565b612ae2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401611807565b600080603f83619c4001026040850201603f5a021015949350505050565b60608180519060200120604051602001612f7a91815260200190565b6040516020818303038152906040529050919050565b6000612fb784612fa187868661301f565b8051602091820120825192909101919091201490565b95945050505050565b600081831215612e045781612d98565b6000818312612e045781612d98565b6000612d98670de0b6b3a764000083612ff786613a9d565b6130019190615976565b61300b919061589a565b613ce1565b6060612d958484600085613f20565b6060600084511161308c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4d65726b6c65547269653a20656d707479206b657900000000000000000000006044820152606401611807565b6000613097846140b6565b905060006130a4866141a2565b90506000846040516020016130bb91815260200190565b60405160208183030381529060405290506000805b8451811015613a145760008582815181106130ed576130ed615c28565b602002602001015190508451831115613188576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4d65726b6c65547269653a206b657920696e646578206578636565647320746f60448201527f74616c206b6579206c656e6774680000000000000000000000000000000000006064820152608401611807565b8260000361324157805180516020918201206040516131d6926131b092910190815260200190565b604051602081830303815290604052858051602091820120825192909101919091201490565b61323c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4d65726b6c65547269653a20696e76616c696420726f6f7420686173680000006044820152606401611807565b613398565b8051516020116132f7578051805160209182012060405161326b926131b092910190815260200190565b61323c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d65726b6c65547269653a20696e76616c6964206c6172676520696e7465726e60448201527f616c2068617368000000000000000000000000000000000000000000000000006064820152608401611807565b805184516020808701919091208251919092012014613398576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4d65726b6c65547269653a20696e76616c696420696e7465726e616c206e6f6460448201527f65206861736800000000000000000000000000000000000000000000000000006064820152608401611807565b6133a460106001615538565b816020015151036135805784518303613518576133de81602001516010815181106133d1576133d1615c28565b6020026020010151614205565b96506000875111613471576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603b60248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286272616e63682900000000006064820152608401611807565b6001865161347f9190615569565b821461350d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286272616e6368290000000000006064820152608401611807565b505050505050612d98565b600085848151811061352c5761352c615c28565b602001015160f81c60f81b60f81c9050600082602001518260ff168151811061355757613557615c28565b6020026020010151905061356a816142b9565b9550613577600186615538565b94505050613a01565b600281602001515103613979576000613598826142de565b90506000816000815181106135af576135af615c28565b016020015160f81c905060006135c6600283615c57565b6135d1906002615c79565b905060006135e2848360ff16614302565b905060006135f08a89614302565b905060006135fe8383614338565b905080835114613690576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a20706174682072656d61696e646572206d7573742060448201527f736861726520616c6c206e6962626c65732077697468206b65790000000000006064820152608401611807565b60ff8516600214806136a5575060ff85166003145b15613894578082511461373a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f4d65726b6c65547269653a206b65792072656d61696e646572206d757374206260448201527f65206964656e746963616c20746f20706174682072656d61696e6465720000006064820152608401611807565b61375487602001516001815181106133d1576133d1615c28565b9c5060008d51116137e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286c65616629000000000000006064820152608401611807565b60018c516137f59190615569565b8814613883576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286c6561662900000000000000006064820152608401611807565b505050505050505050505050612d98565b60ff851615806138a7575060ff85166001145b156138e6576138d387602001516001815181106138c6576138c6615c28565b60200260200101516142b9565b99506138df818a615538565b985061396e565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4d65726b6c65547269653a2072656365697665642061206e6f6465207769746860448201527f20616e20756e6b6e6f776e2070726566697800000000000000000000000000006064820152608401611807565b505050505050613a01565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4d65726b6c65547269653a20726563656976656420616e20756e70617273656160448201527f626c65206e6f64650000000000000000000000000000000000000000000000006064820152608401611807565b5080613a0c81615bf0565b9150506130d0565b506040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4d65726b6c65547269653a2072616e206f7574206f662070726f6f6620656c6560448201527f6d656e74730000000000000000000000000000000000000000000000000000006064820152608401611807565b6000808213613b08576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401611807565b60006060613b15846143ec565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c18213613d1257506000919050565b680755bf798b4a1bf1e58212613d84576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4558505f4f564552464c4f5700000000000000000000000000000000000000006044820152606401611807565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b606082471015613fb2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401611807565b73ffffffffffffffffffffffffffffffffffffffff85163b614030576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401611807565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516140599190615c9c565b60006040518083038185875af1925050503d8060008114614096576040519150601f19603f3d011682016040523d82523d6000602084013e61409b565b606091505b50915091506140ab8282866144c2565b979650505050505050565b80516060908067ffffffffffffffff8111156140d4576140d4614eb1565b60405190808252806020026020018201604052801561411957816020015b60408051808201909152606080825260208201528152602001906001900390816140f25790505b50915060005b8181101561419b57604051806040016040528085838151811061414457614144615c28565b6020026020010151815260200161417386848151811061416657614166615c28565b6020026020010151614515565b81525083828151811061418857614188615c28565b602090810291909101015260010161411f565b5050919050565b606080604051905082518060011b603f8101601f1916830160405280835250602084016020830160005b838110156141fa578060011b82018184015160001a8060041c8253600f8116600183015350506001016141cc565b509295945050505050565b6060600080600061421585614528565b91945092509050600081600181111561423057614230615650565b14614267576040517f1ff9b2e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6142718284615538565b8551146142aa576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612fb7856020015184846149c6565b606060208260000151106142d5576142d082614205565b612328565b61232882614a5a565b60606123286142fd83602001516000815181106133d1576133d1615c28565b6141a2565b6060825182106143215750604080516020810190915260008152612328565b612d9883838486516143339190615569565b614a70565b600080825184511061434b57825161434e565b83515b90505b80821080156143d5575082828151811061436d5761436d615c28565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168483815181106143ac576143ac615c28565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b156143e557816001019150614351565b5092915050565b6000808211614457576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401611807565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b606083156144d1575081612d98565b8251156144e15782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161180791906152f6565b606061232861452383614c48565b614cb5565b6000806000836000015160000361456b576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020840151805160001a607f81116145905760006001600094509450945050506149bf565b60b781116146a65760006145a5608083615569565b9050808760000151116145e4576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001838101517fff0000000000000000000000000000000000000000000000000000000000000016908214801561465c57507f80000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008216105b15614693576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50600195509350600092506149bf915050565b60bf81116148045760006146bb60b783615569565b9050808760000151116146fa576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff0000000000000000000000000000000000000000000000000000000000000016600081900361475c576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c603781116147a4576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6147ae8184615538565b8951116147e7576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6147f2836001615538565b97509550600094506149bf9350505050565b60f7811161486957600061481960c083615569565b905080876000015111614858576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001955093508492506149bf915050565b600061487660f783615569565b9050808760000151116148b5576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614917576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c6037811161495f576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6149698184615538565b8951116149a2576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6149ad836001615538565b97509550600194506149bf9350505050565b9193909250565b60608167ffffffffffffffff8111156149e1576149e1614eb1565b6040519080825280601f01601f191660200182016040528015614a0b576020820181803683370190505b5090508115612d98576000614a208486615538565b90506020820160005b84811015614a41578281015182820152602001614a29565b84811115614a50576000858301525b5050509392505050565b60606123288260200151600084600001516149c6565b60608182601f011015614adf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401611807565b828284011015614b4b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401611807565b81830184511015614bb8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401611807565b606082158015614bd75760405191506000825260208201604052614c3f565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015614c10578051835260209283019201614bf8565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b60408051808201909152600080825260208201528151600003614c97576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50604080518082019091528151815260209182019181019190915290565b60606000806000614cc585614528565b919450925090506001816001811115614ce057614ce0615650565b14614d17576040517f4b9c6abe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8451614d238385615538565b14614d5a576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808252610420820190925290816020015b6040805180820190915260008082526020820152815260200190600190039081614d715790505093506000835b8651811015614e5f57600080614de46040518060400160405280858c60000151614dc89190615569565b8152602001858c60200151614ddd9190615538565b9052614528565b509150915060405180604001604052808383614e009190615538565b8152602001848b60200151614e159190615538565b815250888581518110614e2a57614e2a615c28565b6020908102919091010152614e40600185615538565b9350614e4c8183615538565b614e569084615538565b92505050614d9e565b50845250919392505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461205757600080fd5b67ffffffffffffffff8116811461205757600080fd5b801515811461205757600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160c0810167ffffffffffffffff81118282101715614f0357614f03614eb1565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614f5057614f50614eb1565b604052919050565b600082601f830112614f6957600080fd5b813567ffffffffffffffff811115614f8357614f83614eb1565b614fb460207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614f09565b818152846020838601011115614fc957600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060008060c08789031215614fff57600080fd5b863561500a81614e6b565b95506020870135945060408701359350606087013561502881614e8d565b9250608087013561503881614ea3565b915060a087013567ffffffffffffffff81111561505457600080fd5b61506089828a01614f58565b9150509295509295509295565b600060c0828403121561507f57600080fd5b60405160c0810167ffffffffffffffff82821081831117156150a3576150a3614eb1565b8160405282935084358352602085013591506150be82614e6b565b816020840152604085013591506150d482614e6b565b816040840152606085013560608401526080850135608084015260a085013591508082111561510257600080fd5b5061510f85828601614f58565b60a0830152505092915050565b6000806040838503121561512f57600080fd5b823567ffffffffffffffff81111561514657600080fd5b6151528582860161506d565b925050602083013561516381614e6b565b809150509250929050565b60006020828403121561518057600080fd5b8135612d9881614e6b565b600080600080600085870360e08112156151a457600080fd5b863567ffffffffffffffff808211156151bc57600080fd5b6151c88a838b0161506d565b97506020890135965060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08401121561520157600080fd5b60408901955060c089013592508083111561521b57600080fd5b828901925089601f84011261522f57600080fd5b823591508082111561524057600080fd5b508860208260051b840101111561525657600080fd5b959894975092955050506020019190565b60006020828403121561527957600080fd5b5035919050565b60005b8381101561529b578181015183820152602001615283565b838111156129db5750506000910152565b600081518084526152c4816020860160208601615280565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000612d9860208301846152ac565b6000806040838503121561531c57600080fd5b82359150602083013561516381614e6b565b60ff8116811461205757600080fd5b6000806000806080858703121561535357600080fd5b843561535e81614e6b565b9350602085013561536e8161532e565b93969395505050506040820135916060013590565b63ffffffff8116811461205757600080fd5b6000602082840312156153a757600080fd5b8135612d9881615383565b6000602082840312156153c457600080fd5b813567ffffffffffffffff8111156153db57600080fd5b6153e78482850161506d565b949350505050565b6000806000806080858703121561540557600080fd5b843561541081614e6b565b9350602085013561542081614e6b565b9250604085013561543081614e6b565b9150606085013561544081615383565b939692955090935050565b60006020828403121561545d57600080fd5b8135612d9881614e8d565b6000806040838503121561547b57600080fd5b50508035926020909101359150565b600080600080600060a086880312156154a257600080fd5b85356154ad81614e6b565b94506020860135935060408601356154c481614e8d565b925060608601356154d481614ea3565b9150608086013567ffffffffffffffff8111156154f057600080fd5b6154fc88828901614f58565b9150509295509295909350565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561554b5761554b615509565b500190565b60006020828403121561556257600080fd5b5051919050565b60008282101561557b5761557b615509565b500390565b60006020828403121561559257600080fd5b8151612d9881614e6b565b6000806000606084860312156155b257600080fd5b83516155bd81615383565b60208501519093506155ce81614e8d565b60408501519092506155df81614e6b565b809150509250925092565b6000608082840312156155fc57600080fd5b6040516080810181811067ffffffffffffffff8211171561561f5761561f614eb1565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60006020828403121561569157600080fd5b815160038110612d9857600080fd5b600067ffffffffffffffff808411156156bb576156bb614eb1565b8360051b60206156cc818301614f09565b8681529185019181810190368411156156e457600080fd5b865b84811015615718578035868111156156fe5760008081fd5b61570a36828b01614f58565b8452509183019183016156e6565b50979650505050505050565b60006020828403121561573657600080fd5b8151612d9881614ea3565b60006020828403121561575357600080fd5b8151612d9881614e8d565b60006020828403121561577057600080fd5b8151612d9881615383565b8581528460208201527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b16604082015282151560f81b6048820152600082516157cf816049850160208701615280565b919091016049019695505050505050565b600067ffffffffffffffff8083168185168183048111821515161561580757615807615509565b02949350505050565b600067ffffffffffffffff80831681851680830382111561583357615833615509565b01949350505050565b6000806040838503121561584f57600080fd5b825161585a81614e6b565b60208401519092506151638161532e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826158a9576158a961586b565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f8000000000000000000000000000000000000000000000000000000000000000831416156158fd576158fd615509565b500590565b6000808312837f80000000000000000000000000000000000000000000000000000000000000000183128115161561593c5761593c615509565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01831381161561597057615970615509565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000841360008413858304851182821616156159b7576159b7615509565b7f800000000000000000000000000000000000000000000000000000000000000060008712868205881281841616156159f2576159f2615509565b60008712925087820587128484161615615a0e57615a0e615509565b87850587128184161615615a2457615a24615509565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03841381151615615a6c57615a6c615509565b827f8000000000000000000000000000000000000000000000000000000000000000038412811615615aa057615aa0615509565b50500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615ade57615ade615509565b500290565b600082615af257615af261586b565b500490565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a0830152615b4260c08301846152ac565b98975050505050505050565b600060c08284031215615b6057600080fd5b615b68614ee0565b8251615b7381615383565b81526020830151615b838161532e565b60208201526040830151615b968161532e565b60408201526060830151615ba981615383565b60608201526080830151615bbc81615383565b608082015260a08301516fffffffffffffffffffffffffffffffff81168114615be457600080fd5b60a08201529392505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203615c2157615c21615509565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060ff831680615c6a57615c6a61586b565b8060ff84160691505092915050565b600060ff821660ff841680821015615c9357615c93615509565b90039392505050565b60008251615cae818460208701615280565b919091019291505056fea164736f6c634300080f000a000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000006", - "deployedCode": "0x6080604052600436106101d15760003560e01c80637fc48504116100f7578063a35d99df11610095578063bf653a5c11610064578063bf653a5c14610697578063cff0ab96146106ca578063e9e05c421461076b578063f2b4e6171461077e57600080fd5b8063a35d99df1461059b578063a3860f48146105bb578063b69ef8a8146105db578063bb2c727e146105f057600080fd5b80638e819e54116100d15780638e819e54146104eb578063952b27971461050b5780639bf62d821461053e578063a14238e71461056b57600080fd5b80637fc48504146104ab5780638b4c40b0146101f65780638c3152e9146104cb57600080fd5b80634870496f1161016f5780635c975abb1161013e5780635c975abb1461043657806371c1566e1461044b57806371cfaa3f1461046b5780637d6be8dc1461048b57600080fd5b80634870496f1461034d5780634fd0434c1461036d578063513747ab146103af57806354fd4d50146103ea57600080fd5b80633c9f397c116101ab5780633c9f397c146102a657806343ca1c50146102d8578063452a9320146102f857806345884d321461030d57600080fd5b8063149f2f22146101fd57806333d7e2bd1461021d57806335e80ab31461027457600080fd5b366101f8576101f63334620186a06000604051806020016040528060008152506107ab565b005b600080fd5b34801561020957600080fd5b506101f6610218366004614fe6565b610850565b34801561022957600080fd5b5060375461024a9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561028057600080fd5b5060355461024a90610100900473ffffffffffffffffffffffffffffffffffffffff1681565b3480156102b257600080fd5b50603b546102c39063ffffffff1681565b60405163ffffffff909116815260200161026b565b3480156102e457600080fd5b506101f66102f336600461511c565b610a91565b34801561030457600080fd5b5061024a610f31565b34801561031957600080fd5b5061033d61032836600461516e565b603a6020526000908152604090205460ff1681565b604051901515815260200161026b565b34801561035957600080fd5b506101f661036836600461518b565b610fc9565b34801561037957600080fd5b50603b5461039690640100000000900467ffffffffffffffff1681565b60405167ffffffffffffffff909116815260200161026b565b3480156103bb57600080fd5b506103dc6103ca366004615267565b6000908152603c602052604090205490565b60405190815260200161026b565b3480156103f657600080fd5b50604080518082018252600d81527f332e31312e302d626574612e32000000000000000000000000000000000000006020820152905161026b91906152f6565b34801561044257600080fd5b5061033d611531565b34801561045757600080fd5b506101f6610466366004615309565b6115c4565b34801561047757600080fd5b506101f661048636600461533d565b611c7f565b34801561049757600080fd5b506101f66104a636600461516e565b611e3f565b3480156104b757600080fd5b506101f66104c6366004615395565b611f22565b3480156104d757600080fd5b506101f66104e63660046153b2565b61200e565b3480156104f757600080fd5b506101f66105063660046153ef565b61205a565b34801561051757600080fd5b507f00000000000000000000000000000000000000000000000000000000000000066103dc565b34801561054a57600080fd5b5060325461024a9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561057757600080fd5b5061033d610586366004615267565b60336020526000908152604090205460ff1681565b3480156105a757600080fd5b506103966105b636600461544b565b61230f565b3480156105c757600080fd5b5061024a6105d6366004615468565b61232e565b3480156105e757600080fd5b506103dc612373565b3480156105fc57600080fd5b5061066261060b366004615309565b603960209081526000928352604080842090915290825290205473ffffffffffffffffffffffffffffffffffffffff81169074010000000000000000000000000000000000000000900467ffffffffffffffff1682565b6040805173ffffffffffffffffffffffffffffffffffffffff909316835267ffffffffffffffff90911660208301520161026b565b3480156106a357600080fd5b507f000000000000000000000000000000000000000000000000000000000000000c6103dc565b3480156106d657600080fd5b50600154610732906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff928316602085015291169082015260600161026b565b6101f661077936600461548a565b6107ab565b34801561078a57600080fd5b5060385461024a9073ffffffffffffffffffffffffffffffffffffffff1681565b8260005a905060006107bb6123e9565b50905073ffffffffffffffffffffffffffffffffffffffff811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee148015906107f757503415155b1561082e576040517ff2365b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61083c883489898989612486565b506108478282612632565b50505050505050565b8260005a905060006108606123e9565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8216016108d2576040517f0eaf3c0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87603d60008282546108e49190615538565b90915550506040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610956573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097a9190615550565b905061099e73ffffffffffffffffffffffffffffffffffffffff831633308c6128ff565b6109a88982615538565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015610a12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a369190615550565b14610a6d576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a7b8a8a8a8a8a8a612486565b5050610a878282612632565b5050505050505050565b610a99611531565b15610ad0576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60325473ffffffffffffffffffffffffffffffffffffffff1661dead14610b23576040517f9396d15600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610b2e836129e1565b9050610b3a81836115c4565b6000818152603360209081526040822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558401516032805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff000000000000000000000000000000000000000090921691909117905580610bc56123e9565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff821601610c2857610c218560400151866080015187606001518860a00151612a2e565b9150610e7b565b8073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff1603610c91576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606085015115610e52578460600151603d6000828254610cb19190615569565b90915550506040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610d23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d479190615550565b9050610d7c866040015187606001518473ffffffffffffffffffffffffffffffffffffffff16612a8c9092919063ffffffff16565b6060860151610d8b9082615569565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015610df5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e199190615550565b14610e50576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60a08501515115610e7657610c218560400151866080015160008860a00151612a2e565b600191505b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405183907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b90610edd90851515815260200190565b60405180910390a281158015610ef35750326001145b15610f2a576040517feeae4ed300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa158015610fa0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc49190615580565b905090565b610fd1611531565b15611008576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff1603611071576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6038546040517fbb8aa1fc00000000000000000000000000000000000000000000000000000000815260048101869052600091829173ffffffffffffffffffffffffffffffffffffffff9091169063bb8aa1fc90602401606060405180830381865afa1580156110e5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611109919061559d565b925050915060008173ffffffffffffffffffffffffffffffffffffffff1663bcef3b556040518163ffffffff1660e01b8152600401602060405180830381865afa15801561115b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061117f9190615550565b603b5490915063ffffffff8481169116146111c6576040517f27a10cc200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111dd6111d8368890038801886155ea565b612ae7565b8114611215576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611220896129e1565b905060018373ffffffffffffffffffffffffffffffffffffffff1663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa15801561126f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611293919061567f565b60028111156112a4576112a4615650565b036112db576040517fd357347400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051602081018390526000918101829052606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012090830181905292506113a49101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f010000000000000000000000000000000000000000000000000000000000000060208301529061139a898b6156a0565b8b60400135612b26565b15156000036113df576040517fb05e92fa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051808201825273ffffffffffffffffffffffffffffffffffffffff808716825267ffffffffffffffff4281166020808501918252600088815260398252868120338252825286812095518654935190941674010000000000000000000000000000000000000000027fffffffff0000000000000000000000000000000000000000000000000000000090931693851693909317919091179093558d840151928e01519351928216939091169185917f67a6208cfcc0801d50f6cbe764733f4fddf66ac0b04442061a8a8c0cb6b63f6291a4604051339083907f798f9f13695f8f045aa5f80ed8efebb695f3c7fe65da381969f2f28bf3c60b9790600090a3506000908152603c602090815260408220805460018101825590835291200180547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790555050505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115a0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc49190615724565b600082815260396020908152604080832073ffffffffffffffffffffffffffffffffffffffff85811685529083528184208251808401845290549182168082527401000000000000000000000000000000000000000090920467ffffffffffffffff1681850152818552603a90935292205490919060ff1615611673576040517f09550c7700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b816020015167ffffffffffffffff166000036116bb576040517f94efd49b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061173c8273ffffffffffffffffffffffffffffffffffffffff1663cf09e0d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561170b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061172f9190615741565b67ffffffffffffffff1690565b90508067ffffffffffffffff16836020015167ffffffffffffffff1611611810576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604e60248201527f4f7074696d69736d506f7274616c3a207769746864726177616c2074696d657360448201527f74616d70206c657373207468616e20646973707574652067616d65206372656160648201527f74696f6e2074696d657374616d70000000000000000000000000000000000000608482015260a4015b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000c836020015167ffffffffffffffff164261184b9190615569565b116118d8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a2070726f76656e2077697468647261776160448201527f6c20686173206e6f74206d6174757265642079657400000000000000000000006064820152608401611807565b60028273ffffffffffffffffffffffffffffffffffffffff1663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611925573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611949919061567f565b600281111561195a5761195a615650565b14611991576040517fa080a3c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603b5463ffffffff1663ffffffff16611a1b8373ffffffffffffffffffffffffffffffffffffffff1663bbdc02db6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119ee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a12919061575e565b63ffffffff1690565b63ffffffff1614611a58576040517f27a10cc200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603b5467ffffffffffffffff64010000000090910481169082161015611b26576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604b60248201527f4f7074696d69736d506f7274616c3a20646973707574652067616d652063726560448201527f61746564206265666f7265207265737065637465642067616d6520747970652060648201527f7761732075706461746564000000000000000000000000000000000000000000608482015260a401611807565b7f0000000000000000000000000000000000000000000000000000000000000006611b958373ffffffffffffffffffffffffffffffffffffffff166319effeb46040518163ffffffff1660e01b8152600401602060405180830381865afa15801561170b573d6000803e3d6000fd5b611ba99067ffffffffffffffff1642615569565b11611c36576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4f7074696d69736d506f7274616c3a206f75747075742070726f706f73616c2060448201527f696e206169722d676170000000000000000000000000000000000000000000006064820152608401611807565b60008581526033602052604090205460ff1615610f2a576040517f475a253500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60375473ffffffffffffffffffffffffffffffffffffffff163314611cd0576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611cdc62030d40612b4a565b60405173ffffffffffffffffffffffffffffffffffffffff8516602482015260ff8416604482015260648101839052608481018290526000907342000000000000000000000000000000000000159073deaddeaddeaddeaddeaddeaddeaddeaddead0001907fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32908490819062030d4090829060a401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f71cfaa3f000000000000000000000000000000000000000000000000000000001790529051611df99695949392910161577b565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815290829052611e31916152f6565b60405180910390a450505050565b611e47610f31565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611eab576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81166000818152603a602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055517f192c289026d59a41a27f5aea08f3969b57931b0589202d14f4368cded95d3cda9190a250565b611f2a610f31565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611f8e576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603b805463ffffffff83167fffffffffffffffffffffffffffffffffffffffff00000000000000000000000090911681176401000000004267ffffffffffffffff90811682029290921793849055604051930416917f049fe9dd413cdf037cce27011cc1790c753118272f3630e6e8bdfa5e8208176090600090a350565b565b612016611531565b1561204d576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6120578133610a91565b50565b600054610100900460ff161580801561207a5750600054600160ff909116105b806120945750303b158015612094575060005460ff166001145b612120576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401611807565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561217e57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603880547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff8881169190911790925560378054909116868316179055603580547fffffffffffffffffffffff0000000000000000000000000000000000000000ff16610100868416021790556032541661229e576032805461dead7fffffffffffffffffffffffff0000000000000000000000000000000000000000909116179055603b80547fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166401000000004267ffffffffffffffff16027fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000161763ffffffff84161790555b6122a6612bac565b8015610f2a57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050565b600061231c8260106157e0565b61232890615208615810565b92915050565b603c602052816000526040600020818154811061234a57600080fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff169150829050565b60008061237e6123e9565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8216016123c5574791505090565b5050603d5490565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b603754604080517f4397dfef0000000000000000000000000000000000000000000000000000000081528151600093849373ffffffffffffffffffffffffffffffffffffffff90911692634397dfef92600480830193928290030181865afa158015612459573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061247d919061583c565b90939092509050565b8180156124a8575073ffffffffffffffffffffffffffffffffffffffff861615155b156124df576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6124e9815161230f565b67ffffffffffffffff168367ffffffffffffffff161015612536576040517f4929b80800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6201d4c081511115612574576040517f73052b0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b33328114612595575033731111000000000000000000000000000000001111015b600086868686866040516020016125b095949392919061577b565b604051602081830303815290604052905060008873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c328460405161262091906152f6565b60405180910390a45050505050505050565b600154600090612668907801000000000000000000000000000000000000000000000000900467ffffffffffffffff1643615569565b90506000612674612cbf565b90506000816020015160ff16826000015163ffffffff16612695919061589a565b905082156127cc576001546000906126cc908390700100000000000000000000000000000000900467ffffffffffffffff16615902565b90506000836040015160ff16836126e39190615976565b6001546127039084906fffffffffffffffffffffffffffffffff16615976565b61270d919061589a565b60015490915060009061275e906127379084906fffffffffffffffffffffffffffffffff16615a32565b866060015163ffffffff168760a001516fffffffffffffffffffffffffffffffff16612d80565b9050600186111561278d5761278a61273782876040015160ff1660018a6127859190615569565b612d9f565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b600180548691906010906127ff908490700100000000000000000000000000000000900467ffffffffffffffff16615810565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550816000015163ffffffff16600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff16131561288c576040517f77ebef4d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001546000906128b8906fffffffffffffffffffffffffffffffff1667ffffffffffffffff8816615aa6565b905060006128ca48633b9aca00612df4565b6128d49083615ae3565b905060005a6128e39088615569565b905080821115610a8757610a876128fa8284615569565b612e0b565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526129db9085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612e34565b50505050565b80516020808301516040808501516060860151608087015160a08801519351600097612a11979096959101615af7565b604051602081830303815290604052805190602001209050919050565b6000806000612a3e866000612f40565b905080612a74576308c379a06000526020805278185361666543616c6c3a204e6f7420656e6f756768206761736058526064601cfd5b600080855160208701888b5af1979650505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052612ae29084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401612959565b505050565b60008160000151826020015183604001518460600151604051602001612a11949392919093845260208401929092526040830152606082015260800190565b600080612b3286612f5e565b9050612b4081868686612f90565b9695505050505050565b6001805463ffffffff83169190601090612b83908490700100000000000000000000000000000000900467ffffffffffffffff16615810565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555050565b600054610100900460ff16612c43576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401611807565b6001547801000000000000000000000000000000000000000000000000900467ffffffffffffffff1660000361200c5760408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b6040805160c08082018352600080835260208301819052828401819052606083018190526080830181905260a083015260375483517fcc731b020000000000000000000000000000000000000000000000000000000081529351929373ffffffffffffffffffffffffffffffffffffffff9091169263cc731b02926004808401939192918290030181865afa158015612d5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc49190615b4e565b6000612d95612d8f8585612fc0565b83612fd0565b90505b9392505050565b6000670de0b6b3a7640000612de0612db7858361589a565b612dc990670de0b6b3a7640000615902565b612ddb85670de0b6b3a7640000615976565b612fdf565b612dea9086615976565b612d95919061589a565b600081831015612e045781612d98565b5090919050565b6000805a90505b825a612e1e9083615569565b1015612ae257612e2d82615bf0565b9150612e12565b6000612e96826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166130109092919063ffffffff16565b805190915015612ae25780806020019051810190612eb49190615724565b612ae2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401611807565b600080603f83619c4001026040850201603f5a021015949350505050565b60608180519060200120604051602001612f7a91815260200190565b6040516020818303038152906040529050919050565b6000612fb784612fa187868661301f565b8051602091820120825192909101919091201490565b95945050505050565b600081831215612e045781612d98565b6000818312612e045781612d98565b6000612d98670de0b6b3a764000083612ff786613a9d565b6130019190615976565b61300b919061589a565b613ce1565b6060612d958484600085613f20565b6060600084511161308c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4d65726b6c65547269653a20656d707479206b657900000000000000000000006044820152606401611807565b6000613097846140b6565b905060006130a4866141a2565b90506000846040516020016130bb91815260200190565b60405160208183030381529060405290506000805b8451811015613a145760008582815181106130ed576130ed615c28565b602002602001015190508451831115613188576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4d65726b6c65547269653a206b657920696e646578206578636565647320746f60448201527f74616c206b6579206c656e6774680000000000000000000000000000000000006064820152608401611807565b8260000361324157805180516020918201206040516131d6926131b092910190815260200190565b604051602081830303815290604052858051602091820120825192909101919091201490565b61323c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4d65726b6c65547269653a20696e76616c696420726f6f7420686173680000006044820152606401611807565b613398565b8051516020116132f7578051805160209182012060405161326b926131b092910190815260200190565b61323c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d65726b6c65547269653a20696e76616c6964206c6172676520696e7465726e60448201527f616c2068617368000000000000000000000000000000000000000000000000006064820152608401611807565b805184516020808701919091208251919092012014613398576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4d65726b6c65547269653a20696e76616c696420696e7465726e616c206e6f6460448201527f65206861736800000000000000000000000000000000000000000000000000006064820152608401611807565b6133a460106001615538565b816020015151036135805784518303613518576133de81602001516010815181106133d1576133d1615c28565b6020026020010151614205565b96506000875111613471576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603b60248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286272616e63682900000000006064820152608401611807565b6001865161347f9190615569565b821461350d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286272616e6368290000000000006064820152608401611807565b505050505050612d98565b600085848151811061352c5761352c615c28565b602001015160f81c60f81b60f81c9050600082602001518260ff168151811061355757613557615c28565b6020026020010151905061356a816142b9565b9550613577600186615538565b94505050613a01565b600281602001515103613979576000613598826142de565b90506000816000815181106135af576135af615c28565b016020015160f81c905060006135c6600283615c57565b6135d1906002615c79565b905060006135e2848360ff16614302565b905060006135f08a89614302565b905060006135fe8383614338565b905080835114613690576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a20706174682072656d61696e646572206d7573742060448201527f736861726520616c6c206e6962626c65732077697468206b65790000000000006064820152608401611807565b60ff8516600214806136a5575060ff85166003145b15613894578082511461373a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f4d65726b6c65547269653a206b65792072656d61696e646572206d757374206260448201527f65206964656e746963616c20746f20706174682072656d61696e6465720000006064820152608401611807565b61375487602001516001815181106133d1576133d1615c28565b9c5060008d51116137e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286c65616629000000000000006064820152608401611807565b60018c516137f59190615569565b8814613883576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286c6561662900000000000000006064820152608401611807565b505050505050505050505050612d98565b60ff851615806138a7575060ff85166001145b156138e6576138d387602001516001815181106138c6576138c6615c28565b60200260200101516142b9565b99506138df818a615538565b985061396e565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4d65726b6c65547269653a2072656365697665642061206e6f6465207769746860448201527f20616e20756e6b6e6f776e2070726566697800000000000000000000000000006064820152608401611807565b505050505050613a01565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4d65726b6c65547269653a20726563656976656420616e20756e70617273656160448201527f626c65206e6f64650000000000000000000000000000000000000000000000006064820152608401611807565b5080613a0c81615bf0565b9150506130d0565b506040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4d65726b6c65547269653a2072616e206f7574206f662070726f6f6620656c6560448201527f6d656e74730000000000000000000000000000000000000000000000000000006064820152608401611807565b6000808213613b08576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401611807565b60006060613b15846143ec565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c18213613d1257506000919050565b680755bf798b4a1bf1e58212613d84576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4558505f4f564552464c4f5700000000000000000000000000000000000000006044820152606401611807565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b606082471015613fb2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401611807565b73ffffffffffffffffffffffffffffffffffffffff85163b614030576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401611807565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516140599190615c9c565b60006040518083038185875af1925050503d8060008114614096576040519150601f19603f3d011682016040523d82523d6000602084013e61409b565b606091505b50915091506140ab8282866144c2565b979650505050505050565b80516060908067ffffffffffffffff8111156140d4576140d4614eb1565b60405190808252806020026020018201604052801561411957816020015b60408051808201909152606080825260208201528152602001906001900390816140f25790505b50915060005b8181101561419b57604051806040016040528085838151811061414457614144615c28565b6020026020010151815260200161417386848151811061416657614166615c28565b6020026020010151614515565b81525083828151811061418857614188615c28565b602090810291909101015260010161411f565b5050919050565b606080604051905082518060011b603f8101601f1916830160405280835250602084016020830160005b838110156141fa578060011b82018184015160001a8060041c8253600f8116600183015350506001016141cc565b509295945050505050565b6060600080600061421585614528565b91945092509050600081600181111561423057614230615650565b14614267576040517f1ff9b2e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6142718284615538565b8551146142aa576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612fb7856020015184846149c6565b606060208260000151106142d5576142d082614205565b612328565b61232882614a5a565b60606123286142fd83602001516000815181106133d1576133d1615c28565b6141a2565b6060825182106143215750604080516020810190915260008152612328565b612d9883838486516143339190615569565b614a70565b600080825184511061434b57825161434e565b83515b90505b80821080156143d5575082828151811061436d5761436d615c28565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168483815181106143ac576143ac615c28565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b156143e557816001019150614351565b5092915050565b6000808211614457576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401611807565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b606083156144d1575081612d98565b8251156144e15782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161180791906152f6565b606061232861452383614c48565b614cb5565b6000806000836000015160000361456b576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020840151805160001a607f81116145905760006001600094509450945050506149bf565b60b781116146a65760006145a5608083615569565b9050808760000151116145e4576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001838101517fff0000000000000000000000000000000000000000000000000000000000000016908214801561465c57507f80000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008216105b15614693576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50600195509350600092506149bf915050565b60bf81116148045760006146bb60b783615569565b9050808760000151116146fa576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff0000000000000000000000000000000000000000000000000000000000000016600081900361475c576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c603781116147a4576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6147ae8184615538565b8951116147e7576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6147f2836001615538565b97509550600094506149bf9350505050565b60f7811161486957600061481960c083615569565b905080876000015111614858576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001955093508492506149bf915050565b600061487660f783615569565b9050808760000151116148b5576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614917576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c6037811161495f576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6149698184615538565b8951116149a2576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6149ad836001615538565b97509550600194506149bf9350505050565b9193909250565b60608167ffffffffffffffff8111156149e1576149e1614eb1565b6040519080825280601f01601f191660200182016040528015614a0b576020820181803683370190505b5090508115612d98576000614a208486615538565b90506020820160005b84811015614a41578281015182820152602001614a29565b84811115614a50576000858301525b5050509392505050565b60606123288260200151600084600001516149c6565b60608182601f011015614adf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401611807565b828284011015614b4b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401611807565b81830184511015614bb8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401611807565b606082158015614bd75760405191506000825260208201604052614c3f565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015614c10578051835260209283019201614bf8565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b60408051808201909152600080825260208201528151600003614c97576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50604080518082019091528151815260209182019181019190915290565b60606000806000614cc585614528565b919450925090506001816001811115614ce057614ce0615650565b14614d17576040517f4b9c6abe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8451614d238385615538565b14614d5a576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808252610420820190925290816020015b6040805180820190915260008082526020820152815260200190600190039081614d715790505093506000835b8651811015614e5f57600080614de46040518060400160405280858c60000151614dc89190615569565b8152602001858c60200151614ddd9190615538565b9052614528565b509150915060405180604001604052808383614e009190615538565b8152602001848b60200151614e159190615538565b815250888581518110614e2a57614e2a615c28565b6020908102919091010152614e40600185615538565b9350614e4c8183615538565b614e569084615538565b92505050614d9e565b50845250919392505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461205757600080fd5b67ffffffffffffffff8116811461205757600080fd5b801515811461205757600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160c0810167ffffffffffffffff81118282101715614f0357614f03614eb1565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614f5057614f50614eb1565b604052919050565b600082601f830112614f6957600080fd5b813567ffffffffffffffff811115614f8357614f83614eb1565b614fb460207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614f09565b818152846020838601011115614fc957600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060008060c08789031215614fff57600080fd5b863561500a81614e6b565b95506020870135945060408701359350606087013561502881614e8d565b9250608087013561503881614ea3565b915060a087013567ffffffffffffffff81111561505457600080fd5b61506089828a01614f58565b9150509295509295509295565b600060c0828403121561507f57600080fd5b60405160c0810167ffffffffffffffff82821081831117156150a3576150a3614eb1565b8160405282935084358352602085013591506150be82614e6b565b816020840152604085013591506150d482614e6b565b816040840152606085013560608401526080850135608084015260a085013591508082111561510257600080fd5b5061510f85828601614f58565b60a0830152505092915050565b6000806040838503121561512f57600080fd5b823567ffffffffffffffff81111561514657600080fd5b6151528582860161506d565b925050602083013561516381614e6b565b809150509250929050565b60006020828403121561518057600080fd5b8135612d9881614e6b565b600080600080600085870360e08112156151a457600080fd5b863567ffffffffffffffff808211156151bc57600080fd5b6151c88a838b0161506d565b97506020890135965060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08401121561520157600080fd5b60408901955060c089013592508083111561521b57600080fd5b828901925089601f84011261522f57600080fd5b823591508082111561524057600080fd5b508860208260051b840101111561525657600080fd5b959894975092955050506020019190565b60006020828403121561527957600080fd5b5035919050565b60005b8381101561529b578181015183820152602001615283565b838111156129db5750506000910152565b600081518084526152c4816020860160208601615280565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000612d9860208301846152ac565b6000806040838503121561531c57600080fd5b82359150602083013561516381614e6b565b60ff8116811461205757600080fd5b6000806000806080858703121561535357600080fd5b843561535e81614e6b565b9350602085013561536e8161532e565b93969395505050506040820135916060013590565b63ffffffff8116811461205757600080fd5b6000602082840312156153a757600080fd5b8135612d9881615383565b6000602082840312156153c457600080fd5b813567ffffffffffffffff8111156153db57600080fd5b6153e78482850161506d565b949350505050565b6000806000806080858703121561540557600080fd5b843561541081614e6b565b9350602085013561542081614e6b565b9250604085013561543081614e6b565b9150606085013561544081615383565b939692955090935050565b60006020828403121561545d57600080fd5b8135612d9881614e8d565b6000806040838503121561547b57600080fd5b50508035926020909101359150565b600080600080600060a086880312156154a257600080fd5b85356154ad81614e6b565b94506020860135935060408601356154c481614e8d565b925060608601356154d481614ea3565b9150608086013567ffffffffffffffff8111156154f057600080fd5b6154fc88828901614f58565b9150509295509295909350565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561554b5761554b615509565b500190565b60006020828403121561556257600080fd5b5051919050565b60008282101561557b5761557b615509565b500390565b60006020828403121561559257600080fd5b8151612d9881614e6b565b6000806000606084860312156155b257600080fd5b83516155bd81615383565b60208501519093506155ce81614e8d565b60408501519092506155df81614e6b565b809150509250925092565b6000608082840312156155fc57600080fd5b6040516080810181811067ffffffffffffffff8211171561561f5761561f614eb1565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60006020828403121561569157600080fd5b815160038110612d9857600080fd5b600067ffffffffffffffff808411156156bb576156bb614eb1565b8360051b60206156cc818301614f09565b8681529185019181810190368411156156e457600080fd5b865b84811015615718578035868111156156fe5760008081fd5b61570a36828b01614f58565b8452509183019183016156e6565b50979650505050505050565b60006020828403121561573657600080fd5b8151612d9881614ea3565b60006020828403121561575357600080fd5b8151612d9881614e8d565b60006020828403121561577057600080fd5b8151612d9881615383565b8581528460208201527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b16604082015282151560f81b6048820152600082516157cf816049850160208701615280565b919091016049019695505050505050565b600067ffffffffffffffff8083168185168183048111821515161561580757615807615509565b02949350505050565b600067ffffffffffffffff80831681851680830382111561583357615833615509565b01949350505050565b6000806040838503121561584f57600080fd5b825161585a81614e6b565b60208401519092506151638161532e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826158a9576158a961586b565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f8000000000000000000000000000000000000000000000000000000000000000831416156158fd576158fd615509565b500590565b6000808312837f80000000000000000000000000000000000000000000000000000000000000000183128115161561593c5761593c615509565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01831381161561597057615970615509565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000841360008413858304851182821616156159b7576159b7615509565b7f800000000000000000000000000000000000000000000000000000000000000060008712868205881281841616156159f2576159f2615509565b60008712925087820587128484161615615a0e57615a0e615509565b87850587128184161615615a2457615a24615509565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03841381151615615a6c57615a6c615509565b827f8000000000000000000000000000000000000000000000000000000000000000038412811615615aa057615aa0615509565b50500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615ade57615ade615509565b500290565b600082615af257615af261586b565b500490565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a0830152615b4260c08301846152ac565b98975050505050505050565b600060c08284031215615b6057600080fd5b615b68614ee0565b8251615b7381615383565b81526020830151615b838161532e565b60208201526040830151615b968161532e565b60408201526060830151615ba981615383565b60608201526080830151615bbc81615383565b608082015260a08301516fffffffffffffffffffffffffffffffff81168114615be457600080fd5b60a08201529392505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203615c2157615c21615509565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060ff831680615c6a57615c6a61586b565b8060ff84160691505092915050565b600060ff821660ff841680821015615c9357615c93615509565b90039392505050565b60008251615cae818460208701615280565b919091019291505056fea164736f6c634300080f000a", - "initialized": true, - "kind": "Create", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xae5DadFc48928543f706a9E6Ce25c682aaD2b63b", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xae5DadFc48928543f706a9E6Ce25c682aaD2b63b", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xae5DadFc48928543f706a9E6Ce25c682aaD2b63b", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xae5DadFc48928543f706a9E6Ce25c682aaD2b63b", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xae5DadFc48928543f706a9E6Ce25c682aaD2b63b", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xae5DadFc48928543f706a9E6Ce25c682aaD2b63b", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xae5DadFc48928543f706a9E6Ce25c682aaD2b63b", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000038" - }, - { - "account": "0xae5DadFc48928543f706a9E6Ce25c682aaD2b63b", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000038" - }, - { - "account": "0xae5DadFc48928543f706a9E6Ce25c682aaD2b63b", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000037" - }, - { - "account": "0xae5DadFc48928543f706a9E6Ce25c682aaD2b63b", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000037" - }, - { - "account": "0xae5DadFc48928543f706a9E6Ce25c682aaD2b63b", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000035" - }, - { - "account": "0xae5DadFc48928543f706a9E6Ce25c682aaD2b63b", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000035" - }, - { - "account": "0xae5DadFc48928543f706a9E6Ce25c682aaD2b63b", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000032" - }, - { - "account": "0xae5DadFc48928543f706a9E6Ce25c682aaD2b63b", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000032" - }, - { - "account": "0xae5DadFc48928543f706a9E6Ce25c682aaD2b63b", - "isWrite": true, - "newValue": "0x000000000000000000000000000000000000000000000000000000000000dead", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000032" - }, - { - "account": "0xae5DadFc48928543f706a9E6Ce25c682aaD2b63b", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x000000000000000000000000000000000000000000000000000000000000003b" - }, - { - "account": "0xae5DadFc48928543f706a9E6Ce25c682aaD2b63b", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000100000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x000000000000000000000000000000000000000000000000000000000000003b" - }, - { - "account": "0xae5DadFc48928543f706a9E6Ce25c682aaD2b63b", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xae5DadFc48928543f706a9E6Ce25c682aaD2b63b", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000001" - }, - { - "account": "0xae5DadFc48928543f706a9E6Ce25c682aaD2b63b", - "isWrite": true, - "newValue": "0x000000000000000100000000000000000000000000000000000000003b9aca00", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000001" - }, - { - "account": "0xae5DadFc48928543f706a9E6Ce25c682aaD2b63b", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xae5DadFc48928543f706a9E6Ce25c682aaD2b63b", - "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": "0x000000000000000000000000000000000000000000000000000000000000000f" - } - ], - "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": "0xae5DadFc48928543f706a9E6Ce25c682aaD2b63b", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xf2b4e617", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xae5DadFc48928543f706a9E6Ce25c682aaD2b63b", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000038" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xae5DadFc48928543f706a9E6Ce25c682aaD2b63b", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x33d7e2bd", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xae5DadFc48928543f706a9E6Ce25c682aaD2b63b", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000037" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xae5DadFc48928543f706a9E6Ce25c682aaD2b63b", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x35e80ab3", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xae5DadFc48928543f706a9E6Ce25c682aaD2b63b", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000035" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xae5DadFc48928543f706a9E6Ce25c682aaD2b63b", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x9bf62d82", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xae5DadFc48928543f706a9E6Ce25c682aaD2b63b", - "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": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x638627e586f5e36fe67a77519503a7c6da22f92b150d3c6055fd40bdcfe9ffd160806040523480156200001157600080fd5b506200001e600062000024565b62000292565b600054610100900460ff1615808015620000455750600054600160ff909116105b8062000075575062000062306200016260201b62000ce41760201c565b15801562000075575060005460ff166001145b620000de5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000102576000805461ff0019166101001790555b6200010c62000171565b6200011782620001d9565b80156200015e576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6001600160a01b03163b151590565b600054610100900460ff16620001cd5760405162461bcd60e51b815260206004820152602b60248201526000805160206200185983398151915260448201526a6e697469616c697a696e6760a81b6064820152608401620000d5565b620001d76200022b565b565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16620002875760405162461bcd60e51b815260206004820152602b60248201526000805160206200185983398151915260448201526a6e697469616c697a696e6760a81b6064820152608401620000d5565b620001d733620001d9565b6115b780620002a26000396000f3fe6080604052600436106100e85760003560e01c80636593dc6e1161008a57806396cd97201161005957806396cd972014610313578063bb8aa1fc14610333578063c4d66de814610394578063f2fde38b146103b457600080fd5b80636593dc6e14610293578063715018a6146102c057806382ecf2f6146102d55780638da5cb5b146102e857600080fd5b8063254bd683116100c6578063254bd6831461019c5780634d1975b4146101c957806354fd4d50146101e85780635f0150cb1461023e57600080fd5b806314f6b1a3146100ed5780631b685b9e1461010f5780631e3342401461017c575b600080fd5b3480156100f957600080fd5b5061010d6101083660046110c6565b6103d4565b005b34801561011b57600080fd5b5061015261012a3660046110fd565b60656020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561018857600080fd5b5061010d610197366004611118565b61045e565b3480156101a857600080fd5b506101bc6101b7366004611142565b6104aa565b60405161017391906111ef565b3480156101d557600080fd5b506068545b604051908152602001610173565b3480156101f457600080fd5b506102316040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b60405161017391906112ac565b34801561024a57600080fd5b5061025e6102593660046112bf565b6106ee565b6040805173ffffffffffffffffffffffffffffffffffffffff909316835267ffffffffffffffff909116602083015201610173565b34801561029f57600080fd5b506101da6102ae3660046110fd565b60666020526000908152604090205481565b3480156102cc57600080fd5b5061010d610741565b6101526102e33660046112bf565b610755565b3480156102f457600080fd5b5060335473ffffffffffffffffffffffffffffffffffffffff16610152565b34801561031f57600080fd5b506101da61032e3660046112bf565b6109ef565b34801561033f57600080fd5b5061035361034e366004611346565b610a28565b6040805163ffffffff909416845267ffffffffffffffff909216602084015273ffffffffffffffffffffffffffffffffffffffff1690820152606001610173565b3480156103a057600080fd5b5061010d6103af36600461135f565b610a91565b3480156103c057600080fd5b5061010d6103cf36600461135f565b610c2d565b6103dc610d00565b63ffffffff821660008181526065602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8616908117909155905190917fff513d80e2c7fa487608f70a618dfbc0cf415699dc69588c747e8c71566c88de91a35050565b610466610d00565b63ffffffff8216600081815260666020526040808220849055518392917f74d6665c4b26d5596a5aa13d3014e0c06af4d322075a797f87b03cd4c5bc91ca91a35050565b606854606090831015806104bc575081155b6106e7575060408051600583901b8101602001909152825b8381116106e5576000606882815481106104f0576104f061137c565b600091825260209091200154905060e081901c60a082901c67ffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff831663ffffffff891683036106b6576001865101865260008173ffffffffffffffffffffffffffffffffffffffff1663609d33346040518163ffffffff1660e01b8152600401600060405180830381865afa15801561058a573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526105d091908101906113da565b905060008273ffffffffffffffffffffffffffffffffffffffff1663bcef3b556040518163ffffffff1660e01b8152600401602060405180830381865afa15801561061f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064391906114a5565b90506040518060a001604052808881526020018781526020018567ffffffffffffffff168152602001828152602001838152508860018a5161068591906114be565b815181106106955761069561137c565b6020026020010181905250888851106106b3575050505050506106e5565b50505b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90920191506104d49050565b505b9392505050565b60008060006106ff878787876109ef565b60009081526067602052604090205473ffffffffffffffffffffffffffffffffffffffff81169860a09190911c67ffffffffffffffff16975095505050505050565b610749610d00565b6107536000610d81565b565b63ffffffff841660009081526065602052604081205473ffffffffffffffffffffffffffffffffffffffff16806107c5576040517f031c6de400000000000000000000000000000000000000000000000000000000815263ffffffff871660048201526024015b60405180910390fd5b63ffffffff86166000908152606660205260409020543414610813576040517f8620aa1900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006108206001436114be565b40905061088a338783888860405160200161083f9594939291906114fc565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905273ffffffffffffffffffffffffffffffffffffffff841690610df8565b92508273ffffffffffffffffffffffffffffffffffffffff16638129fc1c346040518263ffffffff1660e01b81526004016000604051808303818588803b1580156108d457600080fd5b505af11580156108e8573d6000803e3d6000fd5b505050505060006108fb888888886109ef565b60008181526067602052604090205490915015610947576040517f014f6fe5000000000000000000000000000000000000000000000000000000008152600481018290526024016107bc565b60004260a01b60e08a901b178517600083815260676020526040808220839055606880546001810182559083527fa2153420d844928b4421650203c77babc8b33d7f2e7b450e2966db0c220977530183905551919250899163ffffffff8c169173ffffffffffffffffffffffffffffffffffffffff8916917f5b565efe82411da98814f356d0e7bcb8f0219b8d970307c5afb4a6903a8b2e359190a450505050949350505050565b600084848484604051602001610a089493929190611549565b604051602081830303815290604052805190602001209050949350505050565b600080600080600080610a8160688881548110610a4757610a4761137c565b906000526020600020015460e081901c9160a082901c67ffffffffffffffff169173ffffffffffffffffffffffffffffffffffffffff1690565b9199909850909650945050505050565b600054610100900460ff1615808015610ab15750600054600160ff909116105b80610acb5750303b158015610acb575060005460ff166001145b610b57576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016107bc565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610bb557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610bbd610e06565b610bc682610d81565b8015610c2957600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b610c35610d00565b73ffffffffffffffffffffffffffffffffffffffff8116610cd8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016107bc565b610ce181610d81565b50565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b60335473ffffffffffffffffffffffffffffffffffffffff163314610753576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016107bc565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006106e760008484610ea5565b600054610100900460ff16610e9d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016107bc565b610753610feb565b600060608203516040830351602084035184518060208701018051600283016c5af43d3d93803e606057fd5bf3895289600d8a035278593da1005b363d3d373d3d3d3d610000806062363936013d738160481b1760218a03527f9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff603a8a035272fd6100003d81600a3d39f336602c57343d527f6062820160781b1761ff9e82106059018a03528060f01b8352606c8101604c8a038cf097505086610f715763301164256000526004601cfd5b905285527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08501527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08401527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa09092019190915292915050565b600054610100900460ff16611082576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016107bc565b61075333610d81565b803563ffffffff8116811461109f57600080fd5b919050565b73ffffffffffffffffffffffffffffffffffffffff81168114610ce157600080fd5b600080604083850312156110d957600080fd5b6110e28361108b565b915060208301356110f2816110a4565b809150509250929050565b60006020828403121561110f57600080fd5b6106e78261108b565b6000806040838503121561112b57600080fd5b6111348361108b565b946020939093013593505050565b60008060006060848603121561115757600080fd5b6111608461108b565b95602085013595506040909401359392505050565b60005b83811015611190578181015183820152602001611178565b8381111561119f576000848401525b50505050565b600081518084526111bd816020860160208601611175565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b8381101561129e578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc001855281518051845287810151888501528681015167ffffffffffffffff16878501526060808201519085015260809081015160a09185018290529061128a818601836111a5565b968901969450505090860190600101611216565b509098975050505050505050565b6020815260006106e760208301846111a5565b600080600080606085870312156112d557600080fd5b6112de8561108b565b935060208501359250604085013567ffffffffffffffff8082111561130257600080fd5b818701915087601f83011261131657600080fd5b81358181111561132557600080fd5b88602082850101111561133757600080fd5b95989497505060200194505050565b60006020828403121561135857600080fd5b5035919050565b60006020828403121561137157600080fd5b81356106e7816110a4565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156113ec57600080fd5b815167ffffffffffffffff8082111561140457600080fd5b818401915084601f83011261141857600080fd5b81518181111561142a5761142a6113ab565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611470576114706113ab565b8160405282815287602084870101111561148957600080fd5b61149a836020830160208801611175565b979650505050505050565b6000602082840312156114b757600080fd5b5051919050565b6000828210156114f7577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b500390565b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008660601b1681528460148201528360348201528183605483013760009101605401908152949350505050565b63ffffffff8516815283602082015260606040820152816060820152818360808301376000818301608090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101939250505056fea164736f6c634300080f000a496e697469616c697a61626c653a20636f6e7472616374206973206e6f742069", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [], - "value": 0 - }, - { - "accessor": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "account": "0x20B168142354Cee65a32f6D8cf3033E592299765", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x60806040523480156200001157600080fd5b506200001e600062000024565b62000292565b600054610100900460ff1615808015620000455750600054600160ff909116105b8062000075575062000062306200016260201b62000ce41760201c565b15801562000075575060005460ff166001145b620000de5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000102576000805461ff0019166101001790555b6200010c62000171565b6200011782620001d9565b80156200015e576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6001600160a01b03163b151590565b600054610100900460ff16620001cd5760405162461bcd60e51b815260206004820152602b60248201526000805160206200185983398151915260448201526a6e697469616c697a696e6760a81b6064820152608401620000d5565b620001d76200022b565b565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16620002875760405162461bcd60e51b815260206004820152602b60248201526000805160206200185983398151915260448201526a6e697469616c697a696e6760a81b6064820152608401620000d5565b620001d733620001d9565b6115b780620002a26000396000f3fe6080604052600436106100e85760003560e01c80636593dc6e1161008a57806396cd97201161005957806396cd972014610313578063bb8aa1fc14610333578063c4d66de814610394578063f2fde38b146103b457600080fd5b80636593dc6e14610293578063715018a6146102c057806382ecf2f6146102d55780638da5cb5b146102e857600080fd5b8063254bd683116100c6578063254bd6831461019c5780634d1975b4146101c957806354fd4d50146101e85780635f0150cb1461023e57600080fd5b806314f6b1a3146100ed5780631b685b9e1461010f5780631e3342401461017c575b600080fd5b3480156100f957600080fd5b5061010d6101083660046110c6565b6103d4565b005b34801561011b57600080fd5b5061015261012a3660046110fd565b60656020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561018857600080fd5b5061010d610197366004611118565b61045e565b3480156101a857600080fd5b506101bc6101b7366004611142565b6104aa565b60405161017391906111ef565b3480156101d557600080fd5b506068545b604051908152602001610173565b3480156101f457600080fd5b506102316040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b60405161017391906112ac565b34801561024a57600080fd5b5061025e6102593660046112bf565b6106ee565b6040805173ffffffffffffffffffffffffffffffffffffffff909316835267ffffffffffffffff909116602083015201610173565b34801561029f57600080fd5b506101da6102ae3660046110fd565b60666020526000908152604090205481565b3480156102cc57600080fd5b5061010d610741565b6101526102e33660046112bf565b610755565b3480156102f457600080fd5b5060335473ffffffffffffffffffffffffffffffffffffffff16610152565b34801561031f57600080fd5b506101da61032e3660046112bf565b6109ef565b34801561033f57600080fd5b5061035361034e366004611346565b610a28565b6040805163ffffffff909416845267ffffffffffffffff909216602084015273ffffffffffffffffffffffffffffffffffffffff1690820152606001610173565b3480156103a057600080fd5b5061010d6103af36600461135f565b610a91565b3480156103c057600080fd5b5061010d6103cf36600461135f565b610c2d565b6103dc610d00565b63ffffffff821660008181526065602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8616908117909155905190917fff513d80e2c7fa487608f70a618dfbc0cf415699dc69588c747e8c71566c88de91a35050565b610466610d00565b63ffffffff8216600081815260666020526040808220849055518392917f74d6665c4b26d5596a5aa13d3014e0c06af4d322075a797f87b03cd4c5bc91ca91a35050565b606854606090831015806104bc575081155b6106e7575060408051600583901b8101602001909152825b8381116106e5576000606882815481106104f0576104f061137c565b600091825260209091200154905060e081901c60a082901c67ffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff831663ffffffff891683036106b6576001865101865260008173ffffffffffffffffffffffffffffffffffffffff1663609d33346040518163ffffffff1660e01b8152600401600060405180830381865afa15801561058a573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526105d091908101906113da565b905060008273ffffffffffffffffffffffffffffffffffffffff1663bcef3b556040518163ffffffff1660e01b8152600401602060405180830381865afa15801561061f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064391906114a5565b90506040518060a001604052808881526020018781526020018567ffffffffffffffff168152602001828152602001838152508860018a5161068591906114be565b815181106106955761069561137c565b6020026020010181905250888851106106b3575050505050506106e5565b50505b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90920191506104d49050565b505b9392505050565b60008060006106ff878787876109ef565b60009081526067602052604090205473ffffffffffffffffffffffffffffffffffffffff81169860a09190911c67ffffffffffffffff16975095505050505050565b610749610d00565b6107536000610d81565b565b63ffffffff841660009081526065602052604081205473ffffffffffffffffffffffffffffffffffffffff16806107c5576040517f031c6de400000000000000000000000000000000000000000000000000000000815263ffffffff871660048201526024015b60405180910390fd5b63ffffffff86166000908152606660205260409020543414610813576040517f8620aa1900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006108206001436114be565b40905061088a338783888860405160200161083f9594939291906114fc565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905273ffffffffffffffffffffffffffffffffffffffff841690610df8565b92508273ffffffffffffffffffffffffffffffffffffffff16638129fc1c346040518263ffffffff1660e01b81526004016000604051808303818588803b1580156108d457600080fd5b505af11580156108e8573d6000803e3d6000fd5b505050505060006108fb888888886109ef565b60008181526067602052604090205490915015610947576040517f014f6fe5000000000000000000000000000000000000000000000000000000008152600481018290526024016107bc565b60004260a01b60e08a901b178517600083815260676020526040808220839055606880546001810182559083527fa2153420d844928b4421650203c77babc8b33d7f2e7b450e2966db0c220977530183905551919250899163ffffffff8c169173ffffffffffffffffffffffffffffffffffffffff8916917f5b565efe82411da98814f356d0e7bcb8f0219b8d970307c5afb4a6903a8b2e359190a450505050949350505050565b600084848484604051602001610a089493929190611549565b604051602081830303815290604052805190602001209050949350505050565b600080600080600080610a8160688881548110610a4757610a4761137c565b906000526020600020015460e081901c9160a082901c67ffffffffffffffff169173ffffffffffffffffffffffffffffffffffffffff1690565b9199909850909650945050505050565b600054610100900460ff1615808015610ab15750600054600160ff909116105b80610acb5750303b158015610acb575060005460ff166001145b610b57576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016107bc565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610bb557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610bbd610e06565b610bc682610d81565b8015610c2957600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b610c35610d00565b73ffffffffffffffffffffffffffffffffffffffff8116610cd8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016107bc565b610ce181610d81565b50565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b60335473ffffffffffffffffffffffffffffffffffffffff163314610753576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016107bc565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006106e760008484610ea5565b600054610100900460ff16610e9d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016107bc565b610753610feb565b600060608203516040830351602084035184518060208701018051600283016c5af43d3d93803e606057fd5bf3895289600d8a035278593da1005b363d3d373d3d3d3d610000806062363936013d738160481b1760218a03527f9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff603a8a035272fd6100003d81600a3d39f336602c57343d527f6062820160781b1761ff9e82106059018a03528060f01b8352606c8101604c8a038cf097505086610f715763301164256000526004601cfd5b905285527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08501527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08401527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa09092019190915292915050565b600054610100900460ff16611082576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016107bc565b61075333610d81565b803563ffffffff8116811461109f57600080fd5b919050565b73ffffffffffffffffffffffffffffffffffffffff81168114610ce157600080fd5b600080604083850312156110d957600080fd5b6110e28361108b565b915060208301356110f2816110a4565b809150509250929050565b60006020828403121561110f57600080fd5b6106e78261108b565b6000806040838503121561112b57600080fd5b6111348361108b565b946020939093013593505050565b60008060006060848603121561115757600080fd5b6111608461108b565b95602085013595506040909401359392505050565b60005b83811015611190578181015183820152602001611178565b8381111561119f576000848401525b50505050565b600081518084526111bd816020860160208601611175565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b8381101561129e578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc001855281518051845287810151888501528681015167ffffffffffffffff16878501526060808201519085015260809081015160a09185018290529061128a818601836111a5565b968901969450505090860190600101611216565b509098975050505050505050565b6020815260006106e760208301846111a5565b600080600080606085870312156112d557600080fd5b6112de8561108b565b935060208501359250604085013567ffffffffffffffff8082111561130257600080fd5b818701915087601f83011261131657600080fd5b81358181111561132557600080fd5b88602082850101111561133757600080fd5b95989497505060200194505050565b60006020828403121561135857600080fd5b5035919050565b60006020828403121561137157600080fd5b81356106e7816110a4565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156113ec57600080fd5b815167ffffffffffffffff8082111561140457600080fd5b818401915084601f83011261141857600080fd5b81518181111561142a5761142a6113ab565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611470576114706113ab565b8160405282815287602084870101111561148957600080fd5b61149a836020830160208801611175565b979650505050505050565b6000602082840312156114b757600080fd5b5051919050565b6000828210156114f7577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b500390565b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008660601b1681528460148201528360348201528183605483013760009101605401908152949350505050565b63ffffffff8516815283602082015260606040820152816060820152818360808301376000818301608090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101939250505056fea164736f6c634300080f000a496e697469616c697a61626c653a20636f6e7472616374206973206e6f742069", - "deployedCode": "0x6080604052600436106100e85760003560e01c80636593dc6e1161008a57806396cd97201161005957806396cd972014610313578063bb8aa1fc14610333578063c4d66de814610394578063f2fde38b146103b457600080fd5b80636593dc6e14610293578063715018a6146102c057806382ecf2f6146102d55780638da5cb5b146102e857600080fd5b8063254bd683116100c6578063254bd6831461019c5780634d1975b4146101c957806354fd4d50146101e85780635f0150cb1461023e57600080fd5b806314f6b1a3146100ed5780631b685b9e1461010f5780631e3342401461017c575b600080fd5b3480156100f957600080fd5b5061010d6101083660046110c6565b6103d4565b005b34801561011b57600080fd5b5061015261012a3660046110fd565b60656020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561018857600080fd5b5061010d610197366004611118565b61045e565b3480156101a857600080fd5b506101bc6101b7366004611142565b6104aa565b60405161017391906111ef565b3480156101d557600080fd5b506068545b604051908152602001610173565b3480156101f457600080fd5b506102316040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b60405161017391906112ac565b34801561024a57600080fd5b5061025e6102593660046112bf565b6106ee565b6040805173ffffffffffffffffffffffffffffffffffffffff909316835267ffffffffffffffff909116602083015201610173565b34801561029f57600080fd5b506101da6102ae3660046110fd565b60666020526000908152604090205481565b3480156102cc57600080fd5b5061010d610741565b6101526102e33660046112bf565b610755565b3480156102f457600080fd5b5060335473ffffffffffffffffffffffffffffffffffffffff16610152565b34801561031f57600080fd5b506101da61032e3660046112bf565b6109ef565b34801561033f57600080fd5b5061035361034e366004611346565b610a28565b6040805163ffffffff909416845267ffffffffffffffff909216602084015273ffffffffffffffffffffffffffffffffffffffff1690820152606001610173565b3480156103a057600080fd5b5061010d6103af36600461135f565b610a91565b3480156103c057600080fd5b5061010d6103cf36600461135f565b610c2d565b6103dc610d00565b63ffffffff821660008181526065602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8616908117909155905190917fff513d80e2c7fa487608f70a618dfbc0cf415699dc69588c747e8c71566c88de91a35050565b610466610d00565b63ffffffff8216600081815260666020526040808220849055518392917f74d6665c4b26d5596a5aa13d3014e0c06af4d322075a797f87b03cd4c5bc91ca91a35050565b606854606090831015806104bc575081155b6106e7575060408051600583901b8101602001909152825b8381116106e5576000606882815481106104f0576104f061137c565b600091825260209091200154905060e081901c60a082901c67ffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff831663ffffffff891683036106b6576001865101865260008173ffffffffffffffffffffffffffffffffffffffff1663609d33346040518163ffffffff1660e01b8152600401600060405180830381865afa15801561058a573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526105d091908101906113da565b905060008273ffffffffffffffffffffffffffffffffffffffff1663bcef3b556040518163ffffffff1660e01b8152600401602060405180830381865afa15801561061f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064391906114a5565b90506040518060a001604052808881526020018781526020018567ffffffffffffffff168152602001828152602001838152508860018a5161068591906114be565b815181106106955761069561137c565b6020026020010181905250888851106106b3575050505050506106e5565b50505b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90920191506104d49050565b505b9392505050565b60008060006106ff878787876109ef565b60009081526067602052604090205473ffffffffffffffffffffffffffffffffffffffff81169860a09190911c67ffffffffffffffff16975095505050505050565b610749610d00565b6107536000610d81565b565b63ffffffff841660009081526065602052604081205473ffffffffffffffffffffffffffffffffffffffff16806107c5576040517f031c6de400000000000000000000000000000000000000000000000000000000815263ffffffff871660048201526024015b60405180910390fd5b63ffffffff86166000908152606660205260409020543414610813576040517f8620aa1900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006108206001436114be565b40905061088a338783888860405160200161083f9594939291906114fc565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905273ffffffffffffffffffffffffffffffffffffffff841690610df8565b92508273ffffffffffffffffffffffffffffffffffffffff16638129fc1c346040518263ffffffff1660e01b81526004016000604051808303818588803b1580156108d457600080fd5b505af11580156108e8573d6000803e3d6000fd5b505050505060006108fb888888886109ef565b60008181526067602052604090205490915015610947576040517f014f6fe5000000000000000000000000000000000000000000000000000000008152600481018290526024016107bc565b60004260a01b60e08a901b178517600083815260676020526040808220839055606880546001810182559083527fa2153420d844928b4421650203c77babc8b33d7f2e7b450e2966db0c220977530183905551919250899163ffffffff8c169173ffffffffffffffffffffffffffffffffffffffff8916917f5b565efe82411da98814f356d0e7bcb8f0219b8d970307c5afb4a6903a8b2e359190a450505050949350505050565b600084848484604051602001610a089493929190611549565b604051602081830303815290604052805190602001209050949350505050565b600080600080600080610a8160688881548110610a4757610a4761137c565b906000526020600020015460e081901c9160a082901c67ffffffffffffffff169173ffffffffffffffffffffffffffffffffffffffff1690565b9199909850909650945050505050565b600054610100900460ff1615808015610ab15750600054600160ff909116105b80610acb5750303b158015610acb575060005460ff166001145b610b57576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016107bc565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610bb557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610bbd610e06565b610bc682610d81565b8015610c2957600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b610c35610d00565b73ffffffffffffffffffffffffffffffffffffffff8116610cd8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016107bc565b610ce181610d81565b50565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b60335473ffffffffffffffffffffffffffffffffffffffff163314610753576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016107bc565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006106e760008484610ea5565b600054610100900460ff16610e9d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016107bc565b610753610feb565b600060608203516040830351602084035184518060208701018051600283016c5af43d3d93803e606057fd5bf3895289600d8a035278593da1005b363d3d373d3d3d3d610000806062363936013d738160481b1760218a03527f9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff603a8a035272fd6100003d81600a3d39f336602c57343d527f6062820160781b1761ff9e82106059018a03528060f01b8352606c8101604c8a038cf097505086610f715763301164256000526004601cfd5b905285527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08501527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08401527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa09092019190915292915050565b600054610100900460ff16611082576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016107bc565b61075333610d81565b803563ffffffff8116811461109f57600080fd5b919050565b73ffffffffffffffffffffffffffffffffffffffff81168114610ce157600080fd5b600080604083850312156110d957600080fd5b6110e28361108b565b915060208301356110f2816110a4565b809150509250929050565b60006020828403121561110f57600080fd5b6106e78261108b565b6000806040838503121561112b57600080fd5b6111348361108b565b946020939093013593505050565b60008060006060848603121561115757600080fd5b6111608461108b565b95602085013595506040909401359392505050565b60005b83811015611190578181015183820152602001611178565b8381111561119f576000848401525b50505050565b600081518084526111bd816020860160208601611175565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b8381101561129e578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc001855281518051845287810151888501528681015167ffffffffffffffff16878501526060808201519085015260809081015160a09185018290529061128a818601836111a5565b968901969450505090860190600101611216565b509098975050505050505050565b6020815260006106e760208301846111a5565b600080600080606085870312156112d557600080fd5b6112de8561108b565b935060208501359250604085013567ffffffffffffffff8082111561130257600080fd5b818701915087601f83011261131657600080fd5b81358181111561132557600080fd5b88602082850101111561133757600080fd5b95989497505060200194505050565b60006020828403121561135857600080fd5b5035919050565b60006020828403121561137157600080fd5b81356106e7816110a4565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156113ec57600080fd5b815167ffffffffffffffff8082111561140457600080fd5b818401915084601f83011261141857600080fd5b81518181111561142a5761142a6113ab565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611470576114706113ab565b8160405282815287602084870101111561148957600080fd5b61149a836020830160208801611175565b979650505050505050565b6000602082840312156114b757600080fd5b5051919050565b6000828210156114f7577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b500390565b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008660601b1681528460148201528360348201528183605483013760009101605401908152949350505050565b63ffffffff8516815283602082015260606040820152816060820152818360808301376000818301608090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101939250505056fea164736f6c634300080f000a", - "initialized": true, - "kind": "Create", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x20B168142354Cee65a32f6D8cf3033E592299765", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x20B168142354Cee65a32f6D8cf3033E592299765", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x20B168142354Cee65a32f6D8cf3033E592299765", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x20B168142354Cee65a32f6D8cf3033E592299765", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x20B168142354Cee65a32f6D8cf3033E592299765", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x20B168142354Cee65a32f6D8cf3033E592299765", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x20B168142354Cee65a32f6D8cf3033E592299765", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x20B168142354Cee65a32f6D8cf3033E592299765", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x20B168142354Cee65a32f6D8cf3033E592299765", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - }, - { - "account": "0x20B168142354Cee65a32f6D8cf3033E592299765", - "isWrite": true, - "newValue": "0x0000000000000000000000004e59b44847b379578588920ca78fbf26c0b4956c", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - }, - { - "account": "0x20B168142354Cee65a32f6D8cf3033E592299765", - "isWrite": false, - "newValue": "0x0000000000000000000000004e59b44847b379578588920ca78fbf26c0b4956c", - "previousValue": "0x0000000000000000000000004e59b44847b379578588920ca78fbf26c0b4956c", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - }, - { - "account": "0x20B168142354Cee65a32f6D8cf3033E592299765", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000004e59b44847b379578588920ca78fbf26c0b4956c", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - }, - { - "account": "0x20B168142354Cee65a32f6D8cf3033E592299765", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x20B168142354Cee65a32f6D8cf3033E592299765", - "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": "0x20B168142354Cee65a32f6D8cf3033E592299765", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x8da5cb5b", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x20B168142354Cee65a32f6D8cf3033E592299765", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - } - ], - "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": "0x7a07653f", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000093a80", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000093a80", - "reverted": false, - "slot": "0x000000000000000000000000000000000000000000000000000000000000003b" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x638627e586f5e36fe67a77519503a7c6da22f92b150d3c6055fd40bdcfe9ffd160a06040523480156200001157600080fd5b506040516200192f3803806200192f8339810160408190526200003491620002d7565b6080819052620000466000806200004d565b50620002f1565b600054610100900460ff16158080156200006e5750600054600160ff909116105b806200009e57506200008b30620001a760201b620011041760201c565b1580156200009e575060005460ff166001145b620001075760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff1916600117905580156200012b576000805461ff0019166101001790555b62000135620001b6565b62000140836200021e565b606880546001600160a01b0319166001600160a01b0384161790558015620001a2576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b6001600160a01b03163b151590565b600054610100900460ff16620002125760405162461bcd60e51b815260206004820152602b60248201526000805160206200190f83398151915260448201526a6e697469616c697a696e6760a81b6064820152608401620000fe565b6200021c62000270565b565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16620002cc5760405162461bcd60e51b815260206004820152602b60248201526000805160206200190f83398151915260448201526a6e697469616c697a696e6760a81b6064820152608401620000fe565b6200021c336200021e565b600060208284031215620002ea57600080fd5b5051919050565b6080516115fb620003146000396000818161033f015261102501526115fb6000f3fe6080604052600436106101845760003560e01c8063715018a6116100d6578063a9059cbb1161007f578063dd62ed3e11610059578063dd62ed3e1461051c578063f2fde38b14610554578063f3fef3a31461057457610193565b8063a9059cbb146104a8578063cd47bde1146104c8578063d0e30db01461019357610193565b80638da5cb5b116100b05780638da5cb5b1461041757806395d89b4114610442578063977a5ec51461048857610193565b8063715018a61461039057806379502c55146103a55780637eee288d146103f757610193565b80632e1a7d4d1161013857806354fd4d501161011257806354fd4d50146102e75780636a42b8f81461033057806370a082311461036357610193565b80632e1a7d4d14610280578063313ce567146102a0578063485cc955146102c757610193565b80630ca35682116101695780630ca356821461022357806318160ddd1461024357806323b872dd1461026057610193565b806306fdde031461019b578063095ea7b3146101f357610193565b3661019357610191610594565b005b610191610594565b3480156101a757600080fd5b5060408051808201909152600d81527f577261707065642045746865720000000000000000000000000000000000000060208201525b6040516101ea91906113fd565b60405180910390f35b3480156101ff57600080fd5b5061021361020e366004611492565b6105ef565b60405190151581526020016101ea565b34801561022f57600080fd5b5061019161023e3660046114be565b610668565b34801561024f57600080fd5b50475b6040519081526020016101ea565b34801561026c57600080fd5b5061021361027b3660046114d7565b6107b9565b34801561028c57600080fd5b5061019161029b3660046114be565b6109d0565b3480156102ac57600080fd5b506102b5601281565b60405160ff90911681526020016101ea565b3480156102d357600080fd5b506101916102e2366004611518565b6109dd565b3480156102f357600080fd5b506101dd6040518060400160405280600a81526020017f312e312e302d72632e310000000000000000000000000000000000000000000081525081565b34801561033c57600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610252565b34801561036f57600080fd5b5061025261037e366004611551565b60656020526000908152604090205481565b34801561039c57600080fd5b50610191610bb9565b3480156103b157600080fd5b506068546103d29073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101ea565b34801561040357600080fd5b50610191610412366004611492565b610bcd565b34801561042357600080fd5b5060335473ffffffffffffffffffffffffffffffffffffffff166103d2565b34801561044e57600080fd5b5060408051808201909152600481527f574554480000000000000000000000000000000000000000000000000000000060208201526101dd565b34801561049457600080fd5b506101916104a3366004611492565b610c21565b3480156104b457600080fd5b506102136104c3366004611492565b610d0e565b3480156104d457600080fd5b506105076104e3366004611518565b60676020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016101ea565b34801561052857600080fd5b50610252610537366004611518565b606660209081526000928352604080842090915290825290205481565b34801561056057600080fd5b5061019161056f366004611551565b610d22565b34801561058057600080fd5b5061019161058f366004611492565b610dd6565b33600090815260656020526040812080543492906105b390849061159d565b909155505060405134815233907fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9060200160405180910390a2565b33600081815260666020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906106579086815260200190565b60405180910390a350600192915050565b60335473ffffffffffffffffffffffffffffffffffffffff1633146106ee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f44656c61796564574554483a206e6f74206f776e65720000000000000000000060448201526064015b60405180910390fd5b60004782106106fd57476106ff565b815b604051909150600090339083908381818185875af1925050503d8060008114610744576040519150601f19603f3d011682016040523d82523d6000602084013e610749565b606091505b50509050806107b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f44656c61796564574554483a207265636f766572206661696c6564000000000060448201526064016106e5565b505050565b73ffffffffffffffffffffffffffffffffffffffff83166000908152606560205260408120548211156107eb57600080fd5b73ffffffffffffffffffffffffffffffffffffffff84163314801590610861575073ffffffffffffffffffffffffffffffffffffffff841660009081526066602090815260408083203384529091529020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14155b156108e95773ffffffffffffffffffffffffffffffffffffffff841660009081526066602090815260408083203384529091529020548211156108a357600080fd5b73ffffffffffffffffffffffffffffffffffffffff84166000908152606660209081526040808320338452909152812080548492906108e39084906115b5565b90915550505b73ffffffffffffffffffffffffffffffffffffffff84166000908152606560205260408120805484929061091e9084906115b5565b909155505073ffffffffffffffffffffffffffffffffffffffff83166000908152606560205260408120805484929061095890849061159d565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516109be91815260200190565b60405180910390a35060019392505050565b6109da3382610dd6565b50565b600054610100900460ff16158080156109fd5750600054600160ff909116105b80610a175750303b158015610a17575060005460ff166001145b610aa3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016106e5565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610b0157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610b09611120565b610b12836111bf565b606880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff841617905580156107b457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a1505050565b610bc1611236565b610bcb60006111bf565b565b33600090815260676020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091528120426001820155805490918391839190610c1790849061159d565b9091555050505050565b60335473ffffffffffffffffffffffffffffffffffffffff163314610ca2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f44656c61796564574554483a206e6f74206f776e65720000000000000000000060448201526064016106e5565b73ffffffffffffffffffffffffffffffffffffffff821660008181526066602090815260408083203380855290835292819020859055518481529192917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a35050565b6000610d1b3384846107b9565b9392505050565b610d2a611236565b73ffffffffffffffffffffffffffffffffffffffff8116610dcd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016106e5565b6109da816111bf565b606860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e6791906115cc565b15610ece576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f44656c61796564574554483a20636f6e7472616374206973207061757365640060448201526064016106e5565b33600090815260676020908152604080832073ffffffffffffffffffffffffffffffffffffffff8616845290915290208054821115610f8f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f44656c61796564574554483a20696e73756666696369656e7420756e6c6f636b60448201527f6564207769746864726177616c0000000000000000000000000000000000000060648201526084016106e5565b6000816001015411611022576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f44656c61796564574554483a207769746864726177616c206e6f7420756e6c6f60448201527f636b65640000000000000000000000000000000000000000000000000000000060648201526084016106e5565b427f00000000000000000000000000000000000000000000000000000000000000008260010154611053919061159d565b11156110e1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f44656c61796564574554483a207769746864726177616c2064656c6179206e6f60448201527f74206d657400000000000000000000000000000000000000000000000000000060648201526084016106e5565b818160000160008282546110f591906115b5565b909155506107b49050826112b7565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b600054610100900460ff166111b7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016106e5565b610bcb61135d565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60335473ffffffffffffffffffffffffffffffffffffffff163314610bcb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106e5565b336000908152606560205260409020548111156112d357600080fd5b33600090815260656020526040812080548392906112f29084906115b5565b9091555050604051339082156108fc029083906000818181858888f19350505050158015611324573d6000803e3d6000fd5b5060405181815233907f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b659060200160405180910390a250565b600054610100900460ff166113f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016106e5565b610bcb336111bf565b600060208083528351808285015260005b8181101561142a5785810183015185820160400152820161140e565b8181111561143c576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b73ffffffffffffffffffffffffffffffffffffffff811681146109da57600080fd5b600080604083850312156114a557600080fd5b82356114b081611470565b946020939093013593505050565b6000602082840312156114d057600080fd5b5035919050565b6000806000606084860312156114ec57600080fd5b83356114f781611470565b9250602084013561150781611470565b929592945050506040919091013590565b6000806040838503121561152b57600080fd5b823561153681611470565b9150602083013561154681611470565b809150509250929050565b60006020828403121561156357600080fd5b8135610d1b81611470565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156115b0576115b061156e565b500190565b6000828210156115c7576115c761156e565b500390565b6000602082840312156115de57600080fd5b81518015158114610d1b57600080fdfea164736f6c634300080f000a496e697469616c697a61626c653a20636f6e7472616374206973206e6f7420690000000000000000000000000000000000000000000000000000000000093a80", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [], - "value": 0 - }, - { - "accessor": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "account": "0x2A6347EDD3C7813CDE46DD7eA61FF1Cf2290BC05", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x60a06040523480156200001157600080fd5b506040516200192f3803806200192f8339810160408190526200003491620002d7565b6080819052620000466000806200004d565b50620002f1565b600054610100900460ff16158080156200006e5750600054600160ff909116105b806200009e57506200008b30620001a760201b620011041760201c565b1580156200009e575060005460ff166001145b620001075760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff1916600117905580156200012b576000805461ff0019166101001790555b62000135620001b6565b62000140836200021e565b606880546001600160a01b0319166001600160a01b0384161790558015620001a2576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b6001600160a01b03163b151590565b600054610100900460ff16620002125760405162461bcd60e51b815260206004820152602b60248201526000805160206200190f83398151915260448201526a6e697469616c697a696e6760a81b6064820152608401620000fe565b6200021c62000270565b565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16620002cc5760405162461bcd60e51b815260206004820152602b60248201526000805160206200190f83398151915260448201526a6e697469616c697a696e6760a81b6064820152608401620000fe565b6200021c336200021e565b600060208284031215620002ea57600080fd5b5051919050565b6080516115fb620003146000396000818161033f015261102501526115fb6000f3fe6080604052600436106101845760003560e01c8063715018a6116100d6578063a9059cbb1161007f578063dd62ed3e11610059578063dd62ed3e1461051c578063f2fde38b14610554578063f3fef3a31461057457610193565b8063a9059cbb146104a8578063cd47bde1146104c8578063d0e30db01461019357610193565b80638da5cb5b116100b05780638da5cb5b1461041757806395d89b4114610442578063977a5ec51461048857610193565b8063715018a61461039057806379502c55146103a55780637eee288d146103f757610193565b80632e1a7d4d1161013857806354fd4d501161011257806354fd4d50146102e75780636a42b8f81461033057806370a082311461036357610193565b80632e1a7d4d14610280578063313ce567146102a0578063485cc955146102c757610193565b80630ca35682116101695780630ca356821461022357806318160ddd1461024357806323b872dd1461026057610193565b806306fdde031461019b578063095ea7b3146101f357610193565b3661019357610191610594565b005b610191610594565b3480156101a757600080fd5b5060408051808201909152600d81527f577261707065642045746865720000000000000000000000000000000000000060208201525b6040516101ea91906113fd565b60405180910390f35b3480156101ff57600080fd5b5061021361020e366004611492565b6105ef565b60405190151581526020016101ea565b34801561022f57600080fd5b5061019161023e3660046114be565b610668565b34801561024f57600080fd5b50475b6040519081526020016101ea565b34801561026c57600080fd5b5061021361027b3660046114d7565b6107b9565b34801561028c57600080fd5b5061019161029b3660046114be565b6109d0565b3480156102ac57600080fd5b506102b5601281565b60405160ff90911681526020016101ea565b3480156102d357600080fd5b506101916102e2366004611518565b6109dd565b3480156102f357600080fd5b506101dd6040518060400160405280600a81526020017f312e312e302d72632e310000000000000000000000000000000000000000000081525081565b34801561033c57600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610252565b34801561036f57600080fd5b5061025261037e366004611551565b60656020526000908152604090205481565b34801561039c57600080fd5b50610191610bb9565b3480156103b157600080fd5b506068546103d29073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101ea565b34801561040357600080fd5b50610191610412366004611492565b610bcd565b34801561042357600080fd5b5060335473ffffffffffffffffffffffffffffffffffffffff166103d2565b34801561044e57600080fd5b5060408051808201909152600481527f574554480000000000000000000000000000000000000000000000000000000060208201526101dd565b34801561049457600080fd5b506101916104a3366004611492565b610c21565b3480156104b457600080fd5b506102136104c3366004611492565b610d0e565b3480156104d457600080fd5b506105076104e3366004611518565b60676020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016101ea565b34801561052857600080fd5b50610252610537366004611518565b606660209081526000928352604080842090915290825290205481565b34801561056057600080fd5b5061019161056f366004611551565b610d22565b34801561058057600080fd5b5061019161058f366004611492565b610dd6565b33600090815260656020526040812080543492906105b390849061159d565b909155505060405134815233907fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9060200160405180910390a2565b33600081815260666020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906106579086815260200190565b60405180910390a350600192915050565b60335473ffffffffffffffffffffffffffffffffffffffff1633146106ee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f44656c61796564574554483a206e6f74206f776e65720000000000000000000060448201526064015b60405180910390fd5b60004782106106fd57476106ff565b815b604051909150600090339083908381818185875af1925050503d8060008114610744576040519150601f19603f3d011682016040523d82523d6000602084013e610749565b606091505b50509050806107b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f44656c61796564574554483a207265636f766572206661696c6564000000000060448201526064016106e5565b505050565b73ffffffffffffffffffffffffffffffffffffffff83166000908152606560205260408120548211156107eb57600080fd5b73ffffffffffffffffffffffffffffffffffffffff84163314801590610861575073ffffffffffffffffffffffffffffffffffffffff841660009081526066602090815260408083203384529091529020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14155b156108e95773ffffffffffffffffffffffffffffffffffffffff841660009081526066602090815260408083203384529091529020548211156108a357600080fd5b73ffffffffffffffffffffffffffffffffffffffff84166000908152606660209081526040808320338452909152812080548492906108e39084906115b5565b90915550505b73ffffffffffffffffffffffffffffffffffffffff84166000908152606560205260408120805484929061091e9084906115b5565b909155505073ffffffffffffffffffffffffffffffffffffffff83166000908152606560205260408120805484929061095890849061159d565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516109be91815260200190565b60405180910390a35060019392505050565b6109da3382610dd6565b50565b600054610100900460ff16158080156109fd5750600054600160ff909116105b80610a175750303b158015610a17575060005460ff166001145b610aa3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016106e5565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610b0157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610b09611120565b610b12836111bf565b606880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff841617905580156107b457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a1505050565b610bc1611236565b610bcb60006111bf565b565b33600090815260676020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091528120426001820155805490918391839190610c1790849061159d565b9091555050505050565b60335473ffffffffffffffffffffffffffffffffffffffff163314610ca2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f44656c61796564574554483a206e6f74206f776e65720000000000000000000060448201526064016106e5565b73ffffffffffffffffffffffffffffffffffffffff821660008181526066602090815260408083203380855290835292819020859055518481529192917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a35050565b6000610d1b3384846107b9565b9392505050565b610d2a611236565b73ffffffffffffffffffffffffffffffffffffffff8116610dcd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016106e5565b6109da816111bf565b606860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e6791906115cc565b15610ece576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f44656c61796564574554483a20636f6e7472616374206973207061757365640060448201526064016106e5565b33600090815260676020908152604080832073ffffffffffffffffffffffffffffffffffffffff8616845290915290208054821115610f8f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f44656c61796564574554483a20696e73756666696369656e7420756e6c6f636b60448201527f6564207769746864726177616c0000000000000000000000000000000000000060648201526084016106e5565b6000816001015411611022576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f44656c61796564574554483a207769746864726177616c206e6f7420756e6c6f60448201527f636b65640000000000000000000000000000000000000000000000000000000060648201526084016106e5565b427f00000000000000000000000000000000000000000000000000000000000000008260010154611053919061159d565b11156110e1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f44656c61796564574554483a207769746864726177616c2064656c6179206e6f60448201527f74206d657400000000000000000000000000000000000000000000000000000060648201526084016106e5565b818160000160008282546110f591906115b5565b909155506107b49050826112b7565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b600054610100900460ff166111b7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016106e5565b610bcb61135d565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60335473ffffffffffffffffffffffffffffffffffffffff163314610bcb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106e5565b336000908152606560205260409020548111156112d357600080fd5b33600090815260656020526040812080548392906112f29084906115b5565b9091555050604051339082156108fc029083906000818181858888f19350505050158015611324573d6000803e3d6000fd5b5060405181815233907f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b659060200160405180910390a250565b600054610100900460ff166113f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016106e5565b610bcb336111bf565b600060208083528351808285015260005b8181101561142a5785810183015185820160400152820161140e565b8181111561143c576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b73ffffffffffffffffffffffffffffffffffffffff811681146109da57600080fd5b600080604083850312156114a557600080fd5b82356114b081611470565b946020939093013593505050565b6000602082840312156114d057600080fd5b5035919050565b6000806000606084860312156114ec57600080fd5b83356114f781611470565b9250602084013561150781611470565b929592945050506040919091013590565b6000806040838503121561152b57600080fd5b823561153681611470565b9150602083013561154681611470565b809150509250929050565b60006020828403121561156357600080fd5b8135610d1b81611470565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156115b0576115b061156e565b500190565b6000828210156115c7576115c761156e565b500390565b6000602082840312156115de57600080fd5b81518015158114610d1b57600080fdfea164736f6c634300080f000a496e697469616c697a61626c653a20636f6e7472616374206973206e6f7420690000000000000000000000000000000000000000000000000000000000093a80", - "deployedCode": "0x6080604052600436106101845760003560e01c8063715018a6116100d6578063a9059cbb1161007f578063dd62ed3e11610059578063dd62ed3e1461051c578063f2fde38b14610554578063f3fef3a31461057457610193565b8063a9059cbb146104a8578063cd47bde1146104c8578063d0e30db01461019357610193565b80638da5cb5b116100b05780638da5cb5b1461041757806395d89b4114610442578063977a5ec51461048857610193565b8063715018a61461039057806379502c55146103a55780637eee288d146103f757610193565b80632e1a7d4d1161013857806354fd4d501161011257806354fd4d50146102e75780636a42b8f81461033057806370a082311461036357610193565b80632e1a7d4d14610280578063313ce567146102a0578063485cc955146102c757610193565b80630ca35682116101695780630ca356821461022357806318160ddd1461024357806323b872dd1461026057610193565b806306fdde031461019b578063095ea7b3146101f357610193565b3661019357610191610594565b005b610191610594565b3480156101a757600080fd5b5060408051808201909152600d81527f577261707065642045746865720000000000000000000000000000000000000060208201525b6040516101ea91906113fd565b60405180910390f35b3480156101ff57600080fd5b5061021361020e366004611492565b6105ef565b60405190151581526020016101ea565b34801561022f57600080fd5b5061019161023e3660046114be565b610668565b34801561024f57600080fd5b50475b6040519081526020016101ea565b34801561026c57600080fd5b5061021361027b3660046114d7565b6107b9565b34801561028c57600080fd5b5061019161029b3660046114be565b6109d0565b3480156102ac57600080fd5b506102b5601281565b60405160ff90911681526020016101ea565b3480156102d357600080fd5b506101916102e2366004611518565b6109dd565b3480156102f357600080fd5b506101dd6040518060400160405280600a81526020017f312e312e302d72632e310000000000000000000000000000000000000000000081525081565b34801561033c57600080fd5b507f0000000000000000000000000000000000000000000000000000000000093a80610252565b34801561036f57600080fd5b5061025261037e366004611551565b60656020526000908152604090205481565b34801561039c57600080fd5b50610191610bb9565b3480156103b157600080fd5b506068546103d29073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101ea565b34801561040357600080fd5b50610191610412366004611492565b610bcd565b34801561042357600080fd5b5060335473ffffffffffffffffffffffffffffffffffffffff166103d2565b34801561044e57600080fd5b5060408051808201909152600481527f574554480000000000000000000000000000000000000000000000000000000060208201526101dd565b34801561049457600080fd5b506101916104a3366004611492565b610c21565b3480156104b457600080fd5b506102136104c3366004611492565b610d0e565b3480156104d457600080fd5b506105076104e3366004611518565b60676020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016101ea565b34801561052857600080fd5b50610252610537366004611518565b606660209081526000928352604080842090915290825290205481565b34801561056057600080fd5b5061019161056f366004611551565b610d22565b34801561058057600080fd5b5061019161058f366004611492565b610dd6565b33600090815260656020526040812080543492906105b390849061159d565b909155505060405134815233907fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9060200160405180910390a2565b33600081815260666020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906106579086815260200190565b60405180910390a350600192915050565b60335473ffffffffffffffffffffffffffffffffffffffff1633146106ee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f44656c61796564574554483a206e6f74206f776e65720000000000000000000060448201526064015b60405180910390fd5b60004782106106fd57476106ff565b815b604051909150600090339083908381818185875af1925050503d8060008114610744576040519150601f19603f3d011682016040523d82523d6000602084013e610749565b606091505b50509050806107b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f44656c61796564574554483a207265636f766572206661696c6564000000000060448201526064016106e5565b505050565b73ffffffffffffffffffffffffffffffffffffffff83166000908152606560205260408120548211156107eb57600080fd5b73ffffffffffffffffffffffffffffffffffffffff84163314801590610861575073ffffffffffffffffffffffffffffffffffffffff841660009081526066602090815260408083203384529091529020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14155b156108e95773ffffffffffffffffffffffffffffffffffffffff841660009081526066602090815260408083203384529091529020548211156108a357600080fd5b73ffffffffffffffffffffffffffffffffffffffff84166000908152606660209081526040808320338452909152812080548492906108e39084906115b5565b90915550505b73ffffffffffffffffffffffffffffffffffffffff84166000908152606560205260408120805484929061091e9084906115b5565b909155505073ffffffffffffffffffffffffffffffffffffffff83166000908152606560205260408120805484929061095890849061159d565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516109be91815260200190565b60405180910390a35060019392505050565b6109da3382610dd6565b50565b600054610100900460ff16158080156109fd5750600054600160ff909116105b80610a175750303b158015610a17575060005460ff166001145b610aa3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016106e5565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610b0157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610b09611120565b610b12836111bf565b606880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff841617905580156107b457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a1505050565b610bc1611236565b610bcb60006111bf565b565b33600090815260676020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091528120426001820155805490918391839190610c1790849061159d565b9091555050505050565b60335473ffffffffffffffffffffffffffffffffffffffff163314610ca2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f44656c61796564574554483a206e6f74206f776e65720000000000000000000060448201526064016106e5565b73ffffffffffffffffffffffffffffffffffffffff821660008181526066602090815260408083203380855290835292819020859055518481529192917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a35050565b6000610d1b3384846107b9565b9392505050565b610d2a611236565b73ffffffffffffffffffffffffffffffffffffffff8116610dcd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016106e5565b6109da816111bf565b606860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e6791906115cc565b15610ece576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f44656c61796564574554483a20636f6e7472616374206973207061757365640060448201526064016106e5565b33600090815260676020908152604080832073ffffffffffffffffffffffffffffffffffffffff8616845290915290208054821115610f8f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f44656c61796564574554483a20696e73756666696369656e7420756e6c6f636b60448201527f6564207769746864726177616c0000000000000000000000000000000000000060648201526084016106e5565b6000816001015411611022576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f44656c61796564574554483a207769746864726177616c206e6f7420756e6c6f60448201527f636b65640000000000000000000000000000000000000000000000000000000060648201526084016106e5565b427f0000000000000000000000000000000000000000000000000000000000093a808260010154611053919061159d565b11156110e1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f44656c61796564574554483a207769746864726177616c2064656c6179206e6f60448201527f74206d657400000000000000000000000000000000000000000000000000000060648201526084016106e5565b818160000160008282546110f591906115b5565b909155506107b49050826112b7565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b600054610100900460ff166111b7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016106e5565b610bcb61135d565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60335473ffffffffffffffffffffffffffffffffffffffff163314610bcb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106e5565b336000908152606560205260409020548111156112d357600080fd5b33600090815260656020526040812080548392906112f29084906115b5565b9091555050604051339082156108fc029083906000818181858888f19350505050158015611324573d6000803e3d6000fd5b5060405181815233907f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b659060200160405180910390a250565b600054610100900460ff166113f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016106e5565b610bcb336111bf565b600060208083528351808285015260005b8181101561142a5785810183015185820160400152820161140e565b8181111561143c576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b73ffffffffffffffffffffffffffffffffffffffff811681146109da57600080fd5b600080604083850312156114a557600080fd5b82356114b081611470565b946020939093013593505050565b6000602082840312156114d057600080fd5b5035919050565b6000806000606084860312156114ec57600080fd5b83356114f781611470565b9250602084013561150781611470565b929592945050506040919091013590565b6000806040838503121561152b57600080fd5b823561153681611470565b9150602083013561154681611470565b809150509250929050565b60006020828403121561156357600080fd5b8135610d1b81611470565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156115b0576115b061156e565b500190565b6000828210156115c7576115c761156e565b500390565b6000602082840312156115de57600080fd5b81518015158114610d1b57600080fdfea164736f6c634300080f000a", - "initialized": true, - "kind": "Create", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x2A6347EDD3C7813CDE46DD7eA61FF1Cf2290BC05", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x2A6347EDD3C7813CDE46DD7eA61FF1Cf2290BC05", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x2A6347EDD3C7813CDE46DD7eA61FF1Cf2290BC05", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x2A6347EDD3C7813CDE46DD7eA61FF1Cf2290BC05", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x2A6347EDD3C7813CDE46DD7eA61FF1Cf2290BC05", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x2A6347EDD3C7813CDE46DD7eA61FF1Cf2290BC05", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x2A6347EDD3C7813CDE46DD7eA61FF1Cf2290BC05", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x2A6347EDD3C7813CDE46DD7eA61FF1Cf2290BC05", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x2A6347EDD3C7813CDE46DD7eA61FF1Cf2290BC05", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - }, - { - "account": "0x2A6347EDD3C7813CDE46DD7eA61FF1Cf2290BC05", - "isWrite": true, - "newValue": "0x0000000000000000000000004e59b44847b379578588920ca78fbf26c0b4956c", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - }, - { - "account": "0x2A6347EDD3C7813CDE46DD7eA61FF1Cf2290BC05", - "isWrite": false, - "newValue": "0x0000000000000000000000004e59b44847b379578588920ca78fbf26c0b4956c", - "previousValue": "0x0000000000000000000000004e59b44847b379578588920ca78fbf26c0b4956c", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - }, - { - "account": "0x2A6347EDD3C7813CDE46DD7eA61FF1Cf2290BC05", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000004e59b44847b379578588920ca78fbf26c0b4956c", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - }, - { - "account": "0x2A6347EDD3C7813CDE46DD7eA61FF1Cf2290BC05", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000068" - }, - { - "account": "0x2A6347EDD3C7813CDE46DD7eA61FF1Cf2290BC05", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000068" - }, - { - "account": "0x2A6347EDD3C7813CDE46DD7eA61FF1Cf2290BC05", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x2A6347EDD3C7813CDE46DD7eA61FF1Cf2290BC05", - "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": "0x2A6347EDD3C7813CDE46DD7eA61FF1Cf2290BC05", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x8da5cb5b", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x2A6347EDD3C7813CDE46DD7eA61FF1Cf2290BC05", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x7a07653f", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000093a80", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000093a80", - "reverted": false, - "slot": "0x000000000000000000000000000000000000000000000000000000000000003b" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x2A6347EDD3C7813CDE46DD7eA61FF1Cf2290BC05", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x6a42b8f8", - "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": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x6d74ca1f", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000002710", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000002710", - "reverted": false, - "slot": "0x000000000000000000000000000000000000000000000000000000000000003c" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xf0deb91f", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000078", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000078", - "reverted": false, - "slot": "0x000000000000000000000000000000000000000000000000000000000000003d" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x638627e586f5e36fe67a77519503a7c6da22f92b150d3c6055fd40bdcfe9ffd160c06040523480156200001157600080fd5b5060405162003b6038038062003b6083398101604081905262000034916200014f565b60a082905260808190526001600160401b038111156200009a5760405162461bcd60e51b815260206004820152601a60248201527f6368616c6c656e676520706572696f6420746f6f206c61726765000000000000604482015260640160405180910390fd5b60005b620000ab600160106200018a565b811015620001465760038160108110620000c957620000c9620001a4565b015460038260108110620000e157620000e1620001a4565b01546040805160208101939093528201526060016040516020818303038152906040528051906020012060038260016200011c9190620001ba565b601081106200012f576200012f620001a4565b0155806200013d81620001d5565b9150506200009d565b505050620001f1565b600080604083850312156200016357600080fd5b505080516020909101519092909150565b634e487b7160e01b600052601160045260246000fd5b6000828210156200019f576200019f62000174565b500390565b634e487b7160e01b600052603260045260246000fd5b60008219821115620001d057620001d062000174565b500190565b600060018201620001ea57620001ea62000174565b5060010190565b60805160a05161393b62000225600039600081816105b00152611dea0152600081816106b001526114f3015261393b6000f3fe6080604052600436106101d85760003560e01c80639d53a64811610102578063ddcd58de11610095578063ec5efcbc11610064578063ec5efcbc14610681578063f3f480d9146106a1578063faf37bc7146106d4578063fef2b4ed146106e757600080fd5b8063ddcd58de146105d4578063e03110e11461060c578063e159261114610641578063ea7139501461066157600080fd5b8063b5e7154c116100d1578063b5e7154c14610555578063d18534b51461056c578063da35c6641461058c578063dd24f9bf146105a157600080fd5b80639d53a6481461048e5780639d7e8769146104dd578063b2e67ba8146104fd578063b4801e611461053557600080fd5b806361238bde1161017a5780637ac54767116101495780637ac54767146103ca5780638542cf50146103ea578063882856ef146104355780638dc4be111461046e57600080fd5b806361238bde1461031e5780636551927b146103565780637051472e1461038e5780637917de1d146103aa57600080fd5b80633909af5c116101b65780633909af5c146102715780634d52b4c91461029357806352f0f3ad146102a857806354fd4d50146102c857600080fd5b8063013cf08b146101dd5780630359a5631461022e5780632055b36b1461025c575b600080fd5b3480156101e957600080fd5b506101fd6101f8366004612e29565b610714565b6040805173ffffffffffffffffffffffffffffffffffffffff90931683526020830191909152015b60405180910390f35b34801561023a57600080fd5b5061024e610249366004612e6b565b610759565b604051908152602001610225565b34801561026857600080fd5b5061024e601081565b34801561027d57600080fd5b5061029161028c366004613073565b610891565b005b34801561029f57600080fd5b5061024e610ae8565b3480156102b457600080fd5b5061024e6102c336600461315f565b610b03565b3480156102d457600080fd5b506103116040518060400160405280600a81526020017f312e312e322d72632e310000000000000000000000000000000000000000000081525081565b60405161022591906131c6565b34801561032a57600080fd5b5061024e610339366004613217565b600160209081526000928352604080842090915290825290205481565b34801561036257600080fd5b5061024e610371366004612e6b565b601560209081526000928352604080842090915290825290205481565b34801561039a57600080fd5b5061024e6703782dace9d9000081565b3480156103b657600080fd5b506102916103c536600461327b565b610bd9565b3480156103d657600080fd5b5061024e6103e5366004612e29565b6110dc565b3480156103f657600080fd5b50610425610405366004613217565b600260209081526000928352604080842090915290825290205460ff1681565b6040519015158152602001610225565b34801561044157600080fd5b50610455610450366004613317565b6110f3565b60405167ffffffffffffffff9091168152602001610225565b34801561047a57600080fd5b5061029161048936600461334a565b61114d565b34801561049a57600080fd5b5061024e6104a9366004612e6b565b73ffffffffffffffffffffffffffffffffffffffff9091166000908152601860209081526040808320938352929052205490565b3480156104e957600080fd5b506102916104f8366004613396565b611248565b34801561050957600080fd5b5061024e610518366004612e6b565b601760209081526000928352604080842090915290825290205481565b34801561054157600080fd5b5061024e610550366004613317565b6113ff565b34801561056157600080fd5b5061024e620186a081565b34801561057857600080fd5b50610291610587366004613073565b611431565b34801561059857600080fd5b5060135461024e565b3480156105ad57600080fd5b507f000000000000000000000000000000000000000000000000000000000000000061024e565b3480156105e057600080fd5b5061024e6105ef366004612e6b565b601660209081526000928352604080842090915290825290205481565b34801561061857600080fd5b5061062c610627366004613217565b611840565b60408051928352602083019190915201610225565b34801561064d57600080fd5b5061029161065c36600461334a565b611931565b34801561066d57600080fd5b5061029161067c366004613422565b611a39565b34801561068d57600080fd5b5061029161069c366004613491565b611b98565b3480156106ad57600080fd5b507f000000000000000000000000000000000000000000000000000000000000000061024e565b6102916106e2366004613519565b611d1e565b3480156106f357600080fd5b5061024e610702366004612e29565b60006020819052908152604090205481565b6013818154811061072457600080fd5b60009182526020909120600290910201805460019091015473ffffffffffffffffffffffffffffffffffffffff909116915082565b73ffffffffffffffffffffffffffffffffffffffff82166000908152601560209081526040808320848452909152812054819061079c9060601c63ffffffff1690565b63ffffffff16905060005b6010811015610889578160011660010361082f5773ffffffffffffffffffffffffffffffffffffffff85166000908152601460209081526040808320878452909152902081601081106107fc576107fc613555565b01546040805160208101929092528101849052606001604051602081830303815290604052805190602001209250610870565b826003826010811061084357610843613555565b01546040805160208101939093528201526060016040516020818303038152906040528051906020012092505b60019190911c9080610881816135b3565b9150506107a7565b505092915050565b600061089d8a8a610759565b90506108c086868360208b01356108bb6108b68d6135eb565b611fea565b61202a565b80156108de57506108de83838360208801356108bb6108b68a6135eb565b610914576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b86604001358860405160200161092a91906136ba565b6040516020818303038152906040528051906020012014610977576040517f1968a90200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83602001358760200135600161098d91906136f8565b146109c4576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a0c886109d28680613710565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061208b92505050565b610a15886121e6565b836040013588604051602001610a2b91906136ba565b6040516020818303038152906040528051906020012003610a78576040517f9843145b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8a1660009081526015602090815260408083208c8452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000166001179055610adc8a8a3361298e565b50505050505050505050565b6001610af660106002613897565b610b0091906138a3565b81565b6000610b0f8686612a47565b9050610b1c8360086136f8565b82101580610b2a5750602083115b15610b61576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000602081815260c085901b82526008959095528251828252600286526040808320858452875280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558484528752808320948352938652838220558181529384905292205592915050565b60608115610bf257610beb8686612af4565b9050610c2c565b85858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050505b3360009081526014602090815260408083208b845290915280822081516102008101928390529160109082845b815481526020019060010190808311610c5957505050505090506000601560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008b81526020019081526020016000205490506000610cda8260601c63ffffffff1690565b63ffffffff169050333214610d1b576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d2b8260801c63ffffffff1690565b63ffffffff16600003610d6a576040517f87138d5c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d748260c01c90565b67ffffffffffffffff1615610db5576040517f475a253500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b898114610dee576040517f60f95d5a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610dfb89898d8886612b6d565b83516020850160888204881415608883061715610e20576307b1daf16000526004601cfd5b60405160c8810160405260005b83811015610ed0578083018051835260208101516020840152604081015160408401526060810151606084015260808101516080840152508460888301526088810460051b8b013560a883015260c882206001860195508560005b610200811015610ec5576001821615610ea55782818b0152610ec5565b8981015160009081526020938452604090209260019290921c9101610e88565b505050608801610e2d565b50505050600160106002610ee49190613897565b610eee91906138a3565b811115610f27576040517f6229572300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f9c610f3a8360401c63ffffffff1690565b610f4a9063ffffffff168a6136f8565b60401b7fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff606084901b167fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff8516171790565b915084156110295777ffffffffffffffffffffffffffffffffffffffffffffffff82164260c01b179150610fd68260801c63ffffffff1690565b63ffffffff16610fec8360401c63ffffffff1690565b63ffffffff1614611029576040517f7b1dafd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360009081526014602090815260408083208e8452909152902061104f90846010612d9f565b503360008181526018602090815260408083208f8452825280832080546001810182559084528284206004820401805460039092166008026101000a67ffffffffffffffff818102199093164390931602919091179055838352601582528083208f8452909152812084905560609190911b81523690601437366014016000a05050505050505050505050565b600381601081106110ec57600080fd5b0154905081565b6018602052826000526040600020602052816000526040600020818154811061111b57600080fd5b906000526020600020906004918282040191900660080292509250509054906101000a900467ffffffffffffffff1681565b60443560008060088301861061116b5763fe2549876000526004601cfd5b60c083901b60805260888386823786600882030151915060206000858360025afa90508061119857600080fd5b50600080517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0400000000000000000000000000000000000000000000000000000000000000178082526002602090815260408084208a8552825280842080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558385528252808420998452988152888320939093558152908190529490942055505050565b600080603087600037602060006030600060025afa806112705763f91129696000526004601cfd5b6000517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f010000000000000000000000000000000000000000000000000000000000000017608081815260a08c905260c08b905260308a60e037603088609083013760008060c083600a5afa9250826112f2576309bde3396000526004601cfd5b602886106113085763fe2549876000526004601cfd5b6000602882015278200000000000000000000000000000000000000000000000008152600881018b905285810151935060308a8237603081019b909b52505060509098207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0500000000000000000000000000000000000000000000000000000000000000176000818152600260209081526040808320868452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845282528083209583529481528482209a909a559081528089529190912096909655505050505050565b6014602052826000526040600020602052816000526040600020816010811061142757600080fd5b0154925083915050565b73ffffffffffffffffffffffffffffffffffffffff891660009081526015602090815260408083208b845290915290205467ffffffffffffffff8116156114a4576040517fc334f06900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6114ae8160c01c90565b67ffffffffffffffff166000036114f1576040517f55d4cbf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000061151c8260c01c90565b6115309067ffffffffffffffff16426138a3565b11611567576040517f55d4cbf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006115738b8b610759565b905061158c87878360208c01356108bb6108b68e6135eb565b80156115aa57506115aa84848360208901356108bb6108b68b6135eb565b6115e0576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8760400135896040516020016115f691906136ba565b6040516020818303038152906040528051906020012014611643576040517f1968a90200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84602001358860200135600161165991906136f8565b14158061168b575060016116738360601c63ffffffff1690565b61167d91906138ba565b63ffffffff16856020013514155b156116c2576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6116d0896109d28780613710565b6116d9896121e6565b60006116e48a612cc0565b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0200000000000000000000000000000000000000000000000000000000000000179050600061173b8460a01c63ffffffff1690565b67ffffffffffffffff169050600160026000848152602001908152602001600020600083815260200190815260200160002060006101000a81548160ff021916908315150217905550601760008e73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008d8152602001908152602001600020546001600084815260200190815260200160002060008381526020019081526020016000208190555061180d8460801c63ffffffff1690565b600083815260208190526040902063ffffffff9190911690556118318d8d8161298e565b50505050505050505050505050565b6000828152600260209081526040808320848452909152812054819060ff166118c9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f7072652d696d616765206d757374206578697374000000000000000000000000604482015260640160405180910390fd5b50600083815260208181526040909120546118e58160086136f8565b6118f08560206136f8565b1061190e57836119018260086136f8565b61190b91906138a3565b91505b506000938452600160209081526040808620948652939052919092205492909150565b60443560008060088301861061194f5763fe2549876000526004601cfd5b60c083901b6080526088838682378087017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80151908490207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f02000000000000000000000000000000000000000000000000000000000000001760008181526002602090815260408083208b8452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845282528083209a83529981528982209390935590815290819052959095209190915550505050565b60008060008060808860601b81528760c01b6014820152858782601c0137601c860181207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0600000000000000000000000000000000000000000000000000000000000000179350604088026260216001603f5a021015611ac35763dd629f866000526004601cfd5b6000808783601c018c5afa94503d6001019150600882018a10611aee5763fe2549876000526004601cfd5b60c082901b81526008018481533d6000600183013e89017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8015160008481526002602090815260408083208d8452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915587845282528083209c83529b81528b8220929092559384528390529790912096909655505050505050565b6000611ba48686610759565b9050611bbd83838360208801356108bb6108b68a6135eb565b611bf3576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602084013515611c2f576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611c37612ddd565b611c45816109d28780613710565b611c4e816121e6565b846040013581604051602001611c6491906136ba565b6040516020818303038152906040528051906020012003611cb1576040517f9843145b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff87166000908152601560209081526040808320898452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000166001179055611d1587873361298e565b50505050505050565b6703782dace9d90000341015611d60576040517fe92c469f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b333214611d99576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611da48160086138df565b63ffffffff168263ffffffff1610611de8576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000008163ffffffff161015611e48576040517f7b1dafd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152601560209081526040808320868452909152902054611e738160801c63ffffffff1690565b63ffffffff1615611eb0576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b608082901b7fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff60a085901b167fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff83161717336000818152601560209081526040808320898452825280832094909455835180850185528381528082018981526013805460018101825590855291517f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a090600290930292830180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909216919091179055517f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a0919091015591815260168252828120968152959052909320349055505050565b600081600001518260200151836040015160405160200161200d93929190613907565b604051602081830303815290604052805190602001209050919050565b60008160005b601081101561207e578060051b880135600186831c16600181146120635760008481526020839052604090209350612074565b600082815260208590526040902093505b5050600101612030565b5090931495945050505050565b608881511461209957600080fd5b602081016020830161211a565b8260031b8201518060001a8160011a60081b178160021a60101b8260031a60181b17178160041a60201b8260051a60281b178260061a60301b8360071a60381b1717179050612114816120ff868560059190911b015190565b1867ffffffffffffffff16600586901b840152565b50505050565b612126600083836120a6565b612132600183836120a6565b61213e600283836120a6565b61214a600383836120a6565b612156600483836120a6565b612162600583836120a6565b61216e600683836120a6565b61217a600783836120a6565b612186600883836120a6565b612192600983836120a6565b61219e600a83836120a6565b6121aa600b83836120a6565b6121b6600c83836120a6565b6121c2600d83836120a6565b6121ce600e83836120a6565b6121da600f83836120a6565b612114601083836120a6565b6040805178010000000000008082800000000000808a8000000080008000602082015279808b00000000800000018000000080008081800000000000800991810191909152788a00000000000000880000000080008009000000008000000a60608201527b8000808b800000000000008b8000000000008089800000000000800360808201527f80000000000080028000000000000080000000000000800a800000008000000a60a08201527f800000008000808180000000000080800000000080000001800000008000800860c082015260009060e0016040516020818303038152906040529050602082016020820161286e565b6102808101516101e082015161014083015160a0840151845118189118186102a082015161020083015161016084015160c0850151602086015118189118186102c083015161022084015161018085015160e0860151604087015118189118186102e08401516102408501516101a0860151610100870151606088015118189118186103008501516102608601516101c0870151610120880151608089015118189118188084603f1c6123998660011b67ffffffffffffffff1690565b18188584603f1c6123b48660011b67ffffffffffffffff1690565b18188584603f1c6123cf8660011b67ffffffffffffffff1690565b181895508483603f1c6123ec8560011b67ffffffffffffffff1690565b181894508387603f1c6124098960011b67ffffffffffffffff1690565b60208b01518b51861867ffffffffffffffff168c5291189190911897508118600181901b603f9190911c18935060c08801518118601481901c602c9190911b1867ffffffffffffffff1660208901526101208801518718602c81901c60149190911b1867ffffffffffffffff1660c08901526102c08801518618600381901c603d9190911b1867ffffffffffffffff166101208901526101c08801518718601981901c60279190911b1867ffffffffffffffff166102c08901526102808801518218602e81901c60129190911b1867ffffffffffffffff166101c089015260408801518618600281901c603e9190911b1867ffffffffffffffff166102808901526101808801518618601581901c602b9190911b1867ffffffffffffffff1660408901526101a08801518518602781901c60199190911b1867ffffffffffffffff166101808901526102608801518718603881901c60089190911b1867ffffffffffffffff166101a08901526102e08801518518600881901c60389190911b1867ffffffffffffffff166102608901526101e08801518218601781901c60299190911b1867ffffffffffffffff166102e089015260808801518718602581901c601b9190911b1867ffffffffffffffff166101e08901526103008801518718603281901c600e9190911b1867ffffffffffffffff1660808901526102a08801518118603e81901c60029190911b1867ffffffffffffffff166103008901526101008801518518600981901c60379190911b1867ffffffffffffffff166102a08901526102008801518118601381901c602d9190911b1867ffffffffffffffff1661010089015260a08801518218601c81901c60249190911b1867ffffffffffffffff1661020089015260608801518518602481901c601c9190911b1867ffffffffffffffff1660a08901526102408801518518602b81901c60159190911b1867ffffffffffffffff1660608901526102208801518618603181901c600f9190911b1867ffffffffffffffff166102408901526101608801518118603681901c600a9190911b1867ffffffffffffffff166102208901525060e08701518518603a81901c60069190911b1867ffffffffffffffff166101608801526101408701518118603d81901c60039190911b1867ffffffffffffffff1660e0880152505067ffffffffffffffff81166101408601525b5050505050565b600582811b8201805160018501831b8401805160028701851b8601805160038901871b8801805160048b0190981b8901805167ffffffffffffffff861985168918811690995283198a16861889169096528819861683188816909352841986168818871690528419831684189095169052919391929190611d15565b612808600082612781565b612813600582612781565b61281e600a82612781565b612829600f82612781565b612834601482612781565b50565b612840816122dc565b612849816127fd565b600383901b820151815160c09190911c9061211490821867ffffffffffffffff168352565b61287a60008284612837565b61288660018284612837565b61289260028284612837565b61289e60038284612837565b6128aa60048284612837565b6128b660058284612837565b6128c260068284612837565b6128ce60078284612837565b6128da60088284612837565b6128e660098284612837565b6128f2600a8284612837565b6128fe600b8284612837565b61290a600c8284612837565b612916600d8284612837565b612922600e8284612837565b61292e600f8284612837565b61293a60108284612837565b61294660118284612837565b61295260128284612837565b61295e60138284612837565b61296a60148284612837565b61297660158284612837565b61298260168284612837565b61211460178284612837565b73ffffffffffffffffffffffffffffffffffffffff83811660009081526016602090815260408083208684529091528082208054908390559051909284169083908381818185875af1925050503d8060008114612a07576040519150601f19603f3d011682016040523d82523d6000602084013e612a0c565b606091505b505090508061277a576040517f83e6cc6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f01000000000000000000000000000000000000000000000000000000000000007effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831617612aed818360408051600093845233602052918152606090922091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790565b9392505050565b6060604051905081602082018181018286833760888306808015612b3d5760888290038501848101848103803687375060806001820353506001845160001a1784538652612b54565b608836843760018353608060878401536088850186525b5050505050601f19603f82510116810160405292915050565b6000612b7f8260a01c63ffffffff1690565b67ffffffffffffffff1690506000612b9d8360801c63ffffffff1690565b63ffffffff1690506000612bb78460401c63ffffffff1690565b63ffffffff169050600883108015612bcd575080155b15612c015760c082901b6000908152883560085283513382526017602090815260408084208a855290915290912055612cb6565b60088310158015612c1f575080612c196008856138a3565b93508310155b8015612c335750612c3087826136f8565b83105b15612cb6576000612c4482856138a3565b905087612c528260206136f8565b10158015612c5e575085155b15612c95576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360009081526017602090815260408083208a845290915290209089013590555b5050505050505050565b6000612d43565b66ff00ff00ff00ff8160081c1667ff00ff00ff00ff00612cf18360081b67ffffffffffffffff1690565b1617905065ffff0000ffff8160101c1667ffff0000ffff0000612d1e8360101b67ffffffffffffffff1690565b1617905060008160201c612d3c8360201b67ffffffffffffffff1690565b1792915050565b60808201516020830190612d5b90612cc7565b612cc7565b6040820151612d6990612cc7565b60401b17612d81612d5660018460059190911b015190565b825160809190911b90612d9390612cc7565b60c01b17179392505050565b8260108101928215612dcd579160200282015b82811115612dcd578251825591602001919060010190612db2565b50612dd9929150612df5565b5090565b6040518060200160405280612df0612e0a565b905290565b5b80821115612dd95760008155600101612df6565b6040518061032001604052806019906020820280368337509192915050565b600060208284031215612e3b57600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114612e6657600080fd5b919050565b60008060408385031215612e7e57600080fd5b612e8783612e42565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610320810167ffffffffffffffff81118282101715612ee857612ee8612e95565b60405290565b6040516060810167ffffffffffffffff81118282101715612ee857612ee8612e95565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715612f5857612f58612e95565b604052919050565b803567ffffffffffffffff81168114612e6657600080fd5b6000610320808385031215612f8c57600080fd5b604051602080820182811067ffffffffffffffff82111715612fb057612fb0612e95565b806040525081935085601f860112612fc757600080fd5b612fcf612ec4565b928501928087851115612fe157600080fd5b865b8581101561300157612ff481612f60565b8352918301918301612fe3565b509092525091949350505050565b60006060828403121561302157600080fd5b50919050565b60008083601f84011261303957600080fd5b50813567ffffffffffffffff81111561305157600080fd5b6020830191508360208260051b850101111561306c57600080fd5b9250929050565b60008060008060008060008060006103e08a8c03121561309257600080fd5b61309b8a612e42565b985060208a013597506130b18b60408c01612f78565b96506103608a013567ffffffffffffffff808211156130cf57600080fd5b6130db8d838e0161300f565b97506103808c01359150808211156130f257600080fd5b6130fe8d838e01613027565b90975095506103a08c013591508082111561311857600080fd5b6131248d838e0161300f565b94506103c08c013591508082111561313b57600080fd5b506131488c828d01613027565b915080935050809150509295985092959850929598565b600080600080600060a0868803121561317757600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b60005b838110156131b557818101518382015260200161319d565b838111156121145750506000910152565b60208152600082518060208401526131e581604085016020870161319a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b6000806040838503121561322a57600080fd5b50508035926020909101359150565b60008083601f84011261324b57600080fd5b50813567ffffffffffffffff81111561326357600080fd5b60208301915083602082850101111561306c57600080fd5b600080600080600080600060a0888a03121561329657600080fd5b8735965060208801359550604088013567ffffffffffffffff808211156132bc57600080fd5b6132c88b838c01613239565b909750955060608a01359150808211156132e157600080fd5b506132ee8a828b01613027565b9094509250506080880135801515811461330757600080fd5b8091505092959891949750929550565b60008060006060848603121561332c57600080fd5b61333584612e42565b95602085013595506040909401359392505050565b60008060006040848603121561335f57600080fd5b83359250602084013567ffffffffffffffff81111561337d57600080fd5b61338986828701613239565b9497909650939450505050565b600080600080600080600060a0888a0312156133b157600080fd5b8735965060208801359550604088013567ffffffffffffffff808211156133d757600080fd5b6133e38b838c01613239565b909750955060608a01359150808211156133fc57600080fd5b506134098a828b01613239565b989b979a50959894979596608090950135949350505050565b60008060008060006080868803121561343a57600080fd5b8535945061344a60208701612e42565b935061345860408701612f60565b9250606086013567ffffffffffffffff81111561347457600080fd5b61348088828901613239565b969995985093965092949392505050565b6000806000806000608086880312156134a957600080fd5b6134b286612e42565b945060208601359350604086013567ffffffffffffffff808211156134d657600080fd5b6134e289838a0161300f565b945060608801359150808211156134f857600080fd5b5061348088828901613027565b803563ffffffff81168114612e6657600080fd5b60008060006060848603121561352e57600080fd5b8335925061353e60208501613505565b915061354c60408501613505565b90509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036135e4576135e4613584565b5060010190565b6000606082360312156135fd57600080fd5b613605612eee565b823567ffffffffffffffff8082111561361d57600080fd5b9084019036601f83011261363057600080fd5b813560208282111561364457613644612e95565b613674817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f85011601612f11565b9250818352368183860101111561368a57600080fd5b81818501828501376000918301810191909152908352848101359083015250604092830135928101929092525090565b81516103208201908260005b60198110156136ef57825167ffffffffffffffff168252602092830192909101906001016136c6565b50505092915050565b6000821982111561370b5761370b613584565b500190565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261374557600080fd5b83018035915067ffffffffffffffff82111561376057600080fd5b60200191503681900382131561306c57600080fd5b600181815b808511156137ce57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156137b4576137b4613584565b808516156137c157918102915b93841c939080029061377a565b509250929050565b6000826137e557506001613891565b816137f257506000613891565b816001811461380857600281146138125761382e565b6001915050613891565b60ff84111561382357613823613584565b50506001821b613891565b5060208310610133831016604e8410600b8410161715613851575081810a613891565b61385b8383613775565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561388d5761388d613584565b0290505b92915050565b6000612aed83836137d6565b6000828210156138b5576138b5613584565b500390565b600063ffffffff838116908316818110156138d7576138d7613584565b039392505050565b600063ffffffff8083168185168083038211156138fe576138fe613584565b01949350505050565b6000845161391981846020890161319a565b9190910192835250602082015260400191905056fea164736f6c634300080f000a00000000000000000000000000000000000000000000000000000000000027100000000000000000000000000000000000000000000000000000000000000078", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [], - "value": 0 - }, - { - "accessor": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "account": "0x373d916D11cce55b548F7051002e76BCFBD7a85d", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x60c06040523480156200001157600080fd5b5060405162003b6038038062003b6083398101604081905262000034916200014f565b60a082905260808190526001600160401b038111156200009a5760405162461bcd60e51b815260206004820152601a60248201527f6368616c6c656e676520706572696f6420746f6f206c61726765000000000000604482015260640160405180910390fd5b60005b620000ab600160106200018a565b811015620001465760038160108110620000c957620000c9620001a4565b015460038260108110620000e157620000e1620001a4565b01546040805160208101939093528201526060016040516020818303038152906040528051906020012060038260016200011c9190620001ba565b601081106200012f576200012f620001a4565b0155806200013d81620001d5565b9150506200009d565b505050620001f1565b600080604083850312156200016357600080fd5b505080516020909101519092909150565b634e487b7160e01b600052601160045260246000fd5b6000828210156200019f576200019f62000174565b500390565b634e487b7160e01b600052603260045260246000fd5b60008219821115620001d057620001d062000174565b500190565b600060018201620001ea57620001ea62000174565b5060010190565b60805160a05161393b62000225600039600081816105b00152611dea0152600081816106b001526114f3015261393b6000f3fe6080604052600436106101d85760003560e01c80639d53a64811610102578063ddcd58de11610095578063ec5efcbc11610064578063ec5efcbc14610681578063f3f480d9146106a1578063faf37bc7146106d4578063fef2b4ed146106e757600080fd5b8063ddcd58de146105d4578063e03110e11461060c578063e159261114610641578063ea7139501461066157600080fd5b8063b5e7154c116100d1578063b5e7154c14610555578063d18534b51461056c578063da35c6641461058c578063dd24f9bf146105a157600080fd5b80639d53a6481461048e5780639d7e8769146104dd578063b2e67ba8146104fd578063b4801e611461053557600080fd5b806361238bde1161017a5780637ac54767116101495780637ac54767146103ca5780638542cf50146103ea578063882856ef146104355780638dc4be111461046e57600080fd5b806361238bde1461031e5780636551927b146103565780637051472e1461038e5780637917de1d146103aa57600080fd5b80633909af5c116101b65780633909af5c146102715780634d52b4c91461029357806352f0f3ad146102a857806354fd4d50146102c857600080fd5b8063013cf08b146101dd5780630359a5631461022e5780632055b36b1461025c575b600080fd5b3480156101e957600080fd5b506101fd6101f8366004612e29565b610714565b6040805173ffffffffffffffffffffffffffffffffffffffff90931683526020830191909152015b60405180910390f35b34801561023a57600080fd5b5061024e610249366004612e6b565b610759565b604051908152602001610225565b34801561026857600080fd5b5061024e601081565b34801561027d57600080fd5b5061029161028c366004613073565b610891565b005b34801561029f57600080fd5b5061024e610ae8565b3480156102b457600080fd5b5061024e6102c336600461315f565b610b03565b3480156102d457600080fd5b506103116040518060400160405280600a81526020017f312e312e322d72632e310000000000000000000000000000000000000000000081525081565b60405161022591906131c6565b34801561032a57600080fd5b5061024e610339366004613217565b600160209081526000928352604080842090915290825290205481565b34801561036257600080fd5b5061024e610371366004612e6b565b601560209081526000928352604080842090915290825290205481565b34801561039a57600080fd5b5061024e6703782dace9d9000081565b3480156103b657600080fd5b506102916103c536600461327b565b610bd9565b3480156103d657600080fd5b5061024e6103e5366004612e29565b6110dc565b3480156103f657600080fd5b50610425610405366004613217565b600260209081526000928352604080842090915290825290205460ff1681565b6040519015158152602001610225565b34801561044157600080fd5b50610455610450366004613317565b6110f3565b60405167ffffffffffffffff9091168152602001610225565b34801561047a57600080fd5b5061029161048936600461334a565b61114d565b34801561049a57600080fd5b5061024e6104a9366004612e6b565b73ffffffffffffffffffffffffffffffffffffffff9091166000908152601860209081526040808320938352929052205490565b3480156104e957600080fd5b506102916104f8366004613396565b611248565b34801561050957600080fd5b5061024e610518366004612e6b565b601760209081526000928352604080842090915290825290205481565b34801561054157600080fd5b5061024e610550366004613317565b6113ff565b34801561056157600080fd5b5061024e620186a081565b34801561057857600080fd5b50610291610587366004613073565b611431565b34801561059857600080fd5b5060135461024e565b3480156105ad57600080fd5b507f000000000000000000000000000000000000000000000000000000000000000061024e565b3480156105e057600080fd5b5061024e6105ef366004612e6b565b601660209081526000928352604080842090915290825290205481565b34801561061857600080fd5b5061062c610627366004613217565b611840565b60408051928352602083019190915201610225565b34801561064d57600080fd5b5061029161065c36600461334a565b611931565b34801561066d57600080fd5b5061029161067c366004613422565b611a39565b34801561068d57600080fd5b5061029161069c366004613491565b611b98565b3480156106ad57600080fd5b507f000000000000000000000000000000000000000000000000000000000000000061024e565b6102916106e2366004613519565b611d1e565b3480156106f357600080fd5b5061024e610702366004612e29565b60006020819052908152604090205481565b6013818154811061072457600080fd5b60009182526020909120600290910201805460019091015473ffffffffffffffffffffffffffffffffffffffff909116915082565b73ffffffffffffffffffffffffffffffffffffffff82166000908152601560209081526040808320848452909152812054819061079c9060601c63ffffffff1690565b63ffffffff16905060005b6010811015610889578160011660010361082f5773ffffffffffffffffffffffffffffffffffffffff85166000908152601460209081526040808320878452909152902081601081106107fc576107fc613555565b01546040805160208101929092528101849052606001604051602081830303815290604052805190602001209250610870565b826003826010811061084357610843613555565b01546040805160208101939093528201526060016040516020818303038152906040528051906020012092505b60019190911c9080610881816135b3565b9150506107a7565b505092915050565b600061089d8a8a610759565b90506108c086868360208b01356108bb6108b68d6135eb565b611fea565b61202a565b80156108de57506108de83838360208801356108bb6108b68a6135eb565b610914576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b86604001358860405160200161092a91906136ba565b6040516020818303038152906040528051906020012014610977576040517f1968a90200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83602001358760200135600161098d91906136f8565b146109c4576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a0c886109d28680613710565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061208b92505050565b610a15886121e6565b836040013588604051602001610a2b91906136ba565b6040516020818303038152906040528051906020012003610a78576040517f9843145b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8a1660009081526015602090815260408083208c8452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000166001179055610adc8a8a3361298e565b50505050505050505050565b6001610af660106002613897565b610b0091906138a3565b81565b6000610b0f8686612a47565b9050610b1c8360086136f8565b82101580610b2a5750602083115b15610b61576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000602081815260c085901b82526008959095528251828252600286526040808320858452875280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558484528752808320948352938652838220558181529384905292205592915050565b60608115610bf257610beb8686612af4565b9050610c2c565b85858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050505b3360009081526014602090815260408083208b845290915280822081516102008101928390529160109082845b815481526020019060010190808311610c5957505050505090506000601560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008b81526020019081526020016000205490506000610cda8260601c63ffffffff1690565b63ffffffff169050333214610d1b576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d2b8260801c63ffffffff1690565b63ffffffff16600003610d6a576040517f87138d5c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d748260c01c90565b67ffffffffffffffff1615610db5576040517f475a253500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b898114610dee576040517f60f95d5a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610dfb89898d8886612b6d565b83516020850160888204881415608883061715610e20576307b1daf16000526004601cfd5b60405160c8810160405260005b83811015610ed0578083018051835260208101516020840152604081015160408401526060810151606084015260808101516080840152508460888301526088810460051b8b013560a883015260c882206001860195508560005b610200811015610ec5576001821615610ea55782818b0152610ec5565b8981015160009081526020938452604090209260019290921c9101610e88565b505050608801610e2d565b50505050600160106002610ee49190613897565b610eee91906138a3565b811115610f27576040517f6229572300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f9c610f3a8360401c63ffffffff1690565b610f4a9063ffffffff168a6136f8565b60401b7fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff606084901b167fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff8516171790565b915084156110295777ffffffffffffffffffffffffffffffffffffffffffffffff82164260c01b179150610fd68260801c63ffffffff1690565b63ffffffff16610fec8360401c63ffffffff1690565b63ffffffff1614611029576040517f7b1dafd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360009081526014602090815260408083208e8452909152902061104f90846010612d9f565b503360008181526018602090815260408083208f8452825280832080546001810182559084528284206004820401805460039092166008026101000a67ffffffffffffffff818102199093164390931602919091179055838352601582528083208f8452909152812084905560609190911b81523690601437366014016000a05050505050505050505050565b600381601081106110ec57600080fd5b0154905081565b6018602052826000526040600020602052816000526040600020818154811061111b57600080fd5b906000526020600020906004918282040191900660080292509250509054906101000a900467ffffffffffffffff1681565b60443560008060088301861061116b5763fe2549876000526004601cfd5b60c083901b60805260888386823786600882030151915060206000858360025afa90508061119857600080fd5b50600080517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0400000000000000000000000000000000000000000000000000000000000000178082526002602090815260408084208a8552825280842080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558385528252808420998452988152888320939093558152908190529490942055505050565b600080603087600037602060006030600060025afa806112705763f91129696000526004601cfd5b6000517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f010000000000000000000000000000000000000000000000000000000000000017608081815260a08c905260c08b905260308a60e037603088609083013760008060c083600a5afa9250826112f2576309bde3396000526004601cfd5b602886106113085763fe2549876000526004601cfd5b6000602882015278200000000000000000000000000000000000000000000000008152600881018b905285810151935060308a8237603081019b909b52505060509098207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0500000000000000000000000000000000000000000000000000000000000000176000818152600260209081526040808320868452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845282528083209583529481528482209a909a559081528089529190912096909655505050505050565b6014602052826000526040600020602052816000526040600020816010811061142757600080fd5b0154925083915050565b73ffffffffffffffffffffffffffffffffffffffff891660009081526015602090815260408083208b845290915290205467ffffffffffffffff8116156114a4576040517fc334f06900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6114ae8160c01c90565b67ffffffffffffffff166000036114f1576040517f55d4cbf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000061151c8260c01c90565b6115309067ffffffffffffffff16426138a3565b11611567576040517f55d4cbf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006115738b8b610759565b905061158c87878360208c01356108bb6108b68e6135eb565b80156115aa57506115aa84848360208901356108bb6108b68b6135eb565b6115e0576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8760400135896040516020016115f691906136ba565b6040516020818303038152906040528051906020012014611643576040517f1968a90200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84602001358860200135600161165991906136f8565b14158061168b575060016116738360601c63ffffffff1690565b61167d91906138ba565b63ffffffff16856020013514155b156116c2576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6116d0896109d28780613710565b6116d9896121e6565b60006116e48a612cc0565b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0200000000000000000000000000000000000000000000000000000000000000179050600061173b8460a01c63ffffffff1690565b67ffffffffffffffff169050600160026000848152602001908152602001600020600083815260200190815260200160002060006101000a81548160ff021916908315150217905550601760008e73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008d8152602001908152602001600020546001600084815260200190815260200160002060008381526020019081526020016000208190555061180d8460801c63ffffffff1690565b600083815260208190526040902063ffffffff9190911690556118318d8d8161298e565b50505050505050505050505050565b6000828152600260209081526040808320848452909152812054819060ff166118c9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f7072652d696d616765206d757374206578697374000000000000000000000000604482015260640160405180910390fd5b50600083815260208181526040909120546118e58160086136f8565b6118f08560206136f8565b1061190e57836119018260086136f8565b61190b91906138a3565b91505b506000938452600160209081526040808620948652939052919092205492909150565b60443560008060088301861061194f5763fe2549876000526004601cfd5b60c083901b6080526088838682378087017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80151908490207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f02000000000000000000000000000000000000000000000000000000000000001760008181526002602090815260408083208b8452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845282528083209a83529981528982209390935590815290819052959095209190915550505050565b60008060008060808860601b81528760c01b6014820152858782601c0137601c860181207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0600000000000000000000000000000000000000000000000000000000000000179350604088026260216001603f5a021015611ac35763dd629f866000526004601cfd5b6000808783601c018c5afa94503d6001019150600882018a10611aee5763fe2549876000526004601cfd5b60c082901b81526008018481533d6000600183013e89017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8015160008481526002602090815260408083208d8452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915587845282528083209c83529b81528b8220929092559384528390529790912096909655505050505050565b6000611ba48686610759565b9050611bbd83838360208801356108bb6108b68a6135eb565b611bf3576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602084013515611c2f576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611c37612ddd565b611c45816109d28780613710565b611c4e816121e6565b846040013581604051602001611c6491906136ba565b6040516020818303038152906040528051906020012003611cb1576040517f9843145b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff87166000908152601560209081526040808320898452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000166001179055611d1587873361298e565b50505050505050565b6703782dace9d90000341015611d60576040517fe92c469f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b333214611d99576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611da48160086138df565b63ffffffff168263ffffffff1610611de8576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000008163ffffffff161015611e48576040517f7b1dafd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152601560209081526040808320868452909152902054611e738160801c63ffffffff1690565b63ffffffff1615611eb0576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b608082901b7fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff60a085901b167fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff83161717336000818152601560209081526040808320898452825280832094909455835180850185528381528082018981526013805460018101825590855291517f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a090600290930292830180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909216919091179055517f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a0919091015591815260168252828120968152959052909320349055505050565b600081600001518260200151836040015160405160200161200d93929190613907565b604051602081830303815290604052805190602001209050919050565b60008160005b601081101561207e578060051b880135600186831c16600181146120635760008481526020839052604090209350612074565b600082815260208590526040902093505b5050600101612030565b5090931495945050505050565b608881511461209957600080fd5b602081016020830161211a565b8260031b8201518060001a8160011a60081b178160021a60101b8260031a60181b17178160041a60201b8260051a60281b178260061a60301b8360071a60381b1717179050612114816120ff868560059190911b015190565b1867ffffffffffffffff16600586901b840152565b50505050565b612126600083836120a6565b612132600183836120a6565b61213e600283836120a6565b61214a600383836120a6565b612156600483836120a6565b612162600583836120a6565b61216e600683836120a6565b61217a600783836120a6565b612186600883836120a6565b612192600983836120a6565b61219e600a83836120a6565b6121aa600b83836120a6565b6121b6600c83836120a6565b6121c2600d83836120a6565b6121ce600e83836120a6565b6121da600f83836120a6565b612114601083836120a6565b6040805178010000000000008082800000000000808a8000000080008000602082015279808b00000000800000018000000080008081800000000000800991810191909152788a00000000000000880000000080008009000000008000000a60608201527b8000808b800000000000008b8000000000008089800000000000800360808201527f80000000000080028000000000000080000000000000800a800000008000000a60a08201527f800000008000808180000000000080800000000080000001800000008000800860c082015260009060e0016040516020818303038152906040529050602082016020820161286e565b6102808101516101e082015161014083015160a0840151845118189118186102a082015161020083015161016084015160c0850151602086015118189118186102c083015161022084015161018085015160e0860151604087015118189118186102e08401516102408501516101a0860151610100870151606088015118189118186103008501516102608601516101c0870151610120880151608089015118189118188084603f1c6123998660011b67ffffffffffffffff1690565b18188584603f1c6123b48660011b67ffffffffffffffff1690565b18188584603f1c6123cf8660011b67ffffffffffffffff1690565b181895508483603f1c6123ec8560011b67ffffffffffffffff1690565b181894508387603f1c6124098960011b67ffffffffffffffff1690565b60208b01518b51861867ffffffffffffffff168c5291189190911897508118600181901b603f9190911c18935060c08801518118601481901c602c9190911b1867ffffffffffffffff1660208901526101208801518718602c81901c60149190911b1867ffffffffffffffff1660c08901526102c08801518618600381901c603d9190911b1867ffffffffffffffff166101208901526101c08801518718601981901c60279190911b1867ffffffffffffffff166102c08901526102808801518218602e81901c60129190911b1867ffffffffffffffff166101c089015260408801518618600281901c603e9190911b1867ffffffffffffffff166102808901526101808801518618601581901c602b9190911b1867ffffffffffffffff1660408901526101a08801518518602781901c60199190911b1867ffffffffffffffff166101808901526102608801518718603881901c60089190911b1867ffffffffffffffff166101a08901526102e08801518518600881901c60389190911b1867ffffffffffffffff166102608901526101e08801518218601781901c60299190911b1867ffffffffffffffff166102e089015260808801518718602581901c601b9190911b1867ffffffffffffffff166101e08901526103008801518718603281901c600e9190911b1867ffffffffffffffff1660808901526102a08801518118603e81901c60029190911b1867ffffffffffffffff166103008901526101008801518518600981901c60379190911b1867ffffffffffffffff166102a08901526102008801518118601381901c602d9190911b1867ffffffffffffffff1661010089015260a08801518218601c81901c60249190911b1867ffffffffffffffff1661020089015260608801518518602481901c601c9190911b1867ffffffffffffffff1660a08901526102408801518518602b81901c60159190911b1867ffffffffffffffff1660608901526102208801518618603181901c600f9190911b1867ffffffffffffffff166102408901526101608801518118603681901c600a9190911b1867ffffffffffffffff166102208901525060e08701518518603a81901c60069190911b1867ffffffffffffffff166101608801526101408701518118603d81901c60039190911b1867ffffffffffffffff1660e0880152505067ffffffffffffffff81166101408601525b5050505050565b600582811b8201805160018501831b8401805160028701851b8601805160038901871b8801805160048b0190981b8901805167ffffffffffffffff861985168918811690995283198a16861889169096528819861683188816909352841986168818871690528419831684189095169052919391929190611d15565b612808600082612781565b612813600582612781565b61281e600a82612781565b612829600f82612781565b612834601482612781565b50565b612840816122dc565b612849816127fd565b600383901b820151815160c09190911c9061211490821867ffffffffffffffff168352565b61287a60008284612837565b61288660018284612837565b61289260028284612837565b61289e60038284612837565b6128aa60048284612837565b6128b660058284612837565b6128c260068284612837565b6128ce60078284612837565b6128da60088284612837565b6128e660098284612837565b6128f2600a8284612837565b6128fe600b8284612837565b61290a600c8284612837565b612916600d8284612837565b612922600e8284612837565b61292e600f8284612837565b61293a60108284612837565b61294660118284612837565b61295260128284612837565b61295e60138284612837565b61296a60148284612837565b61297660158284612837565b61298260168284612837565b61211460178284612837565b73ffffffffffffffffffffffffffffffffffffffff83811660009081526016602090815260408083208684529091528082208054908390559051909284169083908381818185875af1925050503d8060008114612a07576040519150601f19603f3d011682016040523d82523d6000602084013e612a0c565b606091505b505090508061277a576040517f83e6cc6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f01000000000000000000000000000000000000000000000000000000000000007effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831617612aed818360408051600093845233602052918152606090922091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790565b9392505050565b6060604051905081602082018181018286833760888306808015612b3d5760888290038501848101848103803687375060806001820353506001845160001a1784538652612b54565b608836843760018353608060878401536088850186525b5050505050601f19603f82510116810160405292915050565b6000612b7f8260a01c63ffffffff1690565b67ffffffffffffffff1690506000612b9d8360801c63ffffffff1690565b63ffffffff1690506000612bb78460401c63ffffffff1690565b63ffffffff169050600883108015612bcd575080155b15612c015760c082901b6000908152883560085283513382526017602090815260408084208a855290915290912055612cb6565b60088310158015612c1f575080612c196008856138a3565b93508310155b8015612c335750612c3087826136f8565b83105b15612cb6576000612c4482856138a3565b905087612c528260206136f8565b10158015612c5e575085155b15612c95576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360009081526017602090815260408083208a845290915290209089013590555b5050505050505050565b6000612d43565b66ff00ff00ff00ff8160081c1667ff00ff00ff00ff00612cf18360081b67ffffffffffffffff1690565b1617905065ffff0000ffff8160101c1667ffff0000ffff0000612d1e8360101b67ffffffffffffffff1690565b1617905060008160201c612d3c8360201b67ffffffffffffffff1690565b1792915050565b60808201516020830190612d5b90612cc7565b612cc7565b6040820151612d6990612cc7565b60401b17612d81612d5660018460059190911b015190565b825160809190911b90612d9390612cc7565b60c01b17179392505050565b8260108101928215612dcd579160200282015b82811115612dcd578251825591602001919060010190612db2565b50612dd9929150612df5565b5090565b6040518060200160405280612df0612e0a565b905290565b5b80821115612dd95760008155600101612df6565b6040518061032001604052806019906020820280368337509192915050565b600060208284031215612e3b57600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114612e6657600080fd5b919050565b60008060408385031215612e7e57600080fd5b612e8783612e42565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610320810167ffffffffffffffff81118282101715612ee857612ee8612e95565b60405290565b6040516060810167ffffffffffffffff81118282101715612ee857612ee8612e95565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715612f5857612f58612e95565b604052919050565b803567ffffffffffffffff81168114612e6657600080fd5b6000610320808385031215612f8c57600080fd5b604051602080820182811067ffffffffffffffff82111715612fb057612fb0612e95565b806040525081935085601f860112612fc757600080fd5b612fcf612ec4565b928501928087851115612fe157600080fd5b865b8581101561300157612ff481612f60565b8352918301918301612fe3565b509092525091949350505050565b60006060828403121561302157600080fd5b50919050565b60008083601f84011261303957600080fd5b50813567ffffffffffffffff81111561305157600080fd5b6020830191508360208260051b850101111561306c57600080fd5b9250929050565b60008060008060008060008060006103e08a8c03121561309257600080fd5b61309b8a612e42565b985060208a013597506130b18b60408c01612f78565b96506103608a013567ffffffffffffffff808211156130cf57600080fd5b6130db8d838e0161300f565b97506103808c01359150808211156130f257600080fd5b6130fe8d838e01613027565b90975095506103a08c013591508082111561311857600080fd5b6131248d838e0161300f565b94506103c08c013591508082111561313b57600080fd5b506131488c828d01613027565b915080935050809150509295985092959850929598565b600080600080600060a0868803121561317757600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b60005b838110156131b557818101518382015260200161319d565b838111156121145750506000910152565b60208152600082518060208401526131e581604085016020870161319a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b6000806040838503121561322a57600080fd5b50508035926020909101359150565b60008083601f84011261324b57600080fd5b50813567ffffffffffffffff81111561326357600080fd5b60208301915083602082850101111561306c57600080fd5b600080600080600080600060a0888a03121561329657600080fd5b8735965060208801359550604088013567ffffffffffffffff808211156132bc57600080fd5b6132c88b838c01613239565b909750955060608a01359150808211156132e157600080fd5b506132ee8a828b01613027565b9094509250506080880135801515811461330757600080fd5b8091505092959891949750929550565b60008060006060848603121561332c57600080fd5b61333584612e42565b95602085013595506040909401359392505050565b60008060006040848603121561335f57600080fd5b83359250602084013567ffffffffffffffff81111561337d57600080fd5b61338986828701613239565b9497909650939450505050565b600080600080600080600060a0888a0312156133b157600080fd5b8735965060208801359550604088013567ffffffffffffffff808211156133d757600080fd5b6133e38b838c01613239565b909750955060608a01359150808211156133fc57600080fd5b506134098a828b01613239565b989b979a50959894979596608090950135949350505050565b60008060008060006080868803121561343a57600080fd5b8535945061344a60208701612e42565b935061345860408701612f60565b9250606086013567ffffffffffffffff81111561347457600080fd5b61348088828901613239565b969995985093965092949392505050565b6000806000806000608086880312156134a957600080fd5b6134b286612e42565b945060208601359350604086013567ffffffffffffffff808211156134d657600080fd5b6134e289838a0161300f565b945060608801359150808211156134f857600080fd5b5061348088828901613027565b803563ffffffff81168114612e6657600080fd5b60008060006060848603121561352e57600080fd5b8335925061353e60208501613505565b915061354c60408501613505565b90509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036135e4576135e4613584565b5060010190565b6000606082360312156135fd57600080fd5b613605612eee565b823567ffffffffffffffff8082111561361d57600080fd5b9084019036601f83011261363057600080fd5b813560208282111561364457613644612e95565b613674817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f85011601612f11565b9250818352368183860101111561368a57600080fd5b81818501828501376000918301810191909152908352848101359083015250604092830135928101929092525090565b81516103208201908260005b60198110156136ef57825167ffffffffffffffff168252602092830192909101906001016136c6565b50505092915050565b6000821982111561370b5761370b613584565b500190565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261374557600080fd5b83018035915067ffffffffffffffff82111561376057600080fd5b60200191503681900382131561306c57600080fd5b600181815b808511156137ce57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156137b4576137b4613584565b808516156137c157918102915b93841c939080029061377a565b509250929050565b6000826137e557506001613891565b816137f257506000613891565b816001811461380857600281146138125761382e565b6001915050613891565b60ff84111561382357613823613584565b50506001821b613891565b5060208310610133831016604e8410600b8410161715613851575081810a613891565b61385b8383613775565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561388d5761388d613584565b0290505b92915050565b6000612aed83836137d6565b6000828210156138b5576138b5613584565b500390565b600063ffffffff838116908316818110156138d7576138d7613584565b039392505050565b600063ffffffff8083168185168083038211156138fe576138fe613584565b01949350505050565b6000845161391981846020890161319a565b9190910192835250602082015260400191905056fea164736f6c634300080f000a00000000000000000000000000000000000000000000000000000000000027100000000000000000000000000000000000000000000000000000000000000078", - "deployedCode": "0x6080604052600436106101d85760003560e01c80639d53a64811610102578063ddcd58de11610095578063ec5efcbc11610064578063ec5efcbc14610681578063f3f480d9146106a1578063faf37bc7146106d4578063fef2b4ed146106e757600080fd5b8063ddcd58de146105d4578063e03110e11461060c578063e159261114610641578063ea7139501461066157600080fd5b8063b5e7154c116100d1578063b5e7154c14610555578063d18534b51461056c578063da35c6641461058c578063dd24f9bf146105a157600080fd5b80639d53a6481461048e5780639d7e8769146104dd578063b2e67ba8146104fd578063b4801e611461053557600080fd5b806361238bde1161017a5780637ac54767116101495780637ac54767146103ca5780638542cf50146103ea578063882856ef146104355780638dc4be111461046e57600080fd5b806361238bde1461031e5780636551927b146103565780637051472e1461038e5780637917de1d146103aa57600080fd5b80633909af5c116101b65780633909af5c146102715780634d52b4c91461029357806352f0f3ad146102a857806354fd4d50146102c857600080fd5b8063013cf08b146101dd5780630359a5631461022e5780632055b36b1461025c575b600080fd5b3480156101e957600080fd5b506101fd6101f8366004612e29565b610714565b6040805173ffffffffffffffffffffffffffffffffffffffff90931683526020830191909152015b60405180910390f35b34801561023a57600080fd5b5061024e610249366004612e6b565b610759565b604051908152602001610225565b34801561026857600080fd5b5061024e601081565b34801561027d57600080fd5b5061029161028c366004613073565b610891565b005b34801561029f57600080fd5b5061024e610ae8565b3480156102b457600080fd5b5061024e6102c336600461315f565b610b03565b3480156102d457600080fd5b506103116040518060400160405280600a81526020017f312e312e322d72632e310000000000000000000000000000000000000000000081525081565b60405161022591906131c6565b34801561032a57600080fd5b5061024e610339366004613217565b600160209081526000928352604080842090915290825290205481565b34801561036257600080fd5b5061024e610371366004612e6b565b601560209081526000928352604080842090915290825290205481565b34801561039a57600080fd5b5061024e6703782dace9d9000081565b3480156103b657600080fd5b506102916103c536600461327b565b610bd9565b3480156103d657600080fd5b5061024e6103e5366004612e29565b6110dc565b3480156103f657600080fd5b50610425610405366004613217565b600260209081526000928352604080842090915290825290205460ff1681565b6040519015158152602001610225565b34801561044157600080fd5b50610455610450366004613317565b6110f3565b60405167ffffffffffffffff9091168152602001610225565b34801561047a57600080fd5b5061029161048936600461334a565b61114d565b34801561049a57600080fd5b5061024e6104a9366004612e6b565b73ffffffffffffffffffffffffffffffffffffffff9091166000908152601860209081526040808320938352929052205490565b3480156104e957600080fd5b506102916104f8366004613396565b611248565b34801561050957600080fd5b5061024e610518366004612e6b565b601760209081526000928352604080842090915290825290205481565b34801561054157600080fd5b5061024e610550366004613317565b6113ff565b34801561056157600080fd5b5061024e620186a081565b34801561057857600080fd5b50610291610587366004613073565b611431565b34801561059857600080fd5b5060135461024e565b3480156105ad57600080fd5b507f000000000000000000000000000000000000000000000000000000000000271061024e565b3480156105e057600080fd5b5061024e6105ef366004612e6b565b601660209081526000928352604080842090915290825290205481565b34801561061857600080fd5b5061062c610627366004613217565b611840565b60408051928352602083019190915201610225565b34801561064d57600080fd5b5061029161065c36600461334a565b611931565b34801561066d57600080fd5b5061029161067c366004613422565b611a39565b34801561068d57600080fd5b5061029161069c366004613491565b611b98565b3480156106ad57600080fd5b507f000000000000000000000000000000000000000000000000000000000000007861024e565b6102916106e2366004613519565b611d1e565b3480156106f357600080fd5b5061024e610702366004612e29565b60006020819052908152604090205481565b6013818154811061072457600080fd5b60009182526020909120600290910201805460019091015473ffffffffffffffffffffffffffffffffffffffff909116915082565b73ffffffffffffffffffffffffffffffffffffffff82166000908152601560209081526040808320848452909152812054819061079c9060601c63ffffffff1690565b63ffffffff16905060005b6010811015610889578160011660010361082f5773ffffffffffffffffffffffffffffffffffffffff85166000908152601460209081526040808320878452909152902081601081106107fc576107fc613555565b01546040805160208101929092528101849052606001604051602081830303815290604052805190602001209250610870565b826003826010811061084357610843613555565b01546040805160208101939093528201526060016040516020818303038152906040528051906020012092505b60019190911c9080610881816135b3565b9150506107a7565b505092915050565b600061089d8a8a610759565b90506108c086868360208b01356108bb6108b68d6135eb565b611fea565b61202a565b80156108de57506108de83838360208801356108bb6108b68a6135eb565b610914576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b86604001358860405160200161092a91906136ba565b6040516020818303038152906040528051906020012014610977576040517f1968a90200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83602001358760200135600161098d91906136f8565b146109c4576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a0c886109d28680613710565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061208b92505050565b610a15886121e6565b836040013588604051602001610a2b91906136ba565b6040516020818303038152906040528051906020012003610a78576040517f9843145b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8a1660009081526015602090815260408083208c8452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000166001179055610adc8a8a3361298e565b50505050505050505050565b6001610af660106002613897565b610b0091906138a3565b81565b6000610b0f8686612a47565b9050610b1c8360086136f8565b82101580610b2a5750602083115b15610b61576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000602081815260c085901b82526008959095528251828252600286526040808320858452875280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558484528752808320948352938652838220558181529384905292205592915050565b60608115610bf257610beb8686612af4565b9050610c2c565b85858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050505b3360009081526014602090815260408083208b845290915280822081516102008101928390529160109082845b815481526020019060010190808311610c5957505050505090506000601560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008b81526020019081526020016000205490506000610cda8260601c63ffffffff1690565b63ffffffff169050333214610d1b576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d2b8260801c63ffffffff1690565b63ffffffff16600003610d6a576040517f87138d5c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d748260c01c90565b67ffffffffffffffff1615610db5576040517f475a253500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b898114610dee576040517f60f95d5a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610dfb89898d8886612b6d565b83516020850160888204881415608883061715610e20576307b1daf16000526004601cfd5b60405160c8810160405260005b83811015610ed0578083018051835260208101516020840152604081015160408401526060810151606084015260808101516080840152508460888301526088810460051b8b013560a883015260c882206001860195508560005b610200811015610ec5576001821615610ea55782818b0152610ec5565b8981015160009081526020938452604090209260019290921c9101610e88565b505050608801610e2d565b50505050600160106002610ee49190613897565b610eee91906138a3565b811115610f27576040517f6229572300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f9c610f3a8360401c63ffffffff1690565b610f4a9063ffffffff168a6136f8565b60401b7fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff606084901b167fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff8516171790565b915084156110295777ffffffffffffffffffffffffffffffffffffffffffffffff82164260c01b179150610fd68260801c63ffffffff1690565b63ffffffff16610fec8360401c63ffffffff1690565b63ffffffff1614611029576040517f7b1dafd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360009081526014602090815260408083208e8452909152902061104f90846010612d9f565b503360008181526018602090815260408083208f8452825280832080546001810182559084528284206004820401805460039092166008026101000a67ffffffffffffffff818102199093164390931602919091179055838352601582528083208f8452909152812084905560609190911b81523690601437366014016000a05050505050505050505050565b600381601081106110ec57600080fd5b0154905081565b6018602052826000526040600020602052816000526040600020818154811061111b57600080fd5b906000526020600020906004918282040191900660080292509250509054906101000a900467ffffffffffffffff1681565b60443560008060088301861061116b5763fe2549876000526004601cfd5b60c083901b60805260888386823786600882030151915060206000858360025afa90508061119857600080fd5b50600080517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0400000000000000000000000000000000000000000000000000000000000000178082526002602090815260408084208a8552825280842080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558385528252808420998452988152888320939093558152908190529490942055505050565b600080603087600037602060006030600060025afa806112705763f91129696000526004601cfd5b6000517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f010000000000000000000000000000000000000000000000000000000000000017608081815260a08c905260c08b905260308a60e037603088609083013760008060c083600a5afa9250826112f2576309bde3396000526004601cfd5b602886106113085763fe2549876000526004601cfd5b6000602882015278200000000000000000000000000000000000000000000000008152600881018b905285810151935060308a8237603081019b909b52505060509098207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0500000000000000000000000000000000000000000000000000000000000000176000818152600260209081526040808320868452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845282528083209583529481528482209a909a559081528089529190912096909655505050505050565b6014602052826000526040600020602052816000526040600020816010811061142757600080fd5b0154925083915050565b73ffffffffffffffffffffffffffffffffffffffff891660009081526015602090815260408083208b845290915290205467ffffffffffffffff8116156114a4576040517fc334f06900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6114ae8160c01c90565b67ffffffffffffffff166000036114f1576040517f55d4cbf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000007861151c8260c01c90565b6115309067ffffffffffffffff16426138a3565b11611567576040517f55d4cbf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006115738b8b610759565b905061158c87878360208c01356108bb6108b68e6135eb565b80156115aa57506115aa84848360208901356108bb6108b68b6135eb565b6115e0576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8760400135896040516020016115f691906136ba565b6040516020818303038152906040528051906020012014611643576040517f1968a90200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84602001358860200135600161165991906136f8565b14158061168b575060016116738360601c63ffffffff1690565b61167d91906138ba565b63ffffffff16856020013514155b156116c2576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6116d0896109d28780613710565b6116d9896121e6565b60006116e48a612cc0565b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0200000000000000000000000000000000000000000000000000000000000000179050600061173b8460a01c63ffffffff1690565b67ffffffffffffffff169050600160026000848152602001908152602001600020600083815260200190815260200160002060006101000a81548160ff021916908315150217905550601760008e73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008d8152602001908152602001600020546001600084815260200190815260200160002060008381526020019081526020016000208190555061180d8460801c63ffffffff1690565b600083815260208190526040902063ffffffff9190911690556118318d8d8161298e565b50505050505050505050505050565b6000828152600260209081526040808320848452909152812054819060ff166118c9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f7072652d696d616765206d757374206578697374000000000000000000000000604482015260640160405180910390fd5b50600083815260208181526040909120546118e58160086136f8565b6118f08560206136f8565b1061190e57836119018260086136f8565b61190b91906138a3565b91505b506000938452600160209081526040808620948652939052919092205492909150565b60443560008060088301861061194f5763fe2549876000526004601cfd5b60c083901b6080526088838682378087017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80151908490207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f02000000000000000000000000000000000000000000000000000000000000001760008181526002602090815260408083208b8452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845282528083209a83529981528982209390935590815290819052959095209190915550505050565b60008060008060808860601b81528760c01b6014820152858782601c0137601c860181207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0600000000000000000000000000000000000000000000000000000000000000179350604088026260216001603f5a021015611ac35763dd629f866000526004601cfd5b6000808783601c018c5afa94503d6001019150600882018a10611aee5763fe2549876000526004601cfd5b60c082901b81526008018481533d6000600183013e89017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8015160008481526002602090815260408083208d8452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915587845282528083209c83529b81528b8220929092559384528390529790912096909655505050505050565b6000611ba48686610759565b9050611bbd83838360208801356108bb6108b68a6135eb565b611bf3576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602084013515611c2f576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611c37612ddd565b611c45816109d28780613710565b611c4e816121e6565b846040013581604051602001611c6491906136ba565b6040516020818303038152906040528051906020012003611cb1576040517f9843145b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff87166000908152601560209081526040808320898452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000166001179055611d1587873361298e565b50505050505050565b6703782dace9d90000341015611d60576040517fe92c469f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b333214611d99576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611da48160086138df565b63ffffffff168263ffffffff1610611de8576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000027108163ffffffff161015611e48576040517f7b1dafd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152601560209081526040808320868452909152902054611e738160801c63ffffffff1690565b63ffffffff1615611eb0576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b608082901b7fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff60a085901b167fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff83161717336000818152601560209081526040808320898452825280832094909455835180850185528381528082018981526013805460018101825590855291517f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a090600290930292830180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909216919091179055517f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a0919091015591815260168252828120968152959052909320349055505050565b600081600001518260200151836040015160405160200161200d93929190613907565b604051602081830303815290604052805190602001209050919050565b60008160005b601081101561207e578060051b880135600186831c16600181146120635760008481526020839052604090209350612074565b600082815260208590526040902093505b5050600101612030565b5090931495945050505050565b608881511461209957600080fd5b602081016020830161211a565b8260031b8201518060001a8160011a60081b178160021a60101b8260031a60181b17178160041a60201b8260051a60281b178260061a60301b8360071a60381b1717179050612114816120ff868560059190911b015190565b1867ffffffffffffffff16600586901b840152565b50505050565b612126600083836120a6565b612132600183836120a6565b61213e600283836120a6565b61214a600383836120a6565b612156600483836120a6565b612162600583836120a6565b61216e600683836120a6565b61217a600783836120a6565b612186600883836120a6565b612192600983836120a6565b61219e600a83836120a6565b6121aa600b83836120a6565b6121b6600c83836120a6565b6121c2600d83836120a6565b6121ce600e83836120a6565b6121da600f83836120a6565b612114601083836120a6565b6040805178010000000000008082800000000000808a8000000080008000602082015279808b00000000800000018000000080008081800000000000800991810191909152788a00000000000000880000000080008009000000008000000a60608201527b8000808b800000000000008b8000000000008089800000000000800360808201527f80000000000080028000000000000080000000000000800a800000008000000a60a08201527f800000008000808180000000000080800000000080000001800000008000800860c082015260009060e0016040516020818303038152906040529050602082016020820161286e565b6102808101516101e082015161014083015160a0840151845118189118186102a082015161020083015161016084015160c0850151602086015118189118186102c083015161022084015161018085015160e0860151604087015118189118186102e08401516102408501516101a0860151610100870151606088015118189118186103008501516102608601516101c0870151610120880151608089015118189118188084603f1c6123998660011b67ffffffffffffffff1690565b18188584603f1c6123b48660011b67ffffffffffffffff1690565b18188584603f1c6123cf8660011b67ffffffffffffffff1690565b181895508483603f1c6123ec8560011b67ffffffffffffffff1690565b181894508387603f1c6124098960011b67ffffffffffffffff1690565b60208b01518b51861867ffffffffffffffff168c5291189190911897508118600181901b603f9190911c18935060c08801518118601481901c602c9190911b1867ffffffffffffffff1660208901526101208801518718602c81901c60149190911b1867ffffffffffffffff1660c08901526102c08801518618600381901c603d9190911b1867ffffffffffffffff166101208901526101c08801518718601981901c60279190911b1867ffffffffffffffff166102c08901526102808801518218602e81901c60129190911b1867ffffffffffffffff166101c089015260408801518618600281901c603e9190911b1867ffffffffffffffff166102808901526101808801518618601581901c602b9190911b1867ffffffffffffffff1660408901526101a08801518518602781901c60199190911b1867ffffffffffffffff166101808901526102608801518718603881901c60089190911b1867ffffffffffffffff166101a08901526102e08801518518600881901c60389190911b1867ffffffffffffffff166102608901526101e08801518218601781901c60299190911b1867ffffffffffffffff166102e089015260808801518718602581901c601b9190911b1867ffffffffffffffff166101e08901526103008801518718603281901c600e9190911b1867ffffffffffffffff1660808901526102a08801518118603e81901c60029190911b1867ffffffffffffffff166103008901526101008801518518600981901c60379190911b1867ffffffffffffffff166102a08901526102008801518118601381901c602d9190911b1867ffffffffffffffff1661010089015260a08801518218601c81901c60249190911b1867ffffffffffffffff1661020089015260608801518518602481901c601c9190911b1867ffffffffffffffff1660a08901526102408801518518602b81901c60159190911b1867ffffffffffffffff1660608901526102208801518618603181901c600f9190911b1867ffffffffffffffff166102408901526101608801518118603681901c600a9190911b1867ffffffffffffffff166102208901525060e08701518518603a81901c60069190911b1867ffffffffffffffff166101608801526101408701518118603d81901c60039190911b1867ffffffffffffffff1660e0880152505067ffffffffffffffff81166101408601525b5050505050565b600582811b8201805160018501831b8401805160028701851b8601805160038901871b8801805160048b0190981b8901805167ffffffffffffffff861985168918811690995283198a16861889169096528819861683188816909352841986168818871690528419831684189095169052919391929190611d15565b612808600082612781565b612813600582612781565b61281e600a82612781565b612829600f82612781565b612834601482612781565b50565b612840816122dc565b612849816127fd565b600383901b820151815160c09190911c9061211490821867ffffffffffffffff168352565b61287a60008284612837565b61288660018284612837565b61289260028284612837565b61289e60038284612837565b6128aa60048284612837565b6128b660058284612837565b6128c260068284612837565b6128ce60078284612837565b6128da60088284612837565b6128e660098284612837565b6128f2600a8284612837565b6128fe600b8284612837565b61290a600c8284612837565b612916600d8284612837565b612922600e8284612837565b61292e600f8284612837565b61293a60108284612837565b61294660118284612837565b61295260128284612837565b61295e60138284612837565b61296a60148284612837565b61297660158284612837565b61298260168284612837565b61211460178284612837565b73ffffffffffffffffffffffffffffffffffffffff83811660009081526016602090815260408083208684529091528082208054908390559051909284169083908381818185875af1925050503d8060008114612a07576040519150601f19603f3d011682016040523d82523d6000602084013e612a0c565b606091505b505090508061277a576040517f83e6cc6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f01000000000000000000000000000000000000000000000000000000000000007effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831617612aed818360408051600093845233602052918152606090922091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790565b9392505050565b6060604051905081602082018181018286833760888306808015612b3d5760888290038501848101848103803687375060806001820353506001845160001a1784538652612b54565b608836843760018353608060878401536088850186525b5050505050601f19603f82510116810160405292915050565b6000612b7f8260a01c63ffffffff1690565b67ffffffffffffffff1690506000612b9d8360801c63ffffffff1690565b63ffffffff1690506000612bb78460401c63ffffffff1690565b63ffffffff169050600883108015612bcd575080155b15612c015760c082901b6000908152883560085283513382526017602090815260408084208a855290915290912055612cb6565b60088310158015612c1f575080612c196008856138a3565b93508310155b8015612c335750612c3087826136f8565b83105b15612cb6576000612c4482856138a3565b905087612c528260206136f8565b10158015612c5e575085155b15612c95576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360009081526017602090815260408083208a845290915290209089013590555b5050505050505050565b6000612d43565b66ff00ff00ff00ff8160081c1667ff00ff00ff00ff00612cf18360081b67ffffffffffffffff1690565b1617905065ffff0000ffff8160101c1667ffff0000ffff0000612d1e8360101b67ffffffffffffffff1690565b1617905060008160201c612d3c8360201b67ffffffffffffffff1690565b1792915050565b60808201516020830190612d5b90612cc7565b612cc7565b6040820151612d6990612cc7565b60401b17612d81612d5660018460059190911b015190565b825160809190911b90612d9390612cc7565b60c01b17179392505050565b8260108101928215612dcd579160200282015b82811115612dcd578251825591602001919060010190612db2565b50612dd9929150612df5565b5090565b6040518060200160405280612df0612e0a565b905290565b5b80821115612dd95760008155600101612df6565b6040518061032001604052806019906020820280368337509192915050565b600060208284031215612e3b57600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114612e6657600080fd5b919050565b60008060408385031215612e7e57600080fd5b612e8783612e42565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610320810167ffffffffffffffff81118282101715612ee857612ee8612e95565b60405290565b6040516060810167ffffffffffffffff81118282101715612ee857612ee8612e95565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715612f5857612f58612e95565b604052919050565b803567ffffffffffffffff81168114612e6657600080fd5b6000610320808385031215612f8c57600080fd5b604051602080820182811067ffffffffffffffff82111715612fb057612fb0612e95565b806040525081935085601f860112612fc757600080fd5b612fcf612ec4565b928501928087851115612fe157600080fd5b865b8581101561300157612ff481612f60565b8352918301918301612fe3565b509092525091949350505050565b60006060828403121561302157600080fd5b50919050565b60008083601f84011261303957600080fd5b50813567ffffffffffffffff81111561305157600080fd5b6020830191508360208260051b850101111561306c57600080fd5b9250929050565b60008060008060008060008060006103e08a8c03121561309257600080fd5b61309b8a612e42565b985060208a013597506130b18b60408c01612f78565b96506103608a013567ffffffffffffffff808211156130cf57600080fd5b6130db8d838e0161300f565b97506103808c01359150808211156130f257600080fd5b6130fe8d838e01613027565b90975095506103a08c013591508082111561311857600080fd5b6131248d838e0161300f565b94506103c08c013591508082111561313b57600080fd5b506131488c828d01613027565b915080935050809150509295985092959850929598565b600080600080600060a0868803121561317757600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b60005b838110156131b557818101518382015260200161319d565b838111156121145750506000910152565b60208152600082518060208401526131e581604085016020870161319a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b6000806040838503121561322a57600080fd5b50508035926020909101359150565b60008083601f84011261324b57600080fd5b50813567ffffffffffffffff81111561326357600080fd5b60208301915083602082850101111561306c57600080fd5b600080600080600080600060a0888a03121561329657600080fd5b8735965060208801359550604088013567ffffffffffffffff808211156132bc57600080fd5b6132c88b838c01613239565b909750955060608a01359150808211156132e157600080fd5b506132ee8a828b01613027565b9094509250506080880135801515811461330757600080fd5b8091505092959891949750929550565b60008060006060848603121561332c57600080fd5b61333584612e42565b95602085013595506040909401359392505050565b60008060006040848603121561335f57600080fd5b83359250602084013567ffffffffffffffff81111561337d57600080fd5b61338986828701613239565b9497909650939450505050565b600080600080600080600060a0888a0312156133b157600080fd5b8735965060208801359550604088013567ffffffffffffffff808211156133d757600080fd5b6133e38b838c01613239565b909750955060608a01359150808211156133fc57600080fd5b506134098a828b01613239565b989b979a50959894979596608090950135949350505050565b60008060008060006080868803121561343a57600080fd5b8535945061344a60208701612e42565b935061345860408701612f60565b9250606086013567ffffffffffffffff81111561347457600080fd5b61348088828901613239565b969995985093965092949392505050565b6000806000806000608086880312156134a957600080fd5b6134b286612e42565b945060208601359350604086013567ffffffffffffffff808211156134d657600080fd5b6134e289838a0161300f565b945060608801359150808211156134f857600080fd5b5061348088828901613027565b803563ffffffff81168114612e6657600080fd5b60008060006060848603121561352e57600080fd5b8335925061353e60208501613505565b915061354c60408501613505565b90509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036135e4576135e4613584565b5060010190565b6000606082360312156135fd57600080fd5b613605612eee565b823567ffffffffffffffff8082111561361d57600080fd5b9084019036601f83011261363057600080fd5b813560208282111561364457613644612e95565b613674817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f85011601612f11565b9250818352368183860101111561368a57600080fd5b81818501828501376000918301810191909152908352848101359083015250604092830135928101929092525090565b81516103208201908260005b60198110156136ef57825167ffffffffffffffff168252602092830192909101906001016136c6565b50505092915050565b6000821982111561370b5761370b613584565b500190565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261374557600080fd5b83018035915067ffffffffffffffff82111561376057600080fd5b60200191503681900382131561306c57600080fd5b600181815b808511156137ce57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156137b4576137b4613584565b808516156137c157918102915b93841c939080029061377a565b509250929050565b6000826137e557506001613891565b816137f257506000613891565b816001811461380857600281146138125761382e565b6001915050613891565b60ff84111561382357613823613584565b50506001821b613891565b5060208310610133831016604e8410600b8410161715613851575081810a613891565b61385b8383613775565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561388d5761388d613584565b0290505b92915050565b6000612aed83836137d6565b6000828210156138b5576138b5613584565b500390565b600063ffffffff838116908316818110156138d7576138d7613584565b039392505050565b600063ffffffff8083168185168083038211156138fe576138fe613584565b01949350505050565b6000845161391981846020890161319a565b9190910192835250602082015260400191905056fea164736f6c634300080f000a", - "initialized": true, - "kind": "Create", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x373d916D11cce55b548F7051002e76BCFBD7a85d", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000003" - }, - { - "account": "0x373d916D11cce55b548F7051002e76BCFBD7a85d", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000003" - }, - { - "account": "0x373d916D11cce55b548F7051002e76BCFBD7a85d", - "isWrite": true, - "newValue": "0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" - }, - { - "account": "0x373d916D11cce55b548F7051002e76BCFBD7a85d", - "isWrite": false, - "newValue": "0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5", - "previousValue": "0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" - }, - { - "account": "0x373d916D11cce55b548F7051002e76BCFBD7a85d", - "isWrite": false, - "newValue": "0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5", - "previousValue": "0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" - }, - { - "account": "0x373d916D11cce55b548F7051002e76BCFBD7a85d", - "isWrite": true, - "newValue": "0xb4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d30", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" - }, - { - "account": "0x373d916D11cce55b548F7051002e76BCFBD7a85d", - "isWrite": false, - "newValue": "0xb4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d30", - "previousValue": "0xb4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d30", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" - }, - { - "account": "0x373d916D11cce55b548F7051002e76BCFBD7a85d", - "isWrite": false, - "newValue": "0xb4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d30", - "previousValue": "0xb4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d30", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" - }, - { - "account": "0x373d916D11cce55b548F7051002e76BCFBD7a85d", - "isWrite": true, - "newValue": "0x21ddb9a356815c3fac1026b6dec5df3124afbadb485c9ba5a3e3398a04b7ba85", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000006" - }, - { - "account": "0x373d916D11cce55b548F7051002e76BCFBD7a85d", - "isWrite": false, - "newValue": "0x21ddb9a356815c3fac1026b6dec5df3124afbadb485c9ba5a3e3398a04b7ba85", - "previousValue": "0x21ddb9a356815c3fac1026b6dec5df3124afbadb485c9ba5a3e3398a04b7ba85", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000006" - }, - { - "account": "0x373d916D11cce55b548F7051002e76BCFBD7a85d", - "isWrite": false, - "newValue": "0x21ddb9a356815c3fac1026b6dec5df3124afbadb485c9ba5a3e3398a04b7ba85", - "previousValue": "0x21ddb9a356815c3fac1026b6dec5df3124afbadb485c9ba5a3e3398a04b7ba85", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000006" - }, - { - "account": "0x373d916D11cce55b548F7051002e76BCFBD7a85d", - "isWrite": true, - "newValue": "0xe58769b32a1beaf1ea27375a44095a0d1fb664ce2dd358e7fcbfb78c26a19344", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000007" - }, - { - "account": "0x373d916D11cce55b548F7051002e76BCFBD7a85d", - "isWrite": false, - "newValue": "0xe58769b32a1beaf1ea27375a44095a0d1fb664ce2dd358e7fcbfb78c26a19344", - "previousValue": "0xe58769b32a1beaf1ea27375a44095a0d1fb664ce2dd358e7fcbfb78c26a19344", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000007" - }, - { - "account": "0x373d916D11cce55b548F7051002e76BCFBD7a85d", - "isWrite": false, - "newValue": "0xe58769b32a1beaf1ea27375a44095a0d1fb664ce2dd358e7fcbfb78c26a19344", - "previousValue": "0xe58769b32a1beaf1ea27375a44095a0d1fb664ce2dd358e7fcbfb78c26a19344", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000007" - }, - { - "account": "0x373d916D11cce55b548F7051002e76BCFBD7a85d", - "isWrite": true, - "newValue": "0x0eb01ebfc9ed27500cd4dfc979272d1f0913cc9f66540d7e8005811109e1cf2d", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000008" - }, - { - "account": "0x373d916D11cce55b548F7051002e76BCFBD7a85d", - "isWrite": false, - "newValue": "0x0eb01ebfc9ed27500cd4dfc979272d1f0913cc9f66540d7e8005811109e1cf2d", - "previousValue": "0x0eb01ebfc9ed27500cd4dfc979272d1f0913cc9f66540d7e8005811109e1cf2d", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000008" - }, - { - "account": "0x373d916D11cce55b548F7051002e76BCFBD7a85d", - "isWrite": false, - "newValue": "0x0eb01ebfc9ed27500cd4dfc979272d1f0913cc9f66540d7e8005811109e1cf2d", - "previousValue": "0x0eb01ebfc9ed27500cd4dfc979272d1f0913cc9f66540d7e8005811109e1cf2d", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000008" - }, - { - "account": "0x373d916D11cce55b548F7051002e76BCFBD7a85d", - "isWrite": true, - "newValue": "0x887c22bd8750d34016ac3c66b5ff102dacdd73f6b014e710b51e8022af9a1968", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000009" - }, - { - "account": "0x373d916D11cce55b548F7051002e76BCFBD7a85d", - "isWrite": false, - "newValue": "0x887c22bd8750d34016ac3c66b5ff102dacdd73f6b014e710b51e8022af9a1968", - "previousValue": "0x887c22bd8750d34016ac3c66b5ff102dacdd73f6b014e710b51e8022af9a1968", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000009" - }, - { - "account": "0x373d916D11cce55b548F7051002e76BCFBD7a85d", - "isWrite": false, - "newValue": "0x887c22bd8750d34016ac3c66b5ff102dacdd73f6b014e710b51e8022af9a1968", - "previousValue": "0x887c22bd8750d34016ac3c66b5ff102dacdd73f6b014e710b51e8022af9a1968", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000009" - }, - { - "account": "0x373d916D11cce55b548F7051002e76BCFBD7a85d", - "isWrite": true, - "newValue": "0xffd70157e48063fc33c97a050f7f640233bf646cc98d9524c6b92bcf3ab56f83", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x000000000000000000000000000000000000000000000000000000000000000a" - }, - { - "account": "0x373d916D11cce55b548F7051002e76BCFBD7a85d", - "isWrite": false, - "newValue": "0xffd70157e48063fc33c97a050f7f640233bf646cc98d9524c6b92bcf3ab56f83", - "previousValue": "0xffd70157e48063fc33c97a050f7f640233bf646cc98d9524c6b92bcf3ab56f83", - "reverted": false, - "slot": "0x000000000000000000000000000000000000000000000000000000000000000a" - }, - { - "account": "0x373d916D11cce55b548F7051002e76BCFBD7a85d", - "isWrite": false, - "newValue": "0xffd70157e48063fc33c97a050f7f640233bf646cc98d9524c6b92bcf3ab56f83", - "previousValue": "0xffd70157e48063fc33c97a050f7f640233bf646cc98d9524c6b92bcf3ab56f83", - "reverted": false, - "slot": "0x000000000000000000000000000000000000000000000000000000000000000a" - }, - { - "account": "0x373d916D11cce55b548F7051002e76BCFBD7a85d", - "isWrite": true, - "newValue": "0x9867cc5f7f196b93bae1e27e6320742445d290f2263827498b54fec539f756af", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x000000000000000000000000000000000000000000000000000000000000000b" - }, - { - "account": "0x373d916D11cce55b548F7051002e76BCFBD7a85d", - "isWrite": false, - "newValue": "0x9867cc5f7f196b93bae1e27e6320742445d290f2263827498b54fec539f756af", - "previousValue": "0x9867cc5f7f196b93bae1e27e6320742445d290f2263827498b54fec539f756af", - "reverted": false, - "slot": "0x000000000000000000000000000000000000000000000000000000000000000b" - }, - { - "account": "0x373d916D11cce55b548F7051002e76BCFBD7a85d", - "isWrite": false, - "newValue": "0x9867cc5f7f196b93bae1e27e6320742445d290f2263827498b54fec539f756af", - "previousValue": "0x9867cc5f7f196b93bae1e27e6320742445d290f2263827498b54fec539f756af", - "reverted": false, - "slot": "0x000000000000000000000000000000000000000000000000000000000000000b" - }, - { - "account": "0x373d916D11cce55b548F7051002e76BCFBD7a85d", - "isWrite": true, - "newValue": "0xcefad4e508c098b9a7e1d8feb19955fb02ba9675585078710969d3440f5054e0", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x000000000000000000000000000000000000000000000000000000000000000c" - }, - { - "account": "0x373d916D11cce55b548F7051002e76BCFBD7a85d", - "isWrite": false, - "newValue": "0xcefad4e508c098b9a7e1d8feb19955fb02ba9675585078710969d3440f5054e0", - "previousValue": "0xcefad4e508c098b9a7e1d8feb19955fb02ba9675585078710969d3440f5054e0", - "reverted": false, - "slot": "0x000000000000000000000000000000000000000000000000000000000000000c" - }, - { - "account": "0x373d916D11cce55b548F7051002e76BCFBD7a85d", - "isWrite": false, - "newValue": "0xcefad4e508c098b9a7e1d8feb19955fb02ba9675585078710969d3440f5054e0", - "previousValue": "0xcefad4e508c098b9a7e1d8feb19955fb02ba9675585078710969d3440f5054e0", - "reverted": false, - "slot": "0x000000000000000000000000000000000000000000000000000000000000000c" - }, - { - "account": "0x373d916D11cce55b548F7051002e76BCFBD7a85d", - "isWrite": true, - "newValue": "0xf9dc3e7fe016e050eff260334f18a5d4fe391d82092319f5964f2e2eb7c1c3a5", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x000000000000000000000000000000000000000000000000000000000000000d" - }, - { - "account": "0x373d916D11cce55b548F7051002e76BCFBD7a85d", - "isWrite": false, - "newValue": "0xf9dc3e7fe016e050eff260334f18a5d4fe391d82092319f5964f2e2eb7c1c3a5", - "previousValue": "0xf9dc3e7fe016e050eff260334f18a5d4fe391d82092319f5964f2e2eb7c1c3a5", - "reverted": false, - "slot": "0x000000000000000000000000000000000000000000000000000000000000000d" - }, - { - "account": "0x373d916D11cce55b548F7051002e76BCFBD7a85d", - "isWrite": false, - "newValue": "0xf9dc3e7fe016e050eff260334f18a5d4fe391d82092319f5964f2e2eb7c1c3a5", - "previousValue": "0xf9dc3e7fe016e050eff260334f18a5d4fe391d82092319f5964f2e2eb7c1c3a5", - "reverted": false, - "slot": "0x000000000000000000000000000000000000000000000000000000000000000d" - }, - { - "account": "0x373d916D11cce55b548F7051002e76BCFBD7a85d", - "isWrite": true, - "newValue": "0xf8b13a49e282f609c317a833fb8d976d11517c571d1221a265d25af778ecf892", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x000000000000000000000000000000000000000000000000000000000000000e" - }, - { - "account": "0x373d916D11cce55b548F7051002e76BCFBD7a85d", - "isWrite": false, - "newValue": "0xf8b13a49e282f609c317a833fb8d976d11517c571d1221a265d25af778ecf892", - "previousValue": "0xf8b13a49e282f609c317a833fb8d976d11517c571d1221a265d25af778ecf892", - "reverted": false, - "slot": "0x000000000000000000000000000000000000000000000000000000000000000e" - }, - { - "account": "0x373d916D11cce55b548F7051002e76BCFBD7a85d", - "isWrite": false, - "newValue": "0xf8b13a49e282f609c317a833fb8d976d11517c571d1221a265d25af778ecf892", - "previousValue": "0xf8b13a49e282f609c317a833fb8d976d11517c571d1221a265d25af778ecf892", - "reverted": false, - "slot": "0x000000000000000000000000000000000000000000000000000000000000000e" - }, - { - "account": "0x373d916D11cce55b548F7051002e76BCFBD7a85d", - "isWrite": true, - "newValue": "0x3490c6ceeb450aecdc82e28293031d10c7d73bf85e57bf041a97360aa2c5d99c", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x000000000000000000000000000000000000000000000000000000000000000f" - }, - { - "account": "0x373d916D11cce55b548F7051002e76BCFBD7a85d", - "isWrite": false, - "newValue": "0x3490c6ceeb450aecdc82e28293031d10c7d73bf85e57bf041a97360aa2c5d99c", - "previousValue": "0x3490c6ceeb450aecdc82e28293031d10c7d73bf85e57bf041a97360aa2c5d99c", - "reverted": false, - "slot": "0x000000000000000000000000000000000000000000000000000000000000000f" - }, - { - "account": "0x373d916D11cce55b548F7051002e76BCFBD7a85d", - "isWrite": false, - "newValue": "0x3490c6ceeb450aecdc82e28293031d10c7d73bf85e57bf041a97360aa2c5d99c", - "previousValue": "0x3490c6ceeb450aecdc82e28293031d10c7d73bf85e57bf041a97360aa2c5d99c", - "reverted": false, - "slot": "0x000000000000000000000000000000000000000000000000000000000000000f" - }, - { - "account": "0x373d916D11cce55b548F7051002e76BCFBD7a85d", - "isWrite": true, - "newValue": "0xc1df82d9c4b87413eae2ef048f94b4d3554cea73d92b0f7af96e0271c691e2bb", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000010" - }, - { - "account": "0x373d916D11cce55b548F7051002e76BCFBD7a85d", - "isWrite": false, - "newValue": "0xc1df82d9c4b87413eae2ef048f94b4d3554cea73d92b0f7af96e0271c691e2bb", - "previousValue": "0xc1df82d9c4b87413eae2ef048f94b4d3554cea73d92b0f7af96e0271c691e2bb", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000010" - }, - { - "account": "0x373d916D11cce55b548F7051002e76BCFBD7a85d", - "isWrite": false, - "newValue": "0xc1df82d9c4b87413eae2ef048f94b4d3554cea73d92b0f7af96e0271c691e2bb", - "previousValue": "0xc1df82d9c4b87413eae2ef048f94b4d3554cea73d92b0f7af96e0271c691e2bb", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000010" - }, - { - "account": "0x373d916D11cce55b548F7051002e76BCFBD7a85d", - "isWrite": true, - "newValue": "0x5c67add7c6caf302256adedf7ab114da0acfe870d449a3a489f781d659e8becc", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000011" - }, - { - "account": "0x373d916D11cce55b548F7051002e76BCFBD7a85d", - "isWrite": false, - "newValue": "0x5c67add7c6caf302256adedf7ab114da0acfe870d449a3a489f781d659e8becc", - "previousValue": "0x5c67add7c6caf302256adedf7ab114da0acfe870d449a3a489f781d659e8becc", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000011" - }, - { - "account": "0x373d916D11cce55b548F7051002e76BCFBD7a85d", - "isWrite": false, - "newValue": "0x5c67add7c6caf302256adedf7ab114da0acfe870d449a3a489f781d659e8becc", - "previousValue": "0x5c67add7c6caf302256adedf7ab114da0acfe870d449a3a489f781d659e8becc", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000011" - }, - { - "account": "0x373d916D11cce55b548F7051002e76BCFBD7a85d", - "isWrite": true, - "newValue": "0xda7bce9f4e8618b6bd2f4132ce798cdc7a60e7e1460a7299e3c6342a579626d2", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000012" - } - ], - "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": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x638627e586f5e36fe67a77519503a7c6da22f92b150d3c6055fd40bdcfe9ffd160a060405234801561001057600080fd5b506040516200243a3803806200243a83398101604081905261003191610042565b6001600160a01b0316608052610072565b60006020828403121561005457600080fd5b81516001600160a01b038116811461006b57600080fd5b9392505050565b6080516123a6620000946000396000818160b201526106eb01526123a66000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c806354fd4d50146100465780637dc0d1d014610098578063e14ced32146100dc575b600080fd5b6100826040518060400160405280600a81526020017f312e312e302d72632e310000000000000000000000000000000000000000000081525081565b60405161008f91906121ee565b60405180910390f35b60405173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016815260200161008f565b6100ef6100ea3660046122a3565b6100fd565b60405190815260200161008f565b6000610107612164565b6080811461011457600080fd5b6040516106001461012457600080fd5b6084871461013157600080fd5b6101a4851461013f57600080fd5b8635608052602087013560a052604087013560e090811c60c09081526044890135821c82526048890135821c61010052604c890135821c610120526050890135821c61014052605489013590911c61016052605888013560f890811c610180526059890135901c6101a0819052605a89013590911c6101c05260628801906101e09060018111156101f5576040517f0136cc76000000000000000000000000000000000000000000000000000000008152600481fd5b506020810181511461020657600080fd5b60200160005b602081101561023057823560e01c825260049092019160209091019060010161020c565b5050508061012001511561024e576102466103a6565b91505061039d565b6101408101805160010167ffffffffffffffff16905260006101a49050600080600061028385606001518660000151866104f7565b9250925092508163ffffffff1660001480156102a557508063ffffffff16600c145b156102bf576102b387610521565b9550505050505061039d565b6000610339866040805160808101825260008082526020820181905291810182905260608101919091526040518060800160405280836060015163ffffffff168152602001836080015163ffffffff1681526020018360a0015163ffffffff1681526020018360c0015163ffffffff168152509050919050565b6101608701518751919250610356918391906105248888886108f9565b8652805163ffffffff9081166060808901919091526020830151821660808901526040830151821660a08901528201511660c08701526103946103a6565b96505050505050505b95945050505050565b60408051608051815260a051602082015260dc519181019190915260fc51604482015261011c51604882015261013c51604c82015261015c51605082015261017c5160548201526101805161019f5160588301526101a0516101bf5160598401526101d851605a8401526000926102009290916062830191906001811115610453576040517f0136cc76000000000000000000000000000000000000000000000000000000008152600481fd5b60005b602081101561047a57601c8601518452602090950194600490930192600101610456565b506000835283830384a060009450806001811461049a57600395506104c2565b8280156104b257600181146104bb57600296506104c0565b600096506104c0565b600196505b505b50505081900390207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1660f89190911b17919050565b6000806000610507858786610cdf565b925050603f601a83901c8116915082165b93509350939050565b600061052b612164565b608090506000806000806105628561016001516040810151608082015160a083015160c084015160e0909401519294919390929091565b509350935093509350600080610ffa63ffffffff168663ffffffff16036105a75761059285858960e00151610d93565b63ffffffff1660e08a01529092509050610808565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03363ffffffff8716016105e05763400000009150610808565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefe863ffffffff8716016106165760019150610808565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffef6a63ffffffff87160161066a57600161012088015260ff851661010088015261065d6103a6565b9998505050505050505050565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff05d63ffffffff8716016107665760006040518061012001604052808763ffffffff1681526020018663ffffffff1681526020018563ffffffff16815260200189602001518152602001896040015163ffffffff1681526020018b81526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020016107386101a4600160ff16610380020190565b81528951602090910152905061074d81610e27565b8b5263ffffffff1660408b015290935091506108089050565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff05c63ffffffff8716016107cb57602087015160408801516107b1918791879187916105248d5161109f565b63ffffffff1660408b015260208a01529092509050610808565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff02963ffffffff871601610808576108028585611195565b90925090505b6000610882886040805160808101825260008082526020820181905291810182905260608101919091526040518060800160405280836060015163ffffffff168152602001836080015163ffffffff1681526020018360a0015163ffffffff1681526020018360c0015163ffffffff168152509050919050565b61016089015163ffffffff85811660408084019190915285821660e0909301929092526020830180518083168086526004909101831682526060808e01919091529051821660808d015291830151811660a08c0152908201511660c08a015290506108eb6103a6565b9a9950505050505050505050565b84600263ffffffff8416148061091557508263ffffffff166003145b156109675760006002856303ffffff1663ffffffff16901b896020015163f00000001617905061096189898663ffffffff1660021461095557601f610958565b60005b60ff168461124a565b50610cd4565b600080601f601087901c8116908a90601589901c166020811061098c5761098c612317565b602002015192508063ffffffff871615806109ad57508663ffffffff16601c145b156109df578a8263ffffffff16602081106109ca576109ca612317565b6020020151925050601f600b88901c16610a96565b60208763ffffffff161015610a41578663ffffffff16600c1480610a0957508663ffffffff16600d145b80610a1a57508663ffffffff16600e145b15610a2b578761ffff169250610a96565b610a3a8861ffff166010611322565b9250610a96565b60288763ffffffff16101580610a5d57508663ffffffff166022145b80610a6e57508663ffffffff166026145b15610a96578a8263ffffffff1660208110610a8b57610a8b612317565b602002015192508190505b60048763ffffffff1610158015610ab3575060088763ffffffff16105b80610ac457508663ffffffff166001145b15610ae057610ad78c8c898b8689611395565b50505050610cd4565b63ffffffff6000602089831610610b4557610b008a61ffff166010611322565b9095019463fffffffc8616610b168d828e610cdf565b915060288a63ffffffff1610158015610b3657508963ffffffff16603014155b15610b4357809250600093505b505b6000610b558b8b8b8a8a87611583565b63ffffffff1690508963ffffffff166000148015610b7a575060088963ffffffff1610155b8015610b8c5750601c8963ffffffff16105b15610c54578863ffffffff1660081480610bac57508863ffffffff166009145b15610bdf57610bd38f8f8b63ffffffff16600814610bca5786610bcd565b60005b8a61124a565b50505050505050610cd4565b8863ffffffff16600a03610c0157610bd38f8f868a63ffffffff8b1615611ca0565b8863ffffffff16600b03610c2457610bd38f8f868a63ffffffff8b161515611ca0565b60108963ffffffff1610158015610c415750601c8963ffffffff16105b15610c5457610bd38f8f8b8a8a89611d70565b8963ffffffff166038148015610c6f575063ffffffff851615155b15610c9f5760018e8663ffffffff1660208110610c8e57610c8e612317565b63ffffffff90921660209290920201525b8263ffffffff1663ffffffff14610cbe57610cbb838d83612029565b97505b610ccc8f8f86846001611ca0565b505050505050505b979650505050505050565b6000610cea826120cb565b6003831615610cf857600080fd5b6020820191358360051c8160005b601b811015610d5e5760208601953583821c6001168015610d2e5760018114610d4357610d54565b60008481526020839052604090209350610d54565b600082815260208590526040902093505b5050600101610d06565b50868114610d7457630badf00d60005260206000fd5b5050601f93909316601c0360031b9290921c63ffffffff169392505050565b6000808284610fff811615610dad57610fff811661100003015b8663ffffffff16600003610e195784935090810190636000000063ffffffff83161180610de557508463ffffffff168263ffffffff16105b80610dfb57508563ffffffff168163ffffffff16105b15610e14575063ffffffff925060169150839050610518565b610e1d565b8693505b5093509350939050565b6101008101516080820151825160009283929163ffffffff161561109857845163ffffffff167ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb01611052576000610e93866101000151876020015163fffffffc168860e00151610cdf565b606087015190915060001a600103610f1557610f0f86606001518760a0015160408051600093845233602052918152606090922091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790565b60608701525b6000808760c0015173ffffffffffffffffffffffffffffffffffffffff1663e03110e189606001518a608001516040518363ffffffff1660e01b8152600401610f6e92919091825263ffffffff16602082015260400190565b6040805180830381865afa158015610f8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fae9190612346565b60208a015160408b01519294509092509060038216600481900384811015610fd4578094505b5083821015610fe1578193505b8460088502610100031c9450846008828660040303021b9450600180600883600403021b036001806008878560040303021b0391508119811690508581198816179650505061103f8a6020015163fffffffc168b60e0015187612029565b9298505050938601939250611098915050565b845163ffffffff167ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd0161108c5784604001519350611098565b63ffffffff9350600992505b9193509193565b600080858563ffffffff8b16600114806110bf575063ffffffff8b166002145b806110d0575063ffffffff8b166004145b156110dd57889350611187565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa63ffffffff8c160161117b57600061111d868c63fffffffc1689610cdf565b90508860038c166004038b81101561113357809b505b8b965086900360089081029290921c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600193880293841b0116911b17915060009050611187565b63ffffffff9350600992505b975097509750979350505050565b60008063ffffffff83166003036112385763ffffffff841615806111bf575063ffffffff84166005145b806111d0575063ffffffff84166003145b156111de5760009150611243565b63ffffffff8416600114806111f9575063ffffffff84166002145b8061120a575063ffffffff84166006145b8061121b575063ffffffff84166004145b156112295760019150611243565b5063ffffffff90506009611243565b5063ffffffff905060165b9250929050565b836000015160040163ffffffff16846020015163ffffffff16146112cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6a756d7020696e2064656c617920736c6f74000000000000000000000000000060448201526064015b60405180910390fd5b835160208501805163ffffffff908116875283811690915283161561131b5780600801848463ffffffff166020811061130a5761130a612317565b63ffffffff90921660209290920201525b5050505050565b600063ffffffff8381167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80850183169190911c821615159160016020869003821681901b830191861691821b92911b018261137f576000611381565b815b90861663ffffffff16179250505092915050565b6000866000015160040163ffffffff16876020015163ffffffff1614611417576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f6272616e636820696e2064656c617920736c6f7400000000000000000000000060448201526064016112c6565b8463ffffffff166004148061143257508463ffffffff166005145b156114a9576000868463ffffffff166020811061145157611451612317565b602002015190508063ffffffff168363ffffffff1614801561147957508563ffffffff166004145b806114a157508063ffffffff168363ffffffff16141580156114a157508563ffffffff166005145b915050611526565b8463ffffffff166006036114c65760008260030b13159050611526565b8463ffffffff166007036114e25760008260030b139050611526565b8463ffffffff1660010361152657601f601085901c16600081900361150b5760008360030b1291505b8063ffffffff166001036115245760008360030b121591505b505b8651602088015163ffffffff168852811561156757600261154c8661ffff166010611322565b63ffffffff90811690911b8201600401166020890152611579565b60208801805160040163ffffffff1690525b5050505050505050565b600063ffffffff861615806115b0575060088663ffffffff16101580156115b05750600f8663ffffffff16105b156119b05785600881146115f357600981146115fc57600a811461160557600b811461160e57600c811461161757600d811461162057600e81146116295761162e565b6020955061162e565b6021955061162e565b602a955061162e565b602b955061162e565b6024955061162e565b6025955061162e565b602695505b508463ffffffff16600003611653575063ffffffff8216601f600688901c161b611c96565b8463ffffffff16600203611677575063ffffffff8216601f600688901c161c611c96565b8463ffffffff166003036116ab57601f600688901c166116a363ffffffff8516821c6020839003611322565b915050611c96565b8463ffffffff166004036116cb575063ffffffff8216601f84161b611c96565b8463ffffffff166006036116eb575063ffffffff8216601f84161c611c96565b8463ffffffff1660070361171357601f84166116a363ffffffff8516821c6020839003611322565b8463ffffffff16600803611728575082611c96565b8463ffffffff1660090361173d575082611c96565b8463ffffffff16600a03611752575082611c96565b8463ffffffff16600b03611767575082611c96565b8463ffffffff16600c0361177c575082611c96565b8463ffffffff16600f03611791575082611c96565b8463ffffffff166010036117a6575082611c96565b8463ffffffff166011036117bb575082611c96565b8463ffffffff166012036117d0575082611c96565b8463ffffffff166013036117e5575082611c96565b8463ffffffff166018036117fa575082611c96565b8463ffffffff1660190361180f575082611c96565b8463ffffffff16601a03611824575082611c96565b8463ffffffff16601b03611839575082611c96565b8463ffffffff166020036118505750828201611c96565b8463ffffffff166021036118675750828201611c96565b8463ffffffff1660220361187e5750818303611c96565b8463ffffffff166023036118955750818303611c96565b8463ffffffff166024036118ac5750828216611c96565b8463ffffffff166025036118c35750828217611c96565b8463ffffffff166026036118da5750828218611c96565b8463ffffffff166027036118f2575082821719611c96565b8463ffffffff16602a03611921578260030b8460030b12611914576000611917565b60015b60ff169050611c96565b8463ffffffff16602b03611949578263ffffffff168463ffffffff1610611914576000611917565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f696e76616c696420696e737472756374696f6e0000000000000000000000000060448201526064016112c6565b611949565b8563ffffffff16601c03611a30578463ffffffff166002036119d55750828202611c96565b8463ffffffff16602014806119f057508463ffffffff166021145b156119ab578463ffffffff16602003611a07579219925b60005b6380000000851615611a29576401fffffffe600195861b169401611a0a565b9050611c96565b8563ffffffff16600f03611a51575065ffffffff0000601083901b16611c96565b8563ffffffff16602003611a8557611a298460031660080260180363ffffffff168363ffffffff16901c60ff166008611322565b8563ffffffff16602103611aba57611a298460021660080260100363ffffffff168363ffffffff16901c61ffff166010611322565b8563ffffffff16602203611ae8575063ffffffff60086003851602811681811b198416918316901b17611c96565b8563ffffffff16602303611afd575080611c96565b8563ffffffff16602403611b2e578360031660080260180363ffffffff168263ffffffff16901c60ff169050611c96565b8563ffffffff16602503611b60578360021660080260100363ffffffff168263ffffffff16901c61ffff169050611c96565b8563ffffffff16602603611b91575063ffffffff60086003851602601803811681811c198416918316901c17611c96565b8563ffffffff16602803611bc6575060ff63ffffffff60086003861602601803811682811b9091188316918416901b17611c96565b8563ffffffff16602903611bfc575061ffff63ffffffff60086002861602601003811682811b9091188316918416901b17611c96565b8563ffffffff16602a03611c2a575063ffffffff60086003851602811681811c198316918416901c17611c96565b8563ffffffff16602b03611c3f575081611c96565b8563ffffffff16602e03611c70575063ffffffff60086003851602601803811681811b198316918416901b17611c96565b8563ffffffff16603003611c85575080611c96565b8563ffffffff166038036119495750815b9695505050505050565b60208363ffffffff1610611d10576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f76616c696420726567697374657200000000000000000000000000000000000060448201526064016112c6565b63ffffffff831615801590611d225750805b15611d515781848463ffffffff1660208110611d4057611d40612317565b63ffffffff90921660209290920201525b5050505060208101805163ffffffff8082169093526004019091169052565b60008463ffffffff16601003611d8b57506060860151611fd1565b8463ffffffff16601103611daa5763ffffffff84166060880152611fd1565b8463ffffffff16601203611dc357506040860151611fd1565b8463ffffffff16601303611de25763ffffffff84166040880152611fd1565b8463ffffffff16601803611e165763ffffffff600385810b9085900b02602081901c821660608a0152166040880152611fd1565b8463ffffffff16601903611e475763ffffffff84811681851602602081901c821660608a0152166040880152611fd1565b8463ffffffff16601a03611f0a578260030b600003611ec2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d4950533a206469766973696f6e206279207a65726f0000000000000000000060448201526064016112c6565b8260030b8460030b81611ed757611ed761236a565b0763ffffffff166060880152600383810b9085900b81611ef957611ef961236a565b0563ffffffff166040880152611fd1565b8463ffffffff16601b03611fd1578263ffffffff16600003611f88576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d4950533a206469766973696f6e206279207a65726f0000000000000000000060448201526064016112c6565b8263ffffffff168463ffffffff1681611fa357611fa361236a565b0663ffffffff908116606089015283811690851681611fc457611fc461236a565b0463ffffffff1660408801525b63ffffffff8216156120075780868363ffffffff1660208110611ff657611ff6612317565b63ffffffff90921660209290920201525b50505060208401805163ffffffff808216909652600401909416909352505050565b6000612034836120cb565b600384161561204257600080fd5b6020830192601f8516601c0360031b83811b913563ffffffff90911b1916178460051c60005b601b8110156120c05760208601953582821c600116801561209057600181146120a5576120b6565b600085815260208390526040902094506120b6565b600082815260208690526040902094505b5050600101612068565b509095945050505050565b366103808201811015612160576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f636865636b207468617420746865726520697320656e6f7567682063616c6c6460448201527f617461000000000000000000000000000000000000000000000000000000000060648201526084016112c6565b5050565b6040805161018081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081018290526101008101829052610120810182905261014081019190915261016081016121ca6121cf565b905290565b6040518061040001604052806020906020820280368337509192915050565b600060208083528351808285015260005b8181101561221b578581018301518582016040015282016121ff565b8181111561222d576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b60008083601f84011261227357600080fd5b50813567ffffffffffffffff81111561228b57600080fd5b60208301915083602082850101111561124357600080fd5b6000806000806000606086880312156122bb57600080fd5b853567ffffffffffffffff808211156122d357600080fd5b6122df89838a01612261565b909750955060208801359150808211156122f857600080fd5b5061230588828901612261565b96999598509660400135949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000806040838503121561235957600080fd5b505080516020909101519092909150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fdfea164736f6c634300080f000a000000000000000000000000373d916d11cce55b548f7051002e76bcfbd7a85d", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [], - "value": 0 - }, - { - "accessor": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "account": "0x444e09fe6D839273316a87002aB0EFBeA6fe7806", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x60a060405234801561001057600080fd5b506040516200243a3803806200243a83398101604081905261003191610042565b6001600160a01b0316608052610072565b60006020828403121561005457600080fd5b81516001600160a01b038116811461006b57600080fd5b9392505050565b6080516123a6620000946000396000818160b201526106eb01526123a66000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c806354fd4d50146100465780637dc0d1d014610098578063e14ced32146100dc575b600080fd5b6100826040518060400160405280600a81526020017f312e312e302d72632e310000000000000000000000000000000000000000000081525081565b60405161008f91906121ee565b60405180910390f35b60405173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016815260200161008f565b6100ef6100ea3660046122a3565b6100fd565b60405190815260200161008f565b6000610107612164565b6080811461011457600080fd5b6040516106001461012457600080fd5b6084871461013157600080fd5b6101a4851461013f57600080fd5b8635608052602087013560a052604087013560e090811c60c09081526044890135821c82526048890135821c61010052604c890135821c610120526050890135821c61014052605489013590911c61016052605888013560f890811c610180526059890135901c6101a0819052605a89013590911c6101c05260628801906101e09060018111156101f5576040517f0136cc76000000000000000000000000000000000000000000000000000000008152600481fd5b506020810181511461020657600080fd5b60200160005b602081101561023057823560e01c825260049092019160209091019060010161020c565b5050508061012001511561024e576102466103a6565b91505061039d565b6101408101805160010167ffffffffffffffff16905260006101a49050600080600061028385606001518660000151866104f7565b9250925092508163ffffffff1660001480156102a557508063ffffffff16600c145b156102bf576102b387610521565b9550505050505061039d565b6000610339866040805160808101825260008082526020820181905291810182905260608101919091526040518060800160405280836060015163ffffffff168152602001836080015163ffffffff1681526020018360a0015163ffffffff1681526020018360c0015163ffffffff168152509050919050565b6101608701518751919250610356918391906105248888886108f9565b8652805163ffffffff9081166060808901919091526020830151821660808901526040830151821660a08901528201511660c08701526103946103a6565b96505050505050505b95945050505050565b60408051608051815260a051602082015260dc519181019190915260fc51604482015261011c51604882015261013c51604c82015261015c51605082015261017c5160548201526101805161019f5160588301526101a0516101bf5160598401526101d851605a8401526000926102009290916062830191906001811115610453576040517f0136cc76000000000000000000000000000000000000000000000000000000008152600481fd5b60005b602081101561047a57601c8601518452602090950194600490930192600101610456565b506000835283830384a060009450806001811461049a57600395506104c2565b8280156104b257600181146104bb57600296506104c0565b600096506104c0565b600196505b505b50505081900390207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1660f89190911b17919050565b6000806000610507858786610cdf565b925050603f601a83901c8116915082165b93509350939050565b600061052b612164565b608090506000806000806105628561016001516040810151608082015160a083015160c084015160e0909401519294919390929091565b509350935093509350600080610ffa63ffffffff168663ffffffff16036105a75761059285858960e00151610d93565b63ffffffff1660e08a01529092509050610808565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03363ffffffff8716016105e05763400000009150610808565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefe863ffffffff8716016106165760019150610808565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffef6a63ffffffff87160161066a57600161012088015260ff851661010088015261065d6103a6565b9998505050505050505050565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff05d63ffffffff8716016107665760006040518061012001604052808763ffffffff1681526020018663ffffffff1681526020018563ffffffff16815260200189602001518152602001896040015163ffffffff1681526020018b81526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020016107386101a4600160ff16610380020190565b81528951602090910152905061074d81610e27565b8b5263ffffffff1660408b015290935091506108089050565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff05c63ffffffff8716016107cb57602087015160408801516107b1918791879187916105248d5161109f565b63ffffffff1660408b015260208a01529092509050610808565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff02963ffffffff871601610808576108028585611195565b90925090505b6000610882886040805160808101825260008082526020820181905291810182905260608101919091526040518060800160405280836060015163ffffffff168152602001836080015163ffffffff1681526020018360a0015163ffffffff1681526020018360c0015163ffffffff168152509050919050565b61016089015163ffffffff85811660408084019190915285821660e0909301929092526020830180518083168086526004909101831682526060808e01919091529051821660808d015291830151811660a08c0152908201511660c08a015290506108eb6103a6565b9a9950505050505050505050565b84600263ffffffff8416148061091557508263ffffffff166003145b156109675760006002856303ffffff1663ffffffff16901b896020015163f00000001617905061096189898663ffffffff1660021461095557601f610958565b60005b60ff168461124a565b50610cd4565b600080601f601087901c8116908a90601589901c166020811061098c5761098c612317565b602002015192508063ffffffff871615806109ad57508663ffffffff16601c145b156109df578a8263ffffffff16602081106109ca576109ca612317565b6020020151925050601f600b88901c16610a96565b60208763ffffffff161015610a41578663ffffffff16600c1480610a0957508663ffffffff16600d145b80610a1a57508663ffffffff16600e145b15610a2b578761ffff169250610a96565b610a3a8861ffff166010611322565b9250610a96565b60288763ffffffff16101580610a5d57508663ffffffff166022145b80610a6e57508663ffffffff166026145b15610a96578a8263ffffffff1660208110610a8b57610a8b612317565b602002015192508190505b60048763ffffffff1610158015610ab3575060088763ffffffff16105b80610ac457508663ffffffff166001145b15610ae057610ad78c8c898b8689611395565b50505050610cd4565b63ffffffff6000602089831610610b4557610b008a61ffff166010611322565b9095019463fffffffc8616610b168d828e610cdf565b915060288a63ffffffff1610158015610b3657508963ffffffff16603014155b15610b4357809250600093505b505b6000610b558b8b8b8a8a87611583565b63ffffffff1690508963ffffffff166000148015610b7a575060088963ffffffff1610155b8015610b8c5750601c8963ffffffff16105b15610c54578863ffffffff1660081480610bac57508863ffffffff166009145b15610bdf57610bd38f8f8b63ffffffff16600814610bca5786610bcd565b60005b8a61124a565b50505050505050610cd4565b8863ffffffff16600a03610c0157610bd38f8f868a63ffffffff8b1615611ca0565b8863ffffffff16600b03610c2457610bd38f8f868a63ffffffff8b161515611ca0565b60108963ffffffff1610158015610c415750601c8963ffffffff16105b15610c5457610bd38f8f8b8a8a89611d70565b8963ffffffff166038148015610c6f575063ffffffff851615155b15610c9f5760018e8663ffffffff1660208110610c8e57610c8e612317565b63ffffffff90921660209290920201525b8263ffffffff1663ffffffff14610cbe57610cbb838d83612029565b97505b610ccc8f8f86846001611ca0565b505050505050505b979650505050505050565b6000610cea826120cb565b6003831615610cf857600080fd5b6020820191358360051c8160005b601b811015610d5e5760208601953583821c6001168015610d2e5760018114610d4357610d54565b60008481526020839052604090209350610d54565b600082815260208590526040902093505b5050600101610d06565b50868114610d7457630badf00d60005260206000fd5b5050601f93909316601c0360031b9290921c63ffffffff169392505050565b6000808284610fff811615610dad57610fff811661100003015b8663ffffffff16600003610e195784935090810190636000000063ffffffff83161180610de557508463ffffffff168263ffffffff16105b80610dfb57508563ffffffff168163ffffffff16105b15610e14575063ffffffff925060169150839050610518565b610e1d565b8693505b5093509350939050565b6101008101516080820151825160009283929163ffffffff161561109857845163ffffffff167ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb01611052576000610e93866101000151876020015163fffffffc168860e00151610cdf565b606087015190915060001a600103610f1557610f0f86606001518760a0015160408051600093845233602052918152606090922091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790565b60608701525b6000808760c0015173ffffffffffffffffffffffffffffffffffffffff1663e03110e189606001518a608001516040518363ffffffff1660e01b8152600401610f6e92919091825263ffffffff16602082015260400190565b6040805180830381865afa158015610f8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fae9190612346565b60208a015160408b01519294509092509060038216600481900384811015610fd4578094505b5083821015610fe1578193505b8460088502610100031c9450846008828660040303021b9450600180600883600403021b036001806008878560040303021b0391508119811690508581198816179650505061103f8a6020015163fffffffc168b60e0015187612029565b9298505050938601939250611098915050565b845163ffffffff167ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd0161108c5784604001519350611098565b63ffffffff9350600992505b9193509193565b600080858563ffffffff8b16600114806110bf575063ffffffff8b166002145b806110d0575063ffffffff8b166004145b156110dd57889350611187565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa63ffffffff8c160161117b57600061111d868c63fffffffc1689610cdf565b90508860038c166004038b81101561113357809b505b8b965086900360089081029290921c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600193880293841b0116911b17915060009050611187565b63ffffffff9350600992505b975097509750979350505050565b60008063ffffffff83166003036112385763ffffffff841615806111bf575063ffffffff84166005145b806111d0575063ffffffff84166003145b156111de5760009150611243565b63ffffffff8416600114806111f9575063ffffffff84166002145b8061120a575063ffffffff84166006145b8061121b575063ffffffff84166004145b156112295760019150611243565b5063ffffffff90506009611243565b5063ffffffff905060165b9250929050565b836000015160040163ffffffff16846020015163ffffffff16146112cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6a756d7020696e2064656c617920736c6f74000000000000000000000000000060448201526064015b60405180910390fd5b835160208501805163ffffffff908116875283811690915283161561131b5780600801848463ffffffff166020811061130a5761130a612317565b63ffffffff90921660209290920201525b5050505050565b600063ffffffff8381167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80850183169190911c821615159160016020869003821681901b830191861691821b92911b018261137f576000611381565b815b90861663ffffffff16179250505092915050565b6000866000015160040163ffffffff16876020015163ffffffff1614611417576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f6272616e636820696e2064656c617920736c6f7400000000000000000000000060448201526064016112c6565b8463ffffffff166004148061143257508463ffffffff166005145b156114a9576000868463ffffffff166020811061145157611451612317565b602002015190508063ffffffff168363ffffffff1614801561147957508563ffffffff166004145b806114a157508063ffffffff168363ffffffff16141580156114a157508563ffffffff166005145b915050611526565b8463ffffffff166006036114c65760008260030b13159050611526565b8463ffffffff166007036114e25760008260030b139050611526565b8463ffffffff1660010361152657601f601085901c16600081900361150b5760008360030b1291505b8063ffffffff166001036115245760008360030b121591505b505b8651602088015163ffffffff168852811561156757600261154c8661ffff166010611322565b63ffffffff90811690911b8201600401166020890152611579565b60208801805160040163ffffffff1690525b5050505050505050565b600063ffffffff861615806115b0575060088663ffffffff16101580156115b05750600f8663ffffffff16105b156119b05785600881146115f357600981146115fc57600a811461160557600b811461160e57600c811461161757600d811461162057600e81146116295761162e565b6020955061162e565b6021955061162e565b602a955061162e565b602b955061162e565b6024955061162e565b6025955061162e565b602695505b508463ffffffff16600003611653575063ffffffff8216601f600688901c161b611c96565b8463ffffffff16600203611677575063ffffffff8216601f600688901c161c611c96565b8463ffffffff166003036116ab57601f600688901c166116a363ffffffff8516821c6020839003611322565b915050611c96565b8463ffffffff166004036116cb575063ffffffff8216601f84161b611c96565b8463ffffffff166006036116eb575063ffffffff8216601f84161c611c96565b8463ffffffff1660070361171357601f84166116a363ffffffff8516821c6020839003611322565b8463ffffffff16600803611728575082611c96565b8463ffffffff1660090361173d575082611c96565b8463ffffffff16600a03611752575082611c96565b8463ffffffff16600b03611767575082611c96565b8463ffffffff16600c0361177c575082611c96565b8463ffffffff16600f03611791575082611c96565b8463ffffffff166010036117a6575082611c96565b8463ffffffff166011036117bb575082611c96565b8463ffffffff166012036117d0575082611c96565b8463ffffffff166013036117e5575082611c96565b8463ffffffff166018036117fa575082611c96565b8463ffffffff1660190361180f575082611c96565b8463ffffffff16601a03611824575082611c96565b8463ffffffff16601b03611839575082611c96565b8463ffffffff166020036118505750828201611c96565b8463ffffffff166021036118675750828201611c96565b8463ffffffff1660220361187e5750818303611c96565b8463ffffffff166023036118955750818303611c96565b8463ffffffff166024036118ac5750828216611c96565b8463ffffffff166025036118c35750828217611c96565b8463ffffffff166026036118da5750828218611c96565b8463ffffffff166027036118f2575082821719611c96565b8463ffffffff16602a03611921578260030b8460030b12611914576000611917565b60015b60ff169050611c96565b8463ffffffff16602b03611949578263ffffffff168463ffffffff1610611914576000611917565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f696e76616c696420696e737472756374696f6e0000000000000000000000000060448201526064016112c6565b611949565b8563ffffffff16601c03611a30578463ffffffff166002036119d55750828202611c96565b8463ffffffff16602014806119f057508463ffffffff166021145b156119ab578463ffffffff16602003611a07579219925b60005b6380000000851615611a29576401fffffffe600195861b169401611a0a565b9050611c96565b8563ffffffff16600f03611a51575065ffffffff0000601083901b16611c96565b8563ffffffff16602003611a8557611a298460031660080260180363ffffffff168363ffffffff16901c60ff166008611322565b8563ffffffff16602103611aba57611a298460021660080260100363ffffffff168363ffffffff16901c61ffff166010611322565b8563ffffffff16602203611ae8575063ffffffff60086003851602811681811b198416918316901b17611c96565b8563ffffffff16602303611afd575080611c96565b8563ffffffff16602403611b2e578360031660080260180363ffffffff168263ffffffff16901c60ff169050611c96565b8563ffffffff16602503611b60578360021660080260100363ffffffff168263ffffffff16901c61ffff169050611c96565b8563ffffffff16602603611b91575063ffffffff60086003851602601803811681811c198416918316901c17611c96565b8563ffffffff16602803611bc6575060ff63ffffffff60086003861602601803811682811b9091188316918416901b17611c96565b8563ffffffff16602903611bfc575061ffff63ffffffff60086002861602601003811682811b9091188316918416901b17611c96565b8563ffffffff16602a03611c2a575063ffffffff60086003851602811681811c198316918416901c17611c96565b8563ffffffff16602b03611c3f575081611c96565b8563ffffffff16602e03611c70575063ffffffff60086003851602601803811681811b198316918416901b17611c96565b8563ffffffff16603003611c85575080611c96565b8563ffffffff166038036119495750815b9695505050505050565b60208363ffffffff1610611d10576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f76616c696420726567697374657200000000000000000000000000000000000060448201526064016112c6565b63ffffffff831615801590611d225750805b15611d515781848463ffffffff1660208110611d4057611d40612317565b63ffffffff90921660209290920201525b5050505060208101805163ffffffff8082169093526004019091169052565b60008463ffffffff16601003611d8b57506060860151611fd1565b8463ffffffff16601103611daa5763ffffffff84166060880152611fd1565b8463ffffffff16601203611dc357506040860151611fd1565b8463ffffffff16601303611de25763ffffffff84166040880152611fd1565b8463ffffffff16601803611e165763ffffffff600385810b9085900b02602081901c821660608a0152166040880152611fd1565b8463ffffffff16601903611e475763ffffffff84811681851602602081901c821660608a0152166040880152611fd1565b8463ffffffff16601a03611f0a578260030b600003611ec2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d4950533a206469766973696f6e206279207a65726f0000000000000000000060448201526064016112c6565b8260030b8460030b81611ed757611ed761236a565b0763ffffffff166060880152600383810b9085900b81611ef957611ef961236a565b0563ffffffff166040880152611fd1565b8463ffffffff16601b03611fd1578263ffffffff16600003611f88576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d4950533a206469766973696f6e206279207a65726f0000000000000000000060448201526064016112c6565b8263ffffffff168463ffffffff1681611fa357611fa361236a565b0663ffffffff908116606089015283811690851681611fc457611fc461236a565b0463ffffffff1660408801525b63ffffffff8216156120075780868363ffffffff1660208110611ff657611ff6612317565b63ffffffff90921660209290920201525b50505060208401805163ffffffff808216909652600401909416909352505050565b6000612034836120cb565b600384161561204257600080fd5b6020830192601f8516601c0360031b83811b913563ffffffff90911b1916178460051c60005b601b8110156120c05760208601953582821c600116801561209057600181146120a5576120b6565b600085815260208390526040902094506120b6565b600082815260208690526040902094505b5050600101612068565b509095945050505050565b366103808201811015612160576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f636865636b207468617420746865726520697320656e6f7567682063616c6c6460448201527f617461000000000000000000000000000000000000000000000000000000000060648201526084016112c6565b5050565b6040805161018081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081018290526101008101829052610120810182905261014081019190915261016081016121ca6121cf565b905290565b6040518061040001604052806020906020820280368337509192915050565b600060208083528351808285015260005b8181101561221b578581018301518582016040015282016121ff565b8181111561222d576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b60008083601f84011261227357600080fd5b50813567ffffffffffffffff81111561228b57600080fd5b60208301915083602082850101111561124357600080fd5b6000806000806000606086880312156122bb57600080fd5b853567ffffffffffffffff808211156122d357600080fd5b6122df89838a01612261565b909750955060208801359150808211156122f857600080fd5b5061230588828901612261565b96999598509660400135949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000806040838503121561235957600080fd5b505080516020909101519092909150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fdfea164736f6c634300080f000a000000000000000000000000373d916d11cce55b548f7051002e76bcfbd7a85d", - "deployedCode": "0x608060405234801561001057600080fd5b50600436106100415760003560e01c806354fd4d50146100465780637dc0d1d014610098578063e14ced32146100dc575b600080fd5b6100826040518060400160405280600a81526020017f312e312e302d72632e310000000000000000000000000000000000000000000081525081565b60405161008f91906121ee565b60405180910390f35b60405173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000373d916d11cce55b548f7051002e76bcfbd7a85d16815260200161008f565b6100ef6100ea3660046122a3565b6100fd565b60405190815260200161008f565b6000610107612164565b6080811461011457600080fd5b6040516106001461012457600080fd5b6084871461013157600080fd5b6101a4851461013f57600080fd5b8635608052602087013560a052604087013560e090811c60c09081526044890135821c82526048890135821c61010052604c890135821c610120526050890135821c61014052605489013590911c61016052605888013560f890811c610180526059890135901c6101a0819052605a89013590911c6101c05260628801906101e09060018111156101f5576040517f0136cc76000000000000000000000000000000000000000000000000000000008152600481fd5b506020810181511461020657600080fd5b60200160005b602081101561023057823560e01c825260049092019160209091019060010161020c565b5050508061012001511561024e576102466103a6565b91505061039d565b6101408101805160010167ffffffffffffffff16905260006101a49050600080600061028385606001518660000151866104f7565b9250925092508163ffffffff1660001480156102a557508063ffffffff16600c145b156102bf576102b387610521565b9550505050505061039d565b6000610339866040805160808101825260008082526020820181905291810182905260608101919091526040518060800160405280836060015163ffffffff168152602001836080015163ffffffff1681526020018360a0015163ffffffff1681526020018360c0015163ffffffff168152509050919050565b6101608701518751919250610356918391906105248888886108f9565b8652805163ffffffff9081166060808901919091526020830151821660808901526040830151821660a08901528201511660c08701526103946103a6565b96505050505050505b95945050505050565b60408051608051815260a051602082015260dc519181019190915260fc51604482015261011c51604882015261013c51604c82015261015c51605082015261017c5160548201526101805161019f5160588301526101a0516101bf5160598401526101d851605a8401526000926102009290916062830191906001811115610453576040517f0136cc76000000000000000000000000000000000000000000000000000000008152600481fd5b60005b602081101561047a57601c8601518452602090950194600490930192600101610456565b506000835283830384a060009450806001811461049a57600395506104c2565b8280156104b257600181146104bb57600296506104c0565b600096506104c0565b600196505b505b50505081900390207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1660f89190911b17919050565b6000806000610507858786610cdf565b925050603f601a83901c8116915082165b93509350939050565b600061052b612164565b608090506000806000806105628561016001516040810151608082015160a083015160c084015160e0909401519294919390929091565b509350935093509350600080610ffa63ffffffff168663ffffffff16036105a75761059285858960e00151610d93565b63ffffffff1660e08a01529092509050610808565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03363ffffffff8716016105e05763400000009150610808565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefe863ffffffff8716016106165760019150610808565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffef6a63ffffffff87160161066a57600161012088015260ff851661010088015261065d6103a6565b9998505050505050505050565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff05d63ffffffff8716016107665760006040518061012001604052808763ffffffff1681526020018663ffffffff1681526020018563ffffffff16815260200189602001518152602001896040015163ffffffff1681526020018b81526020017f000000000000000000000000373d916d11cce55b548f7051002e76bcfbd7a85d73ffffffffffffffffffffffffffffffffffffffff1681526020016107386101a4600160ff16610380020190565b81528951602090910152905061074d81610e27565b8b5263ffffffff1660408b015290935091506108089050565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff05c63ffffffff8716016107cb57602087015160408801516107b1918791879187916105248d5161109f565b63ffffffff1660408b015260208a01529092509050610808565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff02963ffffffff871601610808576108028585611195565b90925090505b6000610882886040805160808101825260008082526020820181905291810182905260608101919091526040518060800160405280836060015163ffffffff168152602001836080015163ffffffff1681526020018360a0015163ffffffff1681526020018360c0015163ffffffff168152509050919050565b61016089015163ffffffff85811660408084019190915285821660e0909301929092526020830180518083168086526004909101831682526060808e01919091529051821660808d015291830151811660a08c0152908201511660c08a015290506108eb6103a6565b9a9950505050505050505050565b84600263ffffffff8416148061091557508263ffffffff166003145b156109675760006002856303ffffff1663ffffffff16901b896020015163f00000001617905061096189898663ffffffff1660021461095557601f610958565b60005b60ff168461124a565b50610cd4565b600080601f601087901c8116908a90601589901c166020811061098c5761098c612317565b602002015192508063ffffffff871615806109ad57508663ffffffff16601c145b156109df578a8263ffffffff16602081106109ca576109ca612317565b6020020151925050601f600b88901c16610a96565b60208763ffffffff161015610a41578663ffffffff16600c1480610a0957508663ffffffff16600d145b80610a1a57508663ffffffff16600e145b15610a2b578761ffff169250610a96565b610a3a8861ffff166010611322565b9250610a96565b60288763ffffffff16101580610a5d57508663ffffffff166022145b80610a6e57508663ffffffff166026145b15610a96578a8263ffffffff1660208110610a8b57610a8b612317565b602002015192508190505b60048763ffffffff1610158015610ab3575060088763ffffffff16105b80610ac457508663ffffffff166001145b15610ae057610ad78c8c898b8689611395565b50505050610cd4565b63ffffffff6000602089831610610b4557610b008a61ffff166010611322565b9095019463fffffffc8616610b168d828e610cdf565b915060288a63ffffffff1610158015610b3657508963ffffffff16603014155b15610b4357809250600093505b505b6000610b558b8b8b8a8a87611583565b63ffffffff1690508963ffffffff166000148015610b7a575060088963ffffffff1610155b8015610b8c5750601c8963ffffffff16105b15610c54578863ffffffff1660081480610bac57508863ffffffff166009145b15610bdf57610bd38f8f8b63ffffffff16600814610bca5786610bcd565b60005b8a61124a565b50505050505050610cd4565b8863ffffffff16600a03610c0157610bd38f8f868a63ffffffff8b1615611ca0565b8863ffffffff16600b03610c2457610bd38f8f868a63ffffffff8b161515611ca0565b60108963ffffffff1610158015610c415750601c8963ffffffff16105b15610c5457610bd38f8f8b8a8a89611d70565b8963ffffffff166038148015610c6f575063ffffffff851615155b15610c9f5760018e8663ffffffff1660208110610c8e57610c8e612317565b63ffffffff90921660209290920201525b8263ffffffff1663ffffffff14610cbe57610cbb838d83612029565b97505b610ccc8f8f86846001611ca0565b505050505050505b979650505050505050565b6000610cea826120cb565b6003831615610cf857600080fd5b6020820191358360051c8160005b601b811015610d5e5760208601953583821c6001168015610d2e5760018114610d4357610d54565b60008481526020839052604090209350610d54565b600082815260208590526040902093505b5050600101610d06565b50868114610d7457630badf00d60005260206000fd5b5050601f93909316601c0360031b9290921c63ffffffff169392505050565b6000808284610fff811615610dad57610fff811661100003015b8663ffffffff16600003610e195784935090810190636000000063ffffffff83161180610de557508463ffffffff168263ffffffff16105b80610dfb57508563ffffffff168163ffffffff16105b15610e14575063ffffffff925060169150839050610518565b610e1d565b8693505b5093509350939050565b6101008101516080820151825160009283929163ffffffff161561109857845163ffffffff167ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb01611052576000610e93866101000151876020015163fffffffc168860e00151610cdf565b606087015190915060001a600103610f1557610f0f86606001518760a0015160408051600093845233602052918152606090922091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790565b60608701525b6000808760c0015173ffffffffffffffffffffffffffffffffffffffff1663e03110e189606001518a608001516040518363ffffffff1660e01b8152600401610f6e92919091825263ffffffff16602082015260400190565b6040805180830381865afa158015610f8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fae9190612346565b60208a015160408b01519294509092509060038216600481900384811015610fd4578094505b5083821015610fe1578193505b8460088502610100031c9450846008828660040303021b9450600180600883600403021b036001806008878560040303021b0391508119811690508581198816179650505061103f8a6020015163fffffffc168b60e0015187612029565b9298505050938601939250611098915050565b845163ffffffff167ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd0161108c5784604001519350611098565b63ffffffff9350600992505b9193509193565b600080858563ffffffff8b16600114806110bf575063ffffffff8b166002145b806110d0575063ffffffff8b166004145b156110dd57889350611187565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa63ffffffff8c160161117b57600061111d868c63fffffffc1689610cdf565b90508860038c166004038b81101561113357809b505b8b965086900360089081029290921c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600193880293841b0116911b17915060009050611187565b63ffffffff9350600992505b975097509750979350505050565b60008063ffffffff83166003036112385763ffffffff841615806111bf575063ffffffff84166005145b806111d0575063ffffffff84166003145b156111de5760009150611243565b63ffffffff8416600114806111f9575063ffffffff84166002145b8061120a575063ffffffff84166006145b8061121b575063ffffffff84166004145b156112295760019150611243565b5063ffffffff90506009611243565b5063ffffffff905060165b9250929050565b836000015160040163ffffffff16846020015163ffffffff16146112cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6a756d7020696e2064656c617920736c6f74000000000000000000000000000060448201526064015b60405180910390fd5b835160208501805163ffffffff908116875283811690915283161561131b5780600801848463ffffffff166020811061130a5761130a612317565b63ffffffff90921660209290920201525b5050505050565b600063ffffffff8381167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80850183169190911c821615159160016020869003821681901b830191861691821b92911b018261137f576000611381565b815b90861663ffffffff16179250505092915050565b6000866000015160040163ffffffff16876020015163ffffffff1614611417576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f6272616e636820696e2064656c617920736c6f7400000000000000000000000060448201526064016112c6565b8463ffffffff166004148061143257508463ffffffff166005145b156114a9576000868463ffffffff166020811061145157611451612317565b602002015190508063ffffffff168363ffffffff1614801561147957508563ffffffff166004145b806114a157508063ffffffff168363ffffffff16141580156114a157508563ffffffff166005145b915050611526565b8463ffffffff166006036114c65760008260030b13159050611526565b8463ffffffff166007036114e25760008260030b139050611526565b8463ffffffff1660010361152657601f601085901c16600081900361150b5760008360030b1291505b8063ffffffff166001036115245760008360030b121591505b505b8651602088015163ffffffff168852811561156757600261154c8661ffff166010611322565b63ffffffff90811690911b8201600401166020890152611579565b60208801805160040163ffffffff1690525b5050505050505050565b600063ffffffff861615806115b0575060088663ffffffff16101580156115b05750600f8663ffffffff16105b156119b05785600881146115f357600981146115fc57600a811461160557600b811461160e57600c811461161757600d811461162057600e81146116295761162e565b6020955061162e565b6021955061162e565b602a955061162e565b602b955061162e565b6024955061162e565b6025955061162e565b602695505b508463ffffffff16600003611653575063ffffffff8216601f600688901c161b611c96565b8463ffffffff16600203611677575063ffffffff8216601f600688901c161c611c96565b8463ffffffff166003036116ab57601f600688901c166116a363ffffffff8516821c6020839003611322565b915050611c96565b8463ffffffff166004036116cb575063ffffffff8216601f84161b611c96565b8463ffffffff166006036116eb575063ffffffff8216601f84161c611c96565b8463ffffffff1660070361171357601f84166116a363ffffffff8516821c6020839003611322565b8463ffffffff16600803611728575082611c96565b8463ffffffff1660090361173d575082611c96565b8463ffffffff16600a03611752575082611c96565b8463ffffffff16600b03611767575082611c96565b8463ffffffff16600c0361177c575082611c96565b8463ffffffff16600f03611791575082611c96565b8463ffffffff166010036117a6575082611c96565b8463ffffffff166011036117bb575082611c96565b8463ffffffff166012036117d0575082611c96565b8463ffffffff166013036117e5575082611c96565b8463ffffffff166018036117fa575082611c96565b8463ffffffff1660190361180f575082611c96565b8463ffffffff16601a03611824575082611c96565b8463ffffffff16601b03611839575082611c96565b8463ffffffff166020036118505750828201611c96565b8463ffffffff166021036118675750828201611c96565b8463ffffffff1660220361187e5750818303611c96565b8463ffffffff166023036118955750818303611c96565b8463ffffffff166024036118ac5750828216611c96565b8463ffffffff166025036118c35750828217611c96565b8463ffffffff166026036118da5750828218611c96565b8463ffffffff166027036118f2575082821719611c96565b8463ffffffff16602a03611921578260030b8460030b12611914576000611917565b60015b60ff169050611c96565b8463ffffffff16602b03611949578263ffffffff168463ffffffff1610611914576000611917565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f696e76616c696420696e737472756374696f6e0000000000000000000000000060448201526064016112c6565b611949565b8563ffffffff16601c03611a30578463ffffffff166002036119d55750828202611c96565b8463ffffffff16602014806119f057508463ffffffff166021145b156119ab578463ffffffff16602003611a07579219925b60005b6380000000851615611a29576401fffffffe600195861b169401611a0a565b9050611c96565b8563ffffffff16600f03611a51575065ffffffff0000601083901b16611c96565b8563ffffffff16602003611a8557611a298460031660080260180363ffffffff168363ffffffff16901c60ff166008611322565b8563ffffffff16602103611aba57611a298460021660080260100363ffffffff168363ffffffff16901c61ffff166010611322565b8563ffffffff16602203611ae8575063ffffffff60086003851602811681811b198416918316901b17611c96565b8563ffffffff16602303611afd575080611c96565b8563ffffffff16602403611b2e578360031660080260180363ffffffff168263ffffffff16901c60ff169050611c96565b8563ffffffff16602503611b60578360021660080260100363ffffffff168263ffffffff16901c61ffff169050611c96565b8563ffffffff16602603611b91575063ffffffff60086003851602601803811681811c198416918316901c17611c96565b8563ffffffff16602803611bc6575060ff63ffffffff60086003861602601803811682811b9091188316918416901b17611c96565b8563ffffffff16602903611bfc575061ffff63ffffffff60086002861602601003811682811b9091188316918416901b17611c96565b8563ffffffff16602a03611c2a575063ffffffff60086003851602811681811c198316918416901c17611c96565b8563ffffffff16602b03611c3f575081611c96565b8563ffffffff16602e03611c70575063ffffffff60086003851602601803811681811b198316918416901b17611c96565b8563ffffffff16603003611c85575080611c96565b8563ffffffff166038036119495750815b9695505050505050565b60208363ffffffff1610611d10576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f76616c696420726567697374657200000000000000000000000000000000000060448201526064016112c6565b63ffffffff831615801590611d225750805b15611d515781848463ffffffff1660208110611d4057611d40612317565b63ffffffff90921660209290920201525b5050505060208101805163ffffffff8082169093526004019091169052565b60008463ffffffff16601003611d8b57506060860151611fd1565b8463ffffffff16601103611daa5763ffffffff84166060880152611fd1565b8463ffffffff16601203611dc357506040860151611fd1565b8463ffffffff16601303611de25763ffffffff84166040880152611fd1565b8463ffffffff16601803611e165763ffffffff600385810b9085900b02602081901c821660608a0152166040880152611fd1565b8463ffffffff16601903611e475763ffffffff84811681851602602081901c821660608a0152166040880152611fd1565b8463ffffffff16601a03611f0a578260030b600003611ec2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d4950533a206469766973696f6e206279207a65726f0000000000000000000060448201526064016112c6565b8260030b8460030b81611ed757611ed761236a565b0763ffffffff166060880152600383810b9085900b81611ef957611ef961236a565b0563ffffffff166040880152611fd1565b8463ffffffff16601b03611fd1578263ffffffff16600003611f88576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d4950533a206469766973696f6e206279207a65726f0000000000000000000060448201526064016112c6565b8263ffffffff168463ffffffff1681611fa357611fa361236a565b0663ffffffff908116606089015283811690851681611fc457611fc461236a565b0463ffffffff1660408801525b63ffffffff8216156120075780868363ffffffff1660208110611ff657611ff6612317565b63ffffffff90921660209290920201525b50505060208401805163ffffffff808216909652600401909416909352505050565b6000612034836120cb565b600384161561204257600080fd5b6020830192601f8516601c0360031b83811b913563ffffffff90911b1916178460051c60005b601b8110156120c05760208601953582821c600116801561209057600181146120a5576120b6565b600085815260208390526040902094506120b6565b600082815260208690526040902094505b5050600101612068565b509095945050505050565b366103808201811015612160576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f636865636b207468617420746865726520697320656e6f7567682063616c6c6460448201527f617461000000000000000000000000000000000000000000000000000000000060648201526084016112c6565b5050565b6040805161018081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081018290526101008101829052610120810182905261014081019190915261016081016121ca6121cf565b905290565b6040518061040001604052806020906020820280368337509192915050565b600060208083528351808285015260005b8181101561221b578581018301518582016040015282016121ff565b8181111561222d576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b60008083601f84011261227357600080fd5b50813567ffffffffffffffff81111561228b57600080fd5b60208301915083602082850101111561124357600080fd5b6000806000806000606086880312156122bb57600080fd5b853567ffffffffffffffff808211156122d357600080fd5b6122df89838a01612261565b909750955060208801359150808211156122f857600080fd5b5061230588828901612261565b96999598509660400135949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000806040838503121561235957600080fd5b505080516020909101519092909150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fdfea164736f6c634300080f000a", - "initialized": true, - "kind": "Create", - "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": "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": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x638627e586f5e36fe67a77519503a7c6da22f92b150d3c6055fd40bdcfe9ffd160a060405234801561001057600080fd5b506040516111d73803806111d783398101604081905261002f9161010a565b6001600160a01b03811660805261004461004a565b5061013a565b600054610100900460ff16156100b65760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff9081161015610108576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b60006020828403121561011c57600080fd5b81516001600160a01b038116811461013357600080fd5b9392505050565b608051611074610163600039600081816101830152818161033c01526108f801526110746000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c80635e05fbd01161005b5780635e05fbd01461012a5780637258a8071461013d578063838c2d1e14610179578063f2b4e6171461018157600080fd5b806317cf21a91461008257806335e80ab31461009757806354fd4d50146100e1575b600080fd5b610095610090366004610b4c565b6101a7565b005b6002546100b79073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b61011d6040518060400160405280600a81526020017f322e302e302d72632e310000000000000000000000000000000000000000000081525081565b6040516100d89190610bea565b610095610138366004610cc6565b61061c565b61016461014b366004610df0565b6001602081905260009182526040909120805491015482565b604080519283526020830191909152016100d8565b610095610853565b7f00000000000000000000000000000000000000000000000000000000000000006100b7565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa158015610214573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102389190610e0d565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461029c576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060008373ffffffffffffffffffffffffffffffffffffffff1663fa24f7436040518163ffffffff1660e01b8152600401600060405180830381865afa1580156102ec573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526103329190810190610e2a565b92509250925060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16635f0150cb8585856040518463ffffffff1660e01b815260040161039793929190610efb565b6040805180830381865afa1580156103b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103d79190610f29565b5090508473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461043f576040517f6b0f689100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60028573ffffffffffffffffffffffffffffffffffffffff1663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa15801561048c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104b09190610f9f565b60028111156104c1576104c1610f70565b146104f8576040517f8f8af25f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052806105788773ffffffffffffffffffffffffffffffffffffffff1663bcef3b556040518163ffffffff1660e01b8152600401602060405180830381865afa158015610551573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105759190610fc0565b90565b81526020018673ffffffffffffffffffffffffffffffffffffffff16638b85902b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ec9190610fc0565b905263ffffffff909416600090815260016020818152604090922086518155959091015194019390935550505050565b600054610100900460ff161580801561063c5750600054600160ff909116105b806106565750303b158015610656575060005460ff166001145b6106e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561074457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b60005b83518110156107aa57600084828151811061076457610764610fd9565b60209081029190910181015180820151905163ffffffff1660009081526001808452604090912082518155919092015191015550806107a281611008565b915050610747565b50600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8416179055801561084e57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b600033905060008060008373ffffffffffffffffffffffffffffffffffffffff1663fa24f7436040518163ffffffff1660e01b8152600401600060405180830381865afa1580156108a8573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526108ee9190810190610e2a565b92509250925060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16635f0150cb8585856040518463ffffffff1660e01b815260040161095393929190610efb565b6040805180830381865afa15801561096f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109939190610f29565b5090508473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146109fb576040517f6b0f689100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160008563ffffffff1663ffffffff168152602001908152602001600020600101548573ffffffffffffffffffffffffffffffffffffffff16638b85902b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8d9190610fc0565b11610a99575050505050565b60028573ffffffffffffffffffffffffffffffffffffffff1663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ae6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b0a9190610f9f565b6002811115610b1b57610b1b610f70565b146104f8575050505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610b4957600080fd5b50565b600060208284031215610b5e57600080fd5b8135610b6981610b27565b9392505050565b60005b83811015610b8b578181015183820152602001610b73565b83811115610b9a576000848401525b50505050565b60008151808452610bb8816020860160208601610b70565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610b696020830184610ba0565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715610c4f57610c4f610bfd565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610c9c57610c9c610bfd565b604052919050565b63ffffffff81168114610b4957600080fd5b8035610cc181610b27565b919050565b6000806040808486031215610cda57600080fd5b833567ffffffffffffffff80821115610cf257600080fd5b818601915086601f830112610d0657600080fd5b8135602082821115610d1a57610d1a610bfd565b610d28818360051b01610c55565b8281528181019350606092830285018201928a841115610d4757600080fd5b948201945b83861015610dd457858b0381811215610d655760008081fd5b610d6d610c2c565b8735610d7881610ca4565b81527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08201891315610daa5760008081fd5b610db2610c2c565b8886013581528989013586820152818601528652509485019493820193610d4c565b509650610de2888201610cb6565b955050505050509250929050565b600060208284031215610e0257600080fd5b8135610b6981610ca4565b600060208284031215610e1f57600080fd5b8151610b6981610b27565b600080600060608486031215610e3f57600080fd5b8351610e4a81610ca4565b60208501516040860151919450925067ffffffffffffffff80821115610e6f57600080fd5b818601915086601f830112610e8357600080fd5b815181811115610e9557610e95610bfd565b610ec660207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601610c55565b9150808252876020828501011115610edd57600080fd5b610eee816020840160208601610b70565b5080925050509250925092565b63ffffffff84168152826020820152606060408201526000610f206060830184610ba0565b95945050505050565b60008060408385031215610f3c57600080fd5b8251610f4781610b27565b602084015190925067ffffffffffffffff81168114610f6557600080fd5b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600060208284031215610fb157600080fd5b815160038110610b6957600080fd5b600060208284031215610fd257600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611060577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b506001019056fea164736f6c634300080f000a0000000000000000000000005207cfa0166e8de0fcdfd78b4d17b68587be306d", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [], - "value": 0 - }, - { - "accessor": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "account": "0x63B71B96756C693f7065345fecD9b7843b3e7C57", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x60a060405234801561001057600080fd5b506040516111d73803806111d783398101604081905261002f9161010a565b6001600160a01b03811660805261004461004a565b5061013a565b600054610100900460ff16156100b65760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff9081161015610108576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b60006020828403121561011c57600080fd5b81516001600160a01b038116811461013357600080fd5b9392505050565b608051611074610163600039600081816101830152818161033c01526108f801526110746000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c80635e05fbd01161005b5780635e05fbd01461012a5780637258a8071461013d578063838c2d1e14610179578063f2b4e6171461018157600080fd5b806317cf21a91461008257806335e80ab31461009757806354fd4d50146100e1575b600080fd5b610095610090366004610b4c565b6101a7565b005b6002546100b79073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b61011d6040518060400160405280600a81526020017f322e302e302d72632e310000000000000000000000000000000000000000000081525081565b6040516100d89190610bea565b610095610138366004610cc6565b61061c565b61016461014b366004610df0565b6001602081905260009182526040909120805491015482565b604080519283526020830191909152016100d8565b610095610853565b7f00000000000000000000000000000000000000000000000000000000000000006100b7565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa158015610214573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102389190610e0d565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461029c576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060008373ffffffffffffffffffffffffffffffffffffffff1663fa24f7436040518163ffffffff1660e01b8152600401600060405180830381865afa1580156102ec573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526103329190810190610e2a565b92509250925060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16635f0150cb8585856040518463ffffffff1660e01b815260040161039793929190610efb565b6040805180830381865afa1580156103b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103d79190610f29565b5090508473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461043f576040517f6b0f689100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60028573ffffffffffffffffffffffffffffffffffffffff1663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa15801561048c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104b09190610f9f565b60028111156104c1576104c1610f70565b146104f8576040517f8f8af25f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052806105788773ffffffffffffffffffffffffffffffffffffffff1663bcef3b556040518163ffffffff1660e01b8152600401602060405180830381865afa158015610551573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105759190610fc0565b90565b81526020018673ffffffffffffffffffffffffffffffffffffffff16638b85902b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ec9190610fc0565b905263ffffffff909416600090815260016020818152604090922086518155959091015194019390935550505050565b600054610100900460ff161580801561063c5750600054600160ff909116105b806106565750303b158015610656575060005460ff166001145b6106e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561074457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b60005b83518110156107aa57600084828151811061076457610764610fd9565b60209081029190910181015180820151905163ffffffff1660009081526001808452604090912082518155919092015191015550806107a281611008565b915050610747565b50600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8416179055801561084e57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b600033905060008060008373ffffffffffffffffffffffffffffffffffffffff1663fa24f7436040518163ffffffff1660e01b8152600401600060405180830381865afa1580156108a8573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526108ee9190810190610e2a565b92509250925060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16635f0150cb8585856040518463ffffffff1660e01b815260040161095393929190610efb565b6040805180830381865afa15801561096f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109939190610f29565b5090508473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146109fb576040517f6b0f689100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160008563ffffffff1663ffffffff168152602001908152602001600020600101548573ffffffffffffffffffffffffffffffffffffffff16638b85902b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8d9190610fc0565b11610a99575050505050565b60028573ffffffffffffffffffffffffffffffffffffffff1663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ae6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b0a9190610f9f565b6002811115610b1b57610b1b610f70565b146104f8575050505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610b4957600080fd5b50565b600060208284031215610b5e57600080fd5b8135610b6981610b27565b9392505050565b60005b83811015610b8b578181015183820152602001610b73565b83811115610b9a576000848401525b50505050565b60008151808452610bb8816020860160208601610b70565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610b696020830184610ba0565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715610c4f57610c4f610bfd565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610c9c57610c9c610bfd565b604052919050565b63ffffffff81168114610b4957600080fd5b8035610cc181610b27565b919050565b6000806040808486031215610cda57600080fd5b833567ffffffffffffffff80821115610cf257600080fd5b818601915086601f830112610d0657600080fd5b8135602082821115610d1a57610d1a610bfd565b610d28818360051b01610c55565b8281528181019350606092830285018201928a841115610d4757600080fd5b948201945b83861015610dd457858b0381811215610d655760008081fd5b610d6d610c2c565b8735610d7881610ca4565b81527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08201891315610daa5760008081fd5b610db2610c2c565b8886013581528989013586820152818601528652509485019493820193610d4c565b509650610de2888201610cb6565b955050505050509250929050565b600060208284031215610e0257600080fd5b8135610b6981610ca4565b600060208284031215610e1f57600080fd5b8151610b6981610b27565b600080600060608486031215610e3f57600080fd5b8351610e4a81610ca4565b60208501516040860151919450925067ffffffffffffffff80821115610e6f57600080fd5b818601915086601f830112610e8357600080fd5b815181811115610e9557610e95610bfd565b610ec660207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601610c55565b9150808252876020828501011115610edd57600080fd5b610eee816020840160208601610b70565b5080925050509250925092565b63ffffffff84168152826020820152606060408201526000610f206060830184610ba0565b95945050505050565b60008060408385031215610f3c57600080fd5b8251610f4781610b27565b602084015190925067ffffffffffffffff81168114610f6557600080fd5b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600060208284031215610fb157600080fd5b815160038110610b6957600080fd5b600060208284031215610fd257600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611060577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b506001019056fea164736f6c634300080f000a0000000000000000000000005207cfa0166e8de0fcdfd78b4d17b68587be306d", - "deployedCode": "0x608060405234801561001057600080fd5b506004361061007d5760003560e01c80635e05fbd01161005b5780635e05fbd01461012a5780637258a8071461013d578063838c2d1e14610179578063f2b4e6171461018157600080fd5b806317cf21a91461008257806335e80ab31461009757806354fd4d50146100e1575b600080fd5b610095610090366004610b4c565b6101a7565b005b6002546100b79073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b61011d6040518060400160405280600a81526020017f322e302e302d72632e310000000000000000000000000000000000000000000081525081565b6040516100d89190610bea565b610095610138366004610cc6565b61061c565b61016461014b366004610df0565b6001602081905260009182526040909120805491015482565b604080519283526020830191909152016100d8565b610095610853565b7f0000000000000000000000005207cfa0166e8de0fcdfd78b4d17b68587be306d6100b7565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa158015610214573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102389190610e0d565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461029c576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060008373ffffffffffffffffffffffffffffffffffffffff1663fa24f7436040518163ffffffff1660e01b8152600401600060405180830381865afa1580156102ec573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526103329190810190610e2a565b92509250925060007f0000000000000000000000005207cfa0166e8de0fcdfd78b4d17b68587be306d73ffffffffffffffffffffffffffffffffffffffff16635f0150cb8585856040518463ffffffff1660e01b815260040161039793929190610efb565b6040805180830381865afa1580156103b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103d79190610f29565b5090508473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461043f576040517f6b0f689100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60028573ffffffffffffffffffffffffffffffffffffffff1663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa15801561048c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104b09190610f9f565b60028111156104c1576104c1610f70565b146104f8576040517f8f8af25f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052806105788773ffffffffffffffffffffffffffffffffffffffff1663bcef3b556040518163ffffffff1660e01b8152600401602060405180830381865afa158015610551573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105759190610fc0565b90565b81526020018673ffffffffffffffffffffffffffffffffffffffff16638b85902b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ec9190610fc0565b905263ffffffff909416600090815260016020818152604090922086518155959091015194019390935550505050565b600054610100900460ff161580801561063c5750600054600160ff909116105b806106565750303b158015610656575060005460ff166001145b6106e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561074457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b60005b83518110156107aa57600084828151811061076457610764610fd9565b60209081029190910181015180820151905163ffffffff1660009081526001808452604090912082518155919092015191015550806107a281611008565b915050610747565b50600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8416179055801561084e57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b600033905060008060008373ffffffffffffffffffffffffffffffffffffffff1663fa24f7436040518163ffffffff1660e01b8152600401600060405180830381865afa1580156108a8573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526108ee9190810190610e2a565b92509250925060007f0000000000000000000000005207cfa0166e8de0fcdfd78b4d17b68587be306d73ffffffffffffffffffffffffffffffffffffffff16635f0150cb8585856040518463ffffffff1660e01b815260040161095393929190610efb565b6040805180830381865afa15801561096f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109939190610f29565b5090508473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146109fb576040517f6b0f689100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160008563ffffffff1663ffffffff168152602001908152602001600020600101548573ffffffffffffffffffffffffffffffffffffffff16638b85902b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8d9190610fc0565b11610a99575050505050565b60028573ffffffffffffffffffffffffffffffffffffffff1663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ae6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b0a9190610f9f565b6002811115610b1b57610b1b610f70565b146104f8575050505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610b4957600080fd5b50565b600060208284031215610b5e57600080fd5b8135610b6981610b27565b9392505050565b60005b83811015610b8b578181015183820152602001610b73565b83811115610b9a576000848401525b50505050565b60008151808452610bb8816020860160208601610b70565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610b696020830184610ba0565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715610c4f57610c4f610bfd565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610c9c57610c9c610bfd565b604052919050565b63ffffffff81168114610b4957600080fd5b8035610cc181610b27565b919050565b6000806040808486031215610cda57600080fd5b833567ffffffffffffffff80821115610cf257600080fd5b818601915086601f830112610d0657600080fd5b8135602082821115610d1a57610d1a610bfd565b610d28818360051b01610c55565b8281528181019350606092830285018201928a841115610d4757600080fd5b948201945b83861015610dd457858b0381811215610d655760008081fd5b610d6d610c2c565b8735610d7881610ca4565b81527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08201891315610daa5760008081fd5b610db2610c2c565b8886013581528989013586820152818601528652509485019493820193610d4c565b509650610de2888201610cb6565b955050505050509250929050565b600060208284031215610e0257600080fd5b8135610b6981610ca4565b600060208284031215610e1f57600080fd5b8151610b6981610b27565b600080600060608486031215610e3f57600080fd5b8351610e4a81610ca4565b60208501516040860151919450925067ffffffffffffffff80821115610e6f57600080fd5b818601915086601f830112610e8357600080fd5b815181811115610e9557610e95610bfd565b610ec660207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601610c55565b9150808252876020828501011115610edd57600080fd5b610eee816020840160208601610b70565b5080925050509250925092565b63ffffffff84168152826020820152606060408201526000610f206060830184610ba0565b95945050505050565b60008060408385031215610f3c57600080fd5b8251610f4781610b27565b602084015190925067ffffffffffffffff81168114610f6557600080fd5b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600060208284031215610fb157600080fd5b815160038110610b6957600080fd5b600060208284031215610fd257600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611060577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b506001019056fea164736f6c634300080f000a", - "initialized": true, - "kind": "Create", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x63B71B96756C693f7065345fecD9b7843b3e7C57", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x63B71B96756C693f7065345fecD9b7843b3e7C57", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x63B71B96756C693f7065345fecD9b7843b3e7C57", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x63B71B96756C693f7065345fecD9b7843b3e7C57", - "isWrite": true, - "newValue": "0x00000000000000000000000000000000000000000000000000000000000000ff", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "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": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x434da94d", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000044" - } - ], - "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": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x6a76120200000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000001049623609d0000000000000000000000001c23a6d89f95ef3148bcda8e242cab145bf9c0e4000000000000000000000000bdd90485fcbcac869d5b5752179815a3103d813100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b00000000000000000000000039af23e00f1e662025aa01b0ceda19542b78df990000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa60000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab0351000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", - "previousValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x6a76120200000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000001049623609d0000000000000000000000001c23a6d89f95ef3148bcda8e242cab145bf9c0e4000000000000000000000000bdd90485fcbcac869d5b5752179815a3103d813100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b00000000000000000000000039af23e00f1e662025aa01b0ceda19542b78df990000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa60000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab0351000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000002", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000002", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000002", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000002", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000003", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000002", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0xd1b0d319c6526317dce66989b393dcfb4435c9a65e399a088b63bbf65d7aee32" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c8" - } - ], - "value": 0 - }, - { - "accessor": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x9623609d0000000000000000000000001c23a6d89f95ef3148bcda8e242cab145bf9c0e4000000000000000000000000bdd90485fcbcac869d5b5752179815a3103d813100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b00000000000000000000000039af23e00f1e662025aa01b0ceda19542b78df990000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa60000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab035100000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x0000000000000000000000007c0c8a15773ed7b50e7c738d1af4c5e3a2b210bd", - "previousValue": "0x0000000000000000000000007c0c8a15773ed7b50e7c738d1af4c5e3a2b210bd", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x727598a658f6983be3a9f29beef55aaee89ef8a176baeeacbe7edf5ff94a781b" - } - ], - "value": 0 - }, - { - "accessor": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x4f1ef286000000000000000000000000bdd90485fcbcac869d5b5752179815a3103d813100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000064c0c53b8b00000000000000000000000039af23e00f1e662025aa01b0ceda19542b78df990000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa60000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab035100000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", - "isWrite": false, - "newValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "previousValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "reverted": false, - "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" - }, - { - "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", - "isWrite": true, - "newValue": "0x000000000000000000000000bdd90485fcbcac869d5b5752179815a3103d8131", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "account": "0xbdD90485FCbcac869D5b5752179815a3103d8131", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xc0c53b8b00000000000000000000000039af23e00f1e662025aa01b0ceda19542b78df990000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa60000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab0351", - "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": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000036" - }, - { - "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", - "isWrite": true, - "newValue": "0x00000000000000000000000039af23e00f1e662025aa01b0ceda19542b78df99", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000036" - }, - { - "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000037" - }, - { - "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", - "isWrite": true, - "newValue": "0x0000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa6", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000037" - }, - { - "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000035" - }, - { - "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", - "isWrite": true, - "newValue": "0x00000000000000000000004f559f30f5eb88d635fde1548c4267db8fab035100", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000035" - }, - { - "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000032" - }, - { - "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000032" - }, - { - "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", - "isWrite": true, - "newValue": "0x000000000000000000000000000000000000000000000000000000000000dead", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000032" - }, - { - "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000001" - }, - { - "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", - "isWrite": true, - "newValue": "0x000000000000000100000000000000000000000000000000000000003b9aca00", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000001" - }, - { - "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": "0x000000000000000000000000bdd90485fcbcac869d5b5752179815a3103d8131", - "previousValue": "0x000000000000000000000000bdd90485fcbcac869d5b5752179815a3103d8131", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xbdD90485FCbcac869D5b5752179815a3103d8131", - "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": "0x000000000000000000000000000000000000000000000000000000000000000f" - } - ], - "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": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x9b5f694a", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", - "isWrite": false, - "newValue": "0x000000000000000000000000bdd90485fcbcac869d5b5752179815a3103d8131", - "previousValue": "0x000000000000000000000000bdd90485fcbcac869d5b5752179815a3103d8131", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xbdD90485FCbcac869D5b5752179815a3103d8131", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x9b5f694a", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", - "isWrite": false, - "newValue": "0x00000000000000000000000039af23e00f1e662025aa01b0ceda19542b78df99", - "previousValue": "0x00000000000000000000000039af23e00f1e662025aa01b0ceda19542b78df99", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000036" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x33d7e2bd", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", - "isWrite": false, - "newValue": "0x000000000000000000000000bdd90485fcbcac869d5b5752179815a3103d8131", - "previousValue": "0x000000000000000000000000bdd90485fcbcac869d5b5752179815a3103d8131", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xbdD90485FCbcac869D5b5752179815a3103d8131", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x33d7e2bd", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", - "isWrite": false, - "newValue": "0x0000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa6", - "previousValue": "0x0000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa6", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000037" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x452a9320", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", - "isWrite": false, - "newValue": "0x000000000000000000000000bdd90485fcbcac869d5b5752179815a3103d8131", - "previousValue": "0x000000000000000000000000bdd90485fcbcac869d5b5752179815a3103d8131", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xbdD90485FCbcac869D5b5752179815a3103d8131", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x452a9320", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", - "isWrite": false, - "newValue": "0x00000000000000000000004f559f30f5eb88d635fde1548c4267db8fab035100", - "previousValue": "0x00000000000000000000004f559f30f5eb88d635fde1548c4267db8fab035100", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000035" - } - ], - "value": 0 - }, - { - "accessor": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", - "account": "0x4f559F30f5eB88D635FDe1548C4267DB8FaB0351", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x452a9320", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x4f559F30f5eB88D635FDe1548C4267DB8FaB0351", - "isWrite": false, - "newValue": "0x000000000000000000000000068e44eb31e111028c41598e4535be7468674d0a", - "previousValue": "0x000000000000000000000000068e44eb31e111028c41598e4535be7468674d0a", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", - "account": "0x068E44eB31e111028c41598E4535be7468674D0A", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x452a9320", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x4f559F30f5eB88D635FDe1548C4267DB8FaB0351", - "isWrite": false, - "newValue": "0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc", - "previousValue": "0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc", - "reverted": false, - "slot": "0xd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe68" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x35e80ab3", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", - "isWrite": false, - "newValue": "0x000000000000000000000000bdd90485fcbcac869d5b5752179815a3103d8131", - "previousValue": "0x000000000000000000000000bdd90485fcbcac869d5b5752179815a3103d8131", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xbdD90485FCbcac869D5b5752179815a3103d8131", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x35e80ab3", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", - "isWrite": false, - "newValue": "0x00000000000000000000004f559f30f5eb88d635fde1548c4267db8fab035100", - "previousValue": "0x00000000000000000000004f559f30f5eb88d635fde1548c4267db8fab035100", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000035" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x4f559F30f5eB88D635FDe1548C4267DB8FaB0351", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x5c975abb", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x4f559F30f5eB88D635FDe1548C4267DB8FaB0351", - "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": "0x4f559F30f5eB88D635FDe1548C4267DB8FaB0351", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b6" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x5c975abb", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", - "isWrite": false, - "newValue": "0x000000000000000000000000bdd90485fcbcac869d5b5752179815a3103d8131", - "previousValue": "0x000000000000000000000000bdd90485fcbcac869d5b5752179815a3103d8131", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xbdD90485FCbcac869D5b5752179815a3103d8131", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x5c975abb", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", - "isWrite": false, - "newValue": "0x00000000000000000000004f559f30f5eb88d635fde1548c4267db8fab035100", - "previousValue": "0x00000000000000000000004f559f30f5eb88d635fde1548c4267db8fab035100", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000035" - } - ], - "value": 0 - }, - { - "accessor": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", - "account": "0x4f559F30f5eB88D635FDe1548C4267DB8FaB0351", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x5c975abb", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x4f559F30f5eB88D635FDe1548C4267DB8FaB0351", - "isWrite": false, - "newValue": "0x000000000000000000000000068e44eb31e111028c41598e4535be7468674d0a", - "previousValue": "0x000000000000000000000000068e44eb31e111028c41598e4535be7468674d0a", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", - "account": "0x068E44eB31e111028c41598E4535be7468674D0A", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x5c975abb", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x4f559F30f5eB88D635FDe1548C4267DB8FaB0351", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b6" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x9bf62d82", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", - "isWrite": false, - "newValue": "0x000000000000000000000000bdd90485fcbcac869d5b5752179815a3103d8131", - "previousValue": "0x000000000000000000000000bdd90485fcbcac869d5b5752179815a3103d8131", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xbdD90485FCbcac869D5b5752179815a3103d8131", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x9bf62d82", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4", - "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": "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": "0x000000000000000000000000000000000000000000000000000000000000001c" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xf77a09bd", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x000000000000000000000000000000000000000000000000000000000000004a" - } - ], - "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": "0x000000000000000000000000000000000000000000000000000000000000000e" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xbfb14fb7", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x000000000000000000000000000000000000000000000001000c5fc500000558", - "previousValue": "0x000000000000000000000000000000000000000000000001000c5fc500000558", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000031" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xec707517", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x000000000000000000000000000000000000000000000001000c5fc500000558", - "previousValue": "0x000000000000000000000000000000000000000000000001000c5fc500000558", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000031" - } - ], - "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": "0x0000000000000000000000000000000000000000000000000000000000000030" - } - ], - "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": "0x000000000000000000000000000000000000000000000000000000000000001a" - } - ], - "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": "0x000000000000000000000000000000000000000000000000000000000000001b" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x6a76120200000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004a000000000000000000000000000000000000000000000000000000000000003249623609d0000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa600000000000000000000000067866a5052e5302aad08e9f352331fd8622eb6dc00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000284db9040fa0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc000000000000000000000000000000000000000000000000000000000000055800000000000000000000000000000000000000000000000000000000000c5fc50000000000000000000000003c44cdddb6a900fa2b585dd299e03d12fa4293bc00000000000000000000000000000000000000000000000000000000017d78400000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc0000000000000000000000000000000000000000000000000000000001312d00000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000003b9aca0000000000000000000000000000000000000000000000000000000000000f424000000000000000000000000000000000ffffffffffffffffffffffffffffffff000000000000000000000000ff00000000000000000000000000000000000000000000000000000000000000def3bca8c80064589e6787477ffa7dd616b5574f000000000000000000000000d31598c909d9c935a9e35ba70d9a3dd47d4d586500000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d0000000000000000000000005207cfa0166e8de0fcdfd78b4d17b68587be306d0000000000000000000000001c23a6d89f95ef3148bcda8e242cab145bf9c0e4000000000000000000000000c7b87b2b892ea5c3cff47168881fe168c00377fb000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", - "previousValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x6a76120200000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004a000000000000000000000000000000000000000000000000000000000000003249623609d0000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa600000000000000000000000067866a5052e5302aad08e9f352331fd8622eb6dc00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000284db9040fa0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc000000000000000000000000000000000000000000000000000000000000055800000000000000000000000000000000000000000000000000000000000c5fc50000000000000000000000003c44cdddb6a900fa2b585dd299e03d12fa4293bc00000000000000000000000000000000000000000000000000000000017d78400000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc0000000000000000000000000000000000000000000000000000000001312d00000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000003b9aca0000000000000000000000000000000000000000000000000000000000000f424000000000000000000000000000000000ffffffffffffffffffffffffffffffff000000000000000000000000ff00000000000000000000000000000000000000000000000000000000000000def3bca8c80064589e6787477ffa7dd616b5574f000000000000000000000000d31598c909d9c935a9e35ba70d9a3dd47d4d586500000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d0000000000000000000000005207cfa0166e8de0fcdfd78b4d17b68587be306d0000000000000000000000001c23a6d89f95ef3148bcda8e242cab145bf9c0e4000000000000000000000000c7b87b2b892ea5c3cff47168881fe168c00377fb000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000003", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000003", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000003", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000003", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000004", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000003", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0xd1b0d319c6526317dce66989b393dcfb4435c9a65e399a088b63bbf65d7aee32" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c8" - } - ], - "value": 0 - }, - { - "accessor": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x9623609d0000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa600000000000000000000000067866a5052e5302aad08e9f352331fd8622eb6dc00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000284db9040fa0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc000000000000000000000000000000000000000000000000000000000000055800000000000000000000000000000000000000000000000000000000000c5fc50000000000000000000000003c44cdddb6a900fa2b585dd299e03d12fa4293bc00000000000000000000000000000000000000000000000000000000017d78400000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc0000000000000000000000000000000000000000000000000000000001312d00000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000003b9aca0000000000000000000000000000000000000000000000000000000000000f424000000000000000000000000000000000ffffffffffffffffffffffffffffffff000000000000000000000000ff00000000000000000000000000000000000000000000000000000000000000def3bca8c80064589e6787477ffa7dd616b5574f000000000000000000000000d31598c909d9c935a9e35ba70d9a3dd47d4d586500000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d0000000000000000000000005207cfa0166e8de0fcdfd78b4d17b68587be306d0000000000000000000000001c23a6d89f95ef3148bcda8e242cab145bf9c0e4000000000000000000000000c7b87b2b892ea5c3cff47168881fe168c00377fb000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee00000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x0000000000000000000000007c0c8a15773ed7b50e7c738d1af4c5e3a2b210bd", - "previousValue": "0x0000000000000000000000007c0c8a15773ed7b50e7c738d1af4c5e3a2b210bd", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0xa8f0d50211ac8ff1a40793a899dff3ced4762e0466f69b0078ab7b00d037835c" - } - ], - "value": 0 - }, - { - "accessor": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x4f1ef28600000000000000000000000067866a5052e5302aad08e9f352331fd8622eb6dc00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000284db9040fa0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc000000000000000000000000000000000000000000000000000000000000055800000000000000000000000000000000000000000000000000000000000c5fc50000000000000000000000003c44cdddb6a900fa2b585dd299e03d12fa4293bc00000000000000000000000000000000000000000000000000000000017d78400000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc0000000000000000000000000000000000000000000000000000000001312d00000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000003b9aca0000000000000000000000000000000000000000000000000000000000000f424000000000000000000000000000000000ffffffffffffffffffffffffffffffff000000000000000000000000ff00000000000000000000000000000000000000000000000000000000000000def3bca8c80064589e6787477ffa7dd616b5574f000000000000000000000000d31598c909d9c935a9e35ba70d9a3dd47d4d586500000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d0000000000000000000000005207cfa0166e8de0fcdfd78b4d17b68587be306d0000000000000000000000001c23a6d89f95ef3148bcda8e242cab145bf9c0e4000000000000000000000000c7b87b2b892ea5c3cff47168881fe168c00377fb000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee00000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": false, - "newValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "previousValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "reverted": false, - "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" - }, - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": true, - "newValue": "0x00000000000000000000000067866a5052e5302aad08e9f352331fd8622eb6dc", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xdb9040fa0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc000000000000000000000000000000000000000000000000000000000000055800000000000000000000000000000000000000000000000000000000000c5fc50000000000000000000000003c44cdddb6a900fa2b585dd299e03d12fa4293bc00000000000000000000000000000000000000000000000000000000017d78400000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc0000000000000000000000000000000000000000000000000000000001312d00000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000003b9aca0000000000000000000000000000000000000000000000000000000000000f424000000000000000000000000000000000ffffffffffffffffffffffffffffffff000000000000000000000000ff00000000000000000000000000000000000000000000000000000000000000def3bca8c80064589e6787477ffa7dd616b5574f000000000000000000000000d31598c909d9c935a9e35ba70d9a3dd47d4d586500000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d0000000000000000000000005207cfa0166e8de0fcdfd78b4d17b68587be306d0000000000000000000000001c23a6d89f95ef3148bcda8e242cab145bf9c0e4000000000000000000000000c7b87b2b892ea5c3cff47168881fe168c00377fb000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", - "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": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - }, - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": true, - "newValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - }, - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": false, - "newValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "previousValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - }, - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": false, - "newValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "previousValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - }, - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": true, - "newValue": "0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc", - "previousValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - }, - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": true, - "newValue": "0x0000000000000000000000003c44cdddb6a900fa2b585dd299e03d12fa4293bc", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000067" - }, - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000068" - }, - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": true, - "newValue": "0x00000000000000000000000000000000000c5fc5000005580000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000068" - }, - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": true, - "newValue": "0x010000000000000000000000000000000000000000000000000c5fc500000558", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000066" - }, - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000065" - }, - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000069" - }, - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": false, - "newValue": "0x00000000000000000000000000000000000c5fc5000005580000000000000000", - "previousValue": "0x00000000000000000000000000000000000c5fc5000005580000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000068" - }, - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": true, - "newValue": "0x00000000000000000000000000000000000c5fc50000055800000000017d7840", - "previousValue": "0x00000000000000000000000000000000000c5fc5000005580000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000068" - }, - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": true, - "newValue": "0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08" - }, - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": true, - "newValue": "0x000000000000000000000000ff00000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc597" - }, - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": true, - "newValue": "0x000000000000000000000000def3bca8c80064589e6787477ffa7dd616b5574f", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce9580636" - }, - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": true, - "newValue": "0x000000000000000000000000d31598c909d9c935a9e35ba70d9a3dd47d4d5865", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a7" - }, - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": true, - "newValue": "0x00000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad6376" - }, - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": true, - "newValue": "0x0000000000000000000000005207cfa0166e8de0fcdfd78b4d17b68587be306d", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x52322a25d9f59ea17656545543306b7aef62bc0cc53a0e65ccfa0c75b97aa906" - }, - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": true, - "newValue": "0x0000000000000000000000001c23a6d89f95ef3148bcda8e242cab145bf9c0e4", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ac" - }, - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": true, - "newValue": "0x000000000000000000000000c7b87b2b892ea5c3cff47168881fe168c00377fb", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0xa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320c" - }, - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0xa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb19f" - }, - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0xa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb19f" - }, - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": false, - "newValue": "0x00000000000000000000000000000000000c5fc50000055800000000017d7840", - "previousValue": "0x00000000000000000000000000000000000c5fc50000055800000000017d7840", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000068" - }, - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000069" - }, - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": true, - "newValue": "0x0000ffffffffffffffffffffffffffffffff000f42403b9aca00080a01312d00", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000069" - }, - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": false, - "newValue": "0x0000ffffffffffffffffffffffffffffffff000f42403b9aca00080a01312d00", - "previousValue": "0x0000ffffffffffffffffffffffffffffffff000f42403b9aca00080a01312d00", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000069" - }, - { - "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": "0x00000000000000000000000067866a5052e5302aad08e9f352331fd8622eb6dc", - "previousValue": "0x00000000000000000000000067866a5052e5302aad08e9f352331fd8622eb6dc", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "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": "0xcc731b02", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": false, - "newValue": "0x00000000000000000000000067866a5052e5302aad08e9f352331fd8622eb6dc", - "previousValue": "0x00000000000000000000000067866a5052e5302aad08e9f352331fd8622eb6dc", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xcc731b02", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "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": "0x000000000000000000000000000000000000000000000000000000000000000e" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x8da5cb5b", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": false, - "newValue": "0x00000000000000000000000067866a5052e5302aad08e9f352331fd8622eb6dc", - "previousValue": "0x00000000000000000000000067866a5052e5302aad08e9f352331fd8622eb6dc", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x8da5cb5b", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": false, - "newValue": "0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc", - "previousValue": "0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xbfb14fb7", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x000000000000000000000000000000000000000000000001000c5fc500000558", - "previousValue": "0x000000000000000000000000000000000000000000000001000c5fc500000558", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000031" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xbfb14fb7", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": false, - "newValue": "0x00000000000000000000000067866a5052e5302aad08e9f352331fd8622eb6dc", - "previousValue": "0x00000000000000000000000067866a5052e5302aad08e9f352331fd8622eb6dc", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xbfb14fb7", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": false, - "newValue": "0x00000000000000000000000000000000000c5fc50000055800000000017d7840", - "previousValue": "0x00000000000000000000000000000000000c5fc50000055800000000017d7840", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000068" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xec707517", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x000000000000000000000000000000000000000000000001000c5fc500000558", - "previousValue": "0x000000000000000000000000000000000000000000000001000c5fc500000558", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000031" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xec707517", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": false, - "newValue": "0x00000000000000000000000067866a5052e5302aad08e9f352331fd8622eb6dc", - "previousValue": "0x00000000000000000000000067866a5052e5302aad08e9f352331fd8622eb6dc", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xec707517", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": false, - "newValue": "0x00000000000000000000000000000000000c5fc50000055800000000017d7840", - "previousValue": "0x00000000000000000000000000000000000c5fc50000055800000000017d7840", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000068" - } - ], - "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": "0x000000000000000000000000000000000000000000000000000000000000001c" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xe81b2c6d", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": false, - "newValue": "0x00000000000000000000000067866a5052e5302aad08e9f352331fd8622eb6dc", - "previousValue": "0x00000000000000000000000067866a5052e5302aad08e9f352331fd8622eb6dc", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xe81b2c6d", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "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": "0x0000000000000000000000000000000000000000000000000000000000000030" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xf68016b7", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": false, - "newValue": "0x00000000000000000000000067866a5052e5302aad08e9f352331fd8622eb6dc", - "previousValue": "0x00000000000000000000000067866a5052e5302aad08e9f352331fd8622eb6dc", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xf68016b7", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": false, - "newValue": "0x00000000000000000000000000000000000c5fc50000055800000000017d7840", - "previousValue": "0x00000000000000000000000000000000000c5fc50000055800000000017d7840", - "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": "0x000000000000000000000000000000000000000000000000000000000000001a" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x1fd19ee1", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": false, - "newValue": "0x00000000000000000000000067866a5052e5302aad08e9f352331fd8622eb6dc", - "previousValue": "0x00000000000000000000000067866a5052e5302aad08e9f352331fd8622eb6dc", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x1fd19ee1", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": false, - "newValue": "0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc", - "previousValue": "0x0000000000000000000000009965507d1a55bcc2695c58ba16fb37d819b0a4dc", - "reverted": false, - "slot": "0x65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xf45e65d8", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": false, - "newValue": "0x00000000000000000000000067866a5052e5302aad08e9f352331fd8622eb6dc", - "previousValue": "0x00000000000000000000000067866a5052e5302aad08e9f352331fd8622eb6dc", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xf45e65d8", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": false, - "newValue": "0x010000000000000000000000000000000000000000000000000c5fc500000558", - "previousValue": "0x010000000000000000000000000000000000000000000000000c5fc500000558", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000066" - } - ], - "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": "0x000000000000000000000000000000000000000000000000000000000000003e" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x48cd4cb1", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": false, - "newValue": "0x00000000000000000000000067866a5052e5302aad08e9f352331fd8622eb6dc", - "previousValue": "0x00000000000000000000000067866a5052e5302aad08e9f352331fd8622eb6dc", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x48cd4cb1", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "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": "0x000000000000000000000000000000000000000000000000000000000000001b" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xdac6e63a", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": false, - "newValue": "0x00000000000000000000000067866a5052e5302aad08e9f352331fd8622eb6dc", - "previousValue": "0x00000000000000000000000067866a5052e5302aad08e9f352331fd8622eb6dc", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xdac6e63a", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": false, - "newValue": "0x000000000000000000000000ff00000000000000000000000000000000000000", - "previousValue": "0x000000000000000000000000ff00000000000000000000000000000000000000", - "reverted": false, - "slot": "0x71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc597" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xa7119869", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": false, - "newValue": "0x00000000000000000000000067866a5052e5302aad08e9f352331fd8622eb6dc", - "previousValue": "0x00000000000000000000000067866a5052e5302aad08e9f352331fd8622eb6dc", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xa7119869", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": false, - "newValue": "0x000000000000000000000000def3bca8c80064589e6787477ffa7dd616b5574f", - "previousValue": "0x000000000000000000000000def3bca8c80064589e6787477ffa7dd616b5574f", - "reverted": false, - "slot": "0x383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce9580636" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xc4e8ddfa", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": false, - "newValue": "0x00000000000000000000000067866a5052e5302aad08e9f352331fd8622eb6dc", - "previousValue": "0x00000000000000000000000067866a5052e5302aad08e9f352331fd8622eb6dc", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xc4e8ddfa", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": false, - "newValue": "0x000000000000000000000000d31598c909d9c935a9e35ba70d9a3dd47d4d5865", - "previousValue": "0x000000000000000000000000d31598c909d9c935a9e35ba70d9a3dd47d4d5865", - "reverted": false, - "slot": "0x46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a7" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x078f29cf", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": false, - "newValue": "0x00000000000000000000000067866a5052e5302aad08e9f352331fd8622eb6dc", - "previousValue": "0x00000000000000000000000067866a5052e5302aad08e9f352331fd8622eb6dc", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x078f29cf", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": false, - "newValue": "0x00000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d", - "previousValue": "0x00000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d", - "reverted": false, - "slot": "0x9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad6376" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xf2b4e617", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": false, - "newValue": "0x00000000000000000000000067866a5052e5302aad08e9f352331fd8622eb6dc", - "previousValue": "0x00000000000000000000000067866a5052e5302aad08e9f352331fd8622eb6dc", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xf2b4e617", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": false, - "newValue": "0x0000000000000000000000005207cfa0166e8de0fcdfd78b4d17b68587be306d", - "previousValue": "0x0000000000000000000000005207cfa0166e8de0fcdfd78b4d17b68587be306d", - "reverted": false, - "slot": "0x52322a25d9f59ea17656545543306b7aef62bc0cc53a0e65ccfa0c75b97aa906" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x0a49cb03", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": false, - "newValue": "0x00000000000000000000000067866a5052e5302aad08e9f352331fd8622eb6dc", - "previousValue": "0x00000000000000000000000067866a5052e5302aad08e9f352331fd8622eb6dc", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x0a49cb03", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": false, - "newValue": "0x0000000000000000000000001c23a6d89f95ef3148bcda8e242cab145bf9c0e4", - "previousValue": "0x0000000000000000000000001c23a6d89f95ef3148bcda8e242cab145bf9c0e4", - "reverted": false, - "slot": "0x4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ac" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x9b7d7f0a", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": false, - "newValue": "0x00000000000000000000000067866a5052e5302aad08e9f352331fd8622eb6dc", - "previousValue": "0x00000000000000000000000067866a5052e5302aad08e9f352331fd8622eb6dc", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x67866A5052E5302aaD08e9f352331fd8622eB6DC", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x9b7d7f0a", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6", - "isWrite": false, - "newValue": "0x000000000000000000000000c7b87b2b892ea5c3cff47168881fe168c00377fb", - "previousValue": "0x000000000000000000000000c7b87b2b892ea5c3cff47168881fe168c00377fb", - "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": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x6bd9f51600000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x540cf4e2f45b866b44f44bde51e109474016dc46a0670fbe1684ad8eaf90fdc3" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x6a76120200000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000000448d52d4a000000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", - "previousValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x6a76120200000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000000448d52d4a000000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000004", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000004", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000004", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000004", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000005", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000004", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0xd1b0d319c6526317dce66989b393dcfb4435c9a65e399a088b63bbf65d7aee32" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c8" - } - ], - "value": 0 - }, - { - "accessor": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x8d52d4a000000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d0000000000000000000000000000000000000000000000000000000000000001", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x0000000000000000000000007c0c8a15773ed7b50e7c738d1af4c5e3a2b210bd", - "previousValue": "0x0000000000000000000000007c0c8a15773ed7b50e7c738d1af4c5e3a2b210bd", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x540cf4e2f45b866b44f44bde51e109474016dc46a0670fbe1684ad8eaf90fdc3" - }, - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x540cf4e2f45b866b44f44bde51e109474016dc46a0670fbe1684ad8eaf90fdc3" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x6bd9f51600000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x540cf4e2f45b866b44f44bde51e109474016dc46a0670fbe1684ad8eaf90fdc3" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x6a76120200000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000001049623609d00000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d000000000000000000000000b7900b27be8f0e0ff65d1c3a4671e1220437dd2b00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b000000000000000000000000def3bca8c80064589e6787477ffa7dd616b5574f0000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab03510000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", - "previousValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x6a76120200000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000001049623609d00000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d000000000000000000000000b7900b27be8f0e0ff65d1c3a4671e1220437dd2b00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b000000000000000000000000def3bca8c80064589e6787477ffa7dd616b5574f0000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab03510000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000005", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000005", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000005", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000005", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000006", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000005", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0xd1b0d319c6526317dce66989b393dcfb4435c9a65e399a088b63bbf65d7aee32" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c8" - } - ], - "value": 0 - }, - { - "accessor": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x9623609d00000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d000000000000000000000000b7900b27be8f0e0ff65d1c3a4671e1220437dd2b00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b000000000000000000000000def3bca8c80064589e6787477ffa7dd616b5574f0000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab03510000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa600000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x0000000000000000000000007c0c8a15773ed7b50e7c738d1af4c5e3a2b210bd", - "previousValue": "0x0000000000000000000000007c0c8a15773ed7b50e7c738d1af4c5e3a2b210bd", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x540cf4e2f45b866b44f44bde51e109474016dc46a0670fbe1684ad8eaf90fdc3" - }, - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x0000000000000000000000007c0c8a15773ed7b50e7c738d1af4c5e3a2b210bd", - "previousValue": "0x0000000000000000000000007c0c8a15773ed7b50e7c738d1af4c5e3a2b210bd", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x540cf4e2f45b866b44f44bde51e109474016dc46a0670fbe1684ad8eaf90fdc3" - } - ], - "value": 0 - }, - { - "accessor": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x", - "deployedCode": "0x", - "initialized": true, - "kind": "Resume", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [], - "value": 0 - }, - { - "accessor": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x9b0b0fda360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc000000000000000000000000b7900b27be8f0e0ff65d1c3a4671e1220437dd2b", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", - "isWrite": false, - "newValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "previousValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "reverted": false, - "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" - }, - { - "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", - "isWrite": true, - "newValue": "0x000000000000000000000000b7900b27be8f0e0ff65d1c3a4671e1220437dd2b", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xc0c53b8b000000000000000000000000def3bca8c80064589e6787477ffa7dd616b5574f0000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab03510000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa6", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", - "isWrite": false, - "newValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "previousValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "reverted": false, - "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" - } - ], - "value": 0 - }, - { - "accessor": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xb7947262", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x00000000000000000000000050eef481cae4250d252ae577a09bf514f224c6c4", - "previousValue": "0x00000000000000000000000050eef481cae4250d252ae577a09bf514f224c6c4", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000003" - } - ], - "value": 0 - }, - { - "accessor": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x", - "deployedCode": "0x", - "initialized": true, - "kind": "Resume", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", - "isWrite": false, - "newValue": "0x000000000000000000000000b7900b27be8f0e0ff65d1c3a4671e1220437dd2b", - "previousValue": "0x000000000000000000000000b7900b27be8f0e0ff65d1c3a4671e1220437dd2b", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "account": "0xb7900B27Be8f0E0fF65d1C3A4671e1220437dd2b", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xc0c53b8b000000000000000000000000def3bca8c80064589e6787477ffa7dd616b5574f0000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab03510000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa6", - "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": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000032" - }, - { - "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", - "isWrite": true, - "newValue": "0x0000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab0351", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000032" - }, - { - "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - }, - { - "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", - "isWrite": true, - "newValue": "0x0000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa6", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - }, - { - "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000003" - }, - { - "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", - "isWrite": true, - "newValue": "0x000000000000000000000000def3bca8c80064589e6787477ffa7dd616b5574f", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000003" - }, - { - "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" - }, - { - "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", - "isWrite": true, - "newValue": "0x0000000000000000000000004200000000000000000000000000000000000010", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" - }, - { - "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "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": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "previousValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "reverted": false, - "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" - } - ], - "value": 0 - }, - { - "accessor": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xb7947262", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x00000000000000000000000050eef481cae4250d252ae577a09bf514f224c6c4", - "previousValue": "0x00000000000000000000000050eef481cae4250d252ae577a09bf514f224c6c4", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000003" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x", - "deployedCode": "0x", - "initialized": true, - "kind": "Resume", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", - "isWrite": false, - "newValue": "0x000000000000000000000000b7900b27be8f0e0ff65d1c3a4671e1220437dd2b", - "previousValue": "0x000000000000000000000000b7900b27be8f0e0ff65d1c3a4671e1220437dd2b", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xb7900B27Be8f0E0fF65d1C3A4671e1220437dd2b", - "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": "0x927ede2d", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", - "isWrite": false, - "newValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "previousValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "reverted": false, - "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" - } - ], - "value": 0 - }, - { - "accessor": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xb7947262", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x00000000000000000000000050eef481cae4250d252ae577a09bf514f224c6c4", - "previousValue": "0x00000000000000000000000050eef481cae4250d252ae577a09bf514f224c6c4", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000003" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x", - "deployedCode": "0x", - "initialized": true, - "kind": "Resume", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", - "isWrite": false, - "newValue": "0x000000000000000000000000b7900b27be8f0e0ff65d1c3a4671e1220437dd2b", - "previousValue": "0x000000000000000000000000b7900b27be8f0e0ff65d1c3a4671e1220437dd2b", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xb7900B27Be8f0E0fF65d1C3A4671e1220437dd2b", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x927ede2d", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", - "isWrite": false, - "newValue": "0x000000000000000000000000def3bca8c80064589e6787477ffa7dd616b5574f", - "previousValue": "0x000000000000000000000000def3bca8c80064589e6787477ffa7dd616b5574f", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000003" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x3cb747bf", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", - "isWrite": false, - "newValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "previousValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "reverted": false, - "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" - } - ], - "value": 0 - }, - { - "accessor": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xb7947262", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x00000000000000000000000050eef481cae4250d252ae577a09bf514f224c6c4", - "previousValue": "0x00000000000000000000000050eef481cae4250d252ae577a09bf514f224c6c4", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000003" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x", - "deployedCode": "0x", - "initialized": true, - "kind": "Resume", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", - "isWrite": false, - "newValue": "0x000000000000000000000000b7900b27be8f0e0ff65d1c3a4671e1220437dd2b", - "previousValue": "0x000000000000000000000000b7900b27be8f0e0ff65d1c3a4671e1220437dd2b", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xb7900B27Be8f0E0fF65d1C3A4671e1220437dd2b", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x3cb747bf", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", - "isWrite": false, - "newValue": "0x000000000000000000000000def3bca8c80064589e6787477ffa7dd616b5574f", - "previousValue": "0x000000000000000000000000def3bca8c80064589e6787477ffa7dd616b5574f", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000003" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x7f46ddb2", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", - "isWrite": false, - "newValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "previousValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "reverted": false, - "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" - } - ], - "value": 0 - }, - { - "accessor": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xb7947262", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x00000000000000000000000050eef481cae4250d252ae577a09bf514f224c6c4", - "previousValue": "0x00000000000000000000000050eef481cae4250d252ae577a09bf514f224c6c4", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000003" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x", - "deployedCode": "0x", - "initialized": true, - "kind": "Resume", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", - "isWrite": false, - "newValue": "0x000000000000000000000000b7900b27be8f0e0ff65d1c3a4671e1220437dd2b", - "previousValue": "0x000000000000000000000000b7900b27be8f0e0ff65d1c3a4671e1220437dd2b", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xb7900B27Be8f0E0fF65d1C3A4671e1220437dd2b", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x7f46ddb2", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", - "isWrite": false, - "newValue": "0x0000000000000000000000004200000000000000000000000000000000000010", - "previousValue": "0x0000000000000000000000004200000000000000000000000000000000000010", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xc89701a2", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", - "isWrite": false, - "newValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "previousValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "reverted": false, - "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" - } - ], - "value": 0 - }, - { - "accessor": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xb7947262", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x00000000000000000000000050eef481cae4250d252ae577a09bf514f224c6c4", - "previousValue": "0x00000000000000000000000050eef481cae4250d252ae577a09bf514f224c6c4", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000003" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x", - "deployedCode": "0x", - "initialized": true, - "kind": "Resume", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", - "isWrite": false, - "newValue": "0x000000000000000000000000b7900b27be8f0e0ff65d1c3a4671e1220437dd2b", - "previousValue": "0x000000000000000000000000b7900b27be8f0e0ff65d1c3a4671e1220437dd2b", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xb7900B27Be8f0E0fF65d1C3A4671e1220437dd2b", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xc89701a2", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", - "isWrite": false, - "newValue": "0x0000000000000000000000004200000000000000000000000000000000000010", - "previousValue": "0x0000000000000000000000004200000000000000000000000000000000000010", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" - } - ], - "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": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "previousValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "reverted": false, - "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" - } - ], - "value": 0 - }, - { - "accessor": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xb7947262", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x00000000000000000000000050eef481cae4250d252ae577a09bf514f224c6c4", - "previousValue": "0x00000000000000000000000050eef481cae4250d252ae577a09bf514f224c6c4", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000003" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x", - "deployedCode": "0x", - "initialized": true, - "kind": "Resume", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D", - "isWrite": false, - "newValue": "0x000000000000000000000000b7900b27be8f0e0ff65d1c3a4671e1220437dd2b", - "previousValue": "0x000000000000000000000000b7900b27be8f0e0ff65d1c3a4671e1220437dd2b", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xb7900B27Be8f0E0fF65d1C3A4671e1220437dd2b", - "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": "0x0000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab0351", - "previousValue": "0x0000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab0351", - "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": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x6a76120200000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000000e49623609d000000000000000000000000d31598c909d9c935a9e35ba70d9a3dd47d4d58650000000000000000000000005c4f5e749a61a9503c4aae8a9393e89609a0e80400000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000def3bca8c80064589e6787477ffa7dd616b5574f0000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab0351000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", - "previousValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x6a76120200000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000000e49623609d000000000000000000000000d31598c909d9c935a9e35ba70d9a3dd47d4d58650000000000000000000000005c4f5e749a61a9503c4aae8a9393e89609a0e80400000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000def3bca8c80064589e6787477ffa7dd616b5574f0000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab0351000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000006", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000006", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000006", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000006", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000007", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000006", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0xd1b0d319c6526317dce66989b393dcfb4435c9a65e399a088b63bbf65d7aee32" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c8" - } - ], - "value": 0 - }, - { - "accessor": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x9623609d000000000000000000000000d31598c909d9c935a9e35ba70d9a3dd47d4d58650000000000000000000000005c4f5e749a61a9503c4aae8a9393e89609a0e80400000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000def3bca8c80064589e6787477ffa7dd616b5574f0000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab035100000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x0000000000000000000000007c0c8a15773ed7b50e7c738d1af4c5e3a2b210bd", - "previousValue": "0x0000000000000000000000007c0c8a15773ed7b50e7c738d1af4c5e3a2b210bd", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x9ab6929e7d0104b9744ecf48c9c83f65e34bb9eb80c70a88b6b8885e3bf62b15" - } - ], - "value": 0 - }, - { - "accessor": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "account": "0xD31598c909d9C935a9e35bA70d9a3DD47d4D5865", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x4f1ef2860000000000000000000000005c4f5e749a61a9503c4aae8a9393e89609a0e80400000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000044485cc955000000000000000000000000def3bca8c80064589e6787477ffa7dd616b5574f0000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab035100000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xD31598c909d9C935a9e35bA70d9a3DD47d4D5865", - "isWrite": false, - "newValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "previousValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "reverted": false, - "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" - }, - { - "account": "0xD31598c909d9C935a9e35bA70d9a3DD47d4D5865", - "isWrite": true, - "newValue": "0x0000000000000000000000005c4f5e749a61a9503c4aae8a9393e89609a0e804", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "account": "0x5C4F5e749A61a9503c4AAE8a9393e89609a0e804", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x485cc955000000000000000000000000def3bca8c80064589e6787477ffa7dd616b5574f0000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab0351", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xD31598c909d9C935a9e35bA70d9a3DD47d4D5865", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xD31598c909d9C935a9e35bA70d9a3DD47d4D5865", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xD31598c909d9C935a9e35bA70d9a3DD47d4D5865", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xD31598c909d9C935a9e35bA70d9a3DD47d4D5865", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xD31598c909d9C935a9e35bA70d9a3DD47d4D5865", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xD31598c909d9C935a9e35bA70d9a3DD47d4D5865", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xD31598c909d9C935a9e35bA70d9a3DD47d4D5865", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000032" - }, - { - "account": "0xD31598c909d9C935a9e35bA70d9a3DD47d4D5865", - "isWrite": true, - "newValue": "0x0000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab0351", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000032" - }, - { - "account": "0xD31598c909d9C935a9e35bA70d9a3DD47d4D5865", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xD31598c909d9C935a9e35bA70d9a3DD47d4D5865", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000001" - }, - { - "account": "0xD31598c909d9C935a9e35bA70d9a3DD47d4D5865", - "isWrite": true, - "newValue": "0x000000000000000000000000def3bca8c80064589e6787477ffa7dd616b5574f", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000001" - }, - { - "account": "0xD31598c909d9C935a9e35bA70d9a3DD47d4D5865", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000002" - }, - { - "account": "0xD31598c909d9C935a9e35bA70d9a3DD47d4D5865", - "isWrite": true, - "newValue": "0x0000000000000000000000004200000000000000000000000000000000000014", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000002" - }, - { - "account": "0xD31598c909d9C935a9e35bA70d9a3DD47d4D5865", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xD31598c909d9C935a9e35bA70d9a3DD47d4D5865", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xD31598c909d9C935a9e35bA70d9a3DD47d4D5865", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x54fd4d50", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xD31598c909d9C935a9e35bA70d9a3DD47d4D5865", - "isWrite": false, - "newValue": "0x0000000000000000000000005c4f5e749a61a9503c4aae8a9393e89609a0e804", - "previousValue": "0x0000000000000000000000005c4f5e749a61a9503c4aae8a9393e89609a0e804", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x5C4F5e749A61a9503c4AAE8a9393e89609a0e804", - "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": "0xD31598c909d9C935a9e35bA70d9a3DD47d4D5865", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x7f46ddb2", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xD31598c909d9C935a9e35bA70d9a3DD47d4D5865", - "isWrite": false, - "newValue": "0x0000000000000000000000005c4f5e749a61a9503c4aae8a9393e89609a0e804", - "previousValue": "0x0000000000000000000000005c4f5e749a61a9503c4aae8a9393e89609a0e804", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x5C4F5e749A61a9503c4AAE8a9393e89609a0e804", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x7f46ddb2", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xD31598c909d9C935a9e35bA70d9a3DD47d4D5865", - "isWrite": false, - "newValue": "0x0000000000000000000000004200000000000000000000000000000000000014", - "previousValue": "0x0000000000000000000000004200000000000000000000000000000000000014", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000002" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xD31598c909d9C935a9e35bA70d9a3DD47d4D5865", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xc89701a2", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xD31598c909d9C935a9e35bA70d9a3DD47d4D5865", - "isWrite": false, - "newValue": "0x0000000000000000000000005c4f5e749a61a9503c4aae8a9393e89609a0e804", - "previousValue": "0x0000000000000000000000005c4f5e749a61a9503c4aae8a9393e89609a0e804", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x5C4F5e749A61a9503c4AAE8a9393e89609a0e804", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xc89701a2", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xD31598c909d9C935a9e35bA70d9a3DD47d4D5865", - "isWrite": false, - "newValue": "0x0000000000000000000000004200000000000000000000000000000000000014", - "previousValue": "0x0000000000000000000000004200000000000000000000000000000000000014", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000002" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xD31598c909d9C935a9e35bA70d9a3DD47d4D5865", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x927ede2d", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xD31598c909d9C935a9e35bA70d9a3DD47d4D5865", - "isWrite": false, - "newValue": "0x0000000000000000000000005c4f5e749a61a9503c4aae8a9393e89609a0e804", - "previousValue": "0x0000000000000000000000005c4f5e749a61a9503c4aae8a9393e89609a0e804", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x5C4F5e749A61a9503c4AAE8a9393e89609a0e804", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x927ede2d", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xD31598c909d9C935a9e35bA70d9a3DD47d4D5865", - "isWrite": false, - "newValue": "0x000000000000000000000000def3bca8c80064589e6787477ffa7dd616b5574f", - "previousValue": "0x000000000000000000000000def3bca8c80064589e6787477ffa7dd616b5574f", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000001" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xD31598c909d9C935a9e35bA70d9a3DD47d4D5865", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x3cb747bf", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xD31598c909d9C935a9e35bA70d9a3DD47d4D5865", - "isWrite": false, - "newValue": "0x0000000000000000000000005c4f5e749a61a9503c4aae8a9393e89609a0e804", - "previousValue": "0x0000000000000000000000005c4f5e749a61a9503c4aae8a9393e89609a0e804", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x5C4F5e749A61a9503c4AAE8a9393e89609a0e804", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x3cb747bf", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xD31598c909d9C935a9e35bA70d9a3DD47d4D5865", - "isWrite": false, - "newValue": "0x000000000000000000000000def3bca8c80064589e6787477ffa7dd616b5574f", - "previousValue": "0x000000000000000000000000def3bca8c80064589e6787477ffa7dd616b5574f", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000001" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xD31598c909d9C935a9e35bA70d9a3DD47d4D5865", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x35e80ab3", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xD31598c909d9C935a9e35bA70d9a3DD47d4D5865", - "isWrite": false, - "newValue": "0x0000000000000000000000005c4f5e749a61a9503c4aae8a9393e89609a0e804", - "previousValue": "0x0000000000000000000000005c4f5e749a61a9503c4aae8a9393e89609a0e804", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x5C4F5e749A61a9503c4AAE8a9393e89609a0e804", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x35e80ab3", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xD31598c909d9C935a9e35bA70d9a3DD47d4D5865", - "isWrite": false, - "newValue": "0x0000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab0351", - "previousValue": "0x0000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab0351", - "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": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x6a76120200000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000000c49623609d000000000000000000000000c7b87b2b892ea5c3cff47168881fe168c00377fb0000000000000000000000007c06d3a0a2f45e39e1798afbd9c3330971332a4f00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000024c4d66de800000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", - "previousValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x6a76120200000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000000c49623609d000000000000000000000000c7b87b2b892ea5c3cff47168881fe168c00377fb0000000000000000000000007c06d3a0a2f45e39e1798afbd9c3330971332a4f00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000024c4d66de800000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000007", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000007", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000007", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000007", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000008", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000007", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0xd1b0d319c6526317dce66989b393dcfb4435c9a65e399a088b63bbf65d7aee32" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c8" - } - ], - "value": 0 - }, - { - "accessor": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x9623609d000000000000000000000000c7b87b2b892ea5c3cff47168881fe168c00377fb0000000000000000000000007c06d3a0a2f45e39e1798afbd9c3330971332a4f00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000024c4d66de800000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d00000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x0000000000000000000000007c0c8a15773ed7b50e7c738d1af4c5e3a2b210bd", - "previousValue": "0x0000000000000000000000007c0c8a15773ed7b50e7c738d1af4c5e3a2b210bd", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0xf6cecbacbfeb99e6ab0f02c22fd8a103f8837deb80af03d481ac5bc8d5475f58" - } - ], - "value": 0 - }, - { - "accessor": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "account": "0xc7B87b2b892EA5C3CfF47168881FE168C00377FB", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x4f1ef2860000000000000000000000007c06d3a0a2f45e39e1798afbd9c3330971332a4f00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000024c4d66de800000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d00000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xc7B87b2b892EA5C3CfF47168881FE168C00377FB", - "isWrite": false, - "newValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "previousValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "reverted": false, - "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" - }, - { - "account": "0xc7B87b2b892EA5C3CfF47168881FE168C00377FB", - "isWrite": true, - "newValue": "0x0000000000000000000000007c06d3a0a2f45e39e1798afbd9c3330971332a4f", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "account": "0x7c06d3a0a2f45e39E1798afbd9C3330971332a4F", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xc4d66de800000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "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": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000001" - }, - { - "account": "0xc7B87b2b892EA5C3CfF47168881FE168C00377FB", - "isWrite": true, - "newValue": "0x00000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000001" - }, - { - "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": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xc7B87b2b892EA5C3CfF47168881FE168C00377FB", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x54fd4d50", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xc7B87b2b892EA5C3CfF47168881FE168C00377FB", - "isWrite": false, - "newValue": "0x0000000000000000000000007c06d3a0a2f45e39e1798afbd9c3330971332a4f", - "previousValue": "0x0000000000000000000000007c06d3a0a2f45e39e1798afbd9c3330971332a4f", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x7c06d3a0a2f45e39E1798afbd9C3330971332a4F", - "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": "0xc7B87b2b892EA5C3CfF47168881FE168C00377FB", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xee9a31a2", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xc7B87b2b892EA5C3CfF47168881FE168C00377FB", - "isWrite": false, - "newValue": "0x0000000000000000000000007c06d3a0a2f45e39e1798afbd9c3330971332a4f", - "previousValue": "0x0000000000000000000000007c06d3a0a2f45e39e1798afbd9c3330971332a4f", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x7c06d3a0a2f45e39E1798afbd9C3330971332a4F", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xee9a31a2", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xc7B87b2b892EA5C3CfF47168881FE168C00377FB", - "isWrite": false, - "newValue": "0x00000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d", - "previousValue": "0x00000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000001" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xc7B87b2b892EA5C3CfF47168881FE168C00377FB", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xe78cea92", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xc7B87b2b892EA5C3CfF47168881FE168C00377FB", - "isWrite": false, - "newValue": "0x0000000000000000000000007c06d3a0a2f45e39e1798afbd9c3330971332a4f", - "previousValue": "0x0000000000000000000000007c06d3a0a2f45e39e1798afbd9c3330971332a4f", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x7c06d3a0a2f45e39E1798afbd9C3330971332a4F", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xe78cea92", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xc7B87b2b892EA5C3CfF47168881FE168C00377FB", - "isWrite": false, - "newValue": "0x00000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d", - "previousValue": "0x00000000000000000000000020a42a5a785622c6ba2576b2d6e924aa82bfa11d", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000001" - } - ], - "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": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x6bd9f516000000000000000000000000def3bca8c80064589e6787477ffa7dd616b5574f", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x191cda7b5a8219e0cc3bb6c2b45be830e3ba520f78e119446a476c4147fcc284" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x6a76120200000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000000448d52d4a0000000000000000000000000def3bca8c80064589e6787477ffa7dd616b5574f00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", - "previousValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x6a76120200000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000000448d52d4a0000000000000000000000000def3bca8c80064589e6787477ffa7dd616b5574f00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000008", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000008", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000008", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000008", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000009", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000008", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0xd1b0d319c6526317dce66989b393dcfb4435c9a65e399a088b63bbf65d7aee32" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c8" - } - ], - "value": 0 - }, - { - "accessor": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x8d52d4a0000000000000000000000000def3bca8c80064589e6787477ffa7dd616b5574f0000000000000000000000000000000000000000000000000000000000000002", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x0000000000000000000000007c0c8a15773ed7b50e7c738d1af4c5e3a2b210bd", - "previousValue": "0x0000000000000000000000007c0c8a15773ed7b50e7c738d1af4c5e3a2b210bd", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x191cda7b5a8219e0cc3bb6c2b45be830e3ba520f78e119446a476c4147fcc284" - }, - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000002", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x191cda7b5a8219e0cc3bb6c2b45be830e3ba520f78e119446a476c4147fcc284" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x6bd9f516000000000000000000000000def3bca8c80064589e6787477ffa7dd616b5574f", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000002", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000002", - "reverted": false, - "slot": "0x191cda7b5a8219e0cc3bb6c2b45be830e3ba520f78e119446a476c4147fcc284" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x238181ae000000000000000000000000094e6508ba9d9bf1ce421fff3de06ae56e67901b", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0xa90bdf0e44f0927a7a755fa7e7503fcc3da69ee33c69f36790fa0e0ef2db4745" - }, - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0xa90bdf0e44f0927a7a755fa7e7503fcc3da69ee33c69f36790fa0e0ef2db4745" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x6a76120200000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000084860f7cda000000000000000000000000def3bca8c80064589e6787477ffa7dd616b5574f0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001a4f564d5f4c3143726f7373446f6d61696e4d657373656e6765720000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", - "previousValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x6a76120200000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000084860f7cda000000000000000000000000def3bca8c80064589e6787477ffa7dd616b5574f0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001a4f564d5f4c3143726f7373446f6d61696e4d657373656e6765720000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000009", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000009", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000009", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000009", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": true, - "newValue": "0x000000000000000000000000000000000000000000000000000000000000000a", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000009", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0xd1b0d319c6526317dce66989b393dcfb4435c9a65e399a088b63bbf65d7aee32" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c8" - } - ], - "value": 0 - }, - { - "accessor": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x860f7cda000000000000000000000000def3bca8c80064589e6787477ffa7dd616b5574f0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001a4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x0000000000000000000000007c0c8a15773ed7b50e7c738d1af4c5e3a2b210bd", - "previousValue": "0x0000000000000000000000007c0c8a15773ed7b50e7c738d1af4c5e3a2b210bd", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x89a8cb4d9b6f179480a9e676431122d6ba6a5fb2aa9462528e7e48e497a5c045" - }, - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": true, - "newValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x89a8cb4d9b6f179480a9e676431122d6ba6a5fb2aa9462528e7e48e497a5c045" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x238181ae000000000000000000000000def3bca8c80064589e6787477ffa7dd616b5574f", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", - "previousValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", - "reverted": false, - "slot": "0x89a8cb4d9b6f179480a9e676431122d6ba6a5fb2aa9462528e7e48e497a5c045" - }, - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", - "previousValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", - "reverted": false, - "slot": "0x89a8cb4d9b6f179480a9e676431122d6ba6a5fb2aa9462528e7e48e497a5c045" - }, - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", - "previousValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", - "reverted": false, - "slot": "0x89a8cb4d9b6f179480a9e676431122d6ba6a5fb2aa9462528e7e48e497a5c045" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x6a76120200000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000001049623609d000000000000000000000000def3bca8c80064589e6787477ffa7dd616b5574f000000000000000000000000094e6508ba9d9bf1ce421fff3de06ae56e67901b00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b0000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab03510000000000000000000000001c23a6d89f95ef3148bcda8e242cab145bf9c0e40000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", - "previousValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x6a76120200000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000001049623609d000000000000000000000000def3bca8c80064589e6787477ffa7dd616b5574f000000000000000000000000094e6508ba9d9bf1ce421fff3de06ae56e67901b00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b0000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab03510000000000000000000000001c23a6d89f95ef3148bcda8e242cab145bf9c0e40000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x000000000000000000000000000000000000000000000000000000000000000a", - "previousValue": "0x000000000000000000000000000000000000000000000000000000000000000a", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x000000000000000000000000000000000000000000000000000000000000000a", - "previousValue": "0x000000000000000000000000000000000000000000000000000000000000000a", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": true, - "newValue": "0x000000000000000000000000000000000000000000000000000000000000000b", - "previousValue": "0x000000000000000000000000000000000000000000000000000000000000000a", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0xd1b0d319c6526317dce66989b393dcfb4435c9a65e399a088b63bbf65d7aee32" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c8" - } - ], - "value": 0 - }, - { - "accessor": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x9623609d000000000000000000000000def3bca8c80064589e6787477ffa7dd616b5574f000000000000000000000000094e6508ba9d9bf1ce421fff3de06ae56e67901b00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000064c0c53b8b0000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab03510000000000000000000000001c23a6d89f95ef3148bcda8e242cab145bf9c0e40000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa600000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x0000000000000000000000007c0c8a15773ed7b50e7c738d1af4c5e3a2b210bd", - "previousValue": "0x0000000000000000000000007c0c8a15773ed7b50e7c738d1af4c5e3a2b210bd", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000002", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000002", - "reverted": false, - "slot": "0x191cda7b5a8219e0cc3bb6c2b45be830e3ba520f78e119446a476c4147fcc284" - }, - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x0000000000000000000000007c0c8a15773ed7b50e7c738d1af4c5e3a2b210bd", - "previousValue": "0x0000000000000000000000007c0c8a15773ed7b50e7c738d1af4c5e3a2b210bd", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000002", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000002", - "reverted": false, - "slot": "0x191cda7b5a8219e0cc3bb6c2b45be830e3ba520f78e119446a476c4147fcc284" - }, - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", - "previousValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", - "reverted": false, - "slot": "0x89a8cb4d9b6f179480a9e676431122d6ba6a5fb2aa9462528e7e48e497a5c045" - }, - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", - "previousValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", - "reverted": false, - "slot": "0x89a8cb4d9b6f179480a9e676431122d6ba6a5fb2aa9462528e7e48e497a5c045" - }, - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", - "previousValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", - "reverted": false, - "slot": "0x89a8cb4d9b6f179480a9e676431122d6ba6a5fb2aa9462528e7e48e497a5c045" - }, - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x00000000000000000000000050eef481cae4250d252ae577a09bf514f224c6c4", - "previousValue": "0x00000000000000000000000050eef481cae4250d252ae577a09bf514f224c6c4", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000003" - } - ], - "value": 0 - }, - { - "accessor": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "account": "0x50EEf481cae4250d252Ae577A09bF514f224C6C4", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x", - "deployedCode": "0x", - "initialized": true, - "kind": "Resume", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [], - "value": 0 - }, - { - "accessor": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "account": "0x50EEf481cae4250d252Ae577A09bF514f224C6C4", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x9b2ea4bd0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000094e6508ba9d9bf1ce421fff3de06ae56e67901b000000000000000000000000000000000000000000000000000000000000001a4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x50EEf481cae4250d252Ae577A09bF514f224C6C4", - "isWrite": false, - "newValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "previousValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x50EEf481cae4250d252Ae577A09bF514f224C6C4", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x515216935740e67dfdda5cf8e248ea32b3277787818ab59153061ac875c9385e" - }, - { - "account": "0x50EEf481cae4250d252Ae577A09bF514f224C6C4", - "isWrite": true, - "newValue": "0x000000000000000000000000094e6508ba9d9bf1ce421fff3de06ae56e67901b", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x515216935740e67dfdda5cf8e248ea32b3277787818ab59153061ac875c9385e" - } - ], - "value": 0 - }, - { - "accessor": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xc0c53b8b0000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab03510000000000000000000000001c23a6d89f95ef3148bcda8e242cab145bf9c0e40000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa6", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", - "isWrite": false, - "newValue": "0x00000000000000000000000050eef481cae4250d252ae577a09bf514f224c6c4", - "previousValue": "0x00000000000000000000000050eef481cae4250d252ae577a09bf514f224c6c4", - "reverted": false, - "slot": "0x191cda7b5a8219e0cc3bb6c2b45be830e3ba520f78e119446a476c4147fcc284" - }, - { - "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", - "isWrite": false, - "newValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", - "previousValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", - "reverted": false, - "slot": "0x6822ddba83a78589c753bb747cf4919773ec1d36eeb0bb2a09d64b6d87adda0b" - } - ], - "value": 0 - }, - { - "accessor": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", - "account": "0x50EEf481cae4250d252Ae577A09bF514f224C6C4", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xbf40fac10000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001a4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x50EEf481cae4250d252Ae577A09bF514f224C6C4", - "isWrite": false, - "newValue": "0x000000000000000000000000094e6508ba9d9bf1ce421fff3de06ae56e67901b", - "previousValue": "0x000000000000000000000000094e6508ba9d9bf1ce421fff3de06ae56e67901b", - "reverted": false, - "slot": "0x515216935740e67dfdda5cf8e248ea32b3277787818ab59153061ac875c9385e" - } - ], - "value": 0 - }, - { - "accessor": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "account": "0x094e6508ba9d9bf1ce421fff3dE06aE56e67901b", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xc0c53b8b0000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab03510000000000000000000000001c23a6d89f95ef3148bcda8e242cab145bf9c0e40000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa6", - "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": "0x0000000000000000000000010000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", - "isWrite": false, - "newValue": "0x0000000000000000000000010000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000010000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", - "isWrite": true, - "newValue": "0x0000000000000000000001010000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000010000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x00000000000000000000000000000000000000000000000000000000000000fb" - }, - { - "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", - "isWrite": true, - "newValue": "0x0000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab0351", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x00000000000000000000000000000000000000000000000000000000000000fb" - }, - { - "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x00000000000000000000000000000000000000000000000000000000000000fc" - }, - { - "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", - "isWrite": true, - "newValue": "0x0000000000000000000000001c23a6d89f95ef3148bcda8e242cab145bf9c0e4", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x00000000000000000000000000000000000000000000000000000000000000fc" - }, - { - "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x00000000000000000000000000000000000000000000000000000000000000fd" - }, - { - "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", - "isWrite": true, - "newValue": "0x0000000000000000000000000c8b5822b6e02cda722174f19a1439a7495a3fa6", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x00000000000000000000000000000000000000000000000000000000000000fd" - }, - { - "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", - "isWrite": false, - "newValue": "0x0000000000000000000001010000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000001010000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x00000000000000000000000000000000000000000000000000000000000000cc" - }, - { - "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x00000000000000000000000000000000000000000000000000000000000000cc" - }, - { - "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", - "isWrite": true, - "newValue": "0x000000000000000000000000000000000000000000000000000000000000dead", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x00000000000000000000000000000000000000000000000000000000000000cc" - }, - { - "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x00000000000000000000000000000000000000000000000000000000000000cf" - }, - { - "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", - "isWrite": true, - "newValue": "0x0000000000000000000000004200000000000000000000000000000000000007", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x00000000000000000000000000000000000000000000000000000000000000cf" - }, - { - "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", - "isWrite": false, - "newValue": "0x0000000000000000000001010000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000001010000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", - "isWrite": true, - "newValue": "0x0000000000000000000000010000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000001010000000000000000000000000000000000000000", - "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": "0x00000000000000000000000050eef481cae4250d252ae577a09bf514f224c6c4", - "previousValue": "0x00000000000000000000000050eef481cae4250d252ae577a09bf514f224c6c4", - "reverted": false, - "slot": "0x191cda7b5a8219e0cc3bb6c2b45be830e3ba520f78e119446a476c4147fcc284" - }, - { - "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", - "isWrite": false, - "newValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", - "previousValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", - "reverted": false, - "slot": "0x6822ddba83a78589c753bb747cf4919773ec1d36eeb0bb2a09d64b6d87adda0b" - } - ], - "value": 0 - }, - { - "accessor": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", - "account": "0x50EEf481cae4250d252Ae577A09bF514f224C6C4", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xbf40fac10000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001a4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x50EEf481cae4250d252Ae577A09bF514f224C6C4", - "isWrite": false, - "newValue": "0x000000000000000000000000094e6508ba9d9bf1ce421fff3de06ae56e67901b", - "previousValue": "0x000000000000000000000000094e6508ba9d9bf1ce421fff3de06ae56e67901b", - "reverted": false, - "slot": "0x515216935740e67dfdda5cf8e248ea32b3277787818ab59153061ac875c9385e" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x094e6508ba9d9bf1ce421fff3dE06aE56e67901b", - "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": "0x9fce812c", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", - "isWrite": false, - "newValue": "0x00000000000000000000000050eef481cae4250d252ae577a09bf514f224c6c4", - "previousValue": "0x00000000000000000000000050eef481cae4250d252ae577a09bf514f224c6c4", - "reverted": false, - "slot": "0x191cda7b5a8219e0cc3bb6c2b45be830e3ba520f78e119446a476c4147fcc284" - }, - { - "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", - "isWrite": false, - "newValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", - "previousValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", - "reverted": false, - "slot": "0x6822ddba83a78589c753bb747cf4919773ec1d36eeb0bb2a09d64b6d87adda0b" - } - ], - "value": 0 - }, - { - "accessor": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", - "account": "0x50EEf481cae4250d252Ae577A09bF514f224C6C4", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xbf40fac10000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001a4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x50EEf481cae4250d252Ae577A09bF514f224C6C4", - "isWrite": false, - "newValue": "0x000000000000000000000000094e6508ba9d9bf1ce421fff3de06ae56e67901b", - "previousValue": "0x000000000000000000000000094e6508ba9d9bf1ce421fff3de06ae56e67901b", - "reverted": false, - "slot": "0x515216935740e67dfdda5cf8e248ea32b3277787818ab59153061ac875c9385e" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x094e6508ba9d9bf1ce421fff3dE06aE56e67901b", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x9fce812c", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", - "isWrite": false, - "newValue": "0x0000000000000000000000004200000000000000000000000000000000000007", - "previousValue": "0x0000000000000000000000004200000000000000000000000000000000000007", - "reverted": false, - "slot": "0x00000000000000000000000000000000000000000000000000000000000000cf" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xdb505d80", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", - "isWrite": false, - "newValue": "0x00000000000000000000000050eef481cae4250d252ae577a09bf514f224c6c4", - "previousValue": "0x00000000000000000000000050eef481cae4250d252ae577a09bf514f224c6c4", - "reverted": false, - "slot": "0x191cda7b5a8219e0cc3bb6c2b45be830e3ba520f78e119446a476c4147fcc284" - }, - { - "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", - "isWrite": false, - "newValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", - "previousValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", - "reverted": false, - "slot": "0x6822ddba83a78589c753bb747cf4919773ec1d36eeb0bb2a09d64b6d87adda0b" - } - ], - "value": 0 - }, - { - "accessor": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", - "account": "0x50EEf481cae4250d252Ae577A09bF514f224C6C4", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xbf40fac10000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001a4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x50EEf481cae4250d252Ae577A09bF514f224C6C4", - "isWrite": false, - "newValue": "0x000000000000000000000000094e6508ba9d9bf1ce421fff3de06ae56e67901b", - "previousValue": "0x000000000000000000000000094e6508ba9d9bf1ce421fff3de06ae56e67901b", - "reverted": false, - "slot": "0x515216935740e67dfdda5cf8e248ea32b3277787818ab59153061ac875c9385e" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x094e6508ba9d9bf1ce421fff3dE06aE56e67901b", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xdb505d80", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", - "isWrite": false, - "newValue": "0x0000000000000000000000004200000000000000000000000000000000000007", - "previousValue": "0x0000000000000000000000004200000000000000000000000000000000000007", - "reverted": false, - "slot": "0x00000000000000000000000000000000000000000000000000000000000000cf" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x0ff754ea", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", - "isWrite": false, - "newValue": "0x00000000000000000000000050eef481cae4250d252ae577a09bf514f224c6c4", - "previousValue": "0x00000000000000000000000050eef481cae4250d252ae577a09bf514f224c6c4", - "reverted": false, - "slot": "0x191cda7b5a8219e0cc3bb6c2b45be830e3ba520f78e119446a476c4147fcc284" - }, - { - "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", - "isWrite": false, - "newValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", - "previousValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", - "reverted": false, - "slot": "0x6822ddba83a78589c753bb747cf4919773ec1d36eeb0bb2a09d64b6d87adda0b" - } - ], - "value": 0 - }, - { - "accessor": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", - "account": "0x50EEf481cae4250d252Ae577A09bF514f224C6C4", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xbf40fac10000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001a4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x50EEf481cae4250d252Ae577A09bF514f224C6C4", - "isWrite": false, - "newValue": "0x000000000000000000000000094e6508ba9d9bf1ce421fff3de06ae56e67901b", - "previousValue": "0x000000000000000000000000094e6508ba9d9bf1ce421fff3de06ae56e67901b", - "reverted": false, - "slot": "0x515216935740e67dfdda5cf8e248ea32b3277787818ab59153061ac875c9385e" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x094e6508ba9d9bf1ce421fff3dE06aE56e67901b", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x0ff754ea", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", - "isWrite": false, - "newValue": "0x0000000000000000000000001c23a6d89f95ef3148bcda8e242cab145bf9c0e4", - "previousValue": "0x0000000000000000000000001c23a6d89f95ef3148bcda8e242cab145bf9c0e4", - "reverted": false, - "slot": "0x00000000000000000000000000000000000000000000000000000000000000fc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x6425666b", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", - "isWrite": false, - "newValue": "0x00000000000000000000000050eef481cae4250d252ae577a09bf514f224c6c4", - "previousValue": "0x00000000000000000000000050eef481cae4250d252ae577a09bf514f224c6c4", - "reverted": false, - "slot": "0x191cda7b5a8219e0cc3bb6c2b45be830e3ba520f78e119446a476c4147fcc284" - }, - { - "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", - "isWrite": false, - "newValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", - "previousValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", - "reverted": false, - "slot": "0x6822ddba83a78589c753bb747cf4919773ec1d36eeb0bb2a09d64b6d87adda0b" - } - ], - "value": 0 - }, - { - "accessor": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", - "account": "0x50EEf481cae4250d252Ae577A09bF514f224C6C4", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xbf40fac10000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001a4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x50EEf481cae4250d252Ae577A09bF514f224C6C4", - "isWrite": false, - "newValue": "0x000000000000000000000000094e6508ba9d9bf1ce421fff3de06ae56e67901b", - "previousValue": "0x000000000000000000000000094e6508ba9d9bf1ce421fff3de06ae56e67901b", - "reverted": false, - "slot": "0x515216935740e67dfdda5cf8e248ea32b3277787818ab59153061ac875c9385e" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x094e6508ba9d9bf1ce421fff3dE06aE56e67901b", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x6425666b", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", - "isWrite": false, - "newValue": "0x0000000000000000000000001c23a6d89f95ef3148bcda8e242cab145bf9c0e4", - "previousValue": "0x0000000000000000000000001c23a6d89f95ef3148bcda8e242cab145bf9c0e4", - "reverted": false, - "slot": "0x00000000000000000000000000000000000000000000000000000000000000fc" - } - ], - "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": "0x00000000000000000000000050eef481cae4250d252ae577a09bf514f224c6c4", - "previousValue": "0x00000000000000000000000050eef481cae4250d252ae577a09bf514f224c6c4", - "reverted": false, - "slot": "0x191cda7b5a8219e0cc3bb6c2b45be830e3ba520f78e119446a476c4147fcc284" - }, - { - "account": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", - "isWrite": false, - "newValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", - "previousValue": "0x4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000034", - "reverted": false, - "slot": "0x6822ddba83a78589c753bb747cf4919773ec1d36eeb0bb2a09d64b6d87adda0b" - } - ], - "value": 0 - }, - { - "accessor": "0xDeF3bca8c80064589E6787477FFa7Dd616B5574F", - "account": "0x50EEf481cae4250d252Ae577A09bF514f224C6C4", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xbf40fac10000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001a4f564d5f4c3143726f7373446f6d61696e4d657373656e676572000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x50EEf481cae4250d252Ae577A09bF514f224C6C4", - "isWrite": false, - "newValue": "0x000000000000000000000000094e6508ba9d9bf1ce421fff3de06ae56e67901b", - "previousValue": "0x000000000000000000000000094e6508ba9d9bf1ce421fff3de06ae56e67901b", - "reverted": false, - "slot": "0x515216935740e67dfdda5cf8e248ea32b3277787818ab59153061ac875c9385e" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x094e6508ba9d9bf1ce421fff3dE06aE56e67901b", - "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": "0x0000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab0351", - "previousValue": "0x0000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab0351", - "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": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x276b657a", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000006", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000006", - "reverted": false, - "slot": "0x000000000000000000000000000000000000000000000000000000000000001d" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x93991af3", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000002", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000002", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000012" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x5d4546a0", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x000000000000000000000000000000000000000000000000000000000000001f" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x98f34df5", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x000000000000000000000000000000000000000000000000000000000000001e" - }, - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x000000000000000000000000000000000000000000000000000000000000001e" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x241e2d7e", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8", - "previousValue": "0x00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000020" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x08cb822d", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b63", - "previousValue": "0x0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b63", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000021" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xce5db8d6", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000024", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000024", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000022" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x6a76120200000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000001849623609d00000000000000000000000039af23e00f1e662025aa01b0ceda19542b78df9900000000000000000000000019652082f846171168daf378c4fd3ee85a0d4a60000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000e41c89c97d000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c80000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b630000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", - "previousValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x6a76120200000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000001849623609d00000000000000000000000039af23e00f1e662025aa01b0ceda19542b78df9900000000000000000000000019652082f846171168daf378c4fd3ee85a0d4a60000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000e41c89c97d000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c80000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b630000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x000000000000000000000000000000000000000000000000000000000000000b", - "previousValue": "0x000000000000000000000000000000000000000000000000000000000000000b", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x000000000000000000000000000000000000000000000000000000000000000b", - "previousValue": "0x000000000000000000000000000000000000000000000000000000000000000b", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": true, - "newValue": "0x000000000000000000000000000000000000000000000000000000000000000c", - "previousValue": "0x000000000000000000000000000000000000000000000000000000000000000b", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0xd1b0d319c6526317dce66989b393dcfb4435c9a65e399a088b63bbf65d7aee32" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c8" - } - ], - "value": 0 - }, - { - "accessor": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x9623609d00000000000000000000000039af23e00f1e662025aa01b0ceda19542b78df9900000000000000000000000019652082f846171168daf378c4fd3ee85a0d4a60000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000e41c89c97d000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c80000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b63000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x0000000000000000000000007c0c8a15773ed7b50e7c738d1af4c5e3a2b210bd", - "previousValue": "0x0000000000000000000000007c0c8a15773ed7b50e7c738d1af4c5e3a2b210bd", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x134d4d69ca1de3e4a1fde55b9ed577a7c39fd3329d50f2f437a3bff291bb9473" - } - ], - "value": 0 - }, - { - "accessor": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x4f1ef28600000000000000000000000019652082f846171168daf378c4fd3ee85a0d4a60000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000e41c89c97d000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c80000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b63000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "isWrite": false, - "newValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "previousValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "reverted": false, - "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" - }, - { - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "isWrite": true, - "newValue": "0x00000000000000000000000019652082f846171168daf378c4fd3ee85a0d4a60", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x1c89c97d000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c80000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b630000000000000000000000000000000000000000000000000000000000000024", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000006", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" - }, - { - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000002", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" - }, - { - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000001" - }, - { - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000002" - }, - { - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000007" - }, - { - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "isWrite": true, - "newValue": "0x00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000007" - }, - { - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000006" - }, - { - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "isWrite": true, - "newValue": "0x0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b63", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000006" - }, - { - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000024", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000008" - }, - { - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x54fd4d50", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "isWrite": false, - "newValue": "0x00000000000000000000000019652082f846171168daf378c4fd3ee85a0d4a60", - "previousValue": "0x00000000000000000000000019652082f846171168daf378c4fd3ee85a0d4a60", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", - "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": "0x98f34df5", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x000000000000000000000000000000000000000000000000000000000000001e" - }, - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x000000000000000000000000000000000000000000000000000000000000001e" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x276b657a", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000006", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000006", - "reverted": false, - "slot": "0x000000000000000000000000000000000000000000000000000000000000001d" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x529933df", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "isWrite": false, - "newValue": "0x00000000000000000000000019652082f846171168daf378c4fd3ee85a0d4a60", - "previousValue": "0x00000000000000000000000019652082f846171168daf378c4fd3ee85a0d4a60", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x529933df", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000006", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000006", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x276b657a", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000006", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000006", - "reverted": false, - "slot": "0x000000000000000000000000000000000000000000000000000000000000001d" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xe1a41bcf", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "isWrite": false, - "newValue": "0x00000000000000000000000019652082f846171168daf378c4fd3ee85a0d4a60", - "previousValue": "0x00000000000000000000000019652082f846171168daf378c4fd3ee85a0d4a60", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xe1a41bcf", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000006", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000006", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x93991af3", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000002", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000002", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000012" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x002134cc", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "isWrite": false, - "newValue": "0x00000000000000000000000019652082f846171168daf378c4fd3ee85a0d4a60", - "previousValue": "0x00000000000000000000000019652082f846171168daf378c4fd3ee85a0d4a60", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x002134cc", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000002", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000002", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x93991af3", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000002", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000002", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000012" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x93991af3", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "isWrite": false, - "newValue": "0x00000000000000000000000019652082f846171168daf378c4fd3ee85a0d4a60", - "previousValue": "0x00000000000000000000000019652082f846171168daf378c4fd3ee85a0d4a60", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x93991af3", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000002", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000002", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x241e2d7e", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8", - "previousValue": "0x00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000020" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xbffa7f0f", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "isWrite": false, - "newValue": "0x00000000000000000000000019652082f846171168daf378c4fd3ee85a0d4a60", - "previousValue": "0x00000000000000000000000019652082f846171168daf378c4fd3ee85a0d4a60", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xbffa7f0f", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "isWrite": false, - "newValue": "0x00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8", - "previousValue": "0x00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000007" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x241e2d7e", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8", - "previousValue": "0x00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000020" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xa8e4fb90", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "isWrite": false, - "newValue": "0x00000000000000000000000019652082f846171168daf378c4fd3ee85a0d4a60", - "previousValue": "0x00000000000000000000000019652082f846171168daf378c4fd3ee85a0d4a60", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xa8e4fb90", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "isWrite": false, - "newValue": "0x00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8", - "previousValue": "0x00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000007" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x08cb822d", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b63", - "previousValue": "0x0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b63", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000021" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x6b4d98dd", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "isWrite": false, - "newValue": "0x00000000000000000000000019652082f846171168daf378c4fd3ee85a0d4a60", - "previousValue": "0x00000000000000000000000019652082f846171168daf378c4fd3ee85a0d4a60", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x6b4d98dd", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "isWrite": false, - "newValue": "0x0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b63", - "previousValue": "0x0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b63", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000006" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x08cb822d", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b63", - "previousValue": "0x0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b63", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000021" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x534db0e2", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "isWrite": false, - "newValue": "0x00000000000000000000000019652082f846171168daf378c4fd3ee85a0d4a60", - "previousValue": "0x00000000000000000000000019652082f846171168daf378c4fd3ee85a0d4a60", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x534db0e2", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "isWrite": false, - "newValue": "0x0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b63", - "previousValue": "0x0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b63", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000006" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xce5db8d6", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000024", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000024", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000022" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xf4daa291", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "isWrite": false, - "newValue": "0x00000000000000000000000019652082f846171168daf378c4fd3ee85a0d4a60", - "previousValue": "0x00000000000000000000000019652082f846171168daf378c4fd3ee85a0d4a60", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xf4daa291", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000024", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000024", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000008" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xce5db8d6", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000024", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000024", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000022" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xce5db8d6", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "isWrite": false, - "newValue": "0x00000000000000000000000019652082f846171168daf378c4fd3ee85a0d4a60", - "previousValue": "0x00000000000000000000000019652082f846171168daf378c4fd3ee85a0d4a60", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xce5db8d6", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000024", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000024", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000008" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x5d4546a0", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x000000000000000000000000000000000000000000000000000000000000001f" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x70872aa5", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "isWrite": false, - "newValue": "0x00000000000000000000000019652082f846171168daf378c4fd3ee85a0d4a60", - "previousValue": "0x00000000000000000000000019652082f846171168daf378c4fd3ee85a0d4a60", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x70872aa5", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000001" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x88786272", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "isWrite": false, - "newValue": "0x00000000000000000000000019652082f846171168daf378c4fd3ee85a0d4a60", - "previousValue": "0x00000000000000000000000019652082f846171168daf378c4fd3ee85a0d4a60", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x19652082F846171168Daf378C4fD3ee85a0D4A60", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x88786272", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x39Af23E00F1e662025aA01b0cEdA19542B78DF99", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "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": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x6a76120200000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000000c49623609d0000000000000000000000005207cfa0166e8de0fcdfd78b4d17b68587be306d00000000000000000000000020b168142354cee65a32f6d8cf3033e59229976500000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000024c4d66de80000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", - "previousValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x6a76120200000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000000c49623609d0000000000000000000000005207cfa0166e8de0fcdfd78b4d17b68587be306d00000000000000000000000020b168142354cee65a32f6d8cf3033e59229976500000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000024c4d66de80000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x000000000000000000000000000000000000000000000000000000000000000c", - "previousValue": "0x000000000000000000000000000000000000000000000000000000000000000c", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x000000000000000000000000000000000000000000000000000000000000000c", - "previousValue": "0x000000000000000000000000000000000000000000000000000000000000000c", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": true, - "newValue": "0x000000000000000000000000000000000000000000000000000000000000000d", - "previousValue": "0x000000000000000000000000000000000000000000000000000000000000000c", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0xd1b0d319c6526317dce66989b393dcfb4435c9a65e399a088b63bbf65d7aee32" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c8" - } - ], - "value": 0 - }, - { - "accessor": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x9623609d0000000000000000000000005207cfa0166e8de0fcdfd78b4d17b68587be306d00000000000000000000000020b168142354cee65a32f6d8cf3033e59229976500000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000024c4d66de80000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x0000000000000000000000007c0c8a15773ed7b50e7c738d1af4c5e3a2b210bd", - "previousValue": "0x0000000000000000000000007c0c8a15773ed7b50e7c738d1af4c5e3a2b210bd", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x67ba7d8bdda390f76c7887f0749c8ddd97a5488c0685a6600f6146d45a37e9e3" - } - ], - "value": 0 - }, - { - "accessor": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "account": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x4f1ef28600000000000000000000000020b168142354cee65a32f6d8cf3033e59229976500000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000024c4d66de80000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "isWrite": false, - "newValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "previousValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "reverted": false, - "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" - }, - { - "account": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "isWrite": true, - "newValue": "0x00000000000000000000000020b168142354cee65a32f6d8cf3033e592299765", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "account": "0x20B168142354Cee65a32f6D8cf3033E592299765", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xc4d66de80000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - }, - { - "account": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "isWrite": true, - "newValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - }, - { - "account": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "isWrite": false, - "newValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "previousValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - }, - { - "account": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "isWrite": true, - "newValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", - "previousValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - }, - { - "account": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x54fd4d50", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "isWrite": false, - "newValue": "0x00000000000000000000000020b168142354cee65a32f6d8cf3033e592299765", - "previousValue": "0x00000000000000000000000020b168142354cee65a32f6d8cf3033e592299765", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x20B168142354Cee65a32f6D8cf3033E592299765", - "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": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x8da5cb5b", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "isWrite": false, - "newValue": "0x00000000000000000000000020b168142354cee65a32f6d8cf3033e592299765", - "previousValue": "0x00000000000000000000000020b168142354cee65a32f6d8cf3033e592299765", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x20B168142354Cee65a32f6D8cf3033E592299765", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x8da5cb5b", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "isWrite": false, - "newValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", - "previousValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - } - ], - "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": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x6a76120200000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000000e49623609d000000000000000000000000ef179756ea6525afade217ca5ab0b1b5cfe0fd920000000000000000000000002a6347edd3c7813cde46dd7ea61ff1cf2290bc0500000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc9550000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f380000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab0351000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", - "previousValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x6a76120200000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000000e49623609d000000000000000000000000ef179756ea6525afade217ca5ab0b1b5cfe0fd920000000000000000000000002a6347edd3c7813cde46dd7ea61ff1cf2290bc0500000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc9550000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f380000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab0351000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x000000000000000000000000000000000000000000000000000000000000000d", - "previousValue": "0x000000000000000000000000000000000000000000000000000000000000000d", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x000000000000000000000000000000000000000000000000000000000000000d", - "previousValue": "0x000000000000000000000000000000000000000000000000000000000000000d", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": true, - "newValue": "0x000000000000000000000000000000000000000000000000000000000000000e", - "previousValue": "0x000000000000000000000000000000000000000000000000000000000000000d", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0xd1b0d319c6526317dce66989b393dcfb4435c9a65e399a088b63bbf65d7aee32" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c8" - } - ], - "value": 0 - }, - { - "accessor": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x9623609d000000000000000000000000ef179756ea6525afade217ca5ab0b1b5cfe0fd920000000000000000000000002a6347edd3c7813cde46dd7ea61ff1cf2290bc0500000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc9550000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f380000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab035100000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x0000000000000000000000007c0c8a15773ed7b50e7c738d1af4c5e3a2b210bd", - "previousValue": "0x0000000000000000000000007c0c8a15773ed7b50e7c738d1af4c5e3a2b210bd", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x6c22ba077ba2894f0240d58c3ef000efde161f39c3d967610259aa4c063ae31b" - } - ], - "value": 0 - }, - { - "accessor": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "account": "0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x4f1ef2860000000000000000000000002a6347edd3c7813cde46dd7ea61ff1cf2290bc0500000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000044485cc9550000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f380000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab035100000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92", - "isWrite": false, - "newValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "previousValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "reverted": false, - "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" - }, - { - "account": "0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92", - "isWrite": true, - "newValue": "0x0000000000000000000000002a6347edd3c7813cde46dd7ea61ff1cf2290bc05", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "account": "0x2A6347EDD3C7813CDE46DD7eA61FF1Cf2290BC05", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x485cc9550000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f380000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab0351", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - }, - { - "account": "0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92", - "isWrite": true, - "newValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - }, - { - "account": "0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92", - "isWrite": false, - "newValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "previousValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - }, - { - "account": "0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92", - "isWrite": true, - "newValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", - "previousValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - }, - { - "account": "0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000068" - }, - { - "account": "0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92", - "isWrite": true, - "newValue": "0x0000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab0351", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000068" - }, - { - "account": "0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x54fd4d50", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92", - "isWrite": false, - "newValue": "0x0000000000000000000000002a6347edd3c7813cde46dd7ea61ff1cf2290bc05", - "previousValue": "0x0000000000000000000000002a6347edd3c7813cde46dd7ea61ff1cf2290bc05", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x2A6347EDD3C7813CDE46DD7eA61FF1Cf2290BC05", - "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": "0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x8da5cb5b", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92", - "isWrite": false, - "newValue": "0x0000000000000000000000002a6347edd3c7813cde46dd7ea61ff1cf2290bc05", - "previousValue": "0x0000000000000000000000002a6347edd3c7813cde46dd7ea61ff1cf2290bc05", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x2A6347EDD3C7813CDE46DD7eA61FF1Cf2290BC05", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x8da5cb5b", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92", - "isWrite": false, - "newValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", - "previousValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x7a07653f", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000093a80", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000093a80", - "reverted": false, - "slot": "0x000000000000000000000000000000000000000000000000000000000000003b" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x6a42b8f8", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92", - "isWrite": false, - "newValue": "0x0000000000000000000000002a6347edd3c7813cde46dd7ea61ff1cf2290bc05", - "previousValue": "0x0000000000000000000000002a6347edd3c7813cde46dd7ea61ff1cf2290bc05", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x2A6347EDD3C7813CDE46DD7eA61FF1Cf2290BC05", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x6a42b8f8", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x79502c55", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92", - "isWrite": false, - "newValue": "0x0000000000000000000000002a6347edd3c7813cde46dd7ea61ff1cf2290bc05", - "previousValue": "0x0000000000000000000000002a6347edd3c7813cde46dd7ea61ff1cf2290bc05", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x2A6347EDD3C7813CDE46DD7eA61FF1Cf2290BC05", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x79502c55", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92", - "isWrite": false, - "newValue": "0x0000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab0351", - "previousValue": "0x0000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab0351", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000068" - } - ], - "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": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x6a76120200000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000000e49623609d000000000000000000000000d6eaf4c146261653ee059077b78ed088add543090000000000000000000000002a6347edd3c7813cde46dd7ea61ff1cf2290bc0500000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc9550000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f380000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab0351000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", - "previousValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x6a76120200000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000000e49623609d000000000000000000000000d6eaf4c146261653ee059077b78ed088add543090000000000000000000000002a6347edd3c7813cde46dd7ea61ff1cf2290bc0500000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc9550000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f380000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab0351000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x000000000000000000000000000000000000000000000000000000000000000e", - "previousValue": "0x000000000000000000000000000000000000000000000000000000000000000e", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x000000000000000000000000000000000000000000000000000000000000000e", - "previousValue": "0x000000000000000000000000000000000000000000000000000000000000000e", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": true, - "newValue": "0x000000000000000000000000000000000000000000000000000000000000000f", - "previousValue": "0x000000000000000000000000000000000000000000000000000000000000000e", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0xd1b0d319c6526317dce66989b393dcfb4435c9a65e399a088b63bbf65d7aee32" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c8" - } - ], - "value": 0 - }, - { - "accessor": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x9623609d000000000000000000000000d6eaf4c146261653ee059077b78ed088add543090000000000000000000000002a6347edd3c7813cde46dd7ea61ff1cf2290bc0500000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000044485cc9550000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f380000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab035100000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x0000000000000000000000007c0c8a15773ed7b50e7c738d1af4c5e3a2b210bd", - "previousValue": "0x0000000000000000000000007c0c8a15773ed7b50e7c738d1af4c5e3a2b210bd", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0xf08d105018e9af96f1d26510b09691f8b2194940cdd630ffcaf9fa37fb25c6a6" - } - ], - "value": 0 - }, - { - "accessor": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "account": "0xd6EAF4c146261653EE059077B78ED088Add54309", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x4f1ef2860000000000000000000000002a6347edd3c7813cde46dd7ea61ff1cf2290bc0500000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000044485cc9550000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f380000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab035100000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xd6EAF4c146261653EE059077B78ED088Add54309", - "isWrite": false, - "newValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "previousValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "reverted": false, - "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" - }, - { - "account": "0xd6EAF4c146261653EE059077B78ED088Add54309", - "isWrite": true, - "newValue": "0x0000000000000000000000002a6347edd3c7813cde46dd7ea61ff1cf2290bc05", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "account": "0x2A6347EDD3C7813CDE46DD7eA61FF1Cf2290BC05", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x485cc9550000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f380000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab0351", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xd6EAF4c146261653EE059077B78ED088Add54309", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xd6EAF4c146261653EE059077B78ED088Add54309", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xd6EAF4c146261653EE059077B78ED088Add54309", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xd6EAF4c146261653EE059077B78ED088Add54309", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xd6EAF4c146261653EE059077B78ED088Add54309", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xd6EAF4c146261653EE059077B78ED088Add54309", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xd6EAF4c146261653EE059077B78ED088Add54309", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xd6EAF4c146261653EE059077B78ED088Add54309", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xd6EAF4c146261653EE059077B78ED088Add54309", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - }, - { - "account": "0xd6EAF4c146261653EE059077B78ED088Add54309", - "isWrite": true, - "newValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - }, - { - "account": "0xd6EAF4c146261653EE059077B78ED088Add54309", - "isWrite": false, - "newValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "previousValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - }, - { - "account": "0xd6EAF4c146261653EE059077B78ED088Add54309", - "isWrite": true, - "newValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", - "previousValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - }, - { - "account": "0xd6EAF4c146261653EE059077B78ED088Add54309", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000068" - }, - { - "account": "0xd6EAF4c146261653EE059077B78ED088Add54309", - "isWrite": true, - "newValue": "0x0000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab0351", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000068" - }, - { - "account": "0xd6EAF4c146261653EE059077B78ED088Add54309", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0xd6EAF4c146261653EE059077B78ED088Add54309", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xd6EAF4c146261653EE059077B78ED088Add54309", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x54fd4d50", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xd6EAF4c146261653EE059077B78ED088Add54309", - "isWrite": false, - "newValue": "0x0000000000000000000000002a6347edd3c7813cde46dd7ea61ff1cf2290bc05", - "previousValue": "0x0000000000000000000000002a6347edd3c7813cde46dd7ea61ff1cf2290bc05", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x2A6347EDD3C7813CDE46DD7eA61FF1Cf2290BC05", - "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": "0xd6EAF4c146261653EE059077B78ED088Add54309", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x8da5cb5b", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xd6EAF4c146261653EE059077B78ED088Add54309", - "isWrite": false, - "newValue": "0x0000000000000000000000002a6347edd3c7813cde46dd7ea61ff1cf2290bc05", - "previousValue": "0x0000000000000000000000002a6347edd3c7813cde46dd7ea61ff1cf2290bc05", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x2A6347EDD3C7813CDE46DD7eA61FF1Cf2290BC05", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x8da5cb5b", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xd6EAF4c146261653EE059077B78ED088Add54309", - "isWrite": false, - "newValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", - "previousValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x7a07653f", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000093a80", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000093a80", - "reverted": false, - "slot": "0x000000000000000000000000000000000000000000000000000000000000003b" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xd6EAF4c146261653EE059077B78ED088Add54309", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x6a42b8f8", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xd6EAF4c146261653EE059077B78ED088Add54309", - "isWrite": false, - "newValue": "0x0000000000000000000000002a6347edd3c7813cde46dd7ea61ff1cf2290bc05", - "previousValue": "0x0000000000000000000000002a6347edd3c7813cde46dd7ea61ff1cf2290bc05", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x2A6347EDD3C7813CDE46DD7eA61FF1Cf2290BC05", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x6a42b8f8", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xd6EAF4c146261653EE059077B78ED088Add54309", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x79502c55", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xd6EAF4c146261653EE059077B78ED088Add54309", - "isWrite": false, - "newValue": "0x0000000000000000000000002a6347edd3c7813cde46dd7ea61ff1cf2290bc05", - "previousValue": "0x0000000000000000000000002a6347edd3c7813cde46dd7ea61ff1cf2290bc05", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x2A6347EDD3C7813CDE46DD7eA61FF1Cf2290BC05", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x79502c55", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xd6EAF4c146261653EE059077B78ED088Add54309", - "isWrite": false, - "newValue": "0x0000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab0351", - "previousValue": "0x0000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab0351", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000068" - } - ], - "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": "0xb7033188", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef", - "previousValue": "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000036" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xf0e5df46", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000035" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xb7033188", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef", - "previousValue": "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000036" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xf0e5df46", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000035" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xb7033188", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef", - "previousValue": "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000036" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xf0e5df46", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000035" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xb7033188", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef", - "previousValue": "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000036" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xf0e5df46", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000035" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xb7033188", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef", - "previousValue": "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000036" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xf0e5df46", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000035" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x6a76120200000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000046000000000000000000000000000000000000000000000000000000000000002e49623609d000000000000000000000000970670459734a83899773a0fd45941b5afc1200e00000000000000000000000063b71b96756c693f7065345fecd9b7843b3e7c57000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000002445e05fbd000000000000000000000000000000000000000000000000000000000000000400000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab035100000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000000deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fedeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", - "previousValue": "0x000000000000000000000000bb2180ebd78ce97360503434ed37fcf4a1df61c3", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x6a76120200000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000046000000000000000000000000000000000000000000000000000000000000002e49623609d000000000000000000000000970670459734a83899773a0fd45941b5afc1200e00000000000000000000000063b71b96756c693f7065345fecd9b7843b3e7c57000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000002445e05fbd000000000000000000000000000000000000000000000000000000000000000400000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab035100000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000000deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fedeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f3800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x000000000000000000000000000000000000000000000000000000000000000f", - "previousValue": "0x000000000000000000000000000000000000000000000000000000000000000f", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x000000000000000000000000000000000000000000000000000000000000000f", - "previousValue": "0x000000000000000000000000000000000000000000000000000000000000000f", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000010", - "previousValue": "0x000000000000000000000000000000000000000000000000000000000000000f", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000005" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000004" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0xd1b0d319c6526317dce66989b393dcfb4435c9a65e399a088b63bbf65d7aee32" - }, - { - "account": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c8" - } - ], - "value": 0 - }, - { - "accessor": "0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD", - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x9623609d000000000000000000000000970670459734a83899773a0fd45941b5afc1200e00000000000000000000000063b71b96756c693f7065345fecd9b7843b3e7c57000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000002445e05fbd000000000000000000000000000000000000000000000000000000000000000400000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab035100000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000000deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fedeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x0000000000000000000000007c0c8a15773ed7b50e7c738d1af4c5e3a2b210bd", - "previousValue": "0x0000000000000000000000007c0c8a15773ed7b50e7c738d1af4c5e3a2b210bd", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x86458026e238c6fd356c082b2224f486dbd447ea5c3ff57e9610d5d6dedf4935" - } - ], - "value": 0 - }, - { - "accessor": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "account": "0x970670459734a83899773A0fd45941B5afC1200e", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x4f1ef28600000000000000000000000063b71b96756c693f7065345fecd9b7843b3e7c57000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000002445e05fbd000000000000000000000000000000000000000000000000000000000000000400000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab035100000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000000deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fedeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x970670459734a83899773A0fd45941B5afC1200e", - "isWrite": false, - "newValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "previousValue": "0x00000000000000000000000062c20aa1e0272312bc100b4e23b4dc1ed96dd7d1", - "reverted": false, - "slot": "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" - }, - { - "account": "0x970670459734a83899773A0fd45941B5afC1200e", - "isWrite": true, - "newValue": "0x00000000000000000000000063b71b96756c693f7065345fecd9b7843b3e7c57", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1", - "account": "0x63B71B96756C693f7065345fecD9b7843b3e7C57", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x5e05fbd000000000000000000000000000000000000000000000000000000000000000400000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab035100000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000000deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fedeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef0000000000000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x970670459734a83899773A0fd45941B5afC1200e", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x970670459734a83899773A0fd45941B5afC1200e", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x970670459734a83899773A0fd45941B5afC1200e", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x970670459734a83899773A0fd45941B5afC1200e", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x970670459734a83899773A0fd45941B5afC1200e", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x970670459734a83899773A0fd45941B5afC1200e", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x970670459734a83899773A0fd45941B5afC1200e", - "isWrite": true, - "newValue": "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0xa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb49" - }, - { - "account": "0x970670459734a83899773A0fd45941B5afC1200e", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0xa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb4a" - }, - { - "account": "0x970670459734a83899773A0fd45941B5afC1200e", - "isWrite": true, - "newValue": "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0xcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f" - }, - { - "account": "0x970670459734a83899773A0fd45941B5afC1200e", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0xcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b6887930" - }, - { - "account": "0x970670459734a83899773A0fd45941B5afC1200e", - "isWrite": true, - "newValue": "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x24a9e90595537a4321bf3a8fd43f02c179fe79a94dde54a8c1a057e2967a4d0b" - }, - { - "account": "0x970670459734a83899773A0fd45941B5afC1200e", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x24a9e90595537a4321bf3a8fd43f02c179fe79a94dde54a8c1a057e2967a4d0c" - }, - { - "account": "0x970670459734a83899773A0fd45941B5afC1200e", - "isWrite": true, - "newValue": "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0xd9d16d34ffb15ba3a3d852f0d403e2ce1d691fb54de27ac87cd2f993f3ec330f" - }, - { - "account": "0x970670459734a83899773A0fd45941B5afC1200e", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0xd9d16d34ffb15ba3a3d852f0d403e2ce1d691fb54de27ac87cd2f993f3ec3310" - }, - { - "account": "0x970670459734a83899773A0fd45941B5afC1200e", - "isWrite": true, - "newValue": "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x1d32deecea32fd1365d10df47fc6666a05871102e61a115a5c569bca7e5de14d" - }, - { - "account": "0x970670459734a83899773A0fd45941B5afC1200e", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x1d32deecea32fd1365d10df47fc6666a05871102e61a115a5c569bca7e5de14e" - }, - { - "account": "0x970670459734a83899773A0fd45941B5afC1200e", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000002" - }, - { - "account": "0x970670459734a83899773A0fd45941B5afC1200e", - "isWrite": true, - "newValue": "0x0000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab0351", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000002" - }, - { - "account": "0x970670459734a83899773A0fd45941B5afC1200e", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - }, - { - "account": "0x970670459734a83899773A0fd45941B5afC1200e", - "isWrite": true, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000101", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x970670459734a83899773A0fd45941B5afC1200e", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x54fd4d50", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x970670459734a83899773A0fd45941B5afC1200e", - "isWrite": false, - "newValue": "0x00000000000000000000000063b71b96756c693f7065345fecd9b7843b3e7c57", - "previousValue": "0x00000000000000000000000063b71b96756c693f7065345fecd9b7843b3e7c57", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x63B71B96756C693f7065345fecD9b7843b3e7C57", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x54fd4d50", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "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": "0x935e3829", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000034" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x935e3829", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000034" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x0b7b1b30", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000008", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000008", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000037" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x9110ec4a", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x00000000000000000000000000000000000000000000000000000000000004b0", - "previousValue": "0x00000000000000000000000000000000000000000000000000000000000004b0", - "reverted": false, - "slot": "0x000000000000000000000000000000000000000000000000000000000000003a" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x1b685b9e0000000000000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "isWrite": false, - "newValue": "0x00000000000000000000000020b168142354cee65a32f6d8cf3033e592299765", - "previousValue": "0x00000000000000000000000020b168142354cee65a32f6d8cf3033e592299765", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x20B168142354Cee65a32f6D8cf3033E592299765", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x1b685b9e0000000000000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0xffdfc1249c027f9191656349feb0761381bb32c9f557e01f419fd08754bf5a1b" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xe1a05cc3", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000004", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000004", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000038" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xdb75b649", - "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": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xa2af0d1f", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000385", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000385", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000011" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xb6b1579AA54e2F61e621a40d5F2704D717B3544F", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x6101c06040523480156200001257600080fd5b506040516200648a3803806200648a833981016040819052620000359162000436565b620000436001607e6200050d565b60ff168811156200006757604051633beff19960e11b815260040160405180910390fd5b600019871480620000845750876200008188600162000533565b10155b15620000a35760405163e62ccf3960e01b815260040160405180910390fd5b6002871015620000c65760405163e62ccf3960e01b815260040160405180910390fd5b6001600160401b038016846001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200010f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200013591906200054e565b6001600160a01b031663f3f480d96040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000173573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200019991906200056e565b1115620001b95760405163b4e1243360e01b815260040160405180910390fd5b6000620001da876001600160401b0316620003e260201b62000c891760201c565b620001f0906001600160401b0316600262000588565b90506000856001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000233573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200025991906200054e565b6001600160a01b031663f3f480d96040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000297573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002bd91906200056e565b620002dc896001600160401b0316620003e260201b62000c891760201c565b6001600160401b0316620002f1919062000533565b905060006200030c8383620003e560201b62003a261760201c565b90506001600160401b03811115620003375760405163235dfb2b60e21b815260040160405180910390fd5b62000356886001600160401b0316620003e260201b62000c891760201c565b6001600160401b0316816001600160401b03161115620003895760405163235dfb2b60e21b815260040160405180910390fd5b50505063ffffffff9099166101205260809790975260a09590955260c0939093526001600160401b039182166101a0521660e0526001600160a01b039081166101005290811661014052166101605261018052620005aa565b90565b600081831015620003f75781620003f9565b825b9392505050565b80516001600160401b03811681146200041857600080fd5b919050565b6001600160a01b03811681146200043357600080fd5b50565b6000806000806000806000806000806101408b8d0312156200045757600080fd5b8a5163ffffffff811681146200046c57600080fd5b809a505060208b0151985060408b0151975060608b015196506200049360808c0162000400565b9550620004a360a08c0162000400565b945060c08b0151620004b5816200041d565b60e08c0151909450620004c8816200041d565b6101008c0151909350620004dc816200041d565b809250506101208b015190509295989b9194979a5092959850565b634e487b7160e01b600052601160045260246000fd5b600060ff821660ff8416808210156200052a576200052a620004f7565b90039392505050565b60008219821115620005495762000549620004f7565b500190565b6000602082840312156200056157600080fd5b8151620003f9816200041d565b6000602082840312156200058157600080fd5b5051919050565b6000816000190483118215151615620005a557620005a5620004f7565b500290565b60805160a05160c05160e05161010051610120516101405161016051610180516101a051615d5a62000730600039600081816106bb01528181611fbb015281816120260152612059015260008181610a1e01526139390152600081816106130152818161178a01526125e80152600081816105270152818161194c01528181612480015281816129ea0152613e1401526000818161088d015281816125a701526139c80152600081816104b401528181611eba015281816132420152613597015260008181610a7101528181610f6001528181611e2a01528181612089015281816120e801528181612bf60152612c38015260008181610aa401528181611c7301528181611d9901528181611ff7015281816130950152818161379601528181613f0b015281816146280152818161475601528181614857015261492c015260008181610b4b01528181611d3c01528181611e8e01528181612d0601528181612d8c01528181612f8b01526130b601526000818161078601526131540152615d5a6000f3fe6080604052600436106102f25760003560e01c806370872aa51161018f578063c6f0308c116100e1578063ec5e63081161008a578063fa24f74311610064578063fa24f74314610b18578063fa315aa914610b3c578063fe2bbeb214610b6f57600080fd5b8063ec5e630814610a95578063eff0f59214610ac8578063f8f43ff614610af857600080fd5b8063d6ae3cd5116100bb578063d6ae3cd514610a0f578063d8cc1a3c14610a42578063dabd396d14610a6257600080fd5b8063c6f0308c14610937578063cf09e0d0146109c1578063d5d44d80146109e257600080fd5b80638d450a9511610143578063bcef3b551161011d578063bcef3b55146108b7578063bd8da956146108f7578063c395e1ca1461091757600080fd5b80638d450a9514610777578063a445ece6146107aa578063bbdc02db1461087657600080fd5b80638129fc1c116101745780638129fc1c1461071a5780638980e0cc146107225780638b85902b1461073757600080fd5b806370872aa5146106f25780637b0f0adc1461070757600080fd5b80633fc8cef3116102485780635c0cba33116101fc5780636361506d116101d65780636361506d1461066c5780636b6716c0146106ac5780636f034409146106df57600080fd5b80635c0cba3314610604578063609d33341461063757806360e274641461064c57600080fd5b806354fd4d501161022d57806354fd4d501461055e57806357da950e146105b45780635a5fa2d9146105e457600080fd5b80633fc8cef314610518578063472777c61461054b57600080fd5b80632810e1d6116102aa57806337b1b2291161028457806337b1b229146104655780633a768463146104a55780633e3ac912146104d857600080fd5b80632810e1d6146103de5780632ad69aeb146103f357806330dbe5701461041357600080fd5b806319effeb4116102db57806319effeb414610339578063200d2ed21461038457806325fc2ace146103bf57600080fd5b806301935130146102f757806303c2924d14610319575b600080fd5b34801561030357600080fd5b506103176103123660046154e2565b610b9f565b005b34801561032557600080fd5b5061031761033436600461553d565b610ec0565b34801561034557600080fd5b506000546103669068010000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020015b60405180910390f35b34801561039057600080fd5b506000546103b290700100000000000000000000000000000000900460ff1681565b60405161037b919061558e565b3480156103cb57600080fd5b506008545b60405190815260200161037b565b3480156103ea57600080fd5b506103b2611566565b3480156103ff57600080fd5b506103d061040e36600461553d565b61180b565b34801561041f57600080fd5b506001546104409073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161037b565b34801561047157600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90033560601c610440565b3480156104b157600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610440565b3480156104e457600080fd5b50600054610508907201000000000000000000000000000000000000900460ff1681565b604051901515815260200161037b565b34801561052457600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610440565b6103176105593660046155cf565b611841565b34801561056a57600080fd5b506105a76040518060400160405280600a81526020017f312e332e302d72632e310000000000000000000000000000000000000000000081525081565b60405161037b9190615666565b3480156105c057600080fd5b506008546009546105cf919082565b6040805192835260208301919091520161037b565b3480156105f057600080fd5b506103d06105ff366004615679565b611853565b34801561061057600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610440565b34801561064357600080fd5b506105a761188d565b34801561065857600080fd5b506103176106673660046156b7565b61189b565b34801561067857600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003603401356103d0565b3480156106b857600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610366565b6103176106ed3660046156e9565b611a42565b3480156106fe57600080fd5b506009546103d0565b6103176107153660046155cf565b61251b565b610317612528565b34801561072e57600080fd5b506002546103d0565b34801561074357600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401356103d0565b34801561078357600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006103d0565b3480156107b657600080fd5b506108226107c5366004615679565b6007602052600090815260409020805460019091015460ff821691610100810463ffffffff1691650100000000009091046fffffffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff1684565b60408051941515855263ffffffff90931660208501526fffffffffffffffffffffffffffffffff9091169183019190915273ffffffffffffffffffffffffffffffffffffffff16606082015260800161037b565b34801561088257600080fd5b5060405163ffffffff7f000000000000000000000000000000000000000000000000000000000000000016815260200161037b565b3480156108c357600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003601401356103d0565b34801561090357600080fd5b50610366610912366004615679565b612a81565b34801561092357600080fd5b506103d0610932366004615728565b612c60565b34801561094357600080fd5b50610957610952366004615679565b612e43565b6040805163ffffffff909816885273ffffffffffffffffffffffffffffffffffffffff968716602089015295909416948601949094526fffffffffffffffffffffffffffffffff9182166060860152608085015291821660a08401521660c082015260e00161037b565b3480156109cd57600080fd5b506000546103669067ffffffffffffffff1681565b3480156109ee57600080fd5b506103d06109fd3660046156b7565b60036020526000908152604090205481565b348015610a1b57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006103d0565b348015610a4e57600080fd5b50610317610a5d36600461575a565b612eda565b348015610a6e57600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610366565b348015610aa157600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006103d0565b348015610ad457600080fd5b50610508610ae3366004615679565b60046020526000908152604090205460ff1681565b348015610b0457600080fd5b50610317610b133660046155cf565b613509565b348015610b2457600080fd5b50610b2d6139c6565b60405161037b939291906157e4565b348015610b4857600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006103d0565b348015610b7b57600080fd5b50610508610b8a366004615679565b60066020526000908152604090205460ff1681565b60008054700100000000000000000000000000000000900460ff166002811115610bcb57610bcb61555f565b14610c02576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000547201000000000000000000000000000000000000900460ff1615610c55576040517f0ea2e75200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610c8c367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013590565b90565b610ca3610c9e36869003860186615838565b613a41565b14610cda576040517f9cc00b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82606001358282604051610cef9291906158c5565b604051809103902014610d2e576040517fd81d583b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610d77610d7284848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613a9d92505050565b613b0a565b90506000610d9e82600881518110610d9157610d916158d5565b6020026020010151613cc0565b9050602081511115610ddc576040517fd81d583b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602081810151825190910360031b1c367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401358103610e51576040517fb8ed883000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050600180547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790555050600080547fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff1672010000000000000000000000000000000000001790555050565b60008054700100000000000000000000000000000000900460ff166002811115610eec57610eec61555f565b14610f23576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028381548110610f3857610f386158d5565b906000526020600020906005020190506000610f5384612a81565b905067ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081169082161015610fbc576040517ff2440b5300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008481526006602052604090205460ff1615611005576040517ff1a9458100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600084815260056020526040902080548015801561102257508515155b156110bd578354640100000000900473ffffffffffffffffffffffffffffffffffffffff16600081156110555781611071565b600186015473ffffffffffffffffffffffffffffffffffffffff165b905061107d8187613d74565b50505060009485525050600660205250506040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b6000868152600760209081526040918290208251608081018452815460ff81161515808352610100820463ffffffff16948301949094526501000000000090046fffffffffffffffffffffffffffffffff16938101939093526001015473ffffffffffffffffffffffffffffffffffffffff166060830152611160576fffffffffffffffffffffffffffffffff6040820152600181526000869003611160578195505b600086826020015163ffffffff166111789190615933565b90506000838211611189578161118b565b835b602084015190915063ffffffff165b818110156112d75760008682815481106111b6576111b66158d5565b6000918252602080832090910154808352600690915260409091205490915060ff1661120e576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028281548110611223576112236158d5565b600091825260209091206005909102018054909150640100000000900473ffffffffffffffffffffffffffffffffffffffff161580156112805750600481015460408701516fffffffffffffffffffffffffffffffff9182169116115b156112c257600181015473ffffffffffffffffffffffffffffffffffffffff16606087015260048101546fffffffffffffffffffffffffffffffff1660408701525b505080806112cf9061594b565b91505061119a565b5063ffffffff818116602085810191825260008c81526007909152604090819020865181549351928801517fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009094169015157fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ff161761010092909416918202939093177fffffffffffffffffffffff00000000000000000000000000000000ffffffffff16650100000000006fffffffffffffffffffffffffffffffff909316929092029190911782556060850151600190920180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9093169290921790915584900361155b57606083015160008a815260066020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558915801561145757506000547201000000000000000000000000000000000000900460ff165b156114cc5760015473ffffffffffffffffffffffffffffffffffffffff1661147f818a613d74565b885473ffffffffffffffffffffffffffffffffffffffff909116640100000000027fffffffffffffffff0000000000000000000000000000000000000000ffffffff909116178855611559565b61151373ffffffffffffffffffffffffffffffffffffffff8216156114f1578161150d565b600189015473ffffffffffffffffffffffffffffffffffffffff165b89613d74565b87547fffffffffffffffff0000000000000000000000000000000000000000ffffffff1664010000000073ffffffffffffffffffffffffffffffffffffffff8316021788555b505b505050505050505050565b600080600054700100000000000000000000000000000000900460ff1660028111156115945761159461555f565b146115cb576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000805260066020527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f85460ff1661162f576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600260008154811061165b5761165b6158d5565b6000918252602090912060059091020154640100000000900473ffffffffffffffffffffffffffffffffffffffff1614611696576001611699565b60025b6000805467ffffffffffffffff421668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff82168117835592935083927fffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffff000000000000000000ffffffffffffffff9091161770010000000000000000000000000000000083600281111561174a5761174a61555f565b02179055600281111561175f5761175f61555f565b6040517f5e186f09b9c93491f14e277eea7faa5de6a2d4bda75a79af7a3684fbfb42da6090600090a27f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663838c2d1e6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156117f057600080fd5b505af1158015611804573d6000803e3d6000fd5b5050505090565b6005602052816000526040600020818154811061182757600080fd5b90600052602060002001600091509150505481565b905090565b61184e8383836001611a42565b505050565b6000818152600760209081526040808320600590925282208054825461188490610100900463ffffffff1682615983565b95945050505050565b606061183c60546020613e75565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260036020526040812080549082905590819003611900576040517f17bfe5f700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517ff3fef3a300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063f3fef3a390604401600060405180830381600087803b15801561199057600080fd5b505af11580156119a4573d6000803e3d6000fd5b5050505060008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114611a02576040519150601f19603f3d011682016040523d82523d6000602084013e611a07565b606091505b505090508061184e576040517f83e6cc6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008054700100000000000000000000000000000000900460ff166002811115611a6e57611a6e61555f565b14611aa5576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028481548110611aba57611aba6158d5565b60009182526020918290206040805160e0810182526005909302909101805463ffffffff8116845273ffffffffffffffffffffffffffffffffffffffff64010000000090910481169484019490945260018101549093169082015260028201546fffffffffffffffffffffffffffffffff908116606083015260038301546080830181905260049093015480821660a084015270010000000000000000000000000000000090041660c082015291508514611ba1576040517f3014033200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60a0810151600083156fffffffffffffffffffffffffffffffff83161760011b90506000611c61826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169050861580611c9c5750611c997f00000000000000000000000000000000000000000000000000000000000000006002615933565b81145b8015611ca6575084155b15611cdd576040517fa42637bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000547201000000000000000000000000000000000000900460ff168015611d03575086155b15611d3a576040517f0ea2e75200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000000811115611d94576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611dbf7f00000000000000000000000000000000000000000000000000000000000000006001615933565b8103611dd157611dd186888588613ec7565b34611ddb83612c60565b14611e12576040517f8620aa1900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611e1d88612a81565b905067ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811690821603611e85576040517f3381d11400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611eb260017f0000000000000000000000000000000000000000000000000000000000000000615983565b8303611ff0577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f47919061599a565b73ffffffffffffffffffffffffffffffffffffffff1663f3f480d96040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f91573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fb591906159b7565b611fe9907f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff166159d0565b9050612083565b61201b60017f0000000000000000000000000000000000000000000000000000000000000000615983565b830361205657611fe97f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1660026159fc565b507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff165b6120b7817f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff16615a2c565b67ffffffffffffffff166120d28367ffffffffffffffff1690565b67ffffffffffffffff16111561211957612116817f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff16615a2c565b91505b6000604083901b421760008a8152608087901b6fffffffffffffffffffffffffffffffff8d1617602052604081209192509060008181526004602052604090205490915060ff1615612197576040517f80497e3b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60016004600083815260200190815260200160002060006101000a81548160ff02191690831515021790555060026040518060e001604052808d63ffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020013373ffffffffffffffffffffffffffffffffffffffff168152602001346fffffffffffffffffffffffffffffffff1681526020018c8152602001886fffffffffffffffffffffffffffffffff168152602001846fffffffffffffffffffffffffffffffff16815250908060018154018082558091505060019003906000526020600020906005020160009091909190915060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060608201518160020160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055506080820151816003015560a08201518160040160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555060c08201518160040160106101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055505050600560008c8152602001908152602001600020600160028054905061242d9190615983565b81546001810183556000928352602083200155604080517fd0e30db0000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169263d0e30db09234926004808301939282900301818588803b1580156124c557600080fd5b505af11580156124d9573d6000803e3d6000fd5b50506040513393508d92508e91507f9b3245740ec3b155098a55be84957a4da13eaf7f14a8bc6f53126c0b9350f2be90600090a4505050505050505050505050565b61184e8383836000611a42565b60005471010000000000000000000000000000000000900460ff161561257a576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f7258a80700000000000000000000000000000000000000000000000000000000815263ffffffff7f0000000000000000000000000000000000000000000000000000000000000000166004820152600090819073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690637258a807906024016040805180830381865afa15801561262e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126529190615a55565b90925090508161268e576040517f6a6bc3b200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518082019091528281526020018190526008829055600981905536607a146126c157639824bdab6000526004601cfd5b80367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401351161275b576040517ff40239db000000000000000000000000000000000000000000000000000000008152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013560048201526024015b60405180910390fd5b6040805160e08101825263ffffffff8082526000602083018181527ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe369081013560f01c90038035606090811c868801908152346fffffffffffffffffffffffffffffffff81811693890193845260149094013560808901908152600160a08a0181815242871660c08c019081526002805493840181558a529a5160059092027f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace81018054995173ffffffffffffffffffffffffffffffffffffffff908116640100000000027fffffffffffffffff000000000000000000000000000000000000000000000000909b1694909c16939093179890981790915592517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5acf87018054918a167fffffffffffffffffffffffff000000000000000000000000000000000000000090921691909117905592517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad0860180549186167fffffffffffffffffffffffffffffffff0000000000000000000000000000000090921691909117905591517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad185015551955182167001000000000000000000000000000000000295909116949094177f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad29091015580547fffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffff167101000000000000000000000000000000000017815583517fd0e30db000000000000000000000000000000000000000000000000000000000815293517f00000000000000000000000000000000000000000000000000000000000000009092169363d0e30db093926004828101939282900301818588803b158015612a3057600080fd5b505af1158015612a44573d6000803e3d6000fd5b5050600080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000164267ffffffffffffffff161790555050505050565b600080600054700100000000000000000000000000000000900460ff166002811115612aaf57612aaf61555f565b14612ae6576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028381548110612afb57612afb6158d5565b600091825260208220600590910201805490925063ffffffff90811614612b6a57815460028054909163ffffffff16908110612b3957612b396158d5565b906000526020600020906005020160040160109054906101000a90046fffffffffffffffffffffffffffffffff1690505b6004820154600090612ba290700100000000000000000000000000000000900467ffffffffffffffff165b67ffffffffffffffff1690565b612bb69067ffffffffffffffff1642615983565b612bd5612b95846fffffffffffffffffffffffffffffffff1660401c90565b67ffffffffffffffff16612be99190615933565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001667ffffffffffffffff168167ffffffffffffffff1611612c365780611884565b7f000000000000000000000000000000000000000000000000000000000000000095945050505050565b600080612cff836fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690507f0000000000000000000000000000000000000000000000000000000000000000811115612d5e576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b642e90edd00062061a806311e1a3006000612d798383615aa8565b9050670de0b6b3a76400006000612db0827f0000000000000000000000000000000000000000000000000000000000000000615abc565b90506000612dce612dc9670de0b6b3a764000086615abc565b614078565b90506000612ddc84846142d3565b90506000612dea8383614322565b90506000612df782614350565b90506000612e1682612e11670de0b6b3a76400008f615abc565b614538565b90506000612e248b83614322565b9050612e30818d615abc565b9f9e505050505050505050505050505050565b60028181548110612e5357600080fd5b60009182526020909120600590910201805460018201546002830154600384015460049094015463ffffffff8416955064010000000090930473ffffffffffffffffffffffffffffffffffffffff908116949216926fffffffffffffffffffffffffffffffff91821692918082169170010000000000000000000000000000000090041687565b60008054700100000000000000000000000000000000900460ff166002811115612f0657612f0661555f565b14612f3d576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028781548110612f5257612f526158d5565b6000918252602082206005919091020160048101549092506fffffffffffffffffffffffffffffffff16908715821760011b9050612fb17f00000000000000000000000000000000000000000000000000000000000000006001615933565b61304d826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1614613087576040517f5f53dd9800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080891561317e576130da7f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000615983565b6001901b6130f9846fffffffffffffffffffffffffffffffff16614569565b6fffffffffffffffffffffffffffffffff166131159190615af9565b156131525761314961313a60016fffffffffffffffffffffffffffffffff8716615b0d565b865463ffffffff166000614608565b60030154613174565b7f00000000000000000000000000000000000000000000000000000000000000005b91508490506131a8565b600385015491506131a561313a6fffffffffffffffffffffffffffffffff86166001615b36565b90505b600882901b60088a8a6040516131bf9291906158c5565b6040518091039020901b14613200576040517f696550ff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061320b8c6146ec565b9050600061321a836003015490565b6040517fe14ced320000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063e14ced3290613294908f908f908f908f908a90600401615baa565b6020604051808303816000875af11580156132b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132d791906159b7565b600485015491149150600090600290613382906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b61341e896fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b6134289190615be4565b6134329190615c07565b60ff161590508115158103613473576040517ffb4e40dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8754640100000000900473ffffffffffffffffffffffffffffffffffffffff16156134ca576040517f9071e6af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505085547fffffffffffffffff0000000000000000000000000000000000000000ffffffff163364010000000002179095555050505050505050505050565b60008054700100000000000000000000000000000000900460ff1660028111156135355761353561555f565b1461356c576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060008061357b8661471b565b9350935093509350600061359185858585614b24565b905060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015613600573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613624919061599a565b90506001890361371c5773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a84613680367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036034013590565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815260048101939093526024830191909152604482015260206064820152608481018a905260a4015b6020604051808303816000875af11580156136f2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061371691906159b7565b5061155b565b600289036137485773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a8489613680565b600389036137745773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a8487613680565b600489036138fb5760006137ba6fffffffffffffffffffffffffffffffff85167f0000000000000000000000000000000000000000000000000000000000000000614bde565b6009546137c79190615933565b6137d2906001615933565b9050367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360540135811061383b57367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036054013561383d565b805b905073ffffffffffffffffffffffffffffffffffffffff82166352f0f3ad8b8560405160e084901b7fffffffff000000000000000000000000000000000000000000000000000000001681526004810192909252602482015260c084901b604482015260086064820152608481018b905260a4016020604051808303816000875af11580156138d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138f491906159b7565b505061155b565b60058903613994576040517f52f0f3ad000000000000000000000000000000000000000000000000000000008152600481018a9052602481018390527f000000000000000000000000000000000000000000000000000000000000000060c01b6044820152600860648201526084810188905273ffffffffffffffffffffffffffffffffffffffff8216906352f0f3ad9060a4016136d3565b6040517fff137e6500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000000367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003601401356060613a1f61188d565b9050909192565b600081831015613a365781613a38565b825b90505b92915050565b60008160000151826020015183604001518460600151604051602001613a80949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b60408051808201909152600080825260208201528151600003613aec576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50604080518082019091528151815260209182019181019190915290565b60606000806000613b1a85614c8c565b919450925090506001816001811115613b3557613b3561555f565b14613b6c576040517f4b9c6abe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8451613b788385615933565b14613baf576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808252610420820190925290816020015b6040805180820190915260008082526020820152815260200190600190039081613bc65790505093506000835b8651811015613cb457600080613c396040518060400160405280858c60000151613c1d9190615983565b8152602001858c60200151613c329190615933565b9052614c8c565b509150915060405180604001604052808383613c559190615933565b8152602001848b60200151613c6a9190615933565b815250888581518110613c7f57613c7f6158d5565b6020908102919091010152613c95600185615933565b9350613ca18183615933565b613cab9084615933565b92505050613bf3565b50845250919392505050565b60606000806000613cd085614c8c565b919450925090506000816001811115613ceb57613ceb61555f565b14613d22576040517f1ff9b2e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613d2c8284615933565b855114613d65576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6118848560200151848461512a565b600281015473ffffffffffffffffffffffffffffffffffffffff8316600090815260036020526040812080546fffffffffffffffffffffffffffffffff90931692839290613dc3908490615933565b90915550506040517f7eee288d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018390527f00000000000000000000000000000000000000000000000000000000000000001690637eee288d90604401600060405180830381600087803b158015613e5857600080fd5b505af1158015613e6c573d6000803e3d6000fd5b50505050505050565b604051818152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90038284820160208401378260208301016000815260208101604052505092915050565b6000613ee66fffffffffffffffffffffffffffffffff84166001615b36565b90506000613ef682866001614608565b9050600086901a8380613fe25750613f2f60027f0000000000000000000000000000000000000000000000000000000000000000615af9565b6004830154600290613fd3906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b613fdd9190615c07565b60ff16145b1561403a5760ff811660011480613ffc575060ff81166002145b614035576040517ff40239db00000000000000000000000000000000000000000000000000000000815260048101889052602401612752565b613e6c565b60ff811615613e6c576040517ff40239db00000000000000000000000000000000000000000000000000000000815260048101889052602401612752565b6fffffffffffffffffffffffffffffffff811160071b81811c67ffffffffffffffff1060061b1781811c63ffffffff1060051b1781811c61ffff1060041b1781811c60ff1060031b17600082136140d757631615e6386000526004601cfd5b7ff8f9f9faf9fdfafbf9fdfcfdfafbfcfef9fafdfafcfcfbfefafafcfbffffffff6f8421084210842108cc6318c6db6d54be83831c1c601f161a1890811b609f90811c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506029190037d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b302017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d90565b60007812725dd1d243aba0e75fe645cc4873f9e65afe688c928e1f218311670de0b6b3a76400000215820261431057637c5f487d6000526004601cfd5b50670de0b6b3a7640000919091020490565b6000816000190483118202156143405763bac65e5b6000526004601cfd5b50670de0b6b3a764000091020490565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdc0d0570925a462d7821361437e57919050565b680755bf798b4a1bf1e5821261439c5763a37bfec96000526004601cfd5b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b6000613a38670de0b6b3a76400008361455086614078565b61455a9190615c29565b6145649190615ce5565b614350565b6000806145f6837e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b600160ff919091161b90920392915050565b600080826146515761464c6fffffffffffffffffffffffffffffffff86167f00000000000000000000000000000000000000000000000000000000000000006151bf565b61466c565b61466c856fffffffffffffffffffffffffffffffff1661534b565b905060028481548110614681576146816158d5565b906000526020600020906005020191505b60048201546fffffffffffffffffffffffffffffffff8281169116146146e457815460028054909163ffffffff169081106146cf576146cf6158d5565b90600052602060002090600502019150614692565b509392505050565b60008060008060006146fd8661471b565b935093509350935061471184848484614b24565b9695505050505050565b600080600080600085905060006002828154811061473b5761473b6158d5565b600091825260209091206004600590920201908101549091507f000000000000000000000000000000000000000000000000000000000000000090614812906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff161161484c576040517fb34b5c2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000815b60048301547f000000000000000000000000000000000000000000000000000000000000000090614913906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff16925082111561498857825463ffffffff166149527f00000000000000000000000000000000000000000000000000000000000000006001615933565b830361495c578391505b6002818154811061496f5761496f6158d5565b9060005260206000209060050201935080945050614850565b600481810154908401546fffffffffffffffffffffffffffffffff91821691166000816fffffffffffffffffffffffffffffffff166149f16149dc856fffffffffffffffffffffffffffffffff1660011c90565b6fffffffffffffffffffffffffffffffff1690565b6fffffffffffffffffffffffffffffffff161490508015614ac0576000614a29836fffffffffffffffffffffffffffffffff16614569565b6fffffffffffffffffffffffffffffffff161115614a94576000614a6b614a6360016fffffffffffffffffffffffffffffffff8616615b0d565b896001614608565b6003810154600490910154909c506fffffffffffffffffffffffffffffffff169a50614a9a9050565b6008549a505b600386015460048701549099506fffffffffffffffffffffffffffffffff169750614b16565b6000614ae2614a636fffffffffffffffffffffffffffffffff85166001615b36565b6003808901546004808b015492840154930154909e506fffffffffffffffffffffffffffffffff9182169d50919b50169850505b505050505050509193509193565b60006fffffffffffffffffffffffffffffffff841615614b915760408051602081018790526fffffffffffffffffffffffffffffffff8087169282019290925260608101859052908316608082015260a00160405160208183030381529060405280519060200120611884565b8282604051602001614bbf9291909182526fffffffffffffffffffffffffffffffff16602082015260400190565b6040516020818303038152906040528051906020012095945050505050565b600080614c6b847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690508083036001841b600180831b0386831b17039250505092915050565b60008060008360000151600003614ccf576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020840151805160001a607f8111614cf4576000600160009450945094505050615123565b60b78111614e0a576000614d09608083615983565b905080876000015111614d48576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001838101517fff00000000000000000000000000000000000000000000000000000000000000169082148015614dc057507f80000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008216105b15614df7576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5060019550935060009250615123915050565b60bf8111614f68576000614e1f60b783615983565b905080876000015111614e5e576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614ec0576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c60378111614f08576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614f128184615933565b895111614f4b576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614f56836001615933565b97509550600094506151239350505050565b60f78111614fcd576000614f7d60c083615983565b905080876000015111614fbc576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600195509350849250615123915050565b6000614fda60f783615983565b905080876000015111615019576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff0000000000000000000000000000000000000000000000000000000000000016600081900361507b576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c603781116150c3576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6150cd8184615933565b895111615106576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b615111836001615933565b97509550600194506151239350505050565b9193909250565b60608167ffffffffffffffff81111561514557615145615809565b6040519080825280601f01601f19166020018201604052801561516f576020820181803683370190505b50905081156151b85760006151848486615933565b90506020820160005b848110156151a557828101518282015260200161518d565b848111156151b4576000858301525b5050505b9392505050565b60008161525e846fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff16116152745763b34b5c226000526004601cfd5b61527d8361534b565b90508161531c826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1611613a3b57613a38615332836001615933565b6fffffffffffffffffffffffffffffffff8316906153f0565b600081196001830116816153df827e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169390931c8015179392505050565b60008061547d847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169050808303600180821b0385821b179250505092915050565b60008083601f8401126154ab57600080fd5b50813567ffffffffffffffff8111156154c357600080fd5b6020830191508360208285010111156154db57600080fd5b9250929050565b600080600083850360a08112156154f857600080fd5b608081121561550657600080fd5b50839250608084013567ffffffffffffffff81111561552457600080fd5b61553086828701615499565b9497909650939450505050565b6000806040838503121561555057600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60208101600383106155c9577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b6000806000606084860312156155e457600080fd5b505081359360208301359350604090920135919050565b6000815180845260005b8181101561562157602081850181015186830182015201615605565b81811115615633576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000613a3860208301846155fb565b60006020828403121561568b57600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff811681146156b457600080fd5b50565b6000602082840312156156c957600080fd5b81356151b881615692565b803580151581146156e457600080fd5b919050565b600080600080608085870312156156ff57600080fd5b84359350602085013592506040850135915061571d606086016156d4565b905092959194509250565b60006020828403121561573a57600080fd5b81356fffffffffffffffffffffffffffffffff811681146151b857600080fd5b6000806000806000806080878903121561577357600080fd5b86359550615783602088016156d4565b9450604087013567ffffffffffffffff808211156157a057600080fd5b6157ac8a838b01615499565b909650945060608901359150808211156157c557600080fd5b506157d289828a01615499565b979a9699509497509295939492505050565b63ffffffff8416815282602082015260606040820152600061188460608301846155fb565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006080828403121561584a57600080fd5b6040516080810181811067ffffffffffffffff82111715615894577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561594657615946615904565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361597c5761597c615904565b5060010190565b60008282101561599557615995615904565b500390565b6000602082840312156159ac57600080fd5b81516151b881615692565b6000602082840312156159c957600080fd5b5051919050565b600067ffffffffffffffff8083168185168083038211156159f3576159f3615904565b01949350505050565b600067ffffffffffffffff80831681851681830481118215151615615a2357615a23615904565b02949350505050565b600067ffffffffffffffff83811690831681811015615a4d57615a4d615904565b039392505050565b60008060408385031215615a6857600080fd5b505080516020909101519092909150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082615ab757615ab7615a79565b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615af457615af4615904565b500290565b600082615b0857615b08615a79565b500690565b60006fffffffffffffffffffffffffffffffff83811690831681811015615a4d57615a4d615904565b60006fffffffffffffffffffffffffffffffff8083168185168083038211156159f3576159f3615904565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b606081526000615bbe606083018789615b61565b8281036020840152615bd1818688615b61565b9150508260408301529695505050505050565b600060ff821660ff841680821015615bfe57615bfe615904565b90039392505050565b600060ff831680615c1a57615c1a615a79565b8060ff84160691505092915050565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600084136000841385830485118282161615615c6a57615c6a615904565b7f80000000000000000000000000000000000000000000000000000000000000006000871286820588128184161615615ca557615ca5615904565b60008712925087820587128484161615615cc157615cc1615904565b87850587128184161615615cd757615cd7615904565b505050929093029392505050565b600082615cf457615cf4615a79565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f800000000000000000000000000000000000000000000000000000000000000083141615615d4857615d48615904565b50059056fea164736f6c634300080f000a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004b0000000000000000000000000444e09fe6d839273316a87002ab0efbea6fe7806000000000000000000000000ef179756ea6525afade217ca5ab0b1b5cfe0fd92000000000000000000000000970670459734a83899773a0fd45941b5afc1200e0000000000000000000000000000000000000000000000000000000000000385", - "deployedCode": "0x6080604052600436106102f25760003560e01c806370872aa51161018f578063c6f0308c116100e1578063ec5e63081161008a578063fa24f74311610064578063fa24f74314610b18578063fa315aa914610b3c578063fe2bbeb214610b6f57600080fd5b8063ec5e630814610a95578063eff0f59214610ac8578063f8f43ff614610af857600080fd5b8063d6ae3cd5116100bb578063d6ae3cd514610a0f578063d8cc1a3c14610a42578063dabd396d14610a6257600080fd5b8063c6f0308c14610937578063cf09e0d0146109c1578063d5d44d80146109e257600080fd5b80638d450a9511610143578063bcef3b551161011d578063bcef3b55146108b7578063bd8da956146108f7578063c395e1ca1461091757600080fd5b80638d450a9514610777578063a445ece6146107aa578063bbdc02db1461087657600080fd5b80638129fc1c116101745780638129fc1c1461071a5780638980e0cc146107225780638b85902b1461073757600080fd5b806370872aa5146106f25780637b0f0adc1461070757600080fd5b80633fc8cef3116102485780635c0cba33116101fc5780636361506d116101d65780636361506d1461066c5780636b6716c0146106ac5780636f034409146106df57600080fd5b80635c0cba3314610604578063609d33341461063757806360e274641461064c57600080fd5b806354fd4d501161022d57806354fd4d501461055e57806357da950e146105b45780635a5fa2d9146105e457600080fd5b80633fc8cef314610518578063472777c61461054b57600080fd5b80632810e1d6116102aa57806337b1b2291161028457806337b1b229146104655780633a768463146104a55780633e3ac912146104d857600080fd5b80632810e1d6146103de5780632ad69aeb146103f357806330dbe5701461041357600080fd5b806319effeb4116102db57806319effeb414610339578063200d2ed21461038457806325fc2ace146103bf57600080fd5b806301935130146102f757806303c2924d14610319575b600080fd5b34801561030357600080fd5b506103176103123660046154e2565b610b9f565b005b34801561032557600080fd5b5061031761033436600461553d565b610ec0565b34801561034557600080fd5b506000546103669068010000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020015b60405180910390f35b34801561039057600080fd5b506000546103b290700100000000000000000000000000000000900460ff1681565b60405161037b919061558e565b3480156103cb57600080fd5b506008545b60405190815260200161037b565b3480156103ea57600080fd5b506103b2611566565b3480156103ff57600080fd5b506103d061040e36600461553d565b61180b565b34801561041f57600080fd5b506001546104409073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161037b565b34801561047157600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90033560601c610440565b3480156104b157600080fd5b507f000000000000000000000000444e09fe6d839273316a87002ab0efbea6fe7806610440565b3480156104e457600080fd5b50600054610508907201000000000000000000000000000000000000900460ff1681565b604051901515815260200161037b565b34801561052457600080fd5b507f000000000000000000000000ef179756ea6525afade217ca5ab0b1b5cfe0fd92610440565b6103176105593660046155cf565b611841565b34801561056a57600080fd5b506105a76040518060400160405280600a81526020017f312e332e302d72632e310000000000000000000000000000000000000000000081525081565b60405161037b9190615666565b3480156105c057600080fd5b506008546009546105cf919082565b6040805192835260208301919091520161037b565b3480156105f057600080fd5b506103d06105ff366004615679565b611853565b34801561061057600080fd5b507f000000000000000000000000970670459734a83899773a0fd45941b5afc1200e610440565b34801561064357600080fd5b506105a761188d565b34801561065857600080fd5b506103176106673660046156b7565b61189b565b34801561067857600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003603401356103d0565b3480156106b857600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610366565b6103176106ed3660046156e9565b611a42565b3480156106fe57600080fd5b506009546103d0565b6103176107153660046155cf565b61251b565b610317612528565b34801561072e57600080fd5b506002546103d0565b34801561074357600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401356103d0565b34801561078357600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006103d0565b3480156107b657600080fd5b506108226107c5366004615679565b6007602052600090815260409020805460019091015460ff821691610100810463ffffffff1691650100000000009091046fffffffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff1684565b60408051941515855263ffffffff90931660208501526fffffffffffffffffffffffffffffffff9091169183019190915273ffffffffffffffffffffffffffffffffffffffff16606082015260800161037b565b34801561088257600080fd5b5060405163ffffffff7f000000000000000000000000000000000000000000000000000000000000000016815260200161037b565b3480156108c357600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003601401356103d0565b34801561090357600080fd5b50610366610912366004615679565b612a81565b34801561092357600080fd5b506103d0610932366004615728565b612c60565b34801561094357600080fd5b50610957610952366004615679565b612e43565b6040805163ffffffff909816885273ffffffffffffffffffffffffffffffffffffffff968716602089015295909416948601949094526fffffffffffffffffffffffffffffffff9182166060860152608085015291821660a08401521660c082015260e00161037b565b3480156109cd57600080fd5b506000546103669067ffffffffffffffff1681565b3480156109ee57600080fd5b506103d06109fd3660046156b7565b60036020526000908152604090205481565b348015610a1b57600080fd5b507f00000000000000000000000000000000000000000000000000000000000003856103d0565b348015610a4e57600080fd5b50610317610a5d36600461575a565b612eda565b348015610a6e57600080fd5b507f00000000000000000000000000000000000000000000000000000000000004b0610366565b348015610aa157600080fd5b507f00000000000000000000000000000000000000000000000000000000000000046103d0565b348015610ad457600080fd5b50610508610ae3366004615679565b60046020526000908152604090205460ff1681565b348015610b0457600080fd5b50610317610b133660046155cf565b613509565b348015610b2457600080fd5b50610b2d6139c6565b60405161037b939291906157e4565b348015610b4857600080fd5b507f00000000000000000000000000000000000000000000000000000000000000086103d0565b348015610b7b57600080fd5b50610508610b8a366004615679565b60066020526000908152604090205460ff1681565b60008054700100000000000000000000000000000000900460ff166002811115610bcb57610bcb61555f565b14610c02576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000547201000000000000000000000000000000000000900460ff1615610c55576040517f0ea2e75200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610c8c367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013590565b90565b610ca3610c9e36869003860186615838565b613a41565b14610cda576040517f9cc00b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82606001358282604051610cef9291906158c5565b604051809103902014610d2e576040517fd81d583b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610d77610d7284848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613a9d92505050565b613b0a565b90506000610d9e82600881518110610d9157610d916158d5565b6020026020010151613cc0565b9050602081511115610ddc576040517fd81d583b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602081810151825190910360031b1c367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401358103610e51576040517fb8ed883000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050600180547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790555050600080547fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff1672010000000000000000000000000000000000001790555050565b60008054700100000000000000000000000000000000900460ff166002811115610eec57610eec61555f565b14610f23576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028381548110610f3857610f386158d5565b906000526020600020906005020190506000610f5384612a81565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b081169082161015610fbc576040517ff2440b5300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008481526006602052604090205460ff1615611005576040517ff1a9458100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600084815260056020526040902080548015801561102257508515155b156110bd578354640100000000900473ffffffffffffffffffffffffffffffffffffffff16600081156110555781611071565b600186015473ffffffffffffffffffffffffffffffffffffffff165b905061107d8187613d74565b50505060009485525050600660205250506040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b6000868152600760209081526040918290208251608081018452815460ff81161515808352610100820463ffffffff16948301949094526501000000000090046fffffffffffffffffffffffffffffffff16938101939093526001015473ffffffffffffffffffffffffffffffffffffffff166060830152611160576fffffffffffffffffffffffffffffffff6040820152600181526000869003611160578195505b600086826020015163ffffffff166111789190615933565b90506000838211611189578161118b565b835b602084015190915063ffffffff165b818110156112d75760008682815481106111b6576111b66158d5565b6000918252602080832090910154808352600690915260409091205490915060ff1661120e576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028281548110611223576112236158d5565b600091825260209091206005909102018054909150640100000000900473ffffffffffffffffffffffffffffffffffffffff161580156112805750600481015460408701516fffffffffffffffffffffffffffffffff9182169116115b156112c257600181015473ffffffffffffffffffffffffffffffffffffffff16606087015260048101546fffffffffffffffffffffffffffffffff1660408701525b505080806112cf9061594b565b91505061119a565b5063ffffffff818116602085810191825260008c81526007909152604090819020865181549351928801517fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009094169015157fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ff161761010092909416918202939093177fffffffffffffffffffffff00000000000000000000000000000000ffffffffff16650100000000006fffffffffffffffffffffffffffffffff909316929092029190911782556060850151600190920180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9093169290921790915584900361155b57606083015160008a815260066020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558915801561145757506000547201000000000000000000000000000000000000900460ff165b156114cc5760015473ffffffffffffffffffffffffffffffffffffffff1661147f818a613d74565b885473ffffffffffffffffffffffffffffffffffffffff909116640100000000027fffffffffffffffff0000000000000000000000000000000000000000ffffffff909116178855611559565b61151373ffffffffffffffffffffffffffffffffffffffff8216156114f1578161150d565b600189015473ffffffffffffffffffffffffffffffffffffffff165b89613d74565b87547fffffffffffffffff0000000000000000000000000000000000000000ffffffff1664010000000073ffffffffffffffffffffffffffffffffffffffff8316021788555b505b505050505050505050565b600080600054700100000000000000000000000000000000900460ff1660028111156115945761159461555f565b146115cb576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000805260066020527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f85460ff1661162f576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600260008154811061165b5761165b6158d5565b6000918252602090912060059091020154640100000000900473ffffffffffffffffffffffffffffffffffffffff1614611696576001611699565b60025b6000805467ffffffffffffffff421668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff82168117835592935083927fffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffff000000000000000000ffffffffffffffff9091161770010000000000000000000000000000000083600281111561174a5761174a61555f565b02179055600281111561175f5761175f61555f565b6040517f5e186f09b9c93491f14e277eea7faa5de6a2d4bda75a79af7a3684fbfb42da6090600090a27f000000000000000000000000970670459734a83899773a0fd45941b5afc1200e73ffffffffffffffffffffffffffffffffffffffff1663838c2d1e6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156117f057600080fd5b505af1158015611804573d6000803e3d6000fd5b5050505090565b6005602052816000526040600020818154811061182757600080fd5b90600052602060002001600091509150505481565b905090565b61184e8383836001611a42565b505050565b6000818152600760209081526040808320600590925282208054825461188490610100900463ffffffff1682615983565b95945050505050565b606061183c60546020613e75565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260036020526040812080549082905590819003611900576040517f17bfe5f700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517ff3fef3a300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152602482018390527f000000000000000000000000ef179756ea6525afade217ca5ab0b1b5cfe0fd92169063f3fef3a390604401600060405180830381600087803b15801561199057600080fd5b505af11580156119a4573d6000803e3d6000fd5b5050505060008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114611a02576040519150601f19603f3d011682016040523d82523d6000602084013e611a07565b606091505b505090508061184e576040517f83e6cc6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008054700100000000000000000000000000000000900460ff166002811115611a6e57611a6e61555f565b14611aa5576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028481548110611aba57611aba6158d5565b60009182526020918290206040805160e0810182526005909302909101805463ffffffff8116845273ffffffffffffffffffffffffffffffffffffffff64010000000090910481169484019490945260018101549093169082015260028201546fffffffffffffffffffffffffffffffff908116606083015260038301546080830181905260049093015480821660a084015270010000000000000000000000000000000090041660c082015291508514611ba1576040517f3014033200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60a0810151600083156fffffffffffffffffffffffffffffffff83161760011b90506000611c61826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169050861580611c9c5750611c997f00000000000000000000000000000000000000000000000000000000000000046002615933565b81145b8015611ca6575084155b15611cdd576040517fa42637bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000547201000000000000000000000000000000000000900460ff168015611d03575086155b15611d3a576040517f0ea2e75200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000008811115611d94576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611dbf7f00000000000000000000000000000000000000000000000000000000000000046001615933565b8103611dd157611dd186888588613ec7565b34611ddb83612c60565b14611e12576040517f8620aa1900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611e1d88612a81565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b0811690821603611e85576040517f3381d11400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611eb260017f0000000000000000000000000000000000000000000000000000000000000008615983565b8303611ff0577f000000000000000000000000444e09fe6d839273316a87002ab0efbea6fe780673ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f47919061599a565b73ffffffffffffffffffffffffffffffffffffffff1663f3f480d96040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f91573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fb591906159b7565b611fe9907f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff166159d0565b9050612083565b61201b60017f0000000000000000000000000000000000000000000000000000000000000004615983565b830361205657611fe97f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1660026159fc565b507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff165b6120b7817f00000000000000000000000000000000000000000000000000000000000004b067ffffffffffffffff16615a2c565b67ffffffffffffffff166120d28367ffffffffffffffff1690565b67ffffffffffffffff16111561211957612116817f00000000000000000000000000000000000000000000000000000000000004b067ffffffffffffffff16615a2c565b91505b6000604083901b421760008a8152608087901b6fffffffffffffffffffffffffffffffff8d1617602052604081209192509060008181526004602052604090205490915060ff1615612197576040517f80497e3b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60016004600083815260200190815260200160002060006101000a81548160ff02191690831515021790555060026040518060e001604052808d63ffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020013373ffffffffffffffffffffffffffffffffffffffff168152602001346fffffffffffffffffffffffffffffffff1681526020018c8152602001886fffffffffffffffffffffffffffffffff168152602001846fffffffffffffffffffffffffffffffff16815250908060018154018082558091505060019003906000526020600020906005020160009091909190915060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060608201518160020160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055506080820151816003015560a08201518160040160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555060c08201518160040160106101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055505050600560008c8152602001908152602001600020600160028054905061242d9190615983565b81546001810183556000928352602083200155604080517fd0e30db0000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ef179756ea6525afade217ca5ab0b1b5cfe0fd92169263d0e30db09234926004808301939282900301818588803b1580156124c557600080fd5b505af11580156124d9573d6000803e3d6000fd5b50506040513393508d92508e91507f9b3245740ec3b155098a55be84957a4da13eaf7f14a8bc6f53126c0b9350f2be90600090a4505050505050505050505050565b61184e8383836000611a42565b60005471010000000000000000000000000000000000900460ff161561257a576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f7258a80700000000000000000000000000000000000000000000000000000000815263ffffffff7f0000000000000000000000000000000000000000000000000000000000000000166004820152600090819073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000970670459734a83899773a0fd45941b5afc1200e1690637258a807906024016040805180830381865afa15801561262e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126529190615a55565b90925090508161268e576040517f6a6bc3b200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518082019091528281526020018190526008829055600981905536607a146126c157639824bdab6000526004601cfd5b80367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401351161275b576040517ff40239db000000000000000000000000000000000000000000000000000000008152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013560048201526024015b60405180910390fd5b6040805160e08101825263ffffffff8082526000602083018181527ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe369081013560f01c90038035606090811c868801908152346fffffffffffffffffffffffffffffffff81811693890193845260149094013560808901908152600160a08a0181815242871660c08c019081526002805493840181558a529a5160059092027f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace81018054995173ffffffffffffffffffffffffffffffffffffffff908116640100000000027fffffffffffffffff000000000000000000000000000000000000000000000000909b1694909c16939093179890981790915592517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5acf87018054918a167fffffffffffffffffffffffff000000000000000000000000000000000000000090921691909117905592517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad0860180549186167fffffffffffffffffffffffffffffffff0000000000000000000000000000000090921691909117905591517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad185015551955182167001000000000000000000000000000000000295909116949094177f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad29091015580547fffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffff167101000000000000000000000000000000000017815583517fd0e30db000000000000000000000000000000000000000000000000000000000815293517f000000000000000000000000ef179756ea6525afade217ca5ab0b1b5cfe0fd929092169363d0e30db093926004828101939282900301818588803b158015612a3057600080fd5b505af1158015612a44573d6000803e3d6000fd5b5050600080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000164267ffffffffffffffff161790555050505050565b600080600054700100000000000000000000000000000000900460ff166002811115612aaf57612aaf61555f565b14612ae6576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028381548110612afb57612afb6158d5565b600091825260208220600590910201805490925063ffffffff90811614612b6a57815460028054909163ffffffff16908110612b3957612b396158d5565b906000526020600020906005020160040160109054906101000a90046fffffffffffffffffffffffffffffffff1690505b6004820154600090612ba290700100000000000000000000000000000000900467ffffffffffffffff165b67ffffffffffffffff1690565b612bb69067ffffffffffffffff1642615983565b612bd5612b95846fffffffffffffffffffffffffffffffff1660401c90565b67ffffffffffffffff16612be99190615933565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b01667ffffffffffffffff168167ffffffffffffffff1611612c365780611884565b7f00000000000000000000000000000000000000000000000000000000000004b095945050505050565b600080612cff836fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690507f0000000000000000000000000000000000000000000000000000000000000008811115612d5e576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b642e90edd00062061a806311e1a3006000612d798383615aa8565b9050670de0b6b3a76400006000612db0827f0000000000000000000000000000000000000000000000000000000000000008615abc565b90506000612dce612dc9670de0b6b3a764000086615abc565b614078565b90506000612ddc84846142d3565b90506000612dea8383614322565b90506000612df782614350565b90506000612e1682612e11670de0b6b3a76400008f615abc565b614538565b90506000612e248b83614322565b9050612e30818d615abc565b9f9e505050505050505050505050505050565b60028181548110612e5357600080fd5b60009182526020909120600590910201805460018201546002830154600384015460049094015463ffffffff8416955064010000000090930473ffffffffffffffffffffffffffffffffffffffff908116949216926fffffffffffffffffffffffffffffffff91821692918082169170010000000000000000000000000000000090041687565b60008054700100000000000000000000000000000000900460ff166002811115612f0657612f0661555f565b14612f3d576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028781548110612f5257612f526158d5565b6000918252602082206005919091020160048101549092506fffffffffffffffffffffffffffffffff16908715821760011b9050612fb17f00000000000000000000000000000000000000000000000000000000000000086001615933565b61304d826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1614613087576040517f5f53dd9800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080891561317e576130da7f00000000000000000000000000000000000000000000000000000000000000047f0000000000000000000000000000000000000000000000000000000000000008615983565b6001901b6130f9846fffffffffffffffffffffffffffffffff16614569565b6fffffffffffffffffffffffffffffffff166131159190615af9565b156131525761314961313a60016fffffffffffffffffffffffffffffffff8716615b0d565b865463ffffffff166000614608565b60030154613174565b7f00000000000000000000000000000000000000000000000000000000000000005b91508490506131a8565b600385015491506131a561313a6fffffffffffffffffffffffffffffffff86166001615b36565b90505b600882901b60088a8a6040516131bf9291906158c5565b6040518091039020901b14613200576040517f696550ff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061320b8c6146ec565b9050600061321a836003015490565b6040517fe14ced320000000000000000000000000000000000000000000000000000000081527f000000000000000000000000444e09fe6d839273316a87002ab0efbea6fe780673ffffffffffffffffffffffffffffffffffffffff169063e14ced3290613294908f908f908f908f908a90600401615baa565b6020604051808303816000875af11580156132b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132d791906159b7565b600485015491149150600090600290613382906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b61341e896fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b6134289190615be4565b6134329190615c07565b60ff161590508115158103613473576040517ffb4e40dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8754640100000000900473ffffffffffffffffffffffffffffffffffffffff16156134ca576040517f9071e6af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505085547fffffffffffffffff0000000000000000000000000000000000000000ffffffff163364010000000002179095555050505050505050505050565b60008054700100000000000000000000000000000000900460ff1660028111156135355761353561555f565b1461356c576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060008061357b8661471b565b9350935093509350600061359185858585614b24565b905060007f000000000000000000000000444e09fe6d839273316a87002ab0efbea6fe780673ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015613600573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613624919061599a565b90506001890361371c5773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a84613680367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036034013590565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815260048101939093526024830191909152604482015260206064820152608481018a905260a4015b6020604051808303816000875af11580156136f2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061371691906159b7565b5061155b565b600289036137485773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a8489613680565b600389036137745773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a8487613680565b600489036138fb5760006137ba6fffffffffffffffffffffffffffffffff85167f0000000000000000000000000000000000000000000000000000000000000004614bde565b6009546137c79190615933565b6137d2906001615933565b9050367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360540135811061383b57367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036054013561383d565b805b905073ffffffffffffffffffffffffffffffffffffffff82166352f0f3ad8b8560405160e084901b7fffffffff000000000000000000000000000000000000000000000000000000001681526004810192909252602482015260c084901b604482015260086064820152608481018b905260a4016020604051808303816000875af11580156138d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138f491906159b7565b505061155b565b60058903613994576040517f52f0f3ad000000000000000000000000000000000000000000000000000000008152600481018a9052602481018390527f000000000000000000000000000000000000000000000000000000000000038560c01b6044820152600860648201526084810188905273ffffffffffffffffffffffffffffffffffffffff8216906352f0f3ad9060a4016136d3565b6040517fff137e6500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000000367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003601401356060613a1f61188d565b9050909192565b600081831015613a365781613a38565b825b90505b92915050565b60008160000151826020015183604001518460600151604051602001613a80949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b60408051808201909152600080825260208201528151600003613aec576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50604080518082019091528151815260209182019181019190915290565b60606000806000613b1a85614c8c565b919450925090506001816001811115613b3557613b3561555f565b14613b6c576040517f4b9c6abe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8451613b788385615933565b14613baf576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808252610420820190925290816020015b6040805180820190915260008082526020820152815260200190600190039081613bc65790505093506000835b8651811015613cb457600080613c396040518060400160405280858c60000151613c1d9190615983565b8152602001858c60200151613c329190615933565b9052614c8c565b509150915060405180604001604052808383613c559190615933565b8152602001848b60200151613c6a9190615933565b815250888581518110613c7f57613c7f6158d5565b6020908102919091010152613c95600185615933565b9350613ca18183615933565b613cab9084615933565b92505050613bf3565b50845250919392505050565b60606000806000613cd085614c8c565b919450925090506000816001811115613ceb57613ceb61555f565b14613d22576040517f1ff9b2e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613d2c8284615933565b855114613d65576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6118848560200151848461512a565b600281015473ffffffffffffffffffffffffffffffffffffffff8316600090815260036020526040812080546fffffffffffffffffffffffffffffffff90931692839290613dc3908490615933565b90915550506040517f7eee288d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018390527f000000000000000000000000ef179756ea6525afade217ca5ab0b1b5cfe0fd921690637eee288d90604401600060405180830381600087803b158015613e5857600080fd5b505af1158015613e6c573d6000803e3d6000fd5b50505050505050565b604051818152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90038284820160208401378260208301016000815260208101604052505092915050565b6000613ee66fffffffffffffffffffffffffffffffff84166001615b36565b90506000613ef682866001614608565b9050600086901a8380613fe25750613f2f60027f0000000000000000000000000000000000000000000000000000000000000004615af9565b6004830154600290613fd3906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b613fdd9190615c07565b60ff16145b1561403a5760ff811660011480613ffc575060ff81166002145b614035576040517ff40239db00000000000000000000000000000000000000000000000000000000815260048101889052602401612752565b613e6c565b60ff811615613e6c576040517ff40239db00000000000000000000000000000000000000000000000000000000815260048101889052602401612752565b6fffffffffffffffffffffffffffffffff811160071b81811c67ffffffffffffffff1060061b1781811c63ffffffff1060051b1781811c61ffff1060041b1781811c60ff1060031b17600082136140d757631615e6386000526004601cfd5b7ff8f9f9faf9fdfafbf9fdfcfdfafbfcfef9fafdfafcfcfbfefafafcfbffffffff6f8421084210842108cc6318c6db6d54be83831c1c601f161a1890811b609f90811c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506029190037d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b302017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d90565b60007812725dd1d243aba0e75fe645cc4873f9e65afe688c928e1f218311670de0b6b3a76400000215820261431057637c5f487d6000526004601cfd5b50670de0b6b3a7640000919091020490565b6000816000190483118202156143405763bac65e5b6000526004601cfd5b50670de0b6b3a764000091020490565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdc0d0570925a462d7821361437e57919050565b680755bf798b4a1bf1e5821261439c5763a37bfec96000526004601cfd5b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b6000613a38670de0b6b3a76400008361455086614078565b61455a9190615c29565b6145649190615ce5565b614350565b6000806145f6837e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b600160ff919091161b90920392915050565b600080826146515761464c6fffffffffffffffffffffffffffffffff86167f00000000000000000000000000000000000000000000000000000000000000046151bf565b61466c565b61466c856fffffffffffffffffffffffffffffffff1661534b565b905060028481548110614681576146816158d5565b906000526020600020906005020191505b60048201546fffffffffffffffffffffffffffffffff8281169116146146e457815460028054909163ffffffff169081106146cf576146cf6158d5565b90600052602060002090600502019150614692565b509392505050565b60008060008060006146fd8661471b565b935093509350935061471184848484614b24565b9695505050505050565b600080600080600085905060006002828154811061473b5761473b6158d5565b600091825260209091206004600590920201908101549091507f000000000000000000000000000000000000000000000000000000000000000490614812906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff161161484c576040517fb34b5c2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000815b60048301547f000000000000000000000000000000000000000000000000000000000000000490614913906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff16925082111561498857825463ffffffff166149527f00000000000000000000000000000000000000000000000000000000000000046001615933565b830361495c578391505b6002818154811061496f5761496f6158d5565b9060005260206000209060050201935080945050614850565b600481810154908401546fffffffffffffffffffffffffffffffff91821691166000816fffffffffffffffffffffffffffffffff166149f16149dc856fffffffffffffffffffffffffffffffff1660011c90565b6fffffffffffffffffffffffffffffffff1690565b6fffffffffffffffffffffffffffffffff161490508015614ac0576000614a29836fffffffffffffffffffffffffffffffff16614569565b6fffffffffffffffffffffffffffffffff161115614a94576000614a6b614a6360016fffffffffffffffffffffffffffffffff8616615b0d565b896001614608565b6003810154600490910154909c506fffffffffffffffffffffffffffffffff169a50614a9a9050565b6008549a505b600386015460048701549099506fffffffffffffffffffffffffffffffff169750614b16565b6000614ae2614a636fffffffffffffffffffffffffffffffff85166001615b36565b6003808901546004808b015492840154930154909e506fffffffffffffffffffffffffffffffff9182169d50919b50169850505b505050505050509193509193565b60006fffffffffffffffffffffffffffffffff841615614b915760408051602081018790526fffffffffffffffffffffffffffffffff8087169282019290925260608101859052908316608082015260a00160405160208183030381529060405280519060200120611884565b8282604051602001614bbf9291909182526fffffffffffffffffffffffffffffffff16602082015260400190565b6040516020818303038152906040528051906020012095945050505050565b600080614c6b847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690508083036001841b600180831b0386831b17039250505092915050565b60008060008360000151600003614ccf576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020840151805160001a607f8111614cf4576000600160009450945094505050615123565b60b78111614e0a576000614d09608083615983565b905080876000015111614d48576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001838101517fff00000000000000000000000000000000000000000000000000000000000000169082148015614dc057507f80000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008216105b15614df7576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5060019550935060009250615123915050565b60bf8111614f68576000614e1f60b783615983565b905080876000015111614e5e576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614ec0576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c60378111614f08576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614f128184615933565b895111614f4b576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614f56836001615933565b97509550600094506151239350505050565b60f78111614fcd576000614f7d60c083615983565b905080876000015111614fbc576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600195509350849250615123915050565b6000614fda60f783615983565b905080876000015111615019576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff0000000000000000000000000000000000000000000000000000000000000016600081900361507b576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c603781116150c3576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6150cd8184615933565b895111615106576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b615111836001615933565b97509550600194506151239350505050565b9193909250565b60608167ffffffffffffffff81111561514557615145615809565b6040519080825280601f01601f19166020018201604052801561516f576020820181803683370190505b50905081156151b85760006151848486615933565b90506020820160005b848110156151a557828101518282015260200161518d565b848111156151b4576000858301525b5050505b9392505050565b60008161525e846fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff16116152745763b34b5c226000526004601cfd5b61527d8361534b565b90508161531c826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1611613a3b57613a38615332836001615933565b6fffffffffffffffffffffffffffffffff8316906153f0565b600081196001830116816153df827e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169390931c8015179392505050565b60008061547d847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169050808303600180821b0385821b179250505092915050565b60008083601f8401126154ab57600080fd5b50813567ffffffffffffffff8111156154c357600080fd5b6020830191508360208285010111156154db57600080fd5b9250929050565b600080600083850360a08112156154f857600080fd5b608081121561550657600080fd5b50839250608084013567ffffffffffffffff81111561552457600080fd5b61553086828701615499565b9497909650939450505050565b6000806040838503121561555057600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60208101600383106155c9577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b6000806000606084860312156155e457600080fd5b505081359360208301359350604090920135919050565b6000815180845260005b8181101561562157602081850181015186830182015201615605565b81811115615633576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000613a3860208301846155fb565b60006020828403121561568b57600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff811681146156b457600080fd5b50565b6000602082840312156156c957600080fd5b81356151b881615692565b803580151581146156e457600080fd5b919050565b600080600080608085870312156156ff57600080fd5b84359350602085013592506040850135915061571d606086016156d4565b905092959194509250565b60006020828403121561573a57600080fd5b81356fffffffffffffffffffffffffffffffff811681146151b857600080fd5b6000806000806000806080878903121561577357600080fd5b86359550615783602088016156d4565b9450604087013567ffffffffffffffff808211156157a057600080fd5b6157ac8a838b01615499565b909650945060608901359150808211156157c557600080fd5b506157d289828a01615499565b979a9699509497509295939492505050565b63ffffffff8416815282602082015260606040820152600061188460608301846155fb565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006080828403121561584a57600080fd5b6040516080810181811067ffffffffffffffff82111715615894577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561594657615946615904565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361597c5761597c615904565b5060010190565b60008282101561599557615995615904565b500390565b6000602082840312156159ac57600080fd5b81516151b881615692565b6000602082840312156159c957600080fd5b5051919050565b600067ffffffffffffffff8083168185168083038211156159f3576159f3615904565b01949350505050565b600067ffffffffffffffff80831681851681830481118215151615615a2357615a23615904565b02949350505050565b600067ffffffffffffffff83811690831681811015615a4d57615a4d615904565b039392505050565b60008060408385031215615a6857600080fd5b505080516020909101519092909150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082615ab757615ab7615a79565b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615af457615af4615904565b500290565b600082615b0857615b08615a79565b500690565b60006fffffffffffffffffffffffffffffffff83811690831681811015615a4d57615a4d615904565b60006fffffffffffffffffffffffffffffffff8083168185168083038211156159f3576159f3615904565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b606081526000615bbe606083018789615b61565b8281036020840152615bd1818688615b61565b9150508260408301529695505050505050565b600060ff821660ff841680821015615bfe57615bfe615904565b90039392505050565b600060ff831680615c1a57615c1a615a79565b8060ff84160691505092915050565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600084136000841385830485118282161615615c6a57615c6a615904565b7f80000000000000000000000000000000000000000000000000000000000000006000871286820588128184161615615ca557615ca5615904565b60008712925087820587128484161615615cc157615cc1615904565b87850587128184161615615cd757615cd7615904565b505050929093029392505050565b600082615cf457615cf4615a79565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f800000000000000000000000000000000000000000000000000000000000000083141615615d4857615d48615904565b50059056fea164736f6c634300080f000a", - "initialized": true, - "kind": "Create", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [], - "value": 0 - }, - { - "accessor": "0xb6b1579AA54e2F61e621a40d5F2704D717B3544F", - "account": "0x444e09fe6D839273316a87002aB0EFBeA6fe7806", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x7dc0d1d0", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [], - "value": 0 - }, - { - "accessor": "0xb6b1579AA54e2F61e621a40d5F2704D717B3544F", - "account": "0x373d916D11cce55b548F7051002e76BCFBD7a85d", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xf3f480d9", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [], - "value": 0 - }, - { - "accessor": "0xb6b1579AA54e2F61e621a40d5F2704D717B3544F", - "account": "0x444e09fe6D839273316a87002aB0EFBeA6fe7806", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x7dc0d1d0", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [], - "value": 0 - }, - { - "accessor": "0xb6b1579AA54e2F61e621a40d5F2704D717B3544F", - "account": "0x373d916D11cce55b548F7051002e76BCFBD7a85d", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xf3f480d9", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [], - "value": 0 - }, - { - "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", - "account": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "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": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x14f6b1a30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b6b1579aa54e2f61e621a40d5f2704d717b3544f", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "isWrite": false, - "newValue": "0x00000000000000000000000020b168142354cee65a32f6d8cf3033e592299765", - "previousValue": "0x00000000000000000000000020b168142354cee65a32f6d8cf3033e592299765", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x20B168142354Cee65a32f6D8cf3033E592299765", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x14f6b1a30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b6b1579aa54e2f61e621a40d5f2704d717b3544f", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "isWrite": false, - "newValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", - "previousValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - }, - { - "account": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0xffdfc1249c027f9191656349feb0761381bb32c9f557e01f419fd08754bf5a1b" - }, - { - "account": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "isWrite": true, - "newValue": "0x000000000000000000000000b6b1579aa54e2f61e621a40d5f2704d717b3544f", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0xffdfc1249c027f9191656349feb0761381bb32c9f557e01f419fd08754bf5a1b" - } - ], - "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": "0x935e3829", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000034" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x935e3829", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000034" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x0b7b1b30", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000008", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000008", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000037" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x9110ec4a", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x00000000000000000000000000000000000000000000000000000000000004b0", - "previousValue": "0x00000000000000000000000000000000000000000000000000000000000004b0", - "reverted": false, - "slot": "0x000000000000000000000000000000000000000000000000000000000000003a" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x1b685b9e0000000000000000000000000000000000000000000000000000000000000001", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "isWrite": false, - "newValue": "0x00000000000000000000000020b168142354cee65a32f6d8cf3033e592299765", - "previousValue": "0x00000000000000000000000020b168142354cee65a32f6d8cf3033e592299765", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x20B168142354Cee65a32f6D8cf3033E592299765", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x1b685b9e0000000000000000000000000000000000000000000000000000000000000001", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x4d5a9bd2e41301728d41c8e705190becb4e74abe869f75bdb405b63716a35f9e" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xe1a05cc3", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000004", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000004", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000038" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xdb75b649", - "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": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x9110ec4a", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x00000000000000000000000000000000000000000000000000000000000004b0", - "previousValue": "0x00000000000000000000000000000000000000000000000000000000000004b0", - "reverted": false, - "slot": "0x000000000000000000000000000000000000000000000000000000000000003a" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xa2af0d1f", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000385", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000385", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000011" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x241e2d7e", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8", - "previousValue": "0x00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000020" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x08cb822d", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b63", - "previousValue": "0x0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b63", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000021" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x59B99034FBdd5E554661a2100cB2b6b7C5d495F8", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x6102006040523480156200001257600080fd5b506040516200678d3803806200678d833981016040819052620000359162000469565b8b8b8b8b8b8b8b8b8b8b6200004d6001607e6200055c565b60ff168811156200007157604051633beff19960e11b815260040160405180910390fd5b6000198714806200008e5750876200008b88600162000582565b10155b15620000ad5760405163e62ccf3960e01b815260040160405180910390fd5b6002871015620000d05760405163e62ccf3960e01b815260040160405180910390fd5b6001600160401b038016846001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000119573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200013f91906200059d565b6001600160a01b031663f3f480d96040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200017d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001a39190620005bd565b1115620001c35760405163b4e1243360e01b815260040160405180910390fd5b6000620001e4876001600160401b03166200040860201b62000d051760201c565b620001fa906001600160401b03166002620005d7565b90506000856001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200023d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200026391906200059d565b6001600160a01b031663f3f480d96040518163ffffffff1660e01b8152600401602060405180830381865afa158015620002a1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002c79190620005bd565b620002e6896001600160401b03166200040860201b62000d051760201c565b6001600160401b0316620002fb919062000582565b905060006200031683836200040b60201b620026401760201c565b90506001600160401b03811115620003415760405163235dfb2b60e21b815260040160405180910390fd5b62000360886001600160401b03166200040860201b62000d051760201c565b6001600160401b0316816001600160401b03161115620003935760405163235dfb2b60e21b815260040160405180910390fd5b50505063ffffffff9099166101205260809790975260a09590955260c0939093526001600160401b039182166101a0521660e0526001600160a01b03908116610100529081166101405290811661016052610180919091529182166101c052166101e05250620005f998505050505050505050565b90565b6000818310156200041d57816200041f565b825b9392505050565b80516001600160401b03811681146200043e57600080fd5b919050565b6001600160a01b03811681146200045957600080fd5b50565b80516200043e8162000443565b6000806000806000806000806000806000806101808d8f0312156200048d57600080fd5b8c5163ffffffff81168114620004a257600080fd5b809c505060208d01519a5060408d0151995060608d01519850620004c960808e0162000426565b9750620004d960a08e0162000426565b9650620004e960c08e016200045c565b9550620004f960e08e016200045c565b94506200050a6101008e016200045c565b93506101208d01519250620005236101408e016200045c565b9150620005346101608e016200045c565b90509295989b509295989b509295989b565b634e487b7160e01b600052601160045260246000fd5b600060ff821660ff84168082101562000579576200057962000546565b90039392505050565b6000821982111562000598576200059862000546565b500190565b600060208284031215620005b057600080fd5b81516200041f8162000443565b600060208284031215620005d057600080fd5b5051919050565b6000816000190483118215151615620005f457620005f462000546565b500290565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c0516101e051615fd5620007b86000396000818161058301528181611b1501526120b50152600081816108ce01528181611ad601528181611ba401526120760152600081816107040152818161305a015281816130c501526130f8015260008181610a9a015261255301526000818161065c01528181611806015261367a01526000818161053d015281816119c801528181612a2e0152818161351f0152613a7c015260008181610909015281816125e201526136390152600081816104ca015281816121b101528181612f59015261436c015260008181610aed01528181610fdc01528181611d7a01528181611dbc01528181612ec9015281816131280152613187015260008181610b20015281816123b001528181612d1201528181612e3801528181613096015281816141bf0152818161466e0152818161476f015281816148440152818161511b0152615347015260008181610bc701528181611e8a01528181611f1001528181612ddb01528181612f2d015281816140b501526141e00152600081816107cf015261427e0152615fd56000f3fe6080604052600436106103085760003560e01c806370872aa51161019a578063c6f0308c116100e1578063ec5e63081161008a578063fa24f74311610064578063fa24f74314610b94578063fa315aa914610bb8578063fe2bbeb214610beb57600080fd5b8063ec5e630814610b11578063eff0f59214610b44578063f8f43ff614610b7457600080fd5b8063d6ae3cd5116100bb578063d6ae3cd514610a8b578063d8cc1a3c14610abe578063dabd396d14610ade57600080fd5b8063c6f0308c146109b3578063cf09e0d014610a3d578063d5d44d8014610a5e57600080fd5b8063a445ece611610143578063bcef3b551161011d578063bcef3b5514610933578063bd8da95614610973578063c395e1ca1461099357600080fd5b8063a445ece6146107f3578063a8e4fb90146108bf578063bbdc02db146108f257600080fd5b80638980e0cc116101745780638980e0cc1461076b5780638b85902b146107805780638d450a95146107c057600080fd5b806370872aa51461073b5780637b0f0adc146107505780638129fc1c1461076357600080fd5b80633fc8cef31161025e5780635c0cba33116102075780636361506d116101e15780636361506d146106b55780636b6716c0146106f55780636f0344091461072857600080fd5b80635c0cba331461064d578063609d33341461068057806360e274641461069557600080fd5b806354fd4d501161023857806354fd4d50146105a757806357da950e146105fd5780635a5fa2d91461062d57600080fd5b80633fc8cef31461052e578063472777c614610561578063534db0e21461057457600080fd5b80632810e1d6116102c057806337b1b2291161029a57806337b1b2291461047b5780633a768463146104bb5780633e3ac912146104ee57600080fd5b80632810e1d6146103f45780632ad69aeb1461040957806330dbe5701461042957600080fd5b806319effeb4116102f157806319effeb41461034f578063200d2ed21461039a57806325fc2ace146103d557600080fd5b8063019351301461030d57806303c2924d1461032f575b600080fd5b34801561031957600080fd5b5061032d61032836600461575d565b610c1b565b005b34801561033b57600080fd5b5061032d61034a3660046157b8565b610f3c565b34801561035b57600080fd5b5060005461037c9068010000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020015b60405180910390f35b3480156103a657600080fd5b506000546103c890700100000000000000000000000000000000900460ff1681565b6040516103919190615809565b3480156103e157600080fd5b506008545b604051908152602001610391565b34801561040057600080fd5b506103c86115e2565b34801561041557600080fd5b506103e66104243660046157b8565b611887565b34801561043557600080fd5b506001546104569073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610391565b34801561048757600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90033560601c610456565b3480156104c757600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610456565b3480156104fa57600080fd5b5060005461051e907201000000000000000000000000000000000000900460ff1681565b6040519015158152602001610391565b34801561053a57600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610456565b61032d61056f36600461584a565b6118bd565b34801561058057600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610456565b3480156105b357600080fd5b506105f06040518060400160405280600a81526020017f312e332e302d72632e310000000000000000000000000000000000000000000081525081565b60405161039191906158e1565b34801561060957600080fd5b50600854600954610618919082565b60408051928352602083019190915201610391565b34801561063957600080fd5b506103e66106483660046158f4565b6118cf565b34801561065957600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610456565b34801561068c57600080fd5b506105f0611909565b3480156106a157600080fd5b5061032d6106b0366004615932565b611917565b3480156106c157600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003603401356103e6565b34801561070157600080fd5b507f000000000000000000000000000000000000000000000000000000000000000061037c565b61032d610736366004615964565b611abe565b34801561074757600080fd5b506009546103e6565b61032d61075e36600461584a565b611b7f565b61032d611b8c565b34801561077757600080fd5b506002546103e6565b34801561078c57600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401356103e6565b3480156107cc57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006103e6565b3480156107ff57600080fd5b5061086b61080e3660046158f4565b6007602052600090815260409020805460019091015460ff821691610100810463ffffffff1691650100000000009091046fffffffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff1684565b60408051941515855263ffffffff90931660208501526fffffffffffffffffffffffffffffffff9091169183019190915273ffffffffffffffffffffffffffffffffffffffff166060820152608001610391565b3480156108cb57600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610456565b3480156108fe57600080fd5b5060405163ffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610391565b34801561093f57600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003601401356103e6565b34801561097f57600080fd5b5061037c61098e3660046158f4565b611c05565b34801561099f57600080fd5b506103e66109ae3660046159a3565b611de4565b3480156109bf57600080fd5b506109d36109ce3660046158f4565b611fc7565b6040805163ffffffff909816885273ffffffffffffffffffffffffffffffffffffffff968716602089015295909416948601949094526fffffffffffffffffffffffffffffffff9182166060860152608085015291821660a08401521660c082015260e001610391565b348015610a4957600080fd5b5060005461037c9067ffffffffffffffff1681565b348015610a6a57600080fd5b506103e6610a79366004615932565b60036020526000908152604090205481565b348015610a9757600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006103e6565b348015610aca57600080fd5b5061032d610ad93660046159d5565b61205e565b348015610aea57600080fd5b507f000000000000000000000000000000000000000000000000000000000000000061037c565b348015610b1d57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006103e6565b348015610b5057600080fd5b5061051e610b5f3660046158f4565b60046020526000908152604090205460ff1681565b348015610b8057600080fd5b5061032d610b8f36600461584a565b612123565b348015610ba057600080fd5b50610ba96125e0565b60405161039193929190615a5f565b348015610bc457600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006103e6565b348015610bf757600080fd5b5061051e610c063660046158f4565b60066020526000908152604090205460ff1681565b60008054700100000000000000000000000000000000900460ff166002811115610c4757610c476157da565b14610c7e576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000547201000000000000000000000000000000000000900460ff1615610cd1576040517f0ea2e75200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d08367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013590565b90565b610d1f610d1a36869003860186615ab3565b61265b565b14610d56576040517f9cc00b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82606001358282604051610d6b929190615b40565b604051809103902014610daa576040517fd81d583b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610df3610dee84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506126b792505050565b612724565b90506000610e1a82600881518110610e0d57610e0d615b50565b60200260200101516128da565b9050602081511115610e58576040517fd81d583b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602081810151825190910360031b1c367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401358103610ecd576040517fb8ed883000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050600180547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790555050600080547fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff1672010000000000000000000000000000000000001790555050565b60008054700100000000000000000000000000000000900460ff166002811115610f6857610f686157da565b14610f9f576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028381548110610fb457610fb4615b50565b906000526020600020906005020190506000610fcf84611c05565b905067ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081169082161015611038576040517ff2440b5300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008481526006602052604090205460ff1615611081576040517ff1a9458100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600084815260056020526040902080548015801561109e57508515155b15611139578354640100000000900473ffffffffffffffffffffffffffffffffffffffff16600081156110d157816110ed565b600186015473ffffffffffffffffffffffffffffffffffffffff165b90506110f9818761298e565b50505060009485525050600660205250506040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b6000868152600760209081526040918290208251608081018452815460ff81161515808352610100820463ffffffff16948301949094526501000000000090046fffffffffffffffffffffffffffffffff16938101939093526001015473ffffffffffffffffffffffffffffffffffffffff1660608301526111dc576fffffffffffffffffffffffffffffffff60408201526001815260008690036111dc578195505b600086826020015163ffffffff166111f49190615bae565b905060008382116112055781611207565b835b602084015190915063ffffffff165b8181101561135357600086828154811061123257611232615b50565b6000918252602080832090910154808352600690915260409091205490915060ff1661128a576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006002828154811061129f5761129f615b50565b600091825260209091206005909102018054909150640100000000900473ffffffffffffffffffffffffffffffffffffffff161580156112fc5750600481015460408701516fffffffffffffffffffffffffffffffff9182169116115b1561133e57600181015473ffffffffffffffffffffffffffffffffffffffff16606087015260048101546fffffffffffffffffffffffffffffffff1660408701525b5050808061134b90615bc6565b915050611216565b5063ffffffff818116602085810191825260008c81526007909152604090819020865181549351928801517fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009094169015157fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ff161761010092909416918202939093177fffffffffffffffffffffff00000000000000000000000000000000ffffffffff16650100000000006fffffffffffffffffffffffffffffffff909316929092029190911782556060850151600190920180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909316929092179091558490036115d757606083015160008a815260066020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055891580156114d357506000547201000000000000000000000000000000000000900460ff165b156115485760015473ffffffffffffffffffffffffffffffffffffffff166114fb818a61298e565b885473ffffffffffffffffffffffffffffffffffffffff909116640100000000027fffffffffffffffff0000000000000000000000000000000000000000ffffffff9091161788556115d5565b61158f73ffffffffffffffffffffffffffffffffffffffff82161561156d5781611589565b600189015473ffffffffffffffffffffffffffffffffffffffff165b8961298e565b87547fffffffffffffffff0000000000000000000000000000000000000000ffffffff1664010000000073ffffffffffffffffffffffffffffffffffffffff8316021788555b505b505050505050505050565b600080600054700100000000000000000000000000000000900460ff166002811115611610576116106157da565b14611647576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000805260066020527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f85460ff166116ab576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660026000815481106116d7576116d7615b50565b6000918252602090912060059091020154640100000000900473ffffffffffffffffffffffffffffffffffffffff1614611712576001611715565b60025b6000805467ffffffffffffffff421668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff82168117835592935083927fffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffff000000000000000000ffffffffffffffff909116177001000000000000000000000000000000008360028111156117c6576117c66157da565b0217905560028111156117db576117db6157da565b6040517f5e186f09b9c93491f14e277eea7faa5de6a2d4bda75a79af7a3684fbfb42da6090600090a27f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663838c2d1e6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561186c57600080fd5b505af1158015611880573d6000803e3d6000fd5b5050505090565b600560205281600052604060002081815481106118a357600080fd5b90600052602060002001600091509150505481565b905090565b6118ca8383836001611abe565b505050565b6000818152600760209081526040808320600590925282208054825461190090610100900463ffffffff1682615bfe565b95945050505050565b60606118b860546020612a8f565b73ffffffffffffffffffffffffffffffffffffffff811660009081526003602052604081208054908290559081900361197c576040517f17bfe5f700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517ff3fef3a300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063f3fef3a390604401600060405180830381600087803b158015611a0c57600080fd5b505af1158015611a20573d6000803e3d6000fd5b5050505060008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114611a7e576040519150601f19603f3d011682016040523d82523d6000602084013e611a83565b606091505b50509050806118ca576040517f83e6cc6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161480611b3757503373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016145b611b6d576040517fd386ef3e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611b7984848484612ae1565b50505050565b6118ca8383836000611abe565b3273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614611bfb576040517fd386ef3e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611c036135ba565b565b600080600054700100000000000000000000000000000000900460ff166002811115611c3357611c336157da565b14611c6a576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028381548110611c7f57611c7f615b50565b600091825260208220600590910201805490925063ffffffff90811614611cee57815460028054909163ffffffff16908110611cbd57611cbd615b50565b906000526020600020906005020160040160109054906101000a90046fffffffffffffffffffffffffffffffff1690505b6004820154600090611d2690700100000000000000000000000000000000900467ffffffffffffffff165b67ffffffffffffffff1690565b611d3a9067ffffffffffffffff1642615bfe565b611d59611d19846fffffffffffffffffffffffffffffffff1660401c90565b67ffffffffffffffff16611d6d9190615bae565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001667ffffffffffffffff168167ffffffffffffffff1611611dba5780611900565b7f000000000000000000000000000000000000000000000000000000000000000095945050505050565b600080611e83836fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690507f0000000000000000000000000000000000000000000000000000000000000000811115611ee2576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b642e90edd00062061a806311e1a3006000611efd8383615c44565b9050670de0b6b3a76400006000611f34827f0000000000000000000000000000000000000000000000000000000000000000615c58565b90506000611f52611f4d670de0b6b3a764000086615c58565b613b13565b90506000611f608484613d6e565b90506000611f6e8383613dbd565b90506000611f7b82613deb565b90506000611f9a82611f95670de0b6b3a76400008f615c58565b613fd3565b90506000611fa88b83613dbd565b9050611fb4818d615c58565b9f9e505050505050505050505050505050565b60028181548110611fd757600080fd5b60009182526020909120600590910201805460018201546002830154600384015460049094015463ffffffff8416955064010000000090930473ffffffffffffffffffffffffffffffffffffffff908116949216926fffffffffffffffffffffffffffffffff91821692918082169170010000000000000000000000000000000090041687565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614806120d757503373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016145b61210d576040517fd386ef3e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61211b868686868686614004565b505050505050565b60008054700100000000000000000000000000000000900460ff16600281111561214f5761214f6157da565b14612186576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060008061219586614633565b935093509350935060006121ab85858585614a3c565b905060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561221a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061223e9190615c95565b9050600189036123365773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a8461229a367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036034013590565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815260048101939093526024830191909152604482015260206064820152608481018a905260a4015b6020604051808303816000875af115801561230c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123309190615cb2565b506115d7565b600289036123625773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a848961229a565b6003890361238e5773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a848761229a565b600489036125155760006123d46fffffffffffffffffffffffffffffffff85167f0000000000000000000000000000000000000000000000000000000000000000614af6565b6009546123e19190615bae565b6123ec906001615bae565b9050367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360540135811061245557367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360540135612457565b805b905073ffffffffffffffffffffffffffffffffffffffff82166352f0f3ad8b8560405160e084901b7fffffffff000000000000000000000000000000000000000000000000000000001681526004810192909252602482015260c084901b604482015260086064820152608481018b905260a4016020604051808303816000875af11580156124ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061250e9190615cb2565b50506115d7565b600589036125ae576040517f52f0f3ad000000000000000000000000000000000000000000000000000000008152600481018a9052602481018390527f000000000000000000000000000000000000000000000000000000000000000060c01b6044820152600860648201526084810188905273ffffffffffffffffffffffffffffffffffffffff8216906352f0f3ad9060a4016122ed565b6040517fff137e6500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000000367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003601401356060612639611909565b9050909192565b6000818310156126505781612652565b825b90505b92915050565b6000816000015182602001518360400151846060015160405160200161269a949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b60408051808201909152600080825260208201528151600003612706576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50604080518082019091528151815260209182019181019190915290565b6060600080600061273485614ba4565b91945092509050600181600181111561274f5761274f6157da565b14612786576040517f4b9c6abe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84516127928385615bae565b146127c9576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808252610420820190925290816020015b60408051808201909152600080825260208201528152602001906001900390816127e05790505093506000835b86518110156128ce576000806128536040518060400160405280858c600001516128379190615bfe565b8152602001858c6020015161284c9190615bae565b9052614ba4565b50915091506040518060400160405280838361286f9190615bae565b8152602001848b602001516128849190615bae565b81525088858151811061289957612899615b50565b60209081029190910101526128af600185615bae565b93506128bb8183615bae565b6128c59084615bae565b9250505061280d565b50845250919392505050565b606060008060006128ea85614ba4565b919450925090506000816001811115612905576129056157da565b1461293c576040517f1ff9b2e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6129468284615bae565b85511461297f576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61190085602001518484615042565b600281015473ffffffffffffffffffffffffffffffffffffffff8316600090815260036020526040812080546fffffffffffffffffffffffffffffffff909316928392906129dd908490615bae565b90915550506040517f7eee288d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018390527f00000000000000000000000000000000000000000000000000000000000000001690637eee288d90604401600060405180830381600087803b158015612a7257600080fd5b505af1158015612a86573d6000803e3d6000fd5b50505050505050565b604051818152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90038284820160208401378260208301016000815260208101604052505092915050565b60008054700100000000000000000000000000000000900460ff166002811115612b0d57612b0d6157da565b14612b44576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028481548110612b5957612b59615b50565b60009182526020918290206040805160e0810182526005909302909101805463ffffffff8116845273ffffffffffffffffffffffffffffffffffffffff64010000000090910481169484019490945260018101549093169082015260028201546fffffffffffffffffffffffffffffffff908116606083015260038301546080830181905260049093015480821660a084015270010000000000000000000000000000000090041660c082015291508514612c40576040517f3014033200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60a0810151600083156fffffffffffffffffffffffffffffffff83161760011b90506000612d00826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169050861580612d3b5750612d387f00000000000000000000000000000000000000000000000000000000000000006002615bae565b81145b8015612d45575084155b15612d7c576040517fa42637bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000547201000000000000000000000000000000000000900460ff168015612da2575086155b15612dd9576040517f0ea2e75200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000000811115612e33576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612e5e7f00000000000000000000000000000000000000000000000000000000000000006001615bae565b8103612e7057612e70868885886150d7565b34612e7a83611de4565b14612eb1576040517f8620aa1900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612ebc88611c05565b905067ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811690821603612f24576040517f3381d11400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612f5160017f0000000000000000000000000000000000000000000000000000000000000000615bfe565b830361308f577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015612fc2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fe69190615c95565b73ffffffffffffffffffffffffffffffffffffffff1663f3f480d96040518163ffffffff1660e01b8152600401602060405180830381865afa158015613030573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130549190615cb2565b613088907f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff16615ccb565b9050613122565b6130ba60017f0000000000000000000000000000000000000000000000000000000000000000615bfe565b83036130f5576130887f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff166002615cf7565b507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff165b613156817f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff16615d27565b67ffffffffffffffff166131718367ffffffffffffffff1690565b67ffffffffffffffff1611156131b8576131b5817f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff16615d27565b91505b6000604083901b421760008a8152608087901b6fffffffffffffffffffffffffffffffff8d1617602052604081209192509060008181526004602052604090205490915060ff1615613236576040517f80497e3b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60016004600083815260200190815260200160002060006101000a81548160ff02191690831515021790555060026040518060e001604052808d63ffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020013373ffffffffffffffffffffffffffffffffffffffff168152602001346fffffffffffffffffffffffffffffffff1681526020018c8152602001886fffffffffffffffffffffffffffffffff168152602001846fffffffffffffffffffffffffffffffff16815250908060018154018082558091505060019003906000526020600020906005020160009091909190915060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060608201518160020160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055506080820151816003015560a08201518160040160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555060c08201518160040160106101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055505050600560008c815260200190815260200160002060016002805490506134cc9190615bfe565b81546001810183556000928352602083200155604080517fd0e30db0000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169263d0e30db09234926004808301939282900301818588803b15801561356457600080fd5b505af1158015613578573d6000803e3d6000fd5b50506040513393508d92508e91507f9b3245740ec3b155098a55be84957a4da13eaf7f14a8bc6f53126c0b9350f2be90600090a4505050505050505050505050565b60005471010000000000000000000000000000000000900460ff161561360c576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f7258a80700000000000000000000000000000000000000000000000000000000815263ffffffff7f0000000000000000000000000000000000000000000000000000000000000000166004820152600090819073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690637258a807906024016040805180830381865afa1580156136c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136e49190615d50565b909250905081613720576040517f6a6bc3b200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518082019091528281526020018190526008829055600981905536607a1461375357639824bdab6000526004601cfd5b80367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360540135116137ed576040517ff40239db000000000000000000000000000000000000000000000000000000008152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013560048201526024015b60405180910390fd5b6040805160e08101825263ffffffff8082526000602083018181527ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe369081013560f01c90038035606090811c868801908152346fffffffffffffffffffffffffffffffff81811693890193845260149094013560808901908152600160a08a0181815242871660c08c019081526002805493840181558a529a5160059092027f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace81018054995173ffffffffffffffffffffffffffffffffffffffff908116640100000000027fffffffffffffffff000000000000000000000000000000000000000000000000909b1694909c16939093179890981790915592517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5acf87018054918a167fffffffffffffffffffffffff000000000000000000000000000000000000000090921691909117905592517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad0860180549186167fffffffffffffffffffffffffffffffff0000000000000000000000000000000090921691909117905591517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad185015551955182167001000000000000000000000000000000000295909116949094177f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad29091015580547fffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffff167101000000000000000000000000000000000017815583517fd0e30db000000000000000000000000000000000000000000000000000000000815293517f00000000000000000000000000000000000000000000000000000000000000009092169363d0e30db093926004828101939282900301818588803b158015613ac257600080fd5b505af1158015613ad6573d6000803e3d6000fd5b5050600080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000164267ffffffffffffffff161790555050505050565b6fffffffffffffffffffffffffffffffff811160071b81811c67ffffffffffffffff1060061b1781811c63ffffffff1060051b1781811c61ffff1060041b1781811c60ff1060031b1760008213613b7257631615e6386000526004601cfd5b7ff8f9f9faf9fdfafbf9fdfcfdfafbfcfef9fafdfafcfcfbfefafafcfbffffffff6f8421084210842108cc6318c6db6d54be83831c1c601f161a1890811b609f90811c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506029190037d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b302017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d90565b60007812725dd1d243aba0e75fe645cc4873f9e65afe688c928e1f218311670de0b6b3a764000002158202613dab57637c5f487d6000526004601cfd5b50670de0b6b3a7640000919091020490565b600081600019048311820215613ddb5763bac65e5b6000526004601cfd5b50670de0b6b3a764000091020490565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdc0d0570925a462d78213613e1957919050565b680755bf798b4a1bf1e58212613e375763a37bfec96000526004601cfd5b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b6000612652670de0b6b3a764000083613feb86613b13565b613ff59190615d74565b613fff9190615e30565b613deb565b60008054700100000000000000000000000000000000900460ff166002811115614030576140306157da565b14614067576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006002878154811061407c5761407c615b50565b6000918252602082206005919091020160048101549092506fffffffffffffffffffffffffffffffff16908715821760011b90506140db7f00000000000000000000000000000000000000000000000000000000000000006001615bae565b614177826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff16146141b1576040517f5f53dd9800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008089156142a8576142047f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000615bfe565b6001901b614223846fffffffffffffffffffffffffffffffff16615288565b6fffffffffffffffffffffffffffffffff1661423f9190615e98565b1561427c5761427361426460016fffffffffffffffffffffffffffffffff8716615eac565b865463ffffffff166000615327565b6003015461429e565b7f00000000000000000000000000000000000000000000000000000000000000005b91508490506142d2565b600385015491506142cf6142646fffffffffffffffffffffffffffffffff86166001615ed5565b90505b600882901b60088a8a6040516142e9929190615b40565b6040518091039020901b1461432a576040517f696550ff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006143358c61540b565b90506000614344836003015490565b6040517fe14ced320000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063e14ced32906143be908f908f908f908f908a90600401615f49565b6020604051808303816000875af11580156143dd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144019190615cb2565b6004850154911491506000906002906144ac906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b614548896fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b6145529190615f83565b61455c9190615fa6565b60ff16159050811515810361459d576040517ffb4e40dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8754640100000000900473ffffffffffffffffffffffffffffffffffffffff16156145f4576040517f9071e6af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505085547fffffffffffffffff0000000000000000000000000000000000000000ffffffff163364010000000002179095555050505050505050505050565b600080600080600085905060006002828154811061465357614653615b50565b600091825260209091206004600590920201908101549091507f00000000000000000000000000000000000000000000000000000000000000009061472a906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1611614764576040517fb34b5c2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000815b60048301547f00000000000000000000000000000000000000000000000000000000000000009061482b906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1692508211156148a057825463ffffffff1661486a7f00000000000000000000000000000000000000000000000000000000000000006001615bae565b8303614874578391505b6002818154811061488757614887615b50565b9060005260206000209060050201935080945050614768565b600481810154908401546fffffffffffffffffffffffffffffffff91821691166000816fffffffffffffffffffffffffffffffff166149096148f4856fffffffffffffffffffffffffffffffff1660011c90565b6fffffffffffffffffffffffffffffffff1690565b6fffffffffffffffffffffffffffffffff1614905080156149d8576000614941836fffffffffffffffffffffffffffffffff16615288565b6fffffffffffffffffffffffffffffffff1611156149ac57600061498361497b60016fffffffffffffffffffffffffffffffff8616615eac565b896001615327565b6003810154600490910154909c506fffffffffffffffffffffffffffffffff169a506149b29050565b6008549a505b600386015460048701549099506fffffffffffffffffffffffffffffffff169750614a2e565b60006149fa61497b6fffffffffffffffffffffffffffffffff85166001615ed5565b6003808901546004808b015492840154930154909e506fffffffffffffffffffffffffffffffff9182169d50919b50169850505b505050505050509193509193565b60006fffffffffffffffffffffffffffffffff841615614aa95760408051602081018790526fffffffffffffffffffffffffffffffff8087169282019290925260608101859052908316608082015260a00160405160208183030381529060405280519060200120611900565b8282604051602001614ad79291909182526fffffffffffffffffffffffffffffffff16602082015260400190565b6040516020818303038152906040528051906020012095945050505050565b600080614b83847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690508083036001841b600180831b0386831b17039250505092915050565b60008060008360000151600003614be7576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020840151805160001a607f8111614c0c57600060016000945094509450505061503b565b60b78111614d22576000614c21608083615bfe565b905080876000015111614c60576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001838101517fff00000000000000000000000000000000000000000000000000000000000000169082148015614cd857507f80000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008216105b15614d0f576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506001955093506000925061503b915050565b60bf8111614e80576000614d3760b783615bfe565b905080876000015111614d76576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614dd8576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c60378111614e20576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614e2a8184615bae565b895111614e63576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614e6e836001615bae565b975095506000945061503b9350505050565b60f78111614ee5576000614e9560c083615bfe565b905080876000015111614ed4576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60019550935084925061503b915050565b6000614ef260f783615bfe565b905080876000015111614f31576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614f93576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c60378111614fdb576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614fe58184615bae565b89511161501e576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b615029836001615bae565b975095506001945061503b9350505050565b9193909250565b60608167ffffffffffffffff81111561505d5761505d615a84565b6040519080825280601f01601f191660200182016040528015615087576020820181803683370190505b50905081156150d057600061509c8486615bae565b90506020820160005b848110156150bd5782810151828201526020016150a5565b848111156150cc576000858301525b5050505b9392505050565b60006150f66fffffffffffffffffffffffffffffffff84166001615ed5565b9050600061510682866001615327565b9050600086901a83806151f2575061513f60027f0000000000000000000000000000000000000000000000000000000000000000615e98565b60048301546002906151e3906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b6151ed9190615fa6565b60ff16145b1561524a5760ff81166001148061520c575060ff81166002145b615245576040517ff40239db000000000000000000000000000000000000000000000000000000008152600481018890526024016137e4565b612a86565b60ff811615612a86576040517ff40239db000000000000000000000000000000000000000000000000000000008152600481018890526024016137e4565b600080615315837e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b600160ff919091161b90920392915050565b600080826153705761536b6fffffffffffffffffffffffffffffffff86167f000000000000000000000000000000000000000000000000000000000000000061543a565b61538b565b61538b856fffffffffffffffffffffffffffffffff166155c6565b9050600284815481106153a0576153a0615b50565b906000526020600020906005020191505b60048201546fffffffffffffffffffffffffffffffff82811691161461540357815460028054909163ffffffff169081106153ee576153ee615b50565b906000526020600020906005020191506153b1565b509392505050565b600080600080600061541c86614633565b935093509350935061543084848484614a3c565b9695505050505050565b6000816154d9846fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff16116154ef5763b34b5c226000526004601cfd5b6154f8836155c6565b905081615597826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1611612655576126526155ad836001615bae565b6fffffffffffffffffffffffffffffffff83169061566b565b6000811960018301168161565a827e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169390931c8015179392505050565b6000806156f8847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169050808303600180821b0385821b179250505092915050565b60008083601f84011261572657600080fd5b50813567ffffffffffffffff81111561573e57600080fd5b60208301915083602082850101111561575657600080fd5b9250929050565b600080600083850360a081121561577357600080fd5b608081121561578157600080fd5b50839250608084013567ffffffffffffffff81111561579f57600080fd5b6157ab86828701615714565b9497909650939450505050565b600080604083850312156157cb57600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6020810160038310615844577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b60008060006060848603121561585f57600080fd5b505081359360208301359350604090920135919050565b6000815180845260005b8181101561589c57602081850181015186830182015201615880565b818111156158ae576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006126526020830184615876565b60006020828403121561590657600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff8116811461592f57600080fd5b50565b60006020828403121561594457600080fd5b81356150d08161590d565b8035801515811461595f57600080fd5b919050565b6000806000806080858703121561597a57600080fd5b8435935060208501359250604085013591506159986060860161594f565b905092959194509250565b6000602082840312156159b557600080fd5b81356fffffffffffffffffffffffffffffffff811681146150d057600080fd5b600080600080600080608087890312156159ee57600080fd5b863595506159fe6020880161594f565b9450604087013567ffffffffffffffff80821115615a1b57600080fd5b615a278a838b01615714565b90965094506060890135915080821115615a4057600080fd5b50615a4d89828a01615714565b979a9699509497509295939492505050565b63ffffffff841681528260208201526060604082015260006119006060830184615876565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600060808284031215615ac557600080fd5b6040516080810181811067ffffffffffffffff82111715615b0f577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115615bc157615bc1615b7f565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203615bf757615bf7615b7f565b5060010190565b600082821015615c1057615c10615b7f565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082615c5357615c53615c15565b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615c9057615c90615b7f565b500290565b600060208284031215615ca757600080fd5b81516150d08161590d565b600060208284031215615cc457600080fd5b5051919050565b600067ffffffffffffffff808316818516808303821115615cee57615cee615b7f565b01949350505050565b600067ffffffffffffffff80831681851681830481118215151615615d1e57615d1e615b7f565b02949350505050565b600067ffffffffffffffff83811690831681811015615d4857615d48615b7f565b039392505050565b60008060408385031215615d6357600080fd5b505080516020909101519092909150565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600084136000841385830485118282161615615db557615db5615b7f565b7f80000000000000000000000000000000000000000000000000000000000000006000871286820588128184161615615df057615df0615b7f565b60008712925087820587128484161615615e0c57615e0c615b7f565b87850587128184161615615e2257615e22615b7f565b505050929093029392505050565b600082615e3f57615e3f615c15565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f800000000000000000000000000000000000000000000000000000000000000083141615615e9357615e93615b7f565b500590565b600082615ea757615ea7615c15565b500690565b60006fffffffffffffffffffffffffffffffff83811690831681811015615d4857615d48615b7f565b60006fffffffffffffffffffffffffffffffff808316818516808303821115615cee57615cee615b7f565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b606081526000615f5d606083018789615f00565b8281036020840152615f70818688615f00565b9150508260408301529695505050505050565b600060ff821660ff841680821015615f9d57615f9d615b7f565b90039392505050565b600060ff831680615fb957615fb9615c15565b8060ff8416069150509291505056fea164736f6c634300080f000a0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004b0000000000000000000000000444e09fe6d839273316a87002ab0efbea6fe7806000000000000000000000000d6eaf4c146261653ee059077b78ed088add54309000000000000000000000000970670459734a83899773a0fd45941b5afc1200e000000000000000000000000000000000000000000000000000000000000038500000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c80000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b63", - "deployedCode": "0x6080604052600436106103085760003560e01c806370872aa51161019a578063c6f0308c116100e1578063ec5e63081161008a578063fa24f74311610064578063fa24f74314610b94578063fa315aa914610bb8578063fe2bbeb214610beb57600080fd5b8063ec5e630814610b11578063eff0f59214610b44578063f8f43ff614610b7457600080fd5b8063d6ae3cd5116100bb578063d6ae3cd514610a8b578063d8cc1a3c14610abe578063dabd396d14610ade57600080fd5b8063c6f0308c146109b3578063cf09e0d014610a3d578063d5d44d8014610a5e57600080fd5b8063a445ece611610143578063bcef3b551161011d578063bcef3b5514610933578063bd8da95614610973578063c395e1ca1461099357600080fd5b8063a445ece6146107f3578063a8e4fb90146108bf578063bbdc02db146108f257600080fd5b80638980e0cc116101745780638980e0cc1461076b5780638b85902b146107805780638d450a95146107c057600080fd5b806370872aa51461073b5780637b0f0adc146107505780638129fc1c1461076357600080fd5b80633fc8cef31161025e5780635c0cba33116102075780636361506d116101e15780636361506d146106b55780636b6716c0146106f55780636f0344091461072857600080fd5b80635c0cba331461064d578063609d33341461068057806360e274641461069557600080fd5b806354fd4d501161023857806354fd4d50146105a757806357da950e146105fd5780635a5fa2d91461062d57600080fd5b80633fc8cef31461052e578063472777c614610561578063534db0e21461057457600080fd5b80632810e1d6116102c057806337b1b2291161029a57806337b1b2291461047b5780633a768463146104bb5780633e3ac912146104ee57600080fd5b80632810e1d6146103f45780632ad69aeb1461040957806330dbe5701461042957600080fd5b806319effeb4116102f157806319effeb41461034f578063200d2ed21461039a57806325fc2ace146103d557600080fd5b8063019351301461030d57806303c2924d1461032f575b600080fd5b34801561031957600080fd5b5061032d61032836600461575d565b610c1b565b005b34801561033b57600080fd5b5061032d61034a3660046157b8565b610f3c565b34801561035b57600080fd5b5060005461037c9068010000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020015b60405180910390f35b3480156103a657600080fd5b506000546103c890700100000000000000000000000000000000900460ff1681565b6040516103919190615809565b3480156103e157600080fd5b506008545b604051908152602001610391565b34801561040057600080fd5b506103c86115e2565b34801561041557600080fd5b506103e66104243660046157b8565b611887565b34801561043557600080fd5b506001546104569073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610391565b34801561048757600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90033560601c610456565b3480156104c757600080fd5b507f000000000000000000000000444e09fe6d839273316a87002ab0efbea6fe7806610456565b3480156104fa57600080fd5b5060005461051e907201000000000000000000000000000000000000900460ff1681565b6040519015158152602001610391565b34801561053a57600080fd5b507f000000000000000000000000d6eaf4c146261653ee059077b78ed088add54309610456565b61032d61056f36600461584a565b6118bd565b34801561058057600080fd5b507f0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b63610456565b3480156105b357600080fd5b506105f06040518060400160405280600a81526020017f312e332e302d72632e310000000000000000000000000000000000000000000081525081565b60405161039191906158e1565b34801561060957600080fd5b50600854600954610618919082565b60408051928352602083019190915201610391565b34801561063957600080fd5b506103e66106483660046158f4565b6118cf565b34801561065957600080fd5b507f000000000000000000000000970670459734a83899773a0fd45941b5afc1200e610456565b34801561068c57600080fd5b506105f0611909565b3480156106a157600080fd5b5061032d6106b0366004615932565b611917565b3480156106c157600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003603401356103e6565b34801561070157600080fd5b507f000000000000000000000000000000000000000000000000000000000000000061037c565b61032d610736366004615964565b611abe565b34801561074757600080fd5b506009546103e6565b61032d61075e36600461584a565b611b7f565b61032d611b8c565b34801561077757600080fd5b506002546103e6565b34801561078c57600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401356103e6565b3480156107cc57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006103e6565b3480156107ff57600080fd5b5061086b61080e3660046158f4565b6007602052600090815260409020805460019091015460ff821691610100810463ffffffff1691650100000000009091046fffffffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff1684565b60408051941515855263ffffffff90931660208501526fffffffffffffffffffffffffffffffff9091169183019190915273ffffffffffffffffffffffffffffffffffffffff166060820152608001610391565b3480156108cb57600080fd5b507f00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8610456565b3480156108fe57600080fd5b5060405163ffffffff7f0000000000000000000000000000000000000000000000000000000000000001168152602001610391565b34801561093f57600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003601401356103e6565b34801561097f57600080fd5b5061037c61098e3660046158f4565b611c05565b34801561099f57600080fd5b506103e66109ae3660046159a3565b611de4565b3480156109bf57600080fd5b506109d36109ce3660046158f4565b611fc7565b6040805163ffffffff909816885273ffffffffffffffffffffffffffffffffffffffff968716602089015295909416948601949094526fffffffffffffffffffffffffffffffff9182166060860152608085015291821660a08401521660c082015260e001610391565b348015610a4957600080fd5b5060005461037c9067ffffffffffffffff1681565b348015610a6a57600080fd5b506103e6610a79366004615932565b60036020526000908152604090205481565b348015610a9757600080fd5b507f00000000000000000000000000000000000000000000000000000000000003856103e6565b348015610aca57600080fd5b5061032d610ad93660046159d5565b61205e565b348015610aea57600080fd5b507f00000000000000000000000000000000000000000000000000000000000004b061037c565b348015610b1d57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000046103e6565b348015610b5057600080fd5b5061051e610b5f3660046158f4565b60046020526000908152604090205460ff1681565b348015610b8057600080fd5b5061032d610b8f36600461584a565b612123565b348015610ba057600080fd5b50610ba96125e0565b60405161039193929190615a5f565b348015610bc457600080fd5b507f00000000000000000000000000000000000000000000000000000000000000086103e6565b348015610bf757600080fd5b5061051e610c063660046158f4565b60066020526000908152604090205460ff1681565b60008054700100000000000000000000000000000000900460ff166002811115610c4757610c476157da565b14610c7e576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000547201000000000000000000000000000000000000900460ff1615610cd1576040517f0ea2e75200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d08367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013590565b90565b610d1f610d1a36869003860186615ab3565b61265b565b14610d56576040517f9cc00b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82606001358282604051610d6b929190615b40565b604051809103902014610daa576040517fd81d583b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610df3610dee84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506126b792505050565b612724565b90506000610e1a82600881518110610e0d57610e0d615b50565b60200260200101516128da565b9050602081511115610e58576040517fd81d583b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602081810151825190910360031b1c367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401358103610ecd576040517fb8ed883000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050600180547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790555050600080547fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff1672010000000000000000000000000000000000001790555050565b60008054700100000000000000000000000000000000900460ff166002811115610f6857610f686157da565b14610f9f576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028381548110610fb457610fb4615b50565b906000526020600020906005020190506000610fcf84611c05565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b081169082161015611038576040517ff2440b5300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008481526006602052604090205460ff1615611081576040517ff1a9458100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600084815260056020526040902080548015801561109e57508515155b15611139578354640100000000900473ffffffffffffffffffffffffffffffffffffffff16600081156110d157816110ed565b600186015473ffffffffffffffffffffffffffffffffffffffff165b90506110f9818761298e565b50505060009485525050600660205250506040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b6000868152600760209081526040918290208251608081018452815460ff81161515808352610100820463ffffffff16948301949094526501000000000090046fffffffffffffffffffffffffffffffff16938101939093526001015473ffffffffffffffffffffffffffffffffffffffff1660608301526111dc576fffffffffffffffffffffffffffffffff60408201526001815260008690036111dc578195505b600086826020015163ffffffff166111f49190615bae565b905060008382116112055781611207565b835b602084015190915063ffffffff165b8181101561135357600086828154811061123257611232615b50565b6000918252602080832090910154808352600690915260409091205490915060ff1661128a576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006002828154811061129f5761129f615b50565b600091825260209091206005909102018054909150640100000000900473ffffffffffffffffffffffffffffffffffffffff161580156112fc5750600481015460408701516fffffffffffffffffffffffffffffffff9182169116115b1561133e57600181015473ffffffffffffffffffffffffffffffffffffffff16606087015260048101546fffffffffffffffffffffffffffffffff1660408701525b5050808061134b90615bc6565b915050611216565b5063ffffffff818116602085810191825260008c81526007909152604090819020865181549351928801517fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009094169015157fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ff161761010092909416918202939093177fffffffffffffffffffffff00000000000000000000000000000000ffffffffff16650100000000006fffffffffffffffffffffffffffffffff909316929092029190911782556060850151600190920180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909316929092179091558490036115d757606083015160008a815260066020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055891580156114d357506000547201000000000000000000000000000000000000900460ff165b156115485760015473ffffffffffffffffffffffffffffffffffffffff166114fb818a61298e565b885473ffffffffffffffffffffffffffffffffffffffff909116640100000000027fffffffffffffffff0000000000000000000000000000000000000000ffffffff9091161788556115d5565b61158f73ffffffffffffffffffffffffffffffffffffffff82161561156d5781611589565b600189015473ffffffffffffffffffffffffffffffffffffffff165b8961298e565b87547fffffffffffffffff0000000000000000000000000000000000000000ffffffff1664010000000073ffffffffffffffffffffffffffffffffffffffff8316021788555b505b505050505050505050565b600080600054700100000000000000000000000000000000900460ff166002811115611610576116106157da565b14611647576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000805260066020527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f85460ff166116ab576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660026000815481106116d7576116d7615b50565b6000918252602090912060059091020154640100000000900473ffffffffffffffffffffffffffffffffffffffff1614611712576001611715565b60025b6000805467ffffffffffffffff421668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff82168117835592935083927fffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffff000000000000000000ffffffffffffffff909116177001000000000000000000000000000000008360028111156117c6576117c66157da565b0217905560028111156117db576117db6157da565b6040517f5e186f09b9c93491f14e277eea7faa5de6a2d4bda75a79af7a3684fbfb42da6090600090a27f000000000000000000000000970670459734a83899773a0fd45941b5afc1200e73ffffffffffffffffffffffffffffffffffffffff1663838c2d1e6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561186c57600080fd5b505af1158015611880573d6000803e3d6000fd5b5050505090565b600560205281600052604060002081815481106118a357600080fd5b90600052602060002001600091509150505481565b905090565b6118ca8383836001611abe565b505050565b6000818152600760209081526040808320600590925282208054825461190090610100900463ffffffff1682615bfe565b95945050505050565b60606118b860546020612a8f565b73ffffffffffffffffffffffffffffffffffffffff811660009081526003602052604081208054908290559081900361197c576040517f17bfe5f700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517ff3fef3a300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152602482018390527f000000000000000000000000d6eaf4c146261653ee059077b78ed088add54309169063f3fef3a390604401600060405180830381600087803b158015611a0c57600080fd5b505af1158015611a20573d6000803e3d6000fd5b5050505060008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114611a7e576040519150601f19603f3d011682016040523d82523d6000602084013e611a83565b606091505b50509050806118ca576040517f83e6cc6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8161480611b3757503373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b6316145b611b6d576040517fd386ef3e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611b7984848484612ae1565b50505050565b6118ca8383836000611abe565b3273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c81614611bfb576040517fd386ef3e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611c036135ba565b565b600080600054700100000000000000000000000000000000900460ff166002811115611c3357611c336157da565b14611c6a576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028381548110611c7f57611c7f615b50565b600091825260208220600590910201805490925063ffffffff90811614611cee57815460028054909163ffffffff16908110611cbd57611cbd615b50565b906000526020600020906005020160040160109054906101000a90046fffffffffffffffffffffffffffffffff1690505b6004820154600090611d2690700100000000000000000000000000000000900467ffffffffffffffff165b67ffffffffffffffff1690565b611d3a9067ffffffffffffffff1642615bfe565b611d59611d19846fffffffffffffffffffffffffffffffff1660401c90565b67ffffffffffffffff16611d6d9190615bae565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b01667ffffffffffffffff168167ffffffffffffffff1611611dba5780611900565b7f00000000000000000000000000000000000000000000000000000000000004b095945050505050565b600080611e83836fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690507f0000000000000000000000000000000000000000000000000000000000000008811115611ee2576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b642e90edd00062061a806311e1a3006000611efd8383615c44565b9050670de0b6b3a76400006000611f34827f0000000000000000000000000000000000000000000000000000000000000008615c58565b90506000611f52611f4d670de0b6b3a764000086615c58565b613b13565b90506000611f608484613d6e565b90506000611f6e8383613dbd565b90506000611f7b82613deb565b90506000611f9a82611f95670de0b6b3a76400008f615c58565b613fd3565b90506000611fa88b83613dbd565b9050611fb4818d615c58565b9f9e505050505050505050505050505050565b60028181548110611fd757600080fd5b60009182526020909120600590910201805460018201546002830154600384015460049094015463ffffffff8416955064010000000090930473ffffffffffffffffffffffffffffffffffffffff908116949216926fffffffffffffffffffffffffffffffff91821692918082169170010000000000000000000000000000000090041687565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c81614806120d757503373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b6316145b61210d576040517fd386ef3e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61211b868686868686614004565b505050505050565b60008054700100000000000000000000000000000000900460ff16600281111561214f5761214f6157da565b14612186576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060008061219586614633565b935093509350935060006121ab85858585614a3c565b905060007f000000000000000000000000444e09fe6d839273316a87002ab0efbea6fe780673ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561221a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061223e9190615c95565b9050600189036123365773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a8461229a367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036034013590565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815260048101939093526024830191909152604482015260206064820152608481018a905260a4015b6020604051808303816000875af115801561230c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123309190615cb2565b506115d7565b600289036123625773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a848961229a565b6003890361238e5773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a848761229a565b600489036125155760006123d46fffffffffffffffffffffffffffffffff85167f0000000000000000000000000000000000000000000000000000000000000004614af6565b6009546123e19190615bae565b6123ec906001615bae565b9050367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360540135811061245557367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360540135612457565b805b905073ffffffffffffffffffffffffffffffffffffffff82166352f0f3ad8b8560405160e084901b7fffffffff000000000000000000000000000000000000000000000000000000001681526004810192909252602482015260c084901b604482015260086064820152608481018b905260a4016020604051808303816000875af11580156124ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061250e9190615cb2565b50506115d7565b600589036125ae576040517f52f0f3ad000000000000000000000000000000000000000000000000000000008152600481018a9052602481018390527f000000000000000000000000000000000000000000000000000000000000038560c01b6044820152600860648201526084810188905273ffffffffffffffffffffffffffffffffffffffff8216906352f0f3ad9060a4016122ed565b6040517fff137e6500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000001367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003601401356060612639611909565b9050909192565b6000818310156126505781612652565b825b90505b92915050565b6000816000015182602001518360400151846060015160405160200161269a949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b60408051808201909152600080825260208201528151600003612706576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50604080518082019091528151815260209182019181019190915290565b6060600080600061273485614ba4565b91945092509050600181600181111561274f5761274f6157da565b14612786576040517f4b9c6abe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84516127928385615bae565b146127c9576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808252610420820190925290816020015b60408051808201909152600080825260208201528152602001906001900390816127e05790505093506000835b86518110156128ce576000806128536040518060400160405280858c600001516128379190615bfe565b8152602001858c6020015161284c9190615bae565b9052614ba4565b50915091506040518060400160405280838361286f9190615bae565b8152602001848b602001516128849190615bae565b81525088858151811061289957612899615b50565b60209081029190910101526128af600185615bae565b93506128bb8183615bae565b6128c59084615bae565b9250505061280d565b50845250919392505050565b606060008060006128ea85614ba4565b919450925090506000816001811115612905576129056157da565b1461293c576040517f1ff9b2e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6129468284615bae565b85511461297f576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61190085602001518484615042565b600281015473ffffffffffffffffffffffffffffffffffffffff8316600090815260036020526040812080546fffffffffffffffffffffffffffffffff909316928392906129dd908490615bae565b90915550506040517f7eee288d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018390527f000000000000000000000000d6eaf4c146261653ee059077b78ed088add543091690637eee288d90604401600060405180830381600087803b158015612a7257600080fd5b505af1158015612a86573d6000803e3d6000fd5b50505050505050565b604051818152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90038284820160208401378260208301016000815260208101604052505092915050565b60008054700100000000000000000000000000000000900460ff166002811115612b0d57612b0d6157da565b14612b44576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028481548110612b5957612b59615b50565b60009182526020918290206040805160e0810182526005909302909101805463ffffffff8116845273ffffffffffffffffffffffffffffffffffffffff64010000000090910481169484019490945260018101549093169082015260028201546fffffffffffffffffffffffffffffffff908116606083015260038301546080830181905260049093015480821660a084015270010000000000000000000000000000000090041660c082015291508514612c40576040517f3014033200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60a0810151600083156fffffffffffffffffffffffffffffffff83161760011b90506000612d00826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169050861580612d3b5750612d387f00000000000000000000000000000000000000000000000000000000000000046002615bae565b81145b8015612d45575084155b15612d7c576040517fa42637bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000547201000000000000000000000000000000000000900460ff168015612da2575086155b15612dd9576040517f0ea2e75200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000008811115612e33576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612e5e7f00000000000000000000000000000000000000000000000000000000000000046001615bae565b8103612e7057612e70868885886150d7565b34612e7a83611de4565b14612eb1576040517f8620aa1900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612ebc88611c05565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b0811690821603612f24576040517f3381d11400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612f5160017f0000000000000000000000000000000000000000000000000000000000000008615bfe565b830361308f577f000000000000000000000000444e09fe6d839273316a87002ab0efbea6fe780673ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015612fc2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fe69190615c95565b73ffffffffffffffffffffffffffffffffffffffff1663f3f480d96040518163ffffffff1660e01b8152600401602060405180830381865afa158015613030573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130549190615cb2565b613088907f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff16615ccb565b9050613122565b6130ba60017f0000000000000000000000000000000000000000000000000000000000000004615bfe565b83036130f5576130887f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff166002615cf7565b507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff165b613156817f00000000000000000000000000000000000000000000000000000000000004b067ffffffffffffffff16615d27565b67ffffffffffffffff166131718367ffffffffffffffff1690565b67ffffffffffffffff1611156131b8576131b5817f00000000000000000000000000000000000000000000000000000000000004b067ffffffffffffffff16615d27565b91505b6000604083901b421760008a8152608087901b6fffffffffffffffffffffffffffffffff8d1617602052604081209192509060008181526004602052604090205490915060ff1615613236576040517f80497e3b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60016004600083815260200190815260200160002060006101000a81548160ff02191690831515021790555060026040518060e001604052808d63ffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020013373ffffffffffffffffffffffffffffffffffffffff168152602001346fffffffffffffffffffffffffffffffff1681526020018c8152602001886fffffffffffffffffffffffffffffffff168152602001846fffffffffffffffffffffffffffffffff16815250908060018154018082558091505060019003906000526020600020906005020160009091909190915060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060608201518160020160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055506080820151816003015560a08201518160040160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555060c08201518160040160106101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055505050600560008c815260200190815260200160002060016002805490506134cc9190615bfe565b81546001810183556000928352602083200155604080517fd0e30db0000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000d6eaf4c146261653ee059077b78ed088add54309169263d0e30db09234926004808301939282900301818588803b15801561356457600080fd5b505af1158015613578573d6000803e3d6000fd5b50506040513393508d92508e91507f9b3245740ec3b155098a55be84957a4da13eaf7f14a8bc6f53126c0b9350f2be90600090a4505050505050505050505050565b60005471010000000000000000000000000000000000900460ff161561360c576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f7258a80700000000000000000000000000000000000000000000000000000000815263ffffffff7f0000000000000000000000000000000000000000000000000000000000000001166004820152600090819073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000970670459734a83899773a0fd45941b5afc1200e1690637258a807906024016040805180830381865afa1580156136c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136e49190615d50565b909250905081613720576040517f6a6bc3b200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518082019091528281526020018190526008829055600981905536607a1461375357639824bdab6000526004601cfd5b80367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360540135116137ed576040517ff40239db000000000000000000000000000000000000000000000000000000008152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013560048201526024015b60405180910390fd5b6040805160e08101825263ffffffff8082526000602083018181527ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe369081013560f01c90038035606090811c868801908152346fffffffffffffffffffffffffffffffff81811693890193845260149094013560808901908152600160a08a0181815242871660c08c019081526002805493840181558a529a5160059092027f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace81018054995173ffffffffffffffffffffffffffffffffffffffff908116640100000000027fffffffffffffffff000000000000000000000000000000000000000000000000909b1694909c16939093179890981790915592517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5acf87018054918a167fffffffffffffffffffffffff000000000000000000000000000000000000000090921691909117905592517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad0860180549186167fffffffffffffffffffffffffffffffff0000000000000000000000000000000090921691909117905591517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad185015551955182167001000000000000000000000000000000000295909116949094177f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad29091015580547fffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffff167101000000000000000000000000000000000017815583517fd0e30db000000000000000000000000000000000000000000000000000000000815293517f000000000000000000000000d6eaf4c146261653ee059077b78ed088add543099092169363d0e30db093926004828101939282900301818588803b158015613ac257600080fd5b505af1158015613ad6573d6000803e3d6000fd5b5050600080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000164267ffffffffffffffff161790555050505050565b6fffffffffffffffffffffffffffffffff811160071b81811c67ffffffffffffffff1060061b1781811c63ffffffff1060051b1781811c61ffff1060041b1781811c60ff1060031b1760008213613b7257631615e6386000526004601cfd5b7ff8f9f9faf9fdfafbf9fdfcfdfafbfcfef9fafdfafcfcfbfefafafcfbffffffff6f8421084210842108cc6318c6db6d54be83831c1c601f161a1890811b609f90811c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506029190037d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b302017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d90565b60007812725dd1d243aba0e75fe645cc4873f9e65afe688c928e1f218311670de0b6b3a764000002158202613dab57637c5f487d6000526004601cfd5b50670de0b6b3a7640000919091020490565b600081600019048311820215613ddb5763bac65e5b6000526004601cfd5b50670de0b6b3a764000091020490565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdc0d0570925a462d78213613e1957919050565b680755bf798b4a1bf1e58212613e375763a37bfec96000526004601cfd5b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b6000612652670de0b6b3a764000083613feb86613b13565b613ff59190615d74565b613fff9190615e30565b613deb565b60008054700100000000000000000000000000000000900460ff166002811115614030576140306157da565b14614067576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006002878154811061407c5761407c615b50565b6000918252602082206005919091020160048101549092506fffffffffffffffffffffffffffffffff16908715821760011b90506140db7f00000000000000000000000000000000000000000000000000000000000000086001615bae565b614177826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff16146141b1576040517f5f53dd9800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008089156142a8576142047f00000000000000000000000000000000000000000000000000000000000000047f0000000000000000000000000000000000000000000000000000000000000008615bfe565b6001901b614223846fffffffffffffffffffffffffffffffff16615288565b6fffffffffffffffffffffffffffffffff1661423f9190615e98565b1561427c5761427361426460016fffffffffffffffffffffffffffffffff8716615eac565b865463ffffffff166000615327565b6003015461429e565b7f00000000000000000000000000000000000000000000000000000000000000005b91508490506142d2565b600385015491506142cf6142646fffffffffffffffffffffffffffffffff86166001615ed5565b90505b600882901b60088a8a6040516142e9929190615b40565b6040518091039020901b1461432a576040517f696550ff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006143358c61540b565b90506000614344836003015490565b6040517fe14ced320000000000000000000000000000000000000000000000000000000081527f000000000000000000000000444e09fe6d839273316a87002ab0efbea6fe780673ffffffffffffffffffffffffffffffffffffffff169063e14ced32906143be908f908f908f908f908a90600401615f49565b6020604051808303816000875af11580156143dd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144019190615cb2565b6004850154911491506000906002906144ac906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b614548896fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b6145529190615f83565b61455c9190615fa6565b60ff16159050811515810361459d576040517ffb4e40dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8754640100000000900473ffffffffffffffffffffffffffffffffffffffff16156145f4576040517f9071e6af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505085547fffffffffffffffff0000000000000000000000000000000000000000ffffffff163364010000000002179095555050505050505050505050565b600080600080600085905060006002828154811061465357614653615b50565b600091825260209091206004600590920201908101549091507f00000000000000000000000000000000000000000000000000000000000000049061472a906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1611614764576040517fb34b5c2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000815b60048301547f00000000000000000000000000000000000000000000000000000000000000049061482b906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1692508211156148a057825463ffffffff1661486a7f00000000000000000000000000000000000000000000000000000000000000046001615bae565b8303614874578391505b6002818154811061488757614887615b50565b9060005260206000209060050201935080945050614768565b600481810154908401546fffffffffffffffffffffffffffffffff91821691166000816fffffffffffffffffffffffffffffffff166149096148f4856fffffffffffffffffffffffffffffffff1660011c90565b6fffffffffffffffffffffffffffffffff1690565b6fffffffffffffffffffffffffffffffff1614905080156149d8576000614941836fffffffffffffffffffffffffffffffff16615288565b6fffffffffffffffffffffffffffffffff1611156149ac57600061498361497b60016fffffffffffffffffffffffffffffffff8616615eac565b896001615327565b6003810154600490910154909c506fffffffffffffffffffffffffffffffff169a506149b29050565b6008549a505b600386015460048701549099506fffffffffffffffffffffffffffffffff169750614a2e565b60006149fa61497b6fffffffffffffffffffffffffffffffff85166001615ed5565b6003808901546004808b015492840154930154909e506fffffffffffffffffffffffffffffffff9182169d50919b50169850505b505050505050509193509193565b60006fffffffffffffffffffffffffffffffff841615614aa95760408051602081018790526fffffffffffffffffffffffffffffffff8087169282019290925260608101859052908316608082015260a00160405160208183030381529060405280519060200120611900565b8282604051602001614ad79291909182526fffffffffffffffffffffffffffffffff16602082015260400190565b6040516020818303038152906040528051906020012095945050505050565b600080614b83847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690508083036001841b600180831b0386831b17039250505092915050565b60008060008360000151600003614be7576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020840151805160001a607f8111614c0c57600060016000945094509450505061503b565b60b78111614d22576000614c21608083615bfe565b905080876000015111614c60576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001838101517fff00000000000000000000000000000000000000000000000000000000000000169082148015614cd857507f80000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008216105b15614d0f576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506001955093506000925061503b915050565b60bf8111614e80576000614d3760b783615bfe565b905080876000015111614d76576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614dd8576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c60378111614e20576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614e2a8184615bae565b895111614e63576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614e6e836001615bae565b975095506000945061503b9350505050565b60f78111614ee5576000614e9560c083615bfe565b905080876000015111614ed4576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60019550935084925061503b915050565b6000614ef260f783615bfe565b905080876000015111614f31576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614f93576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c60378111614fdb576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614fe58184615bae565b89511161501e576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b615029836001615bae565b975095506001945061503b9350505050565b9193909250565b60608167ffffffffffffffff81111561505d5761505d615a84565b6040519080825280601f01601f191660200182016040528015615087576020820181803683370190505b50905081156150d057600061509c8486615bae565b90506020820160005b848110156150bd5782810151828201526020016150a5565b848111156150cc576000858301525b5050505b9392505050565b60006150f66fffffffffffffffffffffffffffffffff84166001615ed5565b9050600061510682866001615327565b9050600086901a83806151f2575061513f60027f0000000000000000000000000000000000000000000000000000000000000004615e98565b60048301546002906151e3906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b6151ed9190615fa6565b60ff16145b1561524a5760ff81166001148061520c575060ff81166002145b615245576040517ff40239db000000000000000000000000000000000000000000000000000000008152600481018890526024016137e4565b612a86565b60ff811615612a86576040517ff40239db000000000000000000000000000000000000000000000000000000008152600481018890526024016137e4565b600080615315837e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b600160ff919091161b90920392915050565b600080826153705761536b6fffffffffffffffffffffffffffffffff86167f000000000000000000000000000000000000000000000000000000000000000461543a565b61538b565b61538b856fffffffffffffffffffffffffffffffff166155c6565b9050600284815481106153a0576153a0615b50565b906000526020600020906005020191505b60048201546fffffffffffffffffffffffffffffffff82811691161461540357815460028054909163ffffffff169081106153ee576153ee615b50565b906000526020600020906005020191506153b1565b509392505050565b600080600080600061541c86614633565b935093509350935061543084848484614a3c565b9695505050505050565b6000816154d9846fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff16116154ef5763b34b5c226000526004601cfd5b6154f8836155c6565b905081615597826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1611612655576126526155ad836001615bae565b6fffffffffffffffffffffffffffffffff83169061566b565b6000811960018301168161565a827e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169390931c8015179392505050565b6000806156f8847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169050808303600180821b0385821b179250505092915050565b60008083601f84011261572657600080fd5b50813567ffffffffffffffff81111561573e57600080fd5b60208301915083602082850101111561575657600080fd5b9250929050565b600080600083850360a081121561577357600080fd5b608081121561578157600080fd5b50839250608084013567ffffffffffffffff81111561579f57600080fd5b6157ab86828701615714565b9497909650939450505050565b600080604083850312156157cb57600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6020810160038310615844577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b60008060006060848603121561585f57600080fd5b505081359360208301359350604090920135919050565b6000815180845260005b8181101561589c57602081850181015186830182015201615880565b818111156158ae576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006126526020830184615876565b60006020828403121561590657600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff8116811461592f57600080fd5b50565b60006020828403121561594457600080fd5b81356150d08161590d565b8035801515811461595f57600080fd5b919050565b6000806000806080858703121561597a57600080fd5b8435935060208501359250604085013591506159986060860161594f565b905092959194509250565b6000602082840312156159b557600080fd5b81356fffffffffffffffffffffffffffffffff811681146150d057600080fd5b600080600080600080608087890312156159ee57600080fd5b863595506159fe6020880161594f565b9450604087013567ffffffffffffffff80821115615a1b57600080fd5b615a278a838b01615714565b90965094506060890135915080821115615a4057600080fd5b50615a4d89828a01615714565b979a9699509497509295939492505050565b63ffffffff841681528260208201526060604082015260006119006060830184615876565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600060808284031215615ac557600080fd5b6040516080810181811067ffffffffffffffff82111715615b0f577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115615bc157615bc1615b7f565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203615bf757615bf7615b7f565b5060010190565b600082821015615c1057615c10615b7f565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082615c5357615c53615c15565b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615c9057615c90615b7f565b500290565b600060208284031215615ca757600080fd5b81516150d08161590d565b600060208284031215615cc457600080fd5b5051919050565b600067ffffffffffffffff808316818516808303821115615cee57615cee615b7f565b01949350505050565b600067ffffffffffffffff80831681851681830481118215151615615d1e57615d1e615b7f565b02949350505050565b600067ffffffffffffffff83811690831681811015615d4857615d48615b7f565b039392505050565b60008060408385031215615d6357600080fd5b505080516020909101519092909150565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600084136000841385830485118282161615615db557615db5615b7f565b7f80000000000000000000000000000000000000000000000000000000000000006000871286820588128184161615615df057615df0615b7f565b60008712925087820587128484161615615e0c57615e0c615b7f565b87850587128184161615615e2257615e22615b7f565b505050929093029392505050565b600082615e3f57615e3f615c15565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f800000000000000000000000000000000000000000000000000000000000000083141615615e9357615e93615b7f565b500590565b600082615ea757615ea7615c15565b500690565b60006fffffffffffffffffffffffffffffffff83811690831681811015615d4857615d48615b7f565b60006fffffffffffffffffffffffffffffffff808316818516808303821115615cee57615cee615b7f565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b606081526000615f5d606083018789615f00565b8281036020840152615f70818688615f00565b9150508260408301529695505050505050565b600060ff821660ff841680821015615f9d57615f9d615b7f565b90039392505050565b600060ff831680615fb957615fb9615c15565b8060ff8416069150509291505056fea164736f6c634300080f000a", - "initialized": true, - "kind": "Create", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [], - "value": 0 - }, - { - "accessor": "0x59B99034FBdd5E554661a2100cB2b6b7C5d495F8", - "account": "0x444e09fe6D839273316a87002aB0EFBeA6fe7806", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x7dc0d1d0", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [], - "value": 0 - }, - { - "accessor": "0x59B99034FBdd5E554661a2100cB2b6b7C5d495F8", - "account": "0x373d916D11cce55b548F7051002e76BCFBD7a85d", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xf3f480d9", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [], - "value": 0 - }, - { - "accessor": "0x59B99034FBdd5E554661a2100cB2b6b7C5d495F8", - "account": "0x444e09fe6D839273316a87002aB0EFBeA6fe7806", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x7dc0d1d0", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [], - "value": 0 - }, - { - "accessor": "0x59B99034FBdd5E554661a2100cB2b6b7C5d495F8", - "account": "0x373d916D11cce55b548F7051002e76BCFBD7a85d", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xf3f480d9", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [], - "value": 0 - }, - { - "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", - "account": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "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": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x14f6b1a3000000000000000000000000000000000000000000000000000000000000000100000000000000000000000059b99034fbdd5e554661a2100cb2b6b7c5d495f8", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "isWrite": false, - "newValue": "0x00000000000000000000000020b168142354cee65a32f6d8cf3033e592299765", - "previousValue": "0x00000000000000000000000020b168142354cee65a32f6d8cf3033e592299765", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x20B168142354Cee65a32f6D8cf3033E592299765", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x14f6b1a3000000000000000000000000000000000000000000000000000000000000000100000000000000000000000059b99034fbdd5e554661a2100cb2b6b7c5d495f8", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "isWrite": false, - "newValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", - "previousValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - }, - { - "account": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x4d5a9bd2e41301728d41c8e705190becb4e74abe869f75bdb405b63716a35f9e" - }, - { - "account": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "isWrite": true, - "newValue": "0x00000000000000000000000059b99034fbdd5e554661a2100cb2b6b7c5d495f8", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", - "reverted": false, - "slot": "0x4d5a9bd2e41301728d41c8e705190becb4e74abe869f75bdb405b63716a35f9e" - } - ], - "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": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x8da5cb5b", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "isWrite": false, - "newValue": "0x00000000000000000000000020b168142354cee65a32f6d8cf3033e592299765", - "previousValue": "0x00000000000000000000000020b168142354cee65a32f6d8cf3033e592299765", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x20B168142354Cee65a32f6D8cf3033E592299765", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x8da5cb5b", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "isWrite": false, - "newValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", - "previousValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - } - ], - "value": 0 - }, - { - "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", - "account": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "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": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xf2fde38b0000000000000000000000007c0c8a15773ed7b50e7c738d1af4c5e3a2b210bd", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "isWrite": false, - "newValue": "0x00000000000000000000000020b168142354cee65a32f6d8cf3033e592299765", - "previousValue": "0x00000000000000000000000020b168142354cee65a32f6d8cf3033e592299765", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x20B168142354Cee65a32f6D8cf3033E592299765", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xf2fde38b0000000000000000000000007c0c8a15773ed7b50e7c738d1af4c5e3a2b210bd", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "isWrite": false, - "newValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", - "previousValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - }, - { - "account": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "isWrite": false, - "newValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", - "previousValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - }, - { - "account": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "isWrite": true, - "newValue": "0x0000000000000000000000007c0c8a15773ed7b50e7c738d1af4c5e3a2b210bd", - "previousValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x8da5cb5b", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "isWrite": false, - "newValue": "0x00000000000000000000000020b168142354cee65a32f6d8cf3033e592299765", - "previousValue": "0x00000000000000000000000020b168142354cee65a32f6d8cf3033e592299765", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x20B168142354Cee65a32f6D8cf3033E592299765", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x8da5cb5b", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d", - "isWrite": false, - "newValue": "0x0000000000000000000000007c0c8a15773ed7b50e7c738d1af4c5e3a2b210bd", - "previousValue": "0x0000000000000000000000007c0c8a15773ed7b50e7c738d1af4c5e3a2b210bd", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - } - ], - "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": "0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x8da5cb5b", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92", - "isWrite": false, - "newValue": "0x0000000000000000000000002a6347edd3c7813cde46dd7ea61ff1cf2290bc05", - "previousValue": "0x0000000000000000000000002a6347edd3c7813cde46dd7ea61ff1cf2290bc05", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x2A6347EDD3C7813CDE46DD7eA61FF1Cf2290BC05", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x8da5cb5b", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92", - "isWrite": false, - "newValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", - "previousValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - } - ], - "value": 0 - }, - { - "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", - "account": "0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92", - "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": "0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xf2fde38b0000000000000000000000007c0c8a15773ed7b50e7c738d1af4c5e3a2b210bd", - "deployedCode": "0x", - "initialized": true, - "kind": "Call", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92", - "isWrite": false, - "newValue": "0x0000000000000000000000002a6347edd3c7813cde46dd7ea61ff1cf2290bc05", - "previousValue": "0x0000000000000000000000002a6347edd3c7813cde46dd7ea61ff1cf2290bc05", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x2A6347EDD3C7813CDE46DD7eA61FF1Cf2290BC05", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0xf2fde38b0000000000000000000000007c0c8a15773ed7b50e7c738d1af4c5e3a2b210bd", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92", - "isWrite": false, - "newValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", - "previousValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - }, - { - "account": "0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92", - "isWrite": false, - "newValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", - "previousValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - }, - { - "account": "0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92", - "isWrite": true, - "newValue": "0x0000000000000000000000007c0c8a15773ed7b50e7c738d1af4c5e3a2b210bd", - "previousValue": "0x0000000000000000000000001804c8ab1f12e6bbf3894d4083f33e07309d1f38", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x8da5cb5b", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92", - "isWrite": false, - "newValue": "0x0000000000000000000000002a6347edd3c7813cde46dd7ea61ff1cf2290bc05", - "previousValue": "0x0000000000000000000000002a6347edd3c7813cde46dd7ea61ff1cf2290bc05", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x2A6347EDD3C7813CDE46DD7eA61FF1Cf2290BC05", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x8da5cb5b", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92", - "isWrite": false, - "newValue": "0x0000000000000000000000007c0c8a15773ed7b50e7c738d1af4c5e3a2b210bd", - "previousValue": "0x0000000000000000000000007c0c8a15773ed7b50e7c738d1af4c5e3a2b210bd", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000033" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x7a07653f", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c", - "isWrite": false, - "newValue": "0x0000000000000000000000000000000000000000000000000000000000093a80", - "previousValue": "0x0000000000000000000000000000000000000000000000000000000000093a80", - "reverted": false, - "slot": "0x000000000000000000000000000000000000000000000000000000000000003b" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x6a42b8f8", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92", - "isWrite": false, - "newValue": "0x0000000000000000000000002a6347edd3c7813cde46dd7ea61ff1cf2290bc05", - "previousValue": "0x0000000000000000000000002a6347edd3c7813cde46dd7ea61ff1cf2290bc05", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x2A6347EDD3C7813CDE46DD7eA61FF1Cf2290BC05", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x6a42b8f8", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x79502c55", - "deployedCode": "0x", - "initialized": true, - "kind": "StaticCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92", - "isWrite": false, - "newValue": "0x0000000000000000000000002a6347edd3c7813cde46dd7ea61ff1cf2290bc05", - "previousValue": "0x0000000000000000000000002a6347edd3c7813cde46dd7ea61ff1cf2290bc05", - "reverted": false, - "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" - } - ], - "value": 0 - }, - { - "accessor": "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38", - "account": "0x2A6347EDD3C7813CDE46DD7eA61FF1Cf2290BC05", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x79502c55", - "deployedCode": "0x", - "initialized": true, - "kind": "DelegateCall", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [ - { - "account": "0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92", - "isWrite": false, - "newValue": "0x0000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab0351", - "previousValue": "0x0000000000000000000000004f559f30f5eb88d635fde1548c4267db8fab0351", - "reverted": false, - "slot": "0x0000000000000000000000000000000000000000000000000000000000000068" - } - ], - "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 index 3511e68eb8797..3900f45525844 100644 --- a/packages/contracts-bedrock/snapshots/storageLayout/AnchorStateRegistry.json +++ b/packages/contracts-bedrock/snapshots/storageLayout/AnchorStateRegistry.json @@ -25,6 +25,6 @@ "label": "superchainConfig", "offset": 0, "slot": "2", - "type": "contract SuperchainConfig" + "type": "contract ISuperchainConfig" } ] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/storageLayout/DelayedWETH.json b/packages/contracts-bedrock/snapshots/storageLayout/DelayedWETH.json index efc43f45893cb..4e8b771cd9bb3 100644 --- a/packages/contracts-bedrock/snapshots/storageLayout/DelayedWETH.json +++ b/packages/contracts-bedrock/snapshots/storageLayout/DelayedWETH.json @@ -53,13 +53,13 @@ "label": "withdrawals", "offset": 0, "slot": "103", - "type": "mapping(address => mapping(address => struct IDelayedWETH.WithdrawalRequest))" + "type": "mapping(address => mapping(address => struct DelayedWETH.WithdrawalRequest))" }, { "bytes": "20", "label": "config", "offset": 0, "slot": "104", - "type": "contract SuperchainConfig" + "type": "contract ISuperchainConfig" } ] \ 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 f87fa588ed9c5..ec02f23d2e6d2 100644 --- a/packages/contracts-bedrock/snapshots/storageLayout/FaultDisputeGame.json +++ b/packages/contracts-bedrock/snapshots/storageLayout/FaultDisputeGame.json @@ -46,7 +46,7 @@ "label": "claimData", "offset": 0, "slot": "2", - "type": "struct IFaultDisputeGame.ClaimData[]" + "type": "struct FaultDisputeGame.ClaimData[]" }, { "bytes": "32", @@ -81,7 +81,7 @@ "label": "resolutionCheckpoints", "offset": 0, "slot": "7", - "type": "mapping(uint256 => struct IFaultDisputeGame.ResolutionCheckpoint)" + "type": "mapping(uint256 => struct FaultDisputeGame.ResolutionCheckpoint)" }, { "bytes": "64", diff --git a/packages/contracts-bedrock/snapshots/storageLayout/L1BlockInterop.json b/packages/contracts-bedrock/snapshots/storageLayout/L1BlockIsthmus.json similarity index 100% rename from packages/contracts-bedrock/snapshots/storageLayout/L1BlockInterop.json rename to packages/contracts-bedrock/snapshots/storageLayout/L1BlockIsthmus.json diff --git a/packages/contracts-bedrock/snapshots/storageLayout/L1CrossDomainMessenger.json b/packages/contracts-bedrock/snapshots/storageLayout/L1CrossDomainMessenger.json index 5c88be3ca9aea..c68ec541baba9 100644 --- a/packages/contracts-bedrock/snapshots/storageLayout/L1CrossDomainMessenger.json +++ b/packages/contracts-bedrock/snapshots/storageLayout/L1CrossDomainMessenger.json @@ -130,20 +130,20 @@ "label": "superchainConfig", "offset": 0, "slot": "251", - "type": "contract SuperchainConfig" + "type": "contract ISuperchainConfig" }, { "bytes": "20", "label": "portal", "offset": 0, "slot": "252", - "type": "contract OptimismPortal" + "type": "contract IOptimismPortal" }, { "bytes": "20", "label": "systemConfig", "offset": 0, "slot": "253", - "type": "contract SystemConfig" + "type": "contract ISystemConfig" } ] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/storageLayout/L1ERC721Bridge.json b/packages/contracts-bedrock/snapshots/storageLayout/L1ERC721Bridge.json index b08068ee9aeb7..2c14ad25904bb 100644 --- a/packages/contracts-bedrock/snapshots/storageLayout/L1ERC721Bridge.json +++ b/packages/contracts-bedrock/snapshots/storageLayout/L1ERC721Bridge.json @@ -25,7 +25,7 @@ "label": "messenger", "offset": 0, "slot": "1", - "type": "contract CrossDomainMessenger" + "type": "contract ICrossDomainMessenger" }, { "bytes": "20", @@ -53,6 +53,6 @@ "label": "superchainConfig", "offset": 0, "slot": "50", - "type": "contract SuperchainConfig" + "type": "contract ISuperchainConfig" } ] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/storageLayout/L1StandardBridge.json b/packages/contracts-bedrock/snapshots/storageLayout/L1StandardBridge.json index 1ed5eac5d1835..5562a214e4fef 100644 --- a/packages/contracts-bedrock/snapshots/storageLayout/L1StandardBridge.json +++ b/packages/contracts-bedrock/snapshots/storageLayout/L1StandardBridge.json @@ -39,7 +39,7 @@ "label": "messenger", "offset": 0, "slot": "3", - "type": "contract CrossDomainMessenger" + "type": "contract ICrossDomainMessenger" }, { "bytes": "20", @@ -60,13 +60,13 @@ "label": "superchainConfig", "offset": 0, "slot": "50", - "type": "contract SuperchainConfig" + "type": "contract ISuperchainConfig" }, { "bytes": "20", "label": "systemConfig", "offset": 0, "slot": "51", - "type": "contract SystemConfig" + "type": "contract ISystemConfig" } ] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/storageLayout/L2ERC721Bridge.json b/packages/contracts-bedrock/snapshots/storageLayout/L2ERC721Bridge.json index e9facc6579e6e..546b37ba6398a 100644 --- a/packages/contracts-bedrock/snapshots/storageLayout/L2ERC721Bridge.json +++ b/packages/contracts-bedrock/snapshots/storageLayout/L2ERC721Bridge.json @@ -25,7 +25,7 @@ "label": "messenger", "offset": 0, "slot": "1", - "type": "contract CrossDomainMessenger" + "type": "contract ICrossDomainMessenger" }, { "bytes": "20", diff --git a/packages/contracts-bedrock/snapshots/storageLayout/L2StandardBridge.json b/packages/contracts-bedrock/snapshots/storageLayout/L2StandardBridge.json index f5effc6ae7992..c6ccc0fc2e037 100644 --- a/packages/contracts-bedrock/snapshots/storageLayout/L2StandardBridge.json +++ b/packages/contracts-bedrock/snapshots/storageLayout/L2StandardBridge.json @@ -39,7 +39,7 @@ "label": "messenger", "offset": 0, "slot": "3", - "type": "contract CrossDomainMessenger" + "type": "contract ICrossDomainMessenger" }, { "bytes": "20", diff --git a/packages/contracts-bedrock/snapshots/storageLayout/L2StandardBridgeInterop.json b/packages/contracts-bedrock/snapshots/storageLayout/L2StandardBridgeInterop.json index f5effc6ae7992..c6ccc0fc2e037 100644 --- a/packages/contracts-bedrock/snapshots/storageLayout/L2StandardBridgeInterop.json +++ b/packages/contracts-bedrock/snapshots/storageLayout/L2StandardBridgeInterop.json @@ -39,7 +39,7 @@ "label": "messenger", "offset": 0, "slot": "3", - "type": "contract CrossDomainMessenger" + "type": "contract ICrossDomainMessenger" }, { "bytes": "20", diff --git a/packages/contracts-bedrock/snapshots/storageLayout/OPContractsManager.json b/packages/contracts-bedrock/snapshots/storageLayout/OPContractsManager.json new file mode 100644 index 0000000000000..cbb977f214b4f --- /dev/null +++ b/packages/contracts-bedrock/snapshots/storageLayout/OPContractsManager.json @@ -0,0 +1,51 @@ +[ + { + "bytes": "1", + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "uint8" + }, + { + "bytes": "1", + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "bool" + }, + { + "bytes": "32", + "label": "latestRelease", + "offset": 0, + "slot": "1", + "type": "string" + }, + { + "bytes": "32", + "label": "implementations", + "offset": 0, + "slot": "2", + "type": "mapping(string => mapping(string => struct OPContractsManager.Implementation))" + }, + { + "bytes": "32", + "label": "systemConfigs", + "offset": 0, + "slot": "3", + "type": "mapping(uint256 => contract SystemConfig)" + }, + { + "bytes": "256", + "label": "blueprint", + "offset": 0, + "slot": "4", + "type": "struct OPContractsManager.Blueprints" + }, + { + "bytes": "1600", + "label": "__gap", + "offset": 0, + "slot": "12", + "type": "uint256[50]" + } +] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/storageLayout/OPContractsManagerInterop.json b/packages/contracts-bedrock/snapshots/storageLayout/OPContractsManagerInterop.json new file mode 100644 index 0000000000000..cbb977f214b4f --- /dev/null +++ b/packages/contracts-bedrock/snapshots/storageLayout/OPContractsManagerInterop.json @@ -0,0 +1,51 @@ +[ + { + "bytes": "1", + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "uint8" + }, + { + "bytes": "1", + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "bool" + }, + { + "bytes": "32", + "label": "latestRelease", + "offset": 0, + "slot": "1", + "type": "string" + }, + { + "bytes": "32", + "label": "implementations", + "offset": 0, + "slot": "2", + "type": "mapping(string => mapping(string => struct OPContractsManager.Implementation))" + }, + { + "bytes": "32", + "label": "systemConfigs", + "offset": 0, + "slot": "3", + "type": "mapping(uint256 => contract SystemConfig)" + }, + { + "bytes": "256", + "label": "blueprint", + "offset": 0, + "slot": "4", + "type": "struct OPContractsManager.Blueprints" + }, + { + "bytes": "1600", + "label": "__gap", + "offset": 0, + "slot": "12", + "type": "uint256[50]" + } +] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/storageLayout/OptimismMintableERC20.json b/packages/contracts-bedrock/snapshots/storageLayout/OptimismMintableERC20.json index 418a98546cf77..2ad020cb1c4fd 100644 --- a/packages/contracts-bedrock/snapshots/storageLayout/OptimismMintableERC20.json +++ b/packages/contracts-bedrock/snapshots/storageLayout/OptimismMintableERC20.json @@ -33,5 +33,19 @@ "offset": 0, "slot": "4", "type": "string" + }, + { + "bytes": "32", + "label": "_nonces", + "offset": 0, + "slot": "5", + "type": "mapping(address => struct Counters.Counter)" + }, + { + "bytes": "32", + "label": "_PERMIT_TYPEHASH_DEPRECATED_SLOT", + "offset": 0, + "slot": "6", + "type": "bytes32" } ] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/storageLayout/OptimismPortal.json b/packages/contracts-bedrock/snapshots/storageLayout/OptimismPortal.json index 6eff1d1a0790e..d129ef1b87e30 100644 --- a/packages/contracts-bedrock/snapshots/storageLayout/OptimismPortal.json +++ b/packages/contracts-bedrock/snapshots/storageLayout/OptimismPortal.json @@ -60,21 +60,21 @@ "label": "superchainConfig", "offset": 1, "slot": "53", - "type": "contract SuperchainConfig" + "type": "contract ISuperchainConfig" }, { "bytes": "20", "label": "l2Oracle", "offset": 0, "slot": "54", - "type": "contract L2OutputOracle" + "type": "contract IL2OutputOracle" }, { "bytes": "20", "label": "systemConfig", "offset": 0, "slot": "55", - "type": "contract SystemConfig" + "type": "contract ISystemConfig" }, { "bytes": "20", diff --git a/packages/contracts-bedrock/snapshots/storageLayout/OptimismPortal2.json b/packages/contracts-bedrock/snapshots/storageLayout/OptimismPortal2.json index 807e966b6edd0..0fdd65b3e88fb 100644 --- a/packages/contracts-bedrock/snapshots/storageLayout/OptimismPortal2.json +++ b/packages/contracts-bedrock/snapshots/storageLayout/OptimismPortal2.json @@ -60,7 +60,7 @@ "label": "superchainConfig", "offset": 1, "slot": "53", - "type": "contract SuperchainConfig" + "type": "contract ISuperchainConfig" }, { "bytes": "20", @@ -74,14 +74,14 @@ "label": "systemConfig", "offset": 0, "slot": "55", - "type": "contract SystemConfig" + "type": "contract ISystemConfig" }, { "bytes": "20", "label": "disputeGameFactory", "offset": 0, "slot": "56", - "type": "contract DisputeGameFactory" + "type": "contract IDisputeGameFactory" }, { "bytes": "32", diff --git a/packages/contracts-bedrock/snapshots/storageLayout/OptimismPortalInterop.json b/packages/contracts-bedrock/snapshots/storageLayout/OptimismPortalInterop.json index 807e966b6edd0..0fdd65b3e88fb 100644 --- a/packages/contracts-bedrock/snapshots/storageLayout/OptimismPortalInterop.json +++ b/packages/contracts-bedrock/snapshots/storageLayout/OptimismPortalInterop.json @@ -60,7 +60,7 @@ "label": "superchainConfig", "offset": 1, "slot": "53", - "type": "contract SuperchainConfig" + "type": "contract ISuperchainConfig" }, { "bytes": "20", @@ -74,14 +74,14 @@ "label": "systemConfig", "offset": 0, "slot": "55", - "type": "contract SystemConfig" + "type": "contract ISystemConfig" }, { "bytes": "20", "label": "disputeGameFactory", "offset": 0, "slot": "56", - "type": "contract DisputeGameFactory" + "type": "contract IDisputeGameFactory" }, { "bytes": "32", diff --git a/packages/contracts-bedrock/snapshots/storageLayout/OPStackManager.json b/packages/contracts-bedrock/snapshots/storageLayout/OptimismSuperchainERC20Beacon.json similarity index 100% rename from packages/contracts-bedrock/snapshots/storageLayout/OPStackManager.json rename to packages/contracts-bedrock/snapshots/storageLayout/OptimismSuperchainERC20Beacon.json diff --git a/packages/contracts-bedrock/snapshots/storageLayout/OptimismSuperchainERC20Factory.json b/packages/contracts-bedrock/snapshots/storageLayout/OptimismSuperchainERC20Factory.json new file mode 100644 index 0000000000000..3dd455fbc1bd9 --- /dev/null +++ b/packages/contracts-bedrock/snapshots/storageLayout/OptimismSuperchainERC20Factory.json @@ -0,0 +1,9 @@ +[ + { + "bytes": "32", + "label": "deployments", + "offset": 0, + "slot": "0", + "type": "mapping(address => address)" + } +] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/storageLayout/PermissionedDisputeGame.json b/packages/contracts-bedrock/snapshots/storageLayout/PermissionedDisputeGame.json index f87fa588ed9c5..ec02f23d2e6d2 100644 --- a/packages/contracts-bedrock/snapshots/storageLayout/PermissionedDisputeGame.json +++ b/packages/contracts-bedrock/snapshots/storageLayout/PermissionedDisputeGame.json @@ -46,7 +46,7 @@ "label": "claimData", "offset": 0, "slot": "2", - "type": "struct IFaultDisputeGame.ClaimData[]" + "type": "struct FaultDisputeGame.ClaimData[]" }, { "bytes": "32", @@ -81,7 +81,7 @@ "label": "resolutionCheckpoints", "offset": 0, "slot": "7", - "type": "mapping(uint256 => struct IFaultDisputeGame.ResolutionCheckpoint)" + "type": "mapping(uint256 => struct FaultDisputeGame.ResolutionCheckpoint)" }, { "bytes": "64", diff --git a/packages/contracts-bedrock/snapshots/storageLayout/SystemConfig.json b/packages/contracts-bedrock/snapshots/storageLayout/SystemConfig.json index 648245156248f..b0946e1bc4dba 100644 --- a/packages/contracts-bedrock/snapshots/storageLayout/SystemConfig.json +++ b/packages/contracts-bedrock/snapshots/storageLayout/SystemConfig.json @@ -81,6 +81,6 @@ "label": "_resourceConfig", "offset": 0, "slot": "105", - "type": "struct ResourceMetering.ResourceConfig" + "type": "struct IResourceMetering.ResourceConfig" } ] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/storageLayout/SystemConfigInterop.json b/packages/contracts-bedrock/snapshots/storageLayout/SystemConfigInterop.json index 648245156248f..b0946e1bc4dba 100644 --- a/packages/contracts-bedrock/snapshots/storageLayout/SystemConfigInterop.json +++ b/packages/contracts-bedrock/snapshots/storageLayout/SystemConfigInterop.json @@ -81,6 +81,6 @@ "label": "_resourceConfig", "offset": 0, "slot": "105", - "type": "struct ResourceMetering.ResourceConfig" + "type": "struct IResourceMetering.ResourceConfig" } ] \ No newline at end of file diff --git a/packages/contracts-bedrock/src/EAS/EAS.sol b/packages/contracts-bedrock/src/EAS/EAS.sol index f4872eeed26e8..384ffdd0eb02c 100644 --- a/packages/contracts-bedrock/src/EAS/EAS.sol +++ b/packages/contracts-bedrock/src/EAS/EAS.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.19; import { Address } from "@openzeppelin/contracts/utils/Address.sol"; -import { ISemver } from "src/universal/ISemver.sol"; +import { ISemver } from "src/universal/interfaces/ISemver.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; import { EIP1271Verifier } from "src/EAS/eip1271/EIP1271Verifier.sol"; import { ISchemaResolver } from "src/EAS/resolver/ISchemaResolver.sol"; @@ -40,7 +40,7 @@ struct AttestationsResult { bytes32[] uids; // UIDs of the new attestations. } -/// @custom:proxied +/// @custom:proxied true /// @custom:predeploy 0x4200000000000000000000000000000000000021 /// @title EAS /// @notice The Ethereum Attestation Service protocol. @@ -80,8 +80,8 @@ contract EAS is IEAS, ISemver, EIP1271Verifier { uint256[MAX_GAP - 3] private __gap; /// @notice Semantic version. - /// @custom:semver 1.4.0 - string public constant version = "1.4.0"; + /// @custom:semver 1.4.1-beta.1 + string public constant version = "1.4.1-beta.1"; /// @dev Creates a new EAS instance. constructor() EIP1271Verifier("EAS", "1.3.0") { } diff --git a/packages/contracts-bedrock/src/EAS/SchemaRegistry.sol b/packages/contracts-bedrock/src/EAS/SchemaRegistry.sol index e6f5ee3c4d90e..cfed1a928dba6 100644 --- a/packages/contracts-bedrock/src/EAS/SchemaRegistry.sol +++ b/packages/contracts-bedrock/src/EAS/SchemaRegistry.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.19; -import { ISemver } from "src/universal/ISemver.sol"; +import { ISemver } from "src/universal/interfaces/ISemver.sol"; import { ISchemaResolver } from "src/EAS/resolver/ISchemaResolver.sol"; import { EMPTY_UID, MAX_GAP } from "src/EAS/Common.sol"; import { ISchemaRegistry, SchemaRecord } from "src/EAS/ISchemaRegistry.sol"; -/// @custom:proxied +/// @custom:proxied true /// @custom:predeploy 0x4200000000000000000000000000000000000020 /// @title SchemaRegistry /// @notice The global attestation schemas for the Ethereum Attestation Service protocol. @@ -20,8 +20,8 @@ contract SchemaRegistry is ISchemaRegistry, ISemver { uint256[MAX_GAP - 1] private __gap; /// @notice Semantic version. - /// @custom:semver 1.3.0 - string public constant version = "1.3.0"; + /// @custom:semver 1.3.1-beta.1 + string public constant version = "1.3.1-beta.1"; /// @inheritdoc ISchemaRegistry function register(string calldata schema, ISchemaResolver resolver, bool revocable) external returns (bytes32) { diff --git a/packages/contracts-bedrock/src/L1/DataAvailabilityChallenge.sol b/packages/contracts-bedrock/src/L1/DataAvailabilityChallenge.sol index 84ba91b8fa98c..1bb0d1bf6680a 100644 --- a/packages/contracts-bedrock/src/L1/DataAvailabilityChallenge.sol +++ b/packages/contracts-bedrock/src/L1/DataAvailabilityChallenge.sol @@ -1,10 +1,15 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Contracts import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; -import { ISemver } from "src/universal/ISemver.sol"; + +// Libraries import { SafeCall } from "src/libraries/SafeCall.sol"; +// Interfaces +import { ISemver } from "src/universal/interfaces/ISemver.sol"; + /// @dev An enum representing the status of a DA challenge. enum ChallengeStatus { Uninitialized, @@ -29,6 +34,7 @@ struct Challenge { uint256 resolvedBlock; } +/// @custom:proxied true /// @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). @@ -88,8 +94,8 @@ contract DataAvailabilityChallenge is OwnableUpgradeable, ISemver { event BalanceChanged(address account, uint256 balance); /// @notice Semantic version. - /// @custom:semver 1.0.0 - string public constant version = "1.0.0"; + /// @custom:semver 1.0.1-beta.1 + string public constant version = "1.0.1-beta.1"; /// @notice The fixed cost of resolving a challenge. /// @dev The value is estimated by measuring the cost of resolving with `bytes(0)` diff --git a/packages/contracts-bedrock/src/L1/DelayedVetoable.sol b/packages/contracts-bedrock/src/L1/DelayedVetoable.sol index abb40b9ce90f0..ad45b4c9b20aa 100644 --- a/packages/contracts-bedrock/src/L1/DelayedVetoable.sol +++ b/packages/contracts-bedrock/src/L1/DelayedVetoable.sol @@ -1,7 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { ISemver } from "src/universal/ISemver.sol"; +// Interfaces +import { ISemver } from "src/universal/interfaces/ISemver.sol"; /// @title DelayedVetoable /// @notice This contract enables a delay before a call is forwarded to a target contract, and during the delay period @@ -68,8 +69,8 @@ contract DelayedVetoable is ISemver { } /// @notice Semantic version. - /// @custom:semver 1.0.0 - string public constant version = "1.0.0"; + /// @custom:semver 1.0.1-beta.1 + string public constant version = "1.0.1-beta.1"; /// @notice Sets the target admin during contract deployment. /// @param vetoer_ Address of the vetoer. diff --git a/packages/contracts-bedrock/src/L1/L1CrossDomainMessenger.sol b/packages/contracts-bedrock/src/L1/L1CrossDomainMessenger.sol index 4aaf2bd311561..8df4d9bfe7653 100644 --- a/packages/contracts-bedrock/src/L1/L1CrossDomainMessenger.sol +++ b/packages/contracts-bedrock/src/L1/L1CrossDomainMessenger.sol @@ -1,39 +1,44 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { Predeploys } from "src/libraries/Predeploys.sol"; -import { OptimismPortal } from "src/L1/OptimismPortal.sol"; +// Contracts import { CrossDomainMessenger } from "src/universal/CrossDomainMessenger.sol"; -import { ISemver } from "src/universal/ISemver.sol"; -import { SuperchainConfig } from "src/L1/SuperchainConfig.sol"; -import { SystemConfig } from "src/L1/SystemConfig.sol"; -/// @custom:proxied +// Libraries +import { Predeploys } from "src/libraries/Predeploys.sol"; + +// Interfaces +import { ISemver } from "src/universal/interfaces/ISemver.sol"; +import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol"; +import { ISystemConfig } from "src/L1/interfaces/ISystemConfig.sol"; +import { IOptimismPortal } from "src/L1/interfaces/IOptimismPortal.sol"; + +/// @custom:proxied true /// @title L1CrossDomainMessenger /// @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. contract L1CrossDomainMessenger is CrossDomainMessenger, ISemver { /// @notice Contract of the SuperchainConfig. - SuperchainConfig public superchainConfig; + ISuperchainConfig public superchainConfig; /// @notice Contract of the OptimismPortal. /// @custom:network-specific - OptimismPortal public portal; + IOptimismPortal public portal; /// @notice Address of the SystemConfig contract. - SystemConfig public systemConfig; + ISystemConfig public systemConfig; /// @notice Semantic version. - /// @custom:semver 2.4.0 - string public constant version = "2.4.0"; + /// @custom:semver 2.4.1-beta.1 + string public constant version = "2.4.1-beta.1"; /// @notice Constructs the L1CrossDomainMessenger contract. constructor() CrossDomainMessenger() { initialize({ - _superchainConfig: SuperchainConfig(address(0)), - _portal: OptimismPortal(payable(address(0))), - _systemConfig: SystemConfig(address(0)) + _superchainConfig: ISuperchainConfig(address(0)), + _portal: IOptimismPortal(payable(address(0))), + _systemConfig: ISystemConfig(address(0)) }); } @@ -42,9 +47,9 @@ contract L1CrossDomainMessenger is CrossDomainMessenger, ISemver { /// @param _portal Contract of the OptimismPortal contract on this network. /// @param _systemConfig Contract of the SystemConfig contract on this network. function initialize( - SuperchainConfig _superchainConfig, - OptimismPortal _portal, - SystemConfig _systemConfig + ISuperchainConfig _superchainConfig, + IOptimismPortal _portal, + ISystemConfig _systemConfig ) public initializer @@ -64,7 +69,7 @@ contract L1CrossDomainMessenger is CrossDomainMessenger, ISemver { /// Public getter is legacy and will be removed in the future. Use `portal()` instead. /// @return Contract of the OptimismPortal on this chain. /// @custom:legacy - function PORTAL() external view returns (OptimismPortal) { + function PORTAL() external view returns (IOptimismPortal) { return portal; } diff --git a/packages/contracts-bedrock/src/L1/L1ERC721Bridge.sol b/packages/contracts-bedrock/src/L1/L1ERC721Bridge.sol index 75547cb5edc5e..46e7e9f71b4c2 100644 --- a/packages/contracts-bedrock/src/L1/L1ERC721Bridge.sol +++ b/packages/contracts-bedrock/src/L1/L1ERC721Bridge.sol @@ -1,16 +1,21 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Contracts import { ERC721Bridge } from "src/universal/ERC721Bridge.sol"; -import { IERC721 } from "@openzeppelin/contracts/token/ERC721/IERC721.sol"; -import { L2ERC721Bridge } from "src/L2/L2ERC721Bridge.sol"; -import { ISemver } from "src/universal/ISemver.sol"; + +// Libraries import { Predeploys } from "src/libraries/Predeploys.sol"; -import { CrossDomainMessenger } from "src/universal/CrossDomainMessenger.sol"; -import { StandardBridge } from "src/universal/StandardBridge.sol"; import { Constants } from "src/libraries/Constants.sol"; -import { SuperchainConfig } from "src/L1/SuperchainConfig.sol"; +// Interfaces +import { IERC721 } from "@openzeppelin/contracts/token/ERC721/IERC721.sol"; +import { ISemver } from "src/universal/interfaces/ISemver.sol"; +import { ICrossDomainMessenger } from "src/universal/interfaces/ICrossDomainMessenger.sol"; +import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol"; +import { IL2ERC721Bridge } from "src/L2/interfaces/IL2ERC721Bridge.sol"; + +/// @custom:proxied true /// @title L1ERC721Bridge /// @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 @@ -21,21 +26,21 @@ contract L1ERC721Bridge is ERC721Bridge, ISemver { mapping(address => mapping(address => mapping(uint256 => bool))) public deposits; /// @notice Address of the SuperchainConfig contract. - SuperchainConfig public superchainConfig; + ISuperchainConfig public superchainConfig; /// @notice Semantic version. - /// @custom:semver 2.1.1+beta.1 - string public constant version = "2.1.1+beta.1"; + /// @custom:semver 2.1.1-beta.3 + string public constant version = "2.1.1-beta.3"; /// @notice Constructs the L1ERC721Bridge contract. constructor() ERC721Bridge() { - initialize({ _messenger: CrossDomainMessenger(address(0)), _superchainConfig: SuperchainConfig(address(0)) }); + initialize({ _messenger: ICrossDomainMessenger(address(0)), _superchainConfig: ISuperchainConfig(address(0)) }); } /// @notice Initializes the contract. /// @param _messenger Contract of the CrossDomainMessenger on this network. /// @param _superchainConfig Contract of the SuperchainConfig contract on this network. - function initialize(CrossDomainMessenger _messenger, SuperchainConfig _superchainConfig) public initializer { + function initialize(ICrossDomainMessenger _messenger, ISuperchainConfig _superchainConfig) public initializer { superchainConfig = _superchainConfig; __ERC721Bridge_init({ _messenger: _messenger, _otherBridge: ERC721Bridge(payable(Predeploys.L2_ERC721_BRIDGE)) }); } @@ -104,7 +109,7 @@ contract L1ERC721Bridge is ERC721Bridge, ISemver { // Construct calldata for _l2Token.finalizeBridgeERC721(_to, _tokenId) bytes memory message = abi.encodeWithSelector( - L2ERC721Bridge.finalizeBridgeERC721.selector, _remoteToken, _localToken, _from, _to, _tokenId, _extraData + IL2ERC721Bridge.finalizeBridgeERC721.selector, _remoteToken, _localToken, _from, _to, _tokenId, _extraData ); // Lock token into bridge diff --git a/packages/contracts-bedrock/src/L1/L1StandardBridge.sol b/packages/contracts-bedrock/src/L1/L1StandardBridge.sol index 757c140c56e47..6dd648f0d5410 100644 --- a/packages/contracts-bedrock/src/L1/L1StandardBridge.sol +++ b/packages/contracts-bedrock/src/L1/L1StandardBridge.sol @@ -1,15 +1,19 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { Predeploys } from "src/libraries/Predeploys.sol"; +// Contracts import { StandardBridge } from "src/universal/StandardBridge.sol"; -import { ISemver } from "src/universal/ISemver.sol"; -import { CrossDomainMessenger } from "src/universal/CrossDomainMessenger.sol"; -import { SuperchainConfig } from "src/L1/SuperchainConfig.sol"; -import { OptimismPortal } from "src/L1/OptimismPortal.sol"; -import { SystemConfig } from "src/L1/SystemConfig.sol"; -/// @custom:proxied +// Libraries +import { Predeploys } from "src/libraries/Predeploys.sol"; + +// Interfaces +import { ISemver } from "src/universal/interfaces/ISemver.sol"; +import { ICrossDomainMessenger } from "src/universal/interfaces/ICrossDomainMessenger.sol"; +import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol"; +import { ISystemConfig } from "src/L1/interfaces/ISystemConfig.sol"; + +/// @custom:proxied true /// @title L1StandardBridge /// @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 @@ -71,21 +75,21 @@ contract L1StandardBridge is StandardBridge, ISemver { ); /// @notice Semantic version. - /// @custom:semver 2.2.0 - string public constant version = "2.2.0"; + /// @custom:semver 2.2.1-beta.1 + string public constant version = "2.2.1-beta.1"; /// @notice Address of the SuperchainConfig contract. - SuperchainConfig public superchainConfig; + ISuperchainConfig public superchainConfig; /// @notice Address of the SystemConfig contract. - SystemConfig public systemConfig; + ISystemConfig public systemConfig; /// @notice Constructs the L1StandardBridge contract. constructor() StandardBridge() { initialize({ - _messenger: CrossDomainMessenger(address(0)), - _superchainConfig: SuperchainConfig(address(0)), - _systemConfig: SystemConfig(address(0)) + _messenger: ICrossDomainMessenger(address(0)), + _superchainConfig: ISuperchainConfig(address(0)), + _systemConfig: ISystemConfig(address(0)) }); } @@ -93,9 +97,9 @@ contract L1StandardBridge is StandardBridge, ISemver { /// @param _messenger Contract for the CrossDomainMessenger on this network. /// @param _superchainConfig Contract for the SuperchainConfig on this network. function initialize( - CrossDomainMessenger _messenger, - SuperchainConfig _superchainConfig, - SystemConfig _systemConfig + ICrossDomainMessenger _messenger, + ISuperchainConfig _superchainConfig, + ISystemConfig _systemConfig ) public initializer diff --git a/packages/contracts-bedrock/src/L1/L2OutputOracle.sol b/packages/contracts-bedrock/src/L1/L2OutputOracle.sol index fe2c7dd7c8ef6..fb8d681227bf8 100644 --- a/packages/contracts-bedrock/src/L1/L2OutputOracle.sol +++ b/packages/contracts-bedrock/src/L1/L2OutputOracle.sol @@ -1,12 +1,17 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Contracts import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; -import { ISemver } from "src/universal/ISemver.sol"; + +// Libraries import { Types } from "src/libraries/Types.sol"; import { Constants } from "src/libraries/Constants.sol"; -/// @custom:proxied +// Interfaces +import { ISemver } from "src/universal/interfaces/ISemver.sol"; + +/// @custom:proxied true /// @title L2OutputOracle /// @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 @@ -56,8 +61,8 @@ contract L2OutputOracle is Initializable, ISemver { event OutputsDeleted(uint256 indexed prevNextOutputIndex, uint256 indexed newNextOutputIndex); /// @notice Semantic version. - /// @custom:semver 1.8.0 - string public constant version = "1.8.0"; + /// @custom:semver 1.8.1-beta.1 + string public constant version = "1.8.1-beta.1"; /// @notice Constructs the L2OutputOracle contract. Initializes variables to the same values as /// in the getting-started config. diff --git a/packages/contracts-bedrock/src/L1/OPContractsManager.sol b/packages/contracts-bedrock/src/L1/OPContractsManager.sol new file mode 100644 index 0000000000000..d05ba7c8821a7 --- /dev/null +++ b/packages/contracts-bedrock/src/L1/OPContractsManager.sol @@ -0,0 +1,632 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +import { Blueprint } from "src/libraries/Blueprint.sol"; +import { Constants } from "src/libraries/Constants.sol"; + +import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; + +import { ISemver } from "src/universal/interfaces/ISemver.sol"; +import { IResourceMetering } from "src/L1/interfaces/IResourceMetering.sol"; +import { IBigStepper } from "src/dispute/interfaces/IBigStepper.sol"; +import { IDelayedWETH } from "src/dispute/interfaces/IDelayedWETH.sol"; +import { IAnchorStateRegistry } from "src/dispute/interfaces/IAnchorStateRegistry.sol"; +import { IDisputeGame } from "src/dispute/interfaces/IDisputeGame.sol"; + +import { Proxy } from "src/universal/Proxy.sol"; +import { ProxyAdmin } from "src/universal/ProxyAdmin.sol"; +import { SuperchainConfig } from "src/L1/SuperchainConfig.sol"; +import { ProtocolVersions } from "src/L1/ProtocolVersions.sol"; + +import { L1ChugSplashProxy } from "src/legacy/L1ChugSplashProxy.sol"; +import { ResolvedDelegateProxy } from "src/legacy/ResolvedDelegateProxy.sol"; +import { AddressManager } from "src/legacy/AddressManager.sol"; + +import { DelayedWETH } from "src/dispute/DelayedWETH.sol"; +import { DisputeGameFactory } from "src/dispute/DisputeGameFactory.sol"; +import { AnchorStateRegistry } from "src/dispute/AnchorStateRegistry.sol"; +import { FaultDisputeGame } from "src/dispute/FaultDisputeGame.sol"; +import { PermissionedDisputeGame } from "src/dispute/PermissionedDisputeGame.sol"; +import { Claim, Duration, GameType, GameTypes } from "src/dispute/lib/Types.sol"; + +import { SuperchainConfig } from "src/L1/SuperchainConfig.sol"; +import { ProtocolVersions } from "src/L1/ProtocolVersions.sol"; +import { OptimismPortal2 } from "src/L1/OptimismPortal2.sol"; +import { SystemConfig } from "src/L1/SystemConfig.sol"; +import { ResourceMetering } from "src/L1/ResourceMetering.sol"; +import { L1CrossDomainMessenger } from "src/L1/L1CrossDomainMessenger.sol"; +import { L1ERC721Bridge } from "src/L1/L1ERC721Bridge.sol"; +import { L1StandardBridge } from "src/L1/L1StandardBridge.sol"; +import { OptimismMintableERC20Factory } from "src/universal/OptimismMintableERC20Factory.sol"; + +/// @custom:proxied true +contract OPContractsManager is ISemver, Initializable { + // -------- Structs -------- + + /// @notice Represents the roles that can be set when deploying a standard OP Stack chain. + struct Roles { + address opChainProxyAdminOwner; + address systemConfigOwner; + address batcher; + address unsafeBlockSigner; + address proposer; + address challenger; + } + + /// @notice The full set of inputs to deploy a new OP Stack chain. + struct DeployInput { + Roles roles; + uint32 basefeeScalar; + uint32 blobBasefeeScalar; + uint256 l2ChainId; + // The correct type is AnchorStateRegistry.StartingAnchorRoot[] memory, + // but OP Deployer does not yet support structs. + bytes startingAnchorRoots; + } + + /// @notice The full set of outputs from deploying a new OP Stack chain. + struct DeployOutput { + ProxyAdmin opChainProxyAdmin; + AddressManager addressManager; + L1ERC721Bridge l1ERC721BridgeProxy; + SystemConfig systemConfigProxy; + OptimismMintableERC20Factory optimismMintableERC20FactoryProxy; + L1StandardBridge l1StandardBridgeProxy; + L1CrossDomainMessenger l1CrossDomainMessengerProxy; + // Fault proof contracts below. + OptimismPortal2 optimismPortalProxy; + DisputeGameFactory disputeGameFactoryProxy; + AnchorStateRegistry anchorStateRegistryProxy; + AnchorStateRegistry anchorStateRegistryImpl; + FaultDisputeGame faultDisputeGame; + PermissionedDisputeGame permissionedDisputeGame; + DelayedWETH delayedWETHPermissionedGameProxy; + DelayedWETH delayedWETHPermissionlessGameProxy; + } + + /// @notice The logic address and initializer selector for an implementation contract. + struct Implementation { + address logic; // Address containing the deployed logic contract. + bytes4 initializer; // Function selector for the initializer. + } + + /// @notice Used to set the implementation for a contract by mapping a contract + /// name to the implementation data. + struct ImplementationSetter { + string name; // Contract name. + Implementation info; // Implementation to set. + } + + /// @notice Addresses of ERC-5202 Blueprint contracts. There are used for deploying full size + /// contracts, to reduce the code size of this factory contract. If it deployed full contracts + /// using the `new Proxy()` syntax, the code size would get large fast, since this contract would + /// contain the bytecode of every contract it deploys. Therefore we instead use Blueprints to + /// reduce the code size of this contract. + struct Blueprints { + address addressManager; + address proxy; + address proxyAdmin; + address l1ChugSplashProxy; + address resolvedDelegateProxy; + address anchorStateRegistry; + address permissionedDisputeGame1; + address permissionedDisputeGame2; + } + + /// @notice Inputs required when initializing the OPContractsManager. To avoid 'StackTooDeep' errors, + /// all necessary inputs (excluding immutables) for initialization are bundled together in this struct. + struct InitializerInputs { + Blueprints blueprints; + ImplementationSetter[] setters; + string release; + bool isLatest; + } + + // -------- Constants and Variables -------- + + /// @custom:semver 1.0.0-beta.7 + string public constant version = "1.0.0-beta.7"; + + /// @notice Represents the interface version so consumers know how to decode the DeployOutput struct + /// that's emitted in the `Deployed` event. Whenever that struct changes, a new version should be used. + uint256 public constant OUTPUT_VERSION = 0; + + /// @notice Address of the SuperchainConfig contract shared by all chains. + SuperchainConfig public immutable superchainConfig; + + /// @notice Address of the ProtocolVersions contract shared by all chains. + ProtocolVersions public immutable protocolVersions; + + /// @notice The latest release of the OP Contracts Manager, as a string of the format `op-contracts/vX.Y.Z`. + string public latestRelease; + + /// @notice Maps a release version to a contract name to it's implementation data. + mapping(string => mapping(string => Implementation)) public implementations; + + /// @notice Maps an L2 Chain ID to the SystemConfig for that chain. + mapping(uint256 => SystemConfig) public systemConfigs; + + /// @notice Addresses of the Blueprint contracts. + /// This is internal because if public the autogenerated getter method would return a tuple of + /// addresses, but we want it to return a struct. This is also set via `initialize` because + /// we can't make this an immutable variable as it is a non-value type. + Blueprints internal blueprint; + + /// @notice Storage gap for future modifications, so we can expand the number of blueprints + /// without affecting other storage variables. + uint256[50] private __gap; + + // -------- Events -------- + + /// @notice Emitted when a new OP Stack chain is deployed. + /// @param outputVersion Version that indicates how to decode the `deployOutput` argument. + /// @param l2ChainId Chain ID of the new chain. + /// @param deployer Address that deployed the chain. + /// @param deployOutput ABI-encoded output of the deployment. + event Deployed( + uint256 indexed outputVersion, uint256 indexed l2ChainId, address indexed deployer, bytes deployOutput + ); + + // -------- Errors -------- + + /// @notice Thrown when an address is the zero address. + error AddressNotFound(address who); + + /// @notice Throw when a contract address has no code. + error AddressHasNoCode(address who); + + /// @notice Thrown when a release version is already set. + error AlreadyReleased(); + + /// @notice Thrown when an invalid `l2ChainId` is provided to `deploy`. + error InvalidChainId(); + + /// @notice Thrown when a role's address is not valid. + error InvalidRoleAddress(string role); + + /// @notice Thrown when the latest release is not set upon initialization. + error LatestReleaseNotSet(); + + // -------- Methods -------- + + /// @notice OPCM is proxied. Therefore the `initialize` function replaces most constructor logic for this contract. + + constructor(SuperchainConfig _superchainConfig, ProtocolVersions _protocolVersions) { + assertValidContractAddress(address(_superchainConfig)); + assertValidContractAddress(address(_protocolVersions)); + superchainConfig = _superchainConfig; + protocolVersions = _protocolVersions; + _disableInitializers(); + } + + function initialize(InitializerInputs memory _initializerInputs) public initializer { + if (_initializerInputs.isLatest) latestRelease = _initializerInputs.release; + if (keccak256(bytes(latestRelease)) == keccak256("")) revert LatestReleaseNotSet(); + + for (uint256 i = 0; i < _initializerInputs.setters.length; i++) { + ImplementationSetter memory setter = _initializerInputs.setters[i]; + Implementation storage impl = implementations[_initializerInputs.release][setter.name]; + if (impl.logic != address(0)) revert AlreadyReleased(); + + impl.initializer = setter.info.initializer; + impl.logic = setter.info.logic; + } + + blueprint = _initializerInputs.blueprints; + } + + function deploy(DeployInput calldata _input) external returns (DeployOutput memory) { + assertValidInputs(_input); + + // TODO Determine how we want to choose salt, e.g. are we concerned about chain ID squatting + // since this approach means a chain ID can only be used once. + uint256 l2ChainId = _input.l2ChainId; + bytes32 salt = bytes32(_input.l2ChainId); + DeployOutput memory output; + + // -------- Deploy Chain Singletons -------- + + // The ProxyAdmin is the owner of all proxies for the chain. We temporarily set the owner to + // this contract, and then transfer ownership to the specified owner at the end of deployment. + // The AddressManager is used to store the implementation for the L1CrossDomainMessenger + // due to it's usage of the legacy ResolvedDelegateProxy. + output.addressManager = AddressManager(Blueprint.deployFrom(blueprint.addressManager, salt)); + output.opChainProxyAdmin = + ProxyAdmin(Blueprint.deployFrom(blueprint.proxyAdmin, salt, abi.encode(address(this)))); + output.opChainProxyAdmin.setAddressManager(output.addressManager); + + // -------- Deploy Proxy Contracts -------- + + // Deploy ERC-1967 proxied contracts. + output.l1ERC721BridgeProxy = L1ERC721Bridge(deployProxy(l2ChainId, output.opChainProxyAdmin, "L1ERC721Bridge")); + output.optimismPortalProxy = + OptimismPortal2(payable(deployProxy(l2ChainId, output.opChainProxyAdmin, "OptimismPortal"))); + output.systemConfigProxy = SystemConfig(deployProxy(l2ChainId, output.opChainProxyAdmin, "SystemConfig")); + output.optimismMintableERC20FactoryProxy = OptimismMintableERC20Factory( + deployProxy(l2ChainId, output.opChainProxyAdmin, "OptimismMintableERC20Factory") + ); + output.disputeGameFactoryProxy = + DisputeGameFactory(deployProxy(l2ChainId, output.opChainProxyAdmin, "DisputeGameFactory")); + output.anchorStateRegistryProxy = + AnchorStateRegistry(deployProxy(l2ChainId, output.opChainProxyAdmin, "AnchorStateRegistry")); + + // Deploy legacy proxied contracts. + output.l1StandardBridgeProxy = L1StandardBridge( + payable(Blueprint.deployFrom(blueprint.l1ChugSplashProxy, salt, abi.encode(output.opChainProxyAdmin))) + ); + output.opChainProxyAdmin.setProxyType(address(output.l1StandardBridgeProxy), ProxyAdmin.ProxyType.CHUGSPLASH); + + string memory contractName = "OVM_L1CrossDomainMessenger"; + output.l1CrossDomainMessengerProxy = L1CrossDomainMessenger( + Blueprint.deployFrom(blueprint.resolvedDelegateProxy, salt, abi.encode(output.addressManager, contractName)) + ); + output.opChainProxyAdmin.setProxyType( + address(output.l1CrossDomainMessengerProxy), ProxyAdmin.ProxyType.RESOLVED + ); + output.opChainProxyAdmin.setImplementationName(address(output.l1CrossDomainMessengerProxy), contractName); + + // Now that all proxies are deployed, we can transfer ownership of the AddressManager to the ProxyAdmin. + output.addressManager.transferOwnership(address(output.opChainProxyAdmin)); + + // The AnchorStateRegistry Implementation is not MCP Ready, and therefore requires an implementation per chain. + // It must be deployed after the DisputeGameFactoryProxy so that it can be provided as a constructor argument. + output.anchorStateRegistryImpl = AnchorStateRegistry( + Blueprint.deployFrom(blueprint.anchorStateRegistry, salt, abi.encode(output.disputeGameFactoryProxy)) + ); + + // We have two delayed WETH contracts per chain, one for each of the permissioned and permissionless games. + output.delayedWETHPermissionlessGameProxy = + DelayedWETH(payable(deployProxy(l2ChainId, output.opChainProxyAdmin, "DelayedWETHPermissionlessGame"))); + output.delayedWETHPermissionedGameProxy = + DelayedWETH(payable(deployProxy(l2ChainId, output.opChainProxyAdmin, "DelayedWETHPermissionedGame"))); + + // While not a proxy, we deploy the PermissionedDisputeGame here as well because it's bespoke per chain. + output.permissionedDisputeGame = PermissionedDisputeGame( + Blueprint.deployFrom( + blueprint.permissionedDisputeGame1, + blueprint.permissionedDisputeGame2, + salt, + encodePermissionedDisputeGameConstructor(_input, output) + ) + ); + + // -------- Set and Initialize Proxy Implementations -------- + Implementation memory impl; + bytes memory data; + + impl = getLatestImplementation("L1ERC721Bridge"); + data = encodeL1ERC721BridgeInitializer(impl.initializer, output); + upgradeAndCall(output.opChainProxyAdmin, address(output.l1ERC721BridgeProxy), impl.logic, data); + + impl = getLatestImplementation("OptimismPortal"); + data = encodeOptimismPortalInitializer(impl.initializer, output); + upgradeAndCall(output.opChainProxyAdmin, address(output.optimismPortalProxy), impl.logic, data); + + impl = getLatestImplementation("SystemConfig"); + data = encodeSystemConfigInitializer(impl.initializer, _input, output); + upgradeAndCall(output.opChainProxyAdmin, address(output.systemConfigProxy), impl.logic, data); + + impl = getLatestImplementation("OptimismMintableERC20Factory"); + data = encodeOptimismMintableERC20FactoryInitializer(impl.initializer, output); + upgradeAndCall(output.opChainProxyAdmin, address(output.optimismMintableERC20FactoryProxy), impl.logic, data); + + impl = getLatestImplementation("L1CrossDomainMessenger"); + data = encodeL1CrossDomainMessengerInitializer(impl.initializer, output); + upgradeAndCall(output.opChainProxyAdmin, address(output.l1CrossDomainMessengerProxy), impl.logic, data); + + impl = getLatestImplementation("L1StandardBridge"); + data = encodeL1StandardBridgeInitializer(impl.initializer, output); + upgradeAndCall(output.opChainProxyAdmin, address(output.l1StandardBridgeProxy), impl.logic, data); + + impl = getLatestImplementation("DelayedWETH"); + data = encodeDelayedWETHInitializer(impl.initializer, _input); + upgradeAndCall(output.opChainProxyAdmin, address(output.delayedWETHPermissionedGameProxy), impl.logic, data); + upgradeAndCall(output.opChainProxyAdmin, address(output.delayedWETHPermissionlessGameProxy), impl.logic, data); + + // We set the initial owner to this contract, set game implementations, then transfer ownership. + impl = getLatestImplementation("DisputeGameFactory"); + data = encodeDisputeGameFactoryInitializer(impl.initializer, _input); + upgradeAndCall(output.opChainProxyAdmin, address(output.disputeGameFactoryProxy), impl.logic, data); + output.disputeGameFactoryProxy.setImplementation( + GameTypes.PERMISSIONED_CANNON, IDisputeGame(address(output.permissionedDisputeGame)) + ); + output.disputeGameFactoryProxy.setInitBond(GameTypes.PERMISSIONED_CANNON, 0.08 ether); + output.disputeGameFactoryProxy.transferOwnership(address(output.opChainProxyAdmin)); + + impl.logic = address(output.anchorStateRegistryImpl); + impl.initializer = AnchorStateRegistry.initialize.selector; + data = encodeAnchorStateRegistryInitializer(impl.initializer, _input); + upgradeAndCall(output.opChainProxyAdmin, address(output.anchorStateRegistryProxy), impl.logic, data); + + // -------- Finalize Deployment -------- + // Transfer ownership of the ProxyAdmin from this contract to the specified owner. + output.opChainProxyAdmin.transferOwnership(_input.roles.opChainProxyAdminOwner); + + emit Deployed(OUTPUT_VERSION, l2ChainId, msg.sender, abi.encode(output)); + return output; + } + + // -------- Utilities -------- + + /// @notice Verifies that all inputs are valid and reverts if any are invalid. + /// Typically the proxy admin owner is expected to have code, but this is not enforced here. + function assertValidInputs(DeployInput calldata _input) internal view { + if (_input.l2ChainId == 0 || _input.l2ChainId == block.chainid) revert InvalidChainId(); + + if (_input.roles.opChainProxyAdminOwner == address(0)) revert InvalidRoleAddress("opChainProxyAdminOwner"); + if (_input.roles.systemConfigOwner == address(0)) revert InvalidRoleAddress("systemConfigOwner"); + if (_input.roles.batcher == address(0)) revert InvalidRoleAddress("batcher"); + if (_input.roles.unsafeBlockSigner == address(0)) revert InvalidRoleAddress("unsafeBlockSigner"); + if (_input.roles.proposer == address(0)) revert InvalidRoleAddress("proposer"); + if (_input.roles.challenger == address(0)) revert InvalidRoleAddress("challenger"); + } + + /// @notice Maps an L2 chain ID to an L1 batch inbox address as defined by the standard + /// configuration's convention. This convention is `versionByte || keccak256(bytes32(chainId))[:19]`, + /// where || denotes concatenation`, versionByte is 0x00, and chainId is a uint256. + /// https://specs.optimism.io/protocol/configurability.html#consensus-parameters + function chainIdToBatchInboxAddress(uint256 _l2ChainId) public pure returns (address) { + bytes1 versionByte = 0x00; + bytes32 hashedChainId = keccak256(bytes.concat(bytes32(_l2ChainId))); + bytes19 first19Bytes = bytes19(hashedChainId); + return address(uint160(bytes20(bytes.concat(versionByte, first19Bytes)))); + } + + /// @notice Deterministically deploys a new proxy contract owned by the provided ProxyAdmin. + /// The salt is computed as a function of the L2 chain ID and the contract name. This is required + /// because we deploy many identical proxies, so they each require a unique salt for determinism. + function deployProxy( + uint256 _l2ChainId, + ProxyAdmin _proxyAdmin, + string memory _contractName + ) + internal + returns (address) + { + bytes32 salt = keccak256(abi.encode(_l2ChainId, _contractName)); + return Blueprint.deployFrom(blueprint.proxy, salt, abi.encode(_proxyAdmin)); + } + + /// @notice Returns the implementation data for a contract name. Makes a copy of the internal + // Implementation struct in storage to prevent accidental mutation of the internal data. + function getLatestImplementation(string memory _name) internal view returns (Implementation memory) { + Implementation storage impl = implementations[latestRelease][_name]; + return Implementation({ logic: impl.logic, initializer: impl.initializer }); + } + + // -------- Initializer Encoding -------- + + /// @notice Helper method for encoding the L1ERC721Bridge initializer data. + function encodeL1ERC721BridgeInitializer( + bytes4 _selector, + DeployOutput memory _output + ) + internal + view + virtual + returns (bytes memory) + { + return abi.encodeWithSelector(_selector, _output.l1CrossDomainMessengerProxy, superchainConfig); + } + + /// @notice Helper method for encoding the OptimismPortal initializer data. + function encodeOptimismPortalInitializer( + bytes4 _selector, + DeployOutput memory _output + ) + internal + view + virtual + returns (bytes memory) + { + _output; + // TODO make GameTypes.CANNON an input once FPs are supported + return abi.encodeWithSelector( + _selector, + _output.disputeGameFactoryProxy, + _output.systemConfigProxy, + superchainConfig, + GameTypes.PERMISSIONED_CANNON + ); + } + + /// @notice Helper method for encoding the SystemConfig initializer data. + function encodeSystemConfigInitializer( + bytes4 selector, + DeployInput memory _input, + DeployOutput memory _output + ) + internal + view + virtual + returns (bytes memory) + { + (ResourceMetering.ResourceConfig memory referenceResourceConfig, SystemConfig.Addresses memory opChainAddrs) = + defaultSystemConfigParams(selector, _input, _output); + + return abi.encodeWithSelector( + selector, + _input.roles.systemConfigOwner, + _input.basefeeScalar, + _input.blobBasefeeScalar, + bytes32(uint256(uint160(_input.roles.batcher))), // batcherHash + 30_000_000, // gasLimit, TODO should this be an input? + _input.roles.unsafeBlockSigner, + referenceResourceConfig, + chainIdToBatchInboxAddress(_input.l2ChainId), + opChainAddrs + ); + } + + /// @notice Helper method for encoding the OptimismMintableERC20Factory initializer data. + function encodeOptimismMintableERC20FactoryInitializer( + bytes4 _selector, + DeployOutput memory _output + ) + internal + pure + virtual + returns (bytes memory) + { + return abi.encodeWithSelector(_selector, _output.l1StandardBridgeProxy); + } + + /// @notice Helper method for encoding the L1CrossDomainMessenger initializer data. + function encodeL1CrossDomainMessengerInitializer( + bytes4 _selector, + DeployOutput memory _output + ) + internal + view + virtual + returns (bytes memory) + { + return + abi.encodeWithSelector(_selector, superchainConfig, _output.optimismPortalProxy, _output.systemConfigProxy); + } + + /// @notice Helper method for encoding the L1StandardBridge initializer data. + function encodeL1StandardBridgeInitializer( + bytes4 _selector, + DeployOutput memory _output + ) + internal + view + virtual + returns (bytes memory) + { + return abi.encodeWithSelector( + _selector, _output.l1CrossDomainMessengerProxy, superchainConfig, _output.systemConfigProxy + ); + } + + function encodeDisputeGameFactoryInitializer( + bytes4 _selector, + DeployInput memory + ) + internal + view + virtual + returns (bytes memory) + { + // This contract must be the initial owner so we can set game implementations, then + // ownership is transferred after. + return abi.encodeWithSelector(_selector, address(this)); + } + + function encodeAnchorStateRegistryInitializer( + bytes4 _selector, + DeployInput memory _input + ) + internal + view + virtual + returns (bytes memory) + { + // this line fails in the op-deployer tests because it is not passing in any data + AnchorStateRegistry.StartingAnchorRoot[] memory startingAnchorRoots = + abi.decode(_input.startingAnchorRoots, (AnchorStateRegistry.StartingAnchorRoot[])); + return abi.encodeWithSelector(_selector, startingAnchorRoots, superchainConfig); + } + + function encodeDelayedWETHInitializer( + bytes4 _selector, + DeployInput memory _input + ) + internal + view + virtual + returns (bytes memory) + { + return abi.encodeWithSelector(_selector, _input.roles.opChainProxyAdminOwner, superchainConfig); + } + + function encodePermissionedDisputeGameConstructor( + DeployInput memory _input, + DeployOutput memory _output + ) + internal + view + virtual + returns (bytes memory) + { + return abi.encode( + GameType.wrap(1), // Permissioned Cannon + Claim.wrap(bytes32(hex"dead")), // absolutePrestate + 73, // maxGameDepth + 30, // splitDepth + Duration.wrap(3 hours), // clockExtension + Duration.wrap(3.5 days), // maxClockDuration + IBigStepper(getLatestImplementation("MIPS").logic), + IDelayedWETH(payable(address(_output.delayedWETHPermissionedGameProxy))), + IAnchorStateRegistry(address(_output.anchorStateRegistryProxy)), + _input.l2ChainId, + _input.roles.proposer, + _input.roles.challenger + ); + } + + /// @notice Returns default, standard config arguments for the SystemConfig initializer. + /// This is used by subclasses to reduce code duplication. + function defaultSystemConfigParams( + bytes4, /* selector */ + DeployInput memory, /* _input */ + DeployOutput memory _output + ) + internal + view + virtual + returns (ResourceMetering.ResourceConfig memory resourceConfig_, SystemConfig.Addresses memory opChainAddrs_) + { + // We use assembly to easily convert from IResourceMetering.ResourceConfig to ResourceMetering.ResourceConfig. + // This is required because we have not yet fully migrated the codebase to be interface-based. + IResourceMetering.ResourceConfig memory resourceConfig = Constants.DEFAULT_RESOURCE_CONFIG(); + assembly ("memory-safe") { + resourceConfig_ := resourceConfig + } + + opChainAddrs_ = SystemConfig.Addresses({ + l1CrossDomainMessenger: address(_output.l1CrossDomainMessengerProxy), + l1ERC721Bridge: address(_output.l1ERC721BridgeProxy), + l1StandardBridge: address(_output.l1StandardBridgeProxy), + disputeGameFactory: address(_output.disputeGameFactoryProxy), + optimismPortal: address(_output.optimismPortalProxy), + optimismMintableERC20Factory: address(_output.optimismMintableERC20FactoryProxy), + gasPayingToken: Constants.ETHER + }); + + assertValidContractAddress(opChainAddrs_.l1CrossDomainMessenger); + assertValidContractAddress(opChainAddrs_.l1ERC721Bridge); + assertValidContractAddress(opChainAddrs_.l1StandardBridge); + assertValidContractAddress(opChainAddrs_.disputeGameFactory); + assertValidContractAddress(opChainAddrs_.optimismPortal); + assertValidContractAddress(opChainAddrs_.optimismMintableERC20Factory); + } + + /// @notice Makes an external call to the target to initialize the proxy with the specified data. + /// First performs safety checks to ensure the target, implementation, and proxy admin are valid. + function upgradeAndCall( + ProxyAdmin _proxyAdmin, + address _target, + address _implementation, + bytes memory _data + ) + internal + { + assertValidContractAddress(address(_proxyAdmin)); + assertValidContractAddress(_target); + assertValidContractAddress(_implementation); + + _proxyAdmin.upgradeAndCall(payable(address(_target)), _implementation, _data); + } + + function assertValidContractAddress(address _who) internal view { + if (_who == address(0)) revert AddressNotFound(_who); + if (_who.code.length == 0) revert AddressHasNoCode(_who); + } + + /// @notice Returns the blueprint contract addresses. + function blueprints() public view returns (Blueprints memory) { + return blueprint; + } +} diff --git a/packages/contracts-bedrock/src/L1/OPContractsManagerInterop.sol b/packages/contracts-bedrock/src/L1/OPContractsManagerInterop.sol new file mode 100644 index 0000000000000..90fa13e7455c1 --- /dev/null +++ b/packages/contracts-bedrock/src/L1/OPContractsManagerInterop.sol @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +import { OPContractsManager } from "src/L1/OPContractsManager.sol"; +import { SuperchainConfig } from "src/L1/SuperchainConfig.sol"; +import { ProtocolVersions } from "src/L1/ProtocolVersions.sol"; +import { ResourceMetering } from "src/L1/ResourceMetering.sol"; +import { SystemConfig } from "src/L1/SystemConfig.sol"; +import { SystemConfigInterop } from "src/L1/SystemConfigInterop.sol"; + +/// @custom:proxied true +contract OPContractsManagerInterop is OPContractsManager { + constructor( + SuperchainConfig _superchainConfig, + ProtocolVersions _protocolVersions + ) + OPContractsManager(_superchainConfig, _protocolVersions) + { } + + // The `SystemConfigInterop` contract has an extra `address _dependencyManager` argument + // that we must account for. + function encodeSystemConfigInitializer( + bytes4 selector, + DeployInput memory _input, + DeployOutput memory _output + ) + internal + view + virtual + override + returns (bytes memory) + { + (ResourceMetering.ResourceConfig memory referenceResourceConfig, SystemConfig.Addresses memory opChainAddrs) = + defaultSystemConfigParams(selector, _input, _output); + + // TODO For now we assume that the dependency manager is the same as the proxy admin owner. + // This is currently undefined since it's not part of the standard config, so we may need + // to update where this value is pulled from in the future. To support a different dependency + // manager in this contract without an invasive change of redefining the `Roles` struct, + // we will make the change described in https://github.com/ethereum-optimism/optimism/issues/11783. + address dependencyManager = address(_input.roles.opChainProxyAdminOwner); + + return abi.encodeWithSelector( + selector, + _input.roles.systemConfigOwner, + _input.basefeeScalar, + _input.blobBasefeeScalar, + bytes32(uint256(uint160(_input.roles.batcher))), // batcherHash + 30_000_000, // gasLimit TODO make this configurable? + _input.roles.unsafeBlockSigner, + referenceResourceConfig, + chainIdToBatchInboxAddress(_input.l2ChainId), + opChainAddrs, + dependencyManager + ); + } +} diff --git a/packages/contracts-bedrock/src/L1/OPStackManager.sol b/packages/contracts-bedrock/src/L1/OPStackManager.sol deleted file mode 100644 index ce0cb109777b0..0000000000000 --- a/packages/contracts-bedrock/src/L1/OPStackManager.sol +++ /dev/null @@ -1,67 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.15; - -import { ISemver } from "src/universal/ISemver.sol"; -import { SystemConfig } from "src/L1/SystemConfig.sol"; - -/// @custom:proxied -contract OPStackManager is ISemver { - /// @custom:semver 1.0.0-beta.1 - string public constant version = "1.0.0-beta.1"; - - /// @notice Represents the roles that can be set when deploying a standard OP Stack chain. - struct Roles { - address proxyAdminOwner; - address systemConfigOwner; - address batcher; - address unsafeBlockSigner; - address proposer; - address challenger; - } - - /// @notice Emitted when a new OP Stack chain is deployed. - /// @param l2ChainId The chain ID of the new chain. - /// @param systemConfig The address of the new chain's SystemConfig contract. - event Deployed(uint256 indexed l2ChainId, SystemConfig indexed systemConfig); - - /// @notice Thrown when an invalid `l2ChainId` is provided to `deploy`. - error InvalidChainId(); - - /// @notice Thrown when a deployment fails. - error DeploymentFailed(string reason); - - /// @notice Temporary error since the deploy method is not yet implemented. - error NotImplemented(); - - function deploy( - uint256 _l2ChainId, - uint32 _basefeeScalar, - uint32 _blobBasefeeScalar, - Roles calldata _roles - ) - external - view // This is only here to silence the compiler warning until the function is fully implemented. - returns (SystemConfig systemConfig_) - { - if (_l2ChainId == 0 || _l2ChainId == block.chainid) revert InvalidChainId(); - - // Silence compiler warnings. - _roles; - _basefeeScalar; - _blobBasefeeScalar; - systemConfig_; - - revert NotImplemented(); - } - - /// @notice Maps an L2 chain ID to an L1 batch inbox address as defined by the standard - /// configuration's convention. This convention is `versionByte || keccak256(bytes32(chainId))[:19]`, - /// where || denotes concatenation`, versionByte is 0x00, and chainId is a uint256. - /// https://specs.optimism.io/protocol/configurability.html#consensus-parameters - function chainIdToBatchInboxAddress(uint256 _l2ChainId) internal pure returns (address) { - bytes1 versionByte = 0x00; - bytes32 hashedChainId = keccak256(bytes.concat(bytes32(_l2ChainId))); - bytes19 first19Bytes = bytes19(hashedChainId); - return address(uint160(bytes20(bytes.concat(versionByte, first19Bytes)))); - } -} diff --git a/packages/contracts-bedrock/src/L1/OptimismPortal.sol b/packages/contracts-bedrock/src/L1/OptimismPortal.sol index 38c638aa8e48d..885f375742127 100644 --- a/packages/contracts-bedrock/src/L1/OptimismPortal.sol +++ b/packages/contracts-bedrock/src/L1/OptimismPortal.sol @@ -1,25 +1,31 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Contracts import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; +import { ResourceMetering } from "src/L1/ResourceMetering.sol"; + +// Libraries +import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import { SafeCall } from "src/libraries/SafeCall.sol"; -import { L2OutputOracle } from "src/L1/L2OutputOracle.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 { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; -import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import { L1Block } from "src/L2/L1Block.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; +import { AddressAliasHelper } from "src/vendor/AddressAliasHelper.sol"; import "src/libraries/PortalErrors.sol"; -/// @custom:proxied +// Interfaces +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import { ISemver } from "src/universal/interfaces/ISemver.sol"; +import { IL2OutputOracle } from "src/L1/interfaces/IL2OutputOracle.sol"; +import { ISystemConfig } from "src/L1/interfaces/ISystemConfig.sol"; +import { IResourceMetering } from "src/L1/interfaces/IResourceMetering.sol"; +import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol"; +import { IL1Block } from "src/L2/interfaces/IL1Block.sol"; + +/// @custom:proxied true /// @title OptimismPortal /// @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. @@ -64,15 +70,15 @@ contract OptimismPortal is Initializable, ResourceMetering, ISemver { bool private spacer_53_0_1; /// @notice Contract of the Superchain Config. - SuperchainConfig public superchainConfig; + ISuperchainConfig public superchainConfig; /// @notice Contract of the L2OutputOracle. /// @custom:network-specific - L2OutputOracle public l2Oracle; + IL2OutputOracle public l2Oracle; /// @notice Contract of the SystemConfig. /// @custom:network-specific - SystemConfig public systemConfig; + ISystemConfig public systemConfig; /// @custom:spacer disputeGameFactory /// @notice Spacer for backwards compatibility. @@ -128,17 +134,17 @@ contract OptimismPortal is Initializable, ResourceMetering, ISemver { } /// @notice Semantic version. - /// @custom:semver 2.8.1-beta.1 + /// @custom:semver 2.8.1-beta.3 function version() public pure virtual returns (string memory) { - return "2.8.1-beta.1"; + return "2.8.1-beta.3"; } /// @notice Constructs the OptimismPortal contract. constructor() { initialize({ - _l2Oracle: L2OutputOracle(address(0)), - _systemConfig: SystemConfig(address(0)), - _superchainConfig: SuperchainConfig(address(0)) + _l2Oracle: IL2OutputOracle(address(0)), + _systemConfig: ISystemConfig(address(0)), + _superchainConfig: ISuperchainConfig(address(0)) }); } @@ -147,9 +153,9 @@ contract OptimismPortal is Initializable, ResourceMetering, ISemver { /// @param _systemConfig Contract of the SystemConfig. /// @param _superchainConfig Contract of the SuperchainConfig. function initialize( - L2OutputOracle _l2Oracle, - SystemConfig _systemConfig, - SuperchainConfig _superchainConfig + IL2OutputOracle _l2Oracle, + ISystemConfig _systemConfig, + ISuperchainConfig _superchainConfig ) public initializer @@ -222,8 +228,16 @@ contract OptimismPortal is Initializable, ResourceMetering, ISemver { /// 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(); + function _resourceConfig() internal view override returns (ResourceConfig memory) { + IResourceMetering.ResourceConfig memory config = systemConfig.resourceConfig(); + return ResourceConfig({ + maxResourceLimit: config.maxResourceLimit, + elasticityMultiplier: config.elasticityMultiplier, + baseFeeMaxChangeDenominator: config.baseFeeMaxChangeDenominator, + minimumBaseFee: config.minimumBaseFee, + systemTxMaxGas: config.systemTxMaxGas, + maximumBaseFee: config.maximumBaseFee + }); } /// @notice Proves a withdrawal transaction. @@ -578,7 +592,7 @@ contract OptimismPortal is Initializable, ResourceMetering, ISemver { uint256(0), // value uint64(SYSTEM_DEPOSIT_GAS_LIMIT), // gasLimit false, // isCreation, - abi.encodeCall(L1Block.setGasPayingToken, (_token, _decimals, _name, _symbol)) + abi.encodeCall(IL1Block.setGasPayingToken, (_token, _decimals, _name, _symbol)) ) ); } diff --git a/packages/contracts-bedrock/src/L1/OptimismPortal2.sol b/packages/contracts-bedrock/src/L1/OptimismPortal2.sol index 3643ecbaa24e1..3a75269a2020d 100644 --- a/packages/contracts-bedrock/src/L1/OptimismPortal2.sol +++ b/packages/contracts-bedrock/src/L1/OptimismPortal2.sol @@ -1,28 +1,33 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Contracts import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; +import { ResourceMetering } from "src/L1/ResourceMetering.sol"; + +// Libraries +import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.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 { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; -import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import { L1Block } from "src/L2/L1Block.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; - +import { AddressAliasHelper } from "src/vendor/AddressAliasHelper.sol"; import "src/libraries/PortalErrors.sol"; import "src/dispute/lib/Types.sol"; -/// @custom:proxied +// Interfaces +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import { ISemver } from "src/universal/interfaces/ISemver.sol"; +import { ISystemConfig } from "src/L1/interfaces/ISystemConfig.sol"; +import { IResourceMetering } from "src/L1/interfaces/IResourceMetering.sol"; +import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol"; +import { IDisputeGameFactory } from "src/dispute/interfaces/IDisputeGameFactory.sol"; +import { IDisputeGame } from "src/dispute/interfaces/IDisputeGame.sol"; +import { IL1Block } from "src/L2/interfaces/IL1Block.sol"; + +/// @custom:proxied true /// @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. @@ -74,7 +79,7 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver { bool private spacer_53_0_1; /// @notice Contract of the Superchain Config. - SuperchainConfig public superchainConfig; + ISuperchainConfig public superchainConfig; /// @custom:legacy /// @custom:spacer l2Oracle @@ -83,11 +88,11 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver { /// @notice Contract of the SystemConfig. /// @custom:network-specific - SystemConfig public systemConfig; + ISystemConfig public systemConfig; /// @notice Address of the DisputeGameFactory. /// @custom:network-specific - DisputeGameFactory public disputeGameFactory; + IDisputeGameFactory public disputeGameFactory; /// @notice A mapping of withdrawal hashes to proof submitters to `ProvenWithdrawal` data. mapping(bytes32 => mapping(address => ProvenWithdrawal)) public provenWithdrawals; @@ -101,7 +106,13 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver { /// @notice The timestamp at which the respected game type was last updated. uint64 public respectedGameTypeUpdatedAt; - /// @notice Mapping of withdrawal hashes to addresses that have submitted a proof for the withdrawal. + /// @notice Mapping of withdrawal hashes to addresses that have submitted a proof for the + /// withdrawal. Original OptimismPortal contract only allowed one proof to be submitted + /// for any given withdrawal hash. Fault Proofs version of this contract must allow + /// multiple proofs for the same withdrawal hash to prevent a malicious user from + /// blocking other withdrawals by proving them against invalid proposals. Submitters + /// are tracked in an array to simplify the off-chain process of determining which + /// proof submission should be used when finalizing a withdrawal. mapping(bytes32 => address[]) public proofSubmitters; /// @notice Represents the amount of native asset minted in L2. This may not @@ -153,9 +164,9 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver { } /// @notice Semantic version. - /// @custom:semver 3.11.0-beta.2 + /// @custom:semver 3.11.0-beta.5 function version() public pure virtual returns (string memory) { - return "3.11.0-beta.2"; + return "3.11.0-beta.5"; } /// @notice Constructs the OptimismPortal contract. @@ -164,9 +175,9 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver { DISPUTE_GAME_FINALITY_DELAY_SECONDS = _disputeGameFinalityDelaySeconds; initialize({ - _disputeGameFactory: DisputeGameFactory(address(0)), - _systemConfig: SystemConfig(address(0)), - _superchainConfig: SuperchainConfig(address(0)), + _disputeGameFactory: IDisputeGameFactory(address(0)), + _systemConfig: ISystemConfig(address(0)), + _superchainConfig: ISuperchainConfig(address(0)), _initialRespectedGameType: GameType.wrap(0) }); } @@ -176,9 +187,9 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver { /// @param _systemConfig Contract of the SystemConfig. /// @param _superchainConfig Contract of the SuperchainConfig. function initialize( - DisputeGameFactory _disputeGameFactory, - SystemConfig _systemConfig, - SuperchainConfig _superchainConfig, + IDisputeGameFactory _disputeGameFactory, + ISystemConfig _systemConfig, + ISuperchainConfig _superchainConfig, GameType _initialRespectedGameType ) public @@ -271,9 +282,12 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver { /// @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(); + /// @return config_ ResourceMetering ResourceConfig + function _resourceConfig() internal view override returns (ResourceMetering.ResourceConfig memory config_) { + IResourceMetering.ResourceConfig memory config = systemConfig.resourceConfig(); + assembly ("memory-safe") { + config_ := config + } } /// @notice Proves a withdrawal transaction. @@ -592,7 +606,7 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver { uint256(0), // value uint64(SYSTEM_DEPOSIT_GAS_LIMIT), // gasLimit false, // isCreation, - abi.encodeCall(L1Block.setGasPayingToken, (_token, _decimals, _name, _symbol)) + abi.encodeCall(IL1Block.setGasPayingToken, (_token, _decimals, _name, _symbol)) ) ); } diff --git a/packages/contracts-bedrock/src/L1/OptimismPortalInterop.sol b/packages/contracts-bedrock/src/L1/OptimismPortalInterop.sol index 9fad94a0916f6..fd33c5286ebdc 100644 --- a/packages/contracts-bedrock/src/L1/OptimismPortalInterop.sol +++ b/packages/contracts-bedrock/src/L1/OptimismPortalInterop.sol @@ -1,20 +1,21 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Contracts import { OptimismPortal2 } from "src/L1/OptimismPortal2.sol"; -import { L1BlockInterop, ConfigType } from "src/L2/L1BlockInterop.sol"; +import { L1BlockIsthmus, ConfigType } from "src/L2/L1BlockIsthmus.sol"; + +// Libraries import { Predeploys } from "src/libraries/Predeploys.sol"; import { Constants } from "src/libraries/Constants.sol"; +import "src/libraries/PortalErrors.sol"; -/// @custom:proxied +/// @custom:proxied true /// @title OptimismPortalInterop /// @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 OptimismPortalInterop is OptimismPortal2 { - /// @notice Thrown when a non-depositor account attempts update static configuration. - error Unauthorized(); - constructor( uint256 _proofMaturityDelaySeconds, uint256 _disputeGameFinalityDelaySeconds @@ -47,7 +48,7 @@ contract OptimismPortalInterop is OptimismPortal2 { uint256(0), // value uint64(SYSTEM_DEPOSIT_GAS_LIMIT), // gasLimit false, // isCreation, - abi.encodeCall(L1BlockInterop.setConfig, (_type, _value)) + abi.encodeCall(L1BlockIsthmus.setConfig, (_type, _value)) ) ); } diff --git a/packages/contracts-bedrock/src/L1/ProtocolVersions.sol b/packages/contracts-bedrock/src/L1/ProtocolVersions.sol index d3f06b27730b6..f988d43e16975 100644 --- a/packages/contracts-bedrock/src/L1/ProtocolVersions.sol +++ b/packages/contracts-bedrock/src/L1/ProtocolVersions.sol @@ -2,13 +2,14 @@ pragma solidity 0.8.15; import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; -import { ISemver } from "src/universal/ISemver.sol"; +import { ISemver } from "src/universal/interfaces/ISemver.sol"; import { Storage } from "src/libraries/Storage.sol"; import { Constants } from "src/libraries/Constants.sol"; /// @notice ProtocolVersion is a numeric identifier of the protocol version. type ProtocolVersion is uint256; +/// @custom:proxied true /// @title ProtocolVersions /// @notice The ProtocolVersions contract is used to manage superchain protocol version information. contract ProtocolVersions is OwnableUpgradeable, ISemver { @@ -36,8 +37,8 @@ contract ProtocolVersions is OwnableUpgradeable, ISemver { event ConfigUpdate(uint256 indexed version, UpdateType indexed updateType, bytes data); /// @notice Semantic version. - /// @custom:semver 1.0.0 - string public constant version = "1.0.0"; + /// @custom:semver 1.0.1-beta.1 + string public constant version = "1.0.1-beta.1"; /// @notice Constructs the ProtocolVersion contract. Cannot set /// the owner to `address(0)` due to the Ownable contract's diff --git a/packages/contracts-bedrock/src/L1/ResourceMetering.sol b/packages/contracts-bedrock/src/L1/ResourceMetering.sol index feeabe14ee178..196a1573d7e43 100644 --- a/packages/contracts-bedrock/src/L1/ResourceMetering.sol +++ b/packages/contracts-bedrock/src/L1/ResourceMetering.sol @@ -1,7 +1,10 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Contracts import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; + +// Libraries import { Math } from "@openzeppelin/contracts/utils/math/Math.sol"; import { Burn } from "src/libraries/Burn.sol"; import { Arithmetic } from "src/libraries/Arithmetic.sol"; diff --git a/packages/contracts-bedrock/src/L1/SuperchainConfig.sol b/packages/contracts-bedrock/src/L1/SuperchainConfig.sol index 954e1b5df3c72..51b13936c81bc 100644 --- a/packages/contracts-bedrock/src/L1/SuperchainConfig.sol +++ b/packages/contracts-bedrock/src/L1/SuperchainConfig.sol @@ -2,9 +2,10 @@ pragma solidity 0.8.15; import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; -import { ISemver } from "src/universal/ISemver.sol"; +import { ISemver } from "src/universal/interfaces/ISemver.sol"; import { Storage } from "src/libraries/Storage.sol"; +/// @custom:proxied true /// @custom:audit none This contracts is not yet audited. /// @title SuperchainConfig /// @notice The SuperchainConfig contract is used to manage configuration of global superchain values. @@ -35,8 +36,8 @@ contract SuperchainConfig is Initializable, ISemver { event ConfigUpdate(UpdateType indexed updateType, bytes data); /// @notice Semantic version. - /// @custom:semver 1.1.0 - string public constant version = "1.1.0"; + /// @custom:semver 1.1.1-beta.1 + string public constant version = "1.1.1-beta.1"; /// @notice Constructs the SuperchainConfig contract. constructor() { diff --git a/packages/contracts-bedrock/src/L1/SystemConfig.sol b/packages/contracts-bedrock/src/L1/SystemConfig.sol index 3d00077527a88..032cb3227984f 100644 --- a/packages/contracts-bedrock/src/L1/SystemConfig.sol +++ b/packages/contracts-bedrock/src/L1/SystemConfig.sol @@ -1,15 +1,21 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Contracts import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; -import { ISemver } from "src/universal/ISemver.sol"; -import { ResourceMetering } from "src/L1/ResourceMetering.sol"; +import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; + +// Libraries import { Storage } from "src/libraries/Storage.sol"; import { Constants } from "src/libraries/Constants.sol"; -import { OptimismPortal } from "src/L1/OptimismPortal.sol"; import { GasPayingToken, IGasToken } from "src/libraries/GasPayingToken.sol"; -import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +// Interfaces +import { ISemver } from "src/universal/interfaces/ISemver.sol"; +import { IOptimismPortal } from "src/L1/interfaces/IOptimismPortal.sol"; +import { IResourceMetering } from "src/L1/interfaces/IResourceMetering.sol"; + +/// @custom:proxied true /// @title SystemConfig /// @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 @@ -115,7 +121,7 @@ contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken { /// @notice The configuration for the deposit fee market. /// Used by the OptimismPortal to meter the cost of buying L2 gas on L1. /// Set as internal with a getter so that the struct is returned instead of a tuple. - ResourceMetering.ResourceConfig internal _resourceConfig; + IResourceMetering.ResourceConfig internal _resourceConfig; /// @notice Emitted when configuration is updated. /// @param version SystemConfig version. @@ -124,9 +130,9 @@ contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken { event ConfigUpdate(uint256 indexed version, UpdateType indexed updateType, bytes data); /// @notice Semantic version. - /// @custom:semver 2.3.0-beta.2 + /// @custom:semver 2.3.0-beta.3 function version() public pure virtual returns (string memory) { - return "2.3.0-beta.2"; + return "2.3.0-beta.3"; } /// @notice Constructs the SystemConfig contract. Cannot set @@ -143,7 +149,7 @@ contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken { _batcherHash: bytes32(0), _gasLimit: 1, _unsafeBlockSigner: address(0), - _config: ResourceMetering.ResourceConfig({ + _config: IResourceMetering.ResourceConfig({ maxResourceLimit: 1, elasticityMultiplier: 1, baseFeeMaxChangeDenominator: 2, @@ -183,7 +189,7 @@ contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken { bytes32 _batcherHash, uint64 _gasLimit, address _unsafeBlockSigner, - ResourceMetering.ResourceConfig memory _config, + IResourceMetering.ResourceConfig memory _config, address _batchInbox, SystemConfig.Addresses memory _addresses ) @@ -317,7 +323,7 @@ contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken { // Set the gas paying token in storage and in the OptimismPortal. GasPayingToken.set({ _token: _token, _decimals: GAS_PAYING_TOKEN_DECIMALS, _name: name, _symbol: symbol }); - OptimismPortal(payable(optimismPortal())).setGasPayingToken({ + IOptimismPortal(payable(optimismPortal())).setGasPayingToken({ _token: _token, _decimals: GAS_PAYING_TOKEN_DECIMALS, _name: name, @@ -432,7 +438,7 @@ contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken { /// @notice A getter for the resource config. /// Ensures that the struct is returned instead of a tuple. /// @return ResourceConfig - function resourceConfig() external view returns (ResourceMetering.ResourceConfig memory) { + function resourceConfig() external view returns (IResourceMetering.ResourceConfig memory) { return _resourceConfig; } @@ -441,7 +447,7 @@ contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken { /// In the future, this method may emit an event that the `op-node` picks up /// for when the resource config is changed. /// @param _config The new resource config. - function _setResourceConfig(ResourceMetering.ResourceConfig memory _config) internal { + function _setResourceConfig(IResourceMetering.ResourceConfig memory _config) internal { // Min base fee must be less than or equal to max base fee. require( _config.minimumBaseFee <= _config.maximumBaseFee, "SystemConfig: min base fee must be less than max base" diff --git a/packages/contracts-bedrock/src/L1/SystemConfigInterop.sol b/packages/contracts-bedrock/src/L1/SystemConfigInterop.sol index 098b59e1f9f7a..ee5b052e04ece 100644 --- a/packages/contracts-bedrock/src/L1/SystemConfigInterop.sol +++ b/packages/contracts-bedrock/src/L1/SystemConfigInterop.sol @@ -1,16 +1,22 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { Constants } from "src/libraries/Constants.sol"; -import { OptimismPortalInterop as OptimismPortal } from "src/L1/OptimismPortalInterop.sol"; -import { GasPayingToken } from "src/libraries/GasPayingToken.sol"; +// Contracts import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import { IOptimismPortalInterop as IOptimismPortal } from "src/L1/interfaces/IOptimismPortalInterop.sol"; import { SystemConfig } from "src/L1/SystemConfig.sol"; -import { ConfigType } from "src/L2/L1BlockInterop.sol"; +import { ConfigType } from "src/L2/L1BlockIsthmus.sol"; + +// Libraries +import { Constants } from "src/libraries/Constants.sol"; +import { GasPayingToken } from "src/libraries/GasPayingToken.sol"; import { StaticConfig } from "src/libraries/StaticConfig.sol"; -import { ResourceMetering } from "src/L1/ResourceMetering.sol"; import { Storage } from "src/libraries/Storage.sol"; +// Interfaces +import { IResourceMetering } from "src/L1/interfaces/IResourceMetering.sol"; + +/// @custom:proxied true /// @title SystemConfigInterop /// @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 @@ -40,14 +46,14 @@ contract SystemConfigInterop is SystemConfig { bytes32 _batcherHash, uint64 _gasLimit, address _unsafeBlockSigner, - ResourceMetering.ResourceConfig memory _config, + IResourceMetering.ResourceConfig memory _config, address _batchInbox, SystemConfig.Addresses memory _addresses, address _dependencyManager ) external - initializer { + // This method has an initializer modifier, and will revert if already initialized. initialize({ _owner: _owner, _basefeeScalar: _basefeeScalar, @@ -84,7 +90,7 @@ contract SystemConfigInterop is SystemConfig { // Set the gas paying token in storage and in the OptimismPortal. GasPayingToken.set({ _token: _token, _decimals: GAS_PAYING_TOKEN_DECIMALS, _name: name, _symbol: symbol }); - OptimismPortal(payable(optimismPortal())).setConfig( + IOptimismPortal(payable(optimismPortal())).setConfig( ConfigType.SET_GAS_PAYING_TOKEN, StaticConfig.encodeSetGasPayingToken({ _token: _token, @@ -100,7 +106,7 @@ contract SystemConfigInterop is SystemConfig { /// @param _chainId Chain ID of chain to add. function addDependency(uint256 _chainId) external { require(msg.sender == dependencyManager(), "SystemConfig: caller is not the dependency manager"); - OptimismPortal(payable(optimismPortal())).setConfig( + IOptimismPortal(payable(optimismPortal())).setConfig( ConfigType.ADD_DEPENDENCY, StaticConfig.encodeAddDependency(_chainId) ); } @@ -109,7 +115,7 @@ contract SystemConfigInterop is SystemConfig { /// @param _chainId Chain ID of the chain to remove. function removeDependency(uint256 _chainId) external { require(msg.sender == dependencyManager(), "SystemConfig: caller is not the dependency manager"); - OptimismPortal(payable(optimismPortal())).setConfig( + IOptimismPortal(payable(optimismPortal())).setConfig( ConfigType.REMOVE_DEPENDENCY, StaticConfig.encodeRemoveDependency(_chainId) ); } diff --git a/packages/contracts-bedrock/src/L1/interfaces/IDataAvailabilityChallenge.sol b/packages/contracts-bedrock/src/L1/interfaces/IDataAvailabilityChallenge.sol new file mode 100644 index 0000000000000..db3c1680e6c5e --- /dev/null +++ b/packages/contracts-bedrock/src/L1/interfaces/IDataAvailabilityChallenge.sol @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +enum ChallengeStatus { + Uninitialized, + Active, + Resolved, + Expired +} + +enum CommitmentType { + Keccak256 +} + +struct Challenge { + address challenger; + uint256 lockedBond; + uint256 startBlock; + uint256 resolvedBlock; +} + +interface IDataAvailabilityChallenge { + error BondTooLow(uint256 balance, uint256 required); + error ChallengeExists(); + error ChallengeNotActive(); + error ChallengeNotExpired(); + error ChallengeWindowNotOpen(); + error InvalidCommitmentLength(uint8 commitmentType, uint256 expectedLength, uint256 actualLength); + error InvalidInputData(bytes providedDataCommitment, bytes expectedCommitment); + error InvalidResolverRefundPercentage(uint256 invalidResolverRefundPercentage); + error UnknownCommitmentType(uint8 commitmentType); + error WithdrawalFailed(); + + event BalanceChanged(address account, uint256 balance); + event ChallengeStatusChanged( + uint256 indexed challengedBlockNumber, bytes challengedCommitment, ChallengeStatus status + ); + event Initialized(uint8 version); + event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); + event RequiredBondSizeChanged(uint256 challengeWindow); + event ResolverRefundPercentageChanged(uint256 resolverRefundPercentage); + + receive() external payable; + + function balances(address) external view returns (uint256); + function bondSize() external view returns (uint256); + function challenge(uint256 challengedBlockNumber, bytes memory challengedCommitment) external payable; + function challengeWindow() external view returns (uint256); + function deposit() external payable; + function fixedResolutionCost() external view returns (uint256); + function getChallenge( + uint256 challengedBlockNumber, + bytes memory challengedCommitment + ) + external + view + returns (Challenge memory); + function getChallengeStatus( + uint256 challengedBlockNumber, + bytes memory challengedCommitment + ) + external + view + returns (ChallengeStatus); + function initialize( + address _owner, + uint256 _challengeWindow, + uint256 _resolveWindow, + uint256 _bondSize, + uint256 _resolverRefundPercentage + ) + external; + function owner() external view returns (address); + function renounceOwnership() external; + function resolve( + uint256 challengedBlockNumber, + bytes memory challengedCommitment, + bytes memory resolveData + ) + external; + function resolveWindow() external view returns (uint256); + function resolverRefundPercentage() external view returns (uint256); + function setBondSize(uint256 _bondSize) external; + function setResolverRefundPercentage(uint256 _resolverRefundPercentage) external; + function transferOwnership(address newOwner) external; + function unlockBond(uint256 challengedBlockNumber, bytes memory challengedCommitment) external; + function validateCommitment(bytes memory commitment) external pure; + function variableResolutionCost() external view returns (uint256); + function variableResolutionCostPrecision() external view returns (uint256); + function version() external view returns (string memory); + function withdraw() external; + + function __constructor__() external; +} diff --git a/packages/contracts-bedrock/src/L1/interfaces/IDelayedVetoable.sol b/packages/contracts-bedrock/src/L1/interfaces/IDelayedVetoable.sol new file mode 100644 index 0000000000000..0bea81fed34b8 --- /dev/null +++ b/packages/contracts-bedrock/src/L1/interfaces/IDelayedVetoable.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +interface IDelayedVetoable { + error ForwardingEarly(); + error Unauthorized(address expected, address actual); + + event DelayActivated(uint256 delay); + event Forwarded(bytes32 indexed callHash, bytes data); + event Initiated(bytes32 indexed callHash, bytes data); + event Vetoed(bytes32 indexed callHash, bytes data); + + fallback() external; + + function delay() external returns (uint256 delay_); + function initiator() external returns (address initiator_); + function queuedAt(bytes32 callHash) external returns (uint256 queuedAt_); + function target() external returns (address target_); + function version() external view returns (string memory); + function vetoer() external returns (address vetoer_); + + function __constructor__(address vetoer_, address initiator_, address target_, uint256 operatingDelay_) external; +} diff --git a/packages/contracts-bedrock/src/L1/interfaces/IL1CrossDomainMessenger.sol b/packages/contracts-bedrock/src/L1/interfaces/IL1CrossDomainMessenger.sol new file mode 100644 index 0000000000000..bb92e723c7c34 --- /dev/null +++ b/packages/contracts-bedrock/src/L1/interfaces/IL1CrossDomainMessenger.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { ICrossDomainMessenger } from "src/universal/interfaces/ICrossDomainMessenger.sol"; +import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol"; +import { IOptimismPortal } from "src/L1/interfaces/IOptimismPortal.sol"; +import { ISystemConfig } from "src/L1/interfaces/ISystemConfig.sol"; + +interface IL1CrossDomainMessenger is ICrossDomainMessenger { + function PORTAL() external view returns (address); + function initialize( + ISuperchainConfig _superchainConfig, + IOptimismPortal _portal, + ISystemConfig _systemConfig + ) + external; + function portal() external view returns (address); + function superchainConfig() external view returns (address); + function systemConfig() external view returns (address); + function version() external view returns (string memory); +} diff --git a/packages/contracts-bedrock/src/L1/interfaces/IL1ERC721Bridge.sol b/packages/contracts-bedrock/src/L1/interfaces/IL1ERC721Bridge.sol new file mode 100644 index 0000000000000..fd64f40fe5acd --- /dev/null +++ b/packages/contracts-bedrock/src/L1/interfaces/IL1ERC721Bridge.sol @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { IERC721Bridge } from "src/universal/interfaces/IERC721Bridge.sol"; +import { ICrossDomainMessenger } from "src/universal/interfaces/ICrossDomainMessenger.sol"; +import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol"; + +interface IL1ERC721Bridge is IERC721Bridge { + function bridgeERC721( + address _localToken, + address _remoteToken, + uint256 _tokenId, + uint32 _minGasLimit, + bytes memory _extraData + ) + external; + function bridgeERC721To( + address _localToken, + address _remoteToken, + address _to, + uint256 _tokenId, + uint32 _minGasLimit, + bytes memory _extraData + ) + external; + function deposits(address, address, uint256) external view returns (bool); + function finalizeBridgeERC721( + address _localToken, + address _remoteToken, + address _from, + address _to, + uint256 _tokenId, + bytes memory _extraData + ) + external; + function initialize(ICrossDomainMessenger _messenger, ISuperchainConfig _superchainConfig) external; + function paused() external view returns (bool); + function superchainConfig() external view returns (ISuperchainConfig); + function version() external view returns (string memory); +} diff --git a/packages/contracts-bedrock/src/L1/interfaces/IL1StandardBridge.sol b/packages/contracts-bedrock/src/L1/interfaces/IL1StandardBridge.sol new file mode 100644 index 0000000000000..119c8c1f1d8ef --- /dev/null +++ b/packages/contracts-bedrock/src/L1/interfaces/IL1StandardBridge.sol @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { IStandardBridge } from "src/universal/interfaces/IStandardBridge.sol"; +import { ICrossDomainMessenger } from "src/universal/interfaces/ICrossDomainMessenger.sol"; +import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol"; +import { ISystemConfig } from "src/L1/interfaces/ISystemConfig.sol"; + +interface IL1StandardBridge is IStandardBridge { + event ERC20DepositInitiated( + address indexed l1Token, + address indexed l2Token, + address indexed from, + address to, + uint256 amount, + bytes extraData + ); + event ERC20WithdrawalFinalized( + address indexed l1Token, + address indexed l2Token, + address indexed from, + address to, + uint256 amount, + bytes extraData + ); + event ETHDepositInitiated(address indexed from, address indexed to, uint256 amount, bytes extraData); + event ETHWithdrawalFinalized(address indexed from, address indexed to, uint256 amount, bytes extraData); + + function depositERC20( + address _l1Token, + address _l2Token, + uint256 _amount, + uint32 _minGasLimit, + bytes memory _extraData + ) + external; + function depositERC20To( + address _l1Token, + address _l2Token, + address _to, + uint256 _amount, + uint32 _minGasLimit, + bytes memory _extraData + ) + external; + function depositETH(uint32 _minGasLimit, bytes memory _extraData) external payable; + function depositETHTo(address _to, uint32 _minGasLimit, bytes memory _extraData) external payable; + function finalizeERC20Withdrawal( + address _l1Token, + address _l2Token, + address _from, + address _to, + uint256 _amount, + bytes memory _extraData + ) + external; + function finalizeETHWithdrawal( + address _from, + address _to, + uint256 _amount, + bytes memory _extraData + ) + external + payable; + function initialize( + ICrossDomainMessenger _messenger, + ISuperchainConfig _superchainConfig, + ISystemConfig _systemConfig + ) + external; + function l2TokenBridge() external view returns (address); + function superchainConfig() external view returns (ISuperchainConfig); + function systemConfig() external view returns (ISystemConfig); + function version() external view returns (string memory); +} diff --git a/packages/contracts-bedrock/src/L1/interfaces/IL2OutputOracle.sol b/packages/contracts-bedrock/src/L1/interfaces/IL2OutputOracle.sol new file mode 100644 index 0000000000000..408c53c851564 --- /dev/null +++ b/packages/contracts-bedrock/src/L1/interfaces/IL2OutputOracle.sol @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { Types } from "src/libraries/Types.sol"; + +interface IL2OutputOracle { + event Initialized(uint8 version); + event OutputProposed( + bytes32 indexed outputRoot, uint256 indexed l2OutputIndex, uint256 indexed l2BlockNumber, uint256 l1Timestamp + ); + event OutputsDeleted(uint256 indexed prevNextOutputIndex, uint256 indexed newNextOutputIndex); + + function CHALLENGER() external view returns (address); + function FINALIZATION_PERIOD_SECONDS() external view returns (uint256); + function L2_BLOCK_TIME() external view returns (uint256); + function PROPOSER() external view returns (address); + function SUBMISSION_INTERVAL() external view returns (uint256); + function challenger() external view returns (address); + function computeL2Timestamp(uint256 _l2BlockNumber) external view returns (uint256); + function deleteL2Outputs(uint256 _l2OutputIndex) external; + function finalizationPeriodSeconds() external view returns (uint256); + function getL2Output(uint256 _l2OutputIndex) external view returns (Types.OutputProposal memory); + function getL2OutputAfter(uint256 _l2BlockNumber) external view returns (Types.OutputProposal memory); + function getL2OutputIndexAfter(uint256 _l2BlockNumber) external view returns (uint256); + function initialize( + uint256 _submissionInterval, + uint256 _l2BlockTime, + uint256 _startingBlockNumber, + uint256 _startingTimestamp, + address _proposer, + address _challenger, + uint256 _finalizationPeriodSeconds + ) + external; + function l2BlockTime() external view returns (uint256); + function latestBlockNumber() external view returns (uint256); + function latestOutputIndex() external view returns (uint256); + function nextBlockNumber() external view returns (uint256); + function nextOutputIndex() external view returns (uint256); + function proposeL2Output( + bytes32 _outputRoot, + uint256 _l2BlockNumber, + bytes32 _l1BlockHash, + uint256 _l1BlockNumber + ) + external + payable; + function proposer() external view returns (address); + function startingBlockNumber() external view returns (uint256); + function startingTimestamp() external view returns (uint256); + function submissionInterval() external view returns (uint256); + function version() external view returns (string memory); + + function __constructor__() external; +} diff --git a/packages/contracts-bedrock/src/L1/interfaces/IOptimismPortal.sol b/packages/contracts-bedrock/src/L1/interfaces/IOptimismPortal.sol new file mode 100644 index 0000000000000..e80bad00b910a --- /dev/null +++ b/packages/contracts-bedrock/src/L1/interfaces/IOptimismPortal.sol @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { Types } from "src/libraries/Types.sol"; +import { ISystemConfig } from "src/L1/interfaces/ISystemConfig.sol"; +import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol"; +import { IL2OutputOracle } from "src/L1/interfaces/IL2OutputOracle.sol"; + +interface IOptimismPortal { + error BadTarget(); + error CallPaused(); + error ContentLengthMismatch(); + error EmptyItem(); + error GasEstimation(); + error InvalidDataRemainder(); + error InvalidHeader(); + error LargeCalldata(); + error NoValue(); + error NonReentrant(); + error OnlyCustomGasToken(); + error OutOfGas(); + error SmallGasLimit(); + error TransferFailed(); + error Unauthorized(); + error UnexpectedList(); + error UnexpectedString(); + + event Initialized(uint8 version); + event TransactionDeposited(address indexed from, address indexed to, uint256 indexed version, bytes opaqueData); + event WithdrawalFinalized(bytes32 indexed withdrawalHash, bool success); + event WithdrawalProven(bytes32 indexed withdrawalHash, address indexed from, address indexed to); + + receive() external payable; + + function balance() external view returns (uint256); + function depositERC20Transaction( + address _to, + uint256 _mint, + uint256 _value, + uint64 _gasLimit, + bool _isCreation, + bytes memory _data + ) + external; + function depositTransaction( + address _to, + uint256 _value, + uint64 _gasLimit, + bool _isCreation, + bytes memory _data + ) + external + payable; + function donateETH() external payable; + function finalizeWithdrawalTransaction(Types.WithdrawalTransaction memory _tx) external; + function finalizedWithdrawals(bytes32) external view returns (bool); + function guardian() external view returns (address); + function initialize( + IL2OutputOracle _l2Oracle, + ISystemConfig _systemConfig, + ISuperchainConfig _superchainConfig + ) + external; + function isOutputFinalized(uint256 _l2OutputIndex) external view returns (bool); + function l2Oracle() external view returns (IL2OutputOracle); + function l2Sender() external view returns (address); + function minimumGasLimit(uint64 _byteCount) external pure returns (uint64); + function params() external view returns (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum); + function paused() external view returns (bool paused_); + function proveWithdrawalTransaction( + Types.WithdrawalTransaction memory _tx, + uint256 _l2OutputIndex, + Types.OutputRootProof memory _outputRootProof, + bytes[] memory _withdrawalProof + ) + external; + function provenWithdrawals(bytes32) + external + view + returns (bytes32 outputRoot, uint128 timestamp, uint128 l2OutputIndex); + function setGasPayingToken(address _token, uint8 _decimals, bytes32 _name, bytes32 _symbol) external; + function superchainConfig() external view returns (ISuperchainConfig); + function systemConfig() external view returns (ISystemConfig); + function version() external pure returns (string memory); +} diff --git a/packages/contracts-bedrock/src/L1/interfaces/IOptimismPortal2.sol b/packages/contracts-bedrock/src/L1/interfaces/IOptimismPortal2.sol new file mode 100644 index 0000000000000..551bd2832b055 --- /dev/null +++ b/packages/contracts-bedrock/src/L1/interfaces/IOptimismPortal2.sol @@ -0,0 +1,118 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { Types } from "src/libraries/Types.sol"; +import { GameType, Timestamp } from "src/dispute/lib/LibUDT.sol"; +import { IDisputeGame } from "src/dispute/interfaces/IDisputeGame.sol"; +import { IDisputeGameFactory } from "src/dispute/interfaces/IDisputeGameFactory.sol"; +import { ISystemConfig } from "src/L1/interfaces/ISystemConfig.sol"; +import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol"; + +interface IOptimismPortal2 { + error AlreadyFinalized(); + error BadTarget(); + error Blacklisted(); + error CallPaused(); + error ContentLengthMismatch(); + error EmptyItem(); + error GasEstimation(); + error InvalidDataRemainder(); + error InvalidDisputeGame(); + error InvalidGameType(); + error InvalidHeader(); + error InvalidMerkleProof(); + error InvalidProof(); + error LargeCalldata(); + error NoValue(); + error NonReentrant(); + error OnlyCustomGasToken(); + error OutOfGas(); + error ProposalNotValidated(); + error SmallGasLimit(); + error TransferFailed(); + error Unauthorized(); + error UnexpectedList(); + error UnexpectedString(); + error Unproven(); + + event DisputeGameBlacklisted(IDisputeGame indexed disputeGame); + event Initialized(uint8 version); + event RespectedGameTypeSet(GameType indexed newGameType, Timestamp indexed updatedAt); + event TransactionDeposited(address indexed from, address indexed to, uint256 indexed version, bytes opaqueData); + event WithdrawalFinalized(bytes32 indexed withdrawalHash, bool success); + event WithdrawalProven(bytes32 indexed withdrawalHash, address indexed from, address indexed to); + event WithdrawalProvenExtension1(bytes32 indexed withdrawalHash, address indexed proofSubmitter); + + receive() external payable; + + function balance() external view returns (uint256); + function blacklistDisputeGame(IDisputeGame _disputeGame) external; + function checkWithdrawal(bytes32 _withdrawalHash, address _proofSubmitter) external view; + function depositERC20Transaction( + address _to, + uint256 _mint, + uint256 _value, + uint64 _gasLimit, + bool _isCreation, + bytes memory _data + ) + external; + function depositTransaction( + address _to, + uint256 _value, + uint64 _gasLimit, + bool _isCreation, + bytes memory _data + ) + external + payable; + function disputeGameBlacklist(IDisputeGame) external view returns (bool); + function disputeGameFactory() external view returns (IDisputeGameFactory); + function disputeGameFinalityDelaySeconds() external view returns (uint256); + function donateETH() external payable; + function finalizeWithdrawalTransaction(Types.WithdrawalTransaction memory _tx) external; + function finalizeWithdrawalTransactionExternalProof( + Types.WithdrawalTransaction memory _tx, + address _proofSubmitter + ) + external; + function finalizedWithdrawals(bytes32) external view returns (bool); + function guardian() external view returns (address); + function initialize( + IDisputeGameFactory _disputeGameFactory, + ISystemConfig _systemConfig, + ISuperchainConfig _superchainConfig, + GameType _initialRespectedGameType + ) + external; + function l2Sender() external view returns (address); + function minimumGasLimit(uint64 _byteCount) external pure returns (uint64); + function numProofSubmitters(bytes32 _withdrawalHash) external view returns (uint256); + function params() external view returns (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum); + function paused() external view returns (bool); + function proofMaturityDelaySeconds() external view returns (uint256); + function proofSubmitters(bytes32, uint256) external view returns (address); + function proveWithdrawalTransaction( + Types.WithdrawalTransaction memory _tx, + uint256 _disputeGameIndex, + Types.OutputRootProof memory _outputRootProof, + bytes[] memory _withdrawalProof + ) + external; + function provenWithdrawals( + bytes32, + address + ) + external + view + returns (IDisputeGame disputeGameProxy, uint64 timestamp); + function respectedGameType() external view returns (GameType); + function respectedGameTypeUpdatedAt() external view returns (uint64); + function setGasPayingToken(address _token, uint8 _decimals, bytes32 _name, bytes32 _symbol) external; + function setRespectedGameType(GameType _gameType) external; + function superchainConfig() external view returns (ISuperchainConfig); + function systemConfig() external view returns (ISystemConfig); + function version() external pure returns (string memory); + + function __constructor__(uint256 _proofMaturityDelaySeconds, uint256 _disputeGameFinalityDelaySeconds) external; +} diff --git a/packages/contracts-bedrock/src/L1/interfaces/IOptimismPortalInterop.sol b/packages/contracts-bedrock/src/L1/interfaces/IOptimismPortalInterop.sol new file mode 100644 index 0000000000000..682518897362a --- /dev/null +++ b/packages/contracts-bedrock/src/L1/interfaces/IOptimismPortalInterop.sol @@ -0,0 +1,120 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { Types } from "src/libraries/Types.sol"; +import { GameType, Timestamp } from "src/dispute/lib/LibUDT.sol"; +import { IDisputeGame } from "src/dispute/interfaces/IDisputeGame.sol"; +import { IDisputeGameFactory } from "src/dispute/interfaces/IDisputeGameFactory.sol"; +import { ISystemConfig } from "src/L1/interfaces/ISystemConfig.sol"; +import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol"; +import { ConfigType } from "src/L2/L1BlockIsthmus.sol"; + +interface IOptimismPortalInterop { + error AlreadyFinalized(); + error BadTarget(); + error Blacklisted(); + error CallPaused(); + error ContentLengthMismatch(); + error EmptyItem(); + error GasEstimation(); + error InvalidDataRemainder(); + error InvalidDisputeGame(); + error InvalidGameType(); + error InvalidHeader(); + error InvalidMerkleProof(); + error InvalidProof(); + error LargeCalldata(); + error NoValue(); + error NonReentrant(); + error OnlyCustomGasToken(); + error OutOfGas(); + error ProposalNotValidated(); + error SmallGasLimit(); + error TransferFailed(); + error Unauthorized(); + error UnexpectedList(); + error UnexpectedString(); + error Unproven(); + + event DisputeGameBlacklisted(IDisputeGame indexed disputeGame); + event Initialized(uint8 version); + event RespectedGameTypeSet(GameType indexed newGameType, Timestamp indexed updatedAt); + event TransactionDeposited(address indexed from, address indexed to, uint256 indexed version, bytes opaqueData); + event WithdrawalFinalized(bytes32 indexed withdrawalHash, bool success); + event WithdrawalProven(bytes32 indexed withdrawalHash, address indexed from, address indexed to); + event WithdrawalProvenExtension1(bytes32 indexed withdrawalHash, address indexed proofSubmitter); + + receive() external payable; + + function balance() external view returns (uint256); + function blacklistDisputeGame(IDisputeGame _disputeGame) external; + function checkWithdrawal(bytes32 _withdrawalHash, address _proofSubmitter) external view; + function depositERC20Transaction( + address _to, + uint256 _mint, + uint256 _value, + uint64 _gasLimit, + bool _isCreation, + bytes memory _data + ) + external; + function depositTransaction( + address _to, + uint256 _value, + uint64 _gasLimit, + bool _isCreation, + bytes memory _data + ) + external + payable; + function disputeGameBlacklist(IDisputeGame) external view returns (bool); + function disputeGameFactory() external view returns (IDisputeGameFactory); + function disputeGameFinalityDelaySeconds() external view returns (uint256); + function donateETH() external payable; + function finalizeWithdrawalTransaction(Types.WithdrawalTransaction memory _tx) external; + function finalizeWithdrawalTransactionExternalProof( + Types.WithdrawalTransaction memory _tx, + address _proofSubmitter + ) + external; + function finalizedWithdrawals(bytes32) external view returns (bool); + function guardian() external view returns (address); + function initialize( + IDisputeGameFactory _disputeGameFactory, + ISystemConfig _systemConfig, + ISuperchainConfig _superchainConfig, + GameType _initialRespectedGameType + ) + external; + function l2Sender() external view returns (address); + function minimumGasLimit(uint64 _byteCount) external pure returns (uint64); + function numProofSubmitters(bytes32 _withdrawalHash) external view returns (uint256); + function params() external view returns (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum); + function paused() external view returns (bool); + function proofMaturityDelaySeconds() external view returns (uint256); + function proofSubmitters(bytes32, uint256) external view returns (address); + function proveWithdrawalTransaction( + Types.WithdrawalTransaction memory _tx, + uint256 _disputeGameIndex, + Types.OutputRootProof memory _outputRootProof, + bytes[] memory _withdrawalProof + ) + external; + function provenWithdrawals( + bytes32, + address + ) + external + view + returns (IDisputeGame disputeGameProxy, uint64 timestamp); + function respectedGameType() external view returns (GameType); + function respectedGameTypeUpdatedAt() external view returns (uint64); + function setConfig(ConfigType _type, bytes memory _value) external; + function setGasPayingToken(address _token, uint8 _decimals, bytes32 _name, bytes32 _symbol) external; + function setRespectedGameType(GameType _gameType) external; + function superchainConfig() external view returns (ISuperchainConfig); + function systemConfig() external view returns (ISystemConfig); + function version() external pure returns (string memory); + + function __constructor__(uint256 _proofMaturityDelaySeconds, uint256 _disputeGameFinalityDelaySeconds) external; +} diff --git a/packages/contracts-bedrock/src/L1/interfaces/IProtocolVersions.sol b/packages/contracts-bedrock/src/L1/interfaces/IProtocolVersions.sol new file mode 100644 index 0000000000000..aa2de51d48464 --- /dev/null +++ b/packages/contracts-bedrock/src/L1/interfaces/IProtocolVersions.sol @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +type ProtocolVersion is uint256; + +interface IProtocolVersions { + enum UpdateType { + REQUIRED_PROTOCOL_VERSION, + RECOMMENDED_PROTOCOL_VERSION + } + + event ConfigUpdate(uint256 indexed version, UpdateType indexed updateType, bytes data); + event Initialized(uint8 version); + event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); + + function RECOMMENDED_SLOT() external view returns (bytes32); + function REQUIRED_SLOT() external view returns (bytes32); + function VERSION() external view returns (uint256); + function initialize(address _owner, ProtocolVersion _required, ProtocolVersion _recommended) external; + function owner() external view returns (address); + function recommended() external view returns (ProtocolVersion out_); + function renounceOwnership() external; + function required() external view returns (ProtocolVersion out_); + function setRecommended(ProtocolVersion _recommended) external; + function setRequired(ProtocolVersion _required) external; + function transferOwnership(address newOwner) external; + function version() external view returns (string memory); + + function __constructor__() external; +} diff --git a/packages/contracts-bedrock/src/L1/interfaces/IResourceMetering.sol b/packages/contracts-bedrock/src/L1/interfaces/IResourceMetering.sol new file mode 100644 index 0000000000000..4a4ccc133bb86 --- /dev/null +++ b/packages/contracts-bedrock/src/L1/interfaces/IResourceMetering.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +interface IResourceMetering { + struct ResourceParams { + uint128 prevBaseFee; + uint64 prevBoughtGas; + uint64 prevBlockNum; + } + + struct ResourceConfig { + uint32 maxResourceLimit; + uint8 elasticityMultiplier; + uint8 baseFeeMaxChangeDenominator; + uint32 minimumBaseFee; + uint32 systemTxMaxGas; + uint128 maximumBaseFee; + } + + error OutOfGas(); + + event Initialized(uint8 version); + + function params() external view returns (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum); +} diff --git a/packages/contracts-bedrock/src/L1/interfaces/ISuperchainConfig.sol b/packages/contracts-bedrock/src/L1/interfaces/ISuperchainConfig.sol new file mode 100644 index 0000000000000..dc83893958b09 --- /dev/null +++ b/packages/contracts-bedrock/src/L1/interfaces/ISuperchainConfig.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +interface ISuperchainConfig { + enum UpdateType { + GUARDIAN + } + + event ConfigUpdate(UpdateType indexed updateType, bytes data); + event Initialized(uint8 version); + event Paused(string identifier); + event Unpaused(); + + function GUARDIAN_SLOT() external view returns (bytes32); + function PAUSED_SLOT() external view returns (bytes32); + function guardian() external view returns (address guardian_); + function initialize(address _guardian, bool _paused) external; + function pause(string memory _identifier) external; + function paused() external view returns (bool paused_); + function unpause() external; + function version() external view returns (string memory); + + function __constructor__() external; +} diff --git a/packages/contracts-bedrock/src/L1/interfaces/ISystemConfig.sol b/packages/contracts-bedrock/src/L1/interfaces/ISystemConfig.sol new file mode 100644 index 0000000000000..59ae98668cf07 --- /dev/null +++ b/packages/contracts-bedrock/src/L1/interfaces/ISystemConfig.sol @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { IResourceMetering } from "src/L1/interfaces/IResourceMetering.sol"; + +interface ISystemConfig { + enum UpdateType { + BATCHER, + GAS_CONFIG, + GAS_LIMIT, + UNSAFE_BLOCK_SIGNER + } + + struct Addresses { + address l1CrossDomainMessenger; + address l1ERC721Bridge; + address l1StandardBridge; + address disputeGameFactory; + address optimismPortal; + address optimismMintableERC20Factory; + address gasPayingToken; + } + + event ConfigUpdate(uint256 indexed version, UpdateType indexed updateType, bytes data); + event Initialized(uint8 version); + event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); + + function BATCH_INBOX_SLOT() external view returns (bytes32); + function DISPUTE_GAME_FACTORY_SLOT() external view returns (bytes32); + function L1_CROSS_DOMAIN_MESSENGER_SLOT() external view returns (bytes32); + function L1_ERC_721_BRIDGE_SLOT() external view returns (bytes32); + function L1_STANDARD_BRIDGE_SLOT() external view returns (bytes32); + function OPTIMISM_MINTABLE_ERC20_FACTORY_SLOT() external view returns (bytes32); + function OPTIMISM_PORTAL_SLOT() external view returns (bytes32); + function START_BLOCK_SLOT() external view returns (bytes32); + function UNSAFE_BLOCK_SIGNER_SLOT() external view returns (bytes32); + function VERSION() external view returns (uint256); + function basefeeScalar() external view returns (uint32); + function batchInbox() external view returns (address addr_); + function batcherHash() external view returns (bytes32); + function blobbasefeeScalar() external view returns (uint32); + function disputeGameFactory() external view returns (address addr_); + function gasLimit() external view returns (uint64); + function gasPayingToken() external view returns (address addr_, uint8 decimals_); + function gasPayingTokenName() external view returns (string memory name_); + function gasPayingTokenSymbol() external view returns (string memory symbol_); + function initialize( + address _owner, + uint32 _basefeeScalar, + uint32 _blobbasefeeScalar, + bytes32 _batcherHash, + uint64 _gasLimit, + address _unsafeBlockSigner, + IResourceMetering.ResourceConfig memory _config, + address _batchInbox, + Addresses memory _addresses + ) + external; + function isCustomGasToken() external view returns (bool); + function l1CrossDomainMessenger() external view returns (address addr_); + function l1ERC721Bridge() external view returns (address addr_); + function l1StandardBridge() external view returns (address addr_); + function maximumGasLimit() external pure returns (uint64); + function minimumGasLimit() external view returns (uint64); + function optimismMintableERC20Factory() external view returns (address addr_); + function optimismPortal() external view returns (address addr_); + function overhead() external view returns (uint256); + function owner() external view returns (address); + function renounceOwnership() external; + function resourceConfig() external view returns (IResourceMetering.ResourceConfig memory); + function scalar() external view returns (uint256); + function setBatcherHash(bytes32 _batcherHash) external; + function setGasConfig(uint256 _overhead, uint256 _scalar) external; + function setGasConfigEcotone(uint32 _basefeeScalar, uint32 _blobbasefeeScalar) external; + function setGasLimit(uint64 _gasLimit) external; + function setUnsafeBlockSigner(address _unsafeBlockSigner) external; + function startBlock() external view returns (uint256 startBlock_); + function transferOwnership(address newOwner) external; + function unsafeBlockSigner() external view returns (address addr_); + function version() external pure returns (string memory); + + function __constructor__() external; +} diff --git a/packages/contracts-bedrock/src/L1/interfaces/ISystemConfigInterop.sol b/packages/contracts-bedrock/src/L1/interfaces/ISystemConfigInterop.sol new file mode 100644 index 0000000000000..cffa30dd3efc0 --- /dev/null +++ b/packages/contracts-bedrock/src/L1/interfaces/ISystemConfigInterop.sol @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { ISystemConfig } from "src/L1/interfaces/ISystemConfig.sol"; +import { IResourceMetering } from "src/L1/interfaces/IResourceMetering.sol"; + +interface ISystemConfigInterop { + event ConfigUpdate(uint256 indexed version, ISystemConfig.UpdateType indexed updateType, bytes data); + event Initialized(uint8 version); + event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); + + function BATCH_INBOX_SLOT() external view returns (bytes32); + function DISPUTE_GAME_FACTORY_SLOT() external view returns (bytes32); + function L1_CROSS_DOMAIN_MESSENGER_SLOT() external view returns (bytes32); + function L1_ERC_721_BRIDGE_SLOT() external view returns (bytes32); + function L1_STANDARD_BRIDGE_SLOT() external view returns (bytes32); + function OPTIMISM_MINTABLE_ERC20_FACTORY_SLOT() external view returns (bytes32); + function OPTIMISM_PORTAL_SLOT() external view returns (bytes32); + function START_BLOCK_SLOT() external view returns (bytes32); + function UNSAFE_BLOCK_SIGNER_SLOT() external view returns (bytes32); + function VERSION() external view returns (uint256); + function basefeeScalar() external view returns (uint32); + function batchInbox() external view returns (address addr_); + function batcherHash() external view returns (bytes32); + function blobbasefeeScalar() external view returns (uint32); + function disputeGameFactory() external view returns (address addr_); + function gasLimit() external view returns (uint64); + function gasPayingToken() external view returns (address addr_, uint8 decimals_); + function gasPayingTokenName() external view returns (string memory name_); + function gasPayingTokenSymbol() external view returns (string memory symbol_); + function initialize( + address _owner, + uint32 _basefeeScalar, + uint32 _blobbasefeeScalar, + bytes32 _batcherHash, + uint64 _gasLimit, + address _unsafeBlockSigner, + IResourceMetering.ResourceConfig memory _config, + address _batchInbox, + ISystemConfig.Addresses memory _addresses + ) + external; + function isCustomGasToken() external view returns (bool); + function l1CrossDomainMessenger() external view returns (address addr_); + function l1ERC721Bridge() external view returns (address addr_); + function l1StandardBridge() external view returns (address addr_); + function maximumGasLimit() external pure returns (uint64); + function minimumGasLimit() external view returns (uint64); + function optimismMintableERC20Factory() external view returns (address addr_); + function optimismPortal() external view returns (address addr_); + function overhead() external view returns (uint256); + function owner() external view returns (address); + function renounceOwnership() external; + function resourceConfig() external view returns (IResourceMetering.ResourceConfig memory); + function scalar() external view returns (uint256); + function setBatcherHash(bytes32 _batcherHash) external; + function setGasConfig(uint256 _overhead, uint256 _scalar) external; + function setGasConfigEcotone(uint32 _basefeeScalar, uint32 _blobbasefeeScalar) external; + function setGasLimit(uint64 _gasLimit) external; + function setUnsafeBlockSigner(address _unsafeBlockSigner) external; + function startBlock() external view returns (uint256 startBlock_); + function transferOwnership(address newOwner) external; + function unsafeBlockSigner() external view returns (address addr_); + + function addDependency(uint256 _chainId) external; + function removeDependency(uint256 _chainId) external; + function dependencyManager() external view returns (address); + function initialize( + address _owner, + uint32 _basefeeScalar, + uint32 _blobbasefeeScalar, + bytes32 _batcherHash, + uint64 _gasLimit, + address _unsafeBlockSigner, + IResourceMetering.ResourceConfig memory _config, + address _batchInbox, + ISystemConfig.Addresses memory _addresses, + address _dependencyManager + ) + external; + function version() external pure returns (string memory); +} diff --git a/packages/contracts-bedrock/src/L2/BaseFeeVault.sol b/packages/contracts-bedrock/src/L2/BaseFeeVault.sol index ea07fd4ef3be6..2ae63efd599bc 100644 --- a/packages/contracts-bedrock/src/L2/BaseFeeVault.sol +++ b/packages/contracts-bedrock/src/L2/BaseFeeVault.sol @@ -1,17 +1,17 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { ISemver } from "src/universal/ISemver.sol"; +import { ISemver } from "src/universal/interfaces/ISemver.sol"; import { FeeVault } from "src/universal/FeeVault.sol"; -/// @custom:proxied +/// @custom:proxied true /// @custom:predeploy 0x4200000000000000000000000000000000000019 /// @title BaseFeeVault /// @notice The BaseFeeVault accumulates the base fee that is paid by transactions. contract BaseFeeVault is FeeVault, ISemver { /// @notice Semantic version. - /// @custom:semver 1.5.0-beta.1 - string public constant version = "1.5.0-beta.1"; + /// @custom:semver 1.5.0-beta.2 + string public constant version = "1.5.0-beta.2"; /// @notice Constructs the BaseFeeVault contract. /// @param _recipient Wallet that will receive the fees. diff --git a/packages/contracts-bedrock/src/L2/CrossDomainOwnable2.sol b/packages/contracts-bedrock/src/L2/CrossDomainOwnable2.sol index ce14229c9b51e..0711daffce3e3 100644 --- a/packages/contracts-bedrock/src/L2/CrossDomainOwnable2.sol +++ b/packages/contracts-bedrock/src/L2/CrossDomainOwnable2.sol @@ -1,10 +1,15 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import { Predeploys } from "src/libraries/Predeploys.sol"; -import { L2CrossDomainMessenger } from "src/L2/L2CrossDomainMessenger.sol"; +// Contracts import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; +// Libraries +import { Predeploys } from "src/libraries/Predeploys.sol"; + +// Interfaces +import { IL2CrossDomainMessenger } from "src/L2/interfaces/IL2CrossDomainMessenger.sol"; + /// @title CrossDomainOwnable2 /// @notice This contract extends the OpenZeppelin `Ownable` contract for L2 contracts to be owned /// by contracts on L1. Note that this contract is meant to be used with systems that use @@ -15,7 +20,7 @@ abstract contract CrossDomainOwnable2 is Ownable { /// `xDomainMessageSender` is the owner of the contract. This value is set to the caller /// of the L1CrossDomainMessenger. function _checkOwner() internal view override { - L2CrossDomainMessenger messenger = L2CrossDomainMessenger(Predeploys.L2_CROSS_DOMAIN_MESSENGER); + IL2CrossDomainMessenger messenger = IL2CrossDomainMessenger(Predeploys.L2_CROSS_DOMAIN_MESSENGER); require(msg.sender == address(messenger), "CrossDomainOwnable2: caller is not the messenger"); diff --git a/packages/contracts-bedrock/src/L2/CrossDomainOwnable3.sol b/packages/contracts-bedrock/src/L2/CrossDomainOwnable3.sol index 2e4ef7a17c2a5..e940a026df05e 100644 --- a/packages/contracts-bedrock/src/L2/CrossDomainOwnable3.sol +++ b/packages/contracts-bedrock/src/L2/CrossDomainOwnable3.sol @@ -1,10 +1,15 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import { Predeploys } from "src/libraries/Predeploys.sol"; -import { L2CrossDomainMessenger } from "src/L2/L2CrossDomainMessenger.sol"; +// Contracts import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; +// Libraries +import { Predeploys } from "src/libraries/Predeploys.sol"; + +// Interfaces +import { IL2CrossDomainMessenger } from "src/L2/interfaces/IL2CrossDomainMessenger.sol"; + /// @title CrossDomainOwnable3 /// @notice This contract extends the OpenZeppelin `Ownable` contract for L2 contracts to be owned /// by contracts on either L1 or L2. Note that this contract is meant to be used with @@ -42,7 +47,7 @@ abstract contract CrossDomainOwnable3 is Ownable { if (isLocal) { require(owner() == msg.sender, "CrossDomainOwnable3: caller is not the owner"); } else { - L2CrossDomainMessenger messenger = L2CrossDomainMessenger(Predeploys.L2_CROSS_DOMAIN_MESSENGER); + IL2CrossDomainMessenger messenger = IL2CrossDomainMessenger(Predeploys.L2_CROSS_DOMAIN_MESSENGER); require(msg.sender == address(messenger), "CrossDomainOwnable3: caller is not the messenger"); diff --git a/packages/contracts-bedrock/src/L2/CrossL2Inbox.sol b/packages/contracts-bedrock/src/L2/CrossL2Inbox.sol index cb0ccfa7714d0..437e0c62a2e35 100644 --- a/packages/contracts-bedrock/src/L2/CrossL2Inbox.sol +++ b/packages/contracts-bedrock/src/L2/CrossL2Inbox.sol @@ -3,19 +3,11 @@ pragma solidity 0.8.25; import { Predeploys } from "src/libraries/Predeploys.sol"; import { TransientContext, TransientReentrancyAware } from "src/libraries/TransientContext.sol"; -import { ISemver } from "src/universal/ISemver.sol"; -import { ICrossL2Inbox } from "src/L2/ICrossL2Inbox.sol"; +import { ISemver } from "src/universal/interfaces/ISemver.sol"; +import { ICrossL2Inbox } from "src/L2/interfaces/ICrossL2Inbox.sol"; import { SafeCall } from "src/libraries/SafeCall.sol"; - -/// @title IDependencySet -/// @notice Interface for L1Block with only `isInDependencySet(uint256)` method. -interface IDependencySet { - /// @notice Returns true if the chain associated with input chain ID is in the interop dependency set. - /// Every chain is in the interop dependency set of itself. - /// @param _chainId Input chain ID. - /// @return True if the input chain ID corresponds to a chain in the interop dependency set, and false otherwise. - function isInDependencySet(uint256 _chainId) external view returns (bool); -} +import { IDependencySet } from "src/L2/interfaces/IDependencySet.sol"; +import { IL1BlockIsthmus } from "src/L2/interfaces/IL1BlockIsthmus.sol"; /// @notice Thrown when the caller is not DEPOSITOR_ACCOUNT when calling `setInteropStart()` error NotDepositor(); @@ -35,7 +27,10 @@ error InvalidChainId(); /// @notice Thrown when trying to execute a cross chain message and the target call fails. error TargetCallFailed(); -/// @custom:proxied +/// @notice Thrown when trying to execute a cross chain message on a deposit transaction. +error NoExecutingDeposits(); + +/// @custom:proxied true /// @custom:predeploy 0x4200000000000000000000000000000000000022 /// @title CrossL2Inbox /// @notice The CrossL2Inbox is responsible for executing a cross chain message on the destination @@ -70,8 +65,8 @@ contract CrossL2Inbox is ICrossL2Inbox, ISemver, TransientReentrancyAware { address internal constant DEPOSITOR_ACCOUNT = 0xDeaDDEaDDeAdDeAdDEAdDEaddeAddEAdDEAd0001; /// @notice Semantic version. - /// @custom:semver 1.0.0-beta.5 - string public constant version = "1.0.0-beta.5"; + /// @custom:semver 1.0.0-beta.7 + string public constant version = "1.0.0-beta.7"; /// @notice Emitted when a cross chain message is being executed. /// @param msgHash Hash of message payload being executed. @@ -144,6 +139,9 @@ contract CrossL2Inbox is ICrossL2Inbox, ISemver, TransientReentrancyAware { payable reentrantAware { + // We need to know if this is being called on a depositTx + if (IL1BlockIsthmus(Predeploys.L1_BLOCK_ATTRIBUTES).isDeposit()) revert NoExecutingDeposits(); + // Check the Identifier. _checkIdentifier(_id); @@ -166,6 +164,9 @@ contract CrossL2Inbox is ICrossL2Inbox, ISemver, TransientReentrancyAware { /// @param _id Identifier of the message. /// @param _msgHash Hash of the message payload to call target with. function validateMessage(Identifier calldata _id, bytes32 _msgHash) external { + // We need to know if this is being called on a depositTx + if (IL1BlockIsthmus(Predeploys.L1_BLOCK_ATTRIBUTES).isDeposit()) revert NoExecutingDeposits(); + // Check the Identifier. _checkIdentifier(_id); diff --git a/packages/contracts-bedrock/src/L2/ETHLiquidity.sol b/packages/contracts-bedrock/src/L2/ETHLiquidity.sol index 4dd4c4b57eb50..6118288df77df 100644 --- a/packages/contracts-bedrock/src/L2/ETHLiquidity.sol +++ b/packages/contracts-bedrock/src/L2/ETHLiquidity.sol @@ -1,11 +1,16 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Contracts +import { SafeSend } from "src/universal/SafeSend.sol"; + +// Libraries import { Unauthorized, NotCustomGasToken } from "src/libraries/errors/CommonErrors.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; -import { L1Block } from "src/L2/L1Block.sol"; -import { SafeSend } from "src/universal/SafeSend.sol"; -import { ISemver } from "src/universal/ISemver.sol"; + +// Interfaces +import { ISemver } from "src/universal/interfaces/ISemver.sol"; +import { IL1Block } from "src/L2/interfaces/IL1Block.sol"; /// @title ETHLiquidity /// @notice The ETHLiquidity contract allows other contracts to access ETH liquidity without @@ -18,13 +23,13 @@ contract ETHLiquidity is ISemver { event LiquidityMinted(address indexed caller, uint256 value); /// @notice Semantic version. - /// @custom:semver 1.0.0-beta.1 - string public constant version = "1.0.0-beta.1"; + /// @custom:semver 1.0.0-beta.3 + string public constant version = "1.0.0-beta.3"; /// @notice Allows an address to lock ETH liquidity into this contract. function burn() external payable { if (msg.sender != Predeploys.SUPERCHAIN_WETH) revert Unauthorized(); - if (L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).isCustomGasToken()) revert NotCustomGasToken(); + if (IL1Block(Predeploys.L1_BLOCK_ATTRIBUTES).isCustomGasToken()) revert NotCustomGasToken(); emit LiquidityBurned(msg.sender, msg.value); } @@ -32,7 +37,7 @@ contract ETHLiquidity is ISemver { /// @param _amount The amount of liquidity to unlock. function mint(uint256 _amount) external { if (msg.sender != Predeploys.SUPERCHAIN_WETH) revert Unauthorized(); - if (L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).isCustomGasToken()) revert NotCustomGasToken(); + if (IL1Block(Predeploys.L1_BLOCK_ATTRIBUTES).isCustomGasToken()) revert NotCustomGasToken(); new SafeSend{ value: _amount }(payable(msg.sender)); emit LiquidityMinted(msg.sender, _amount); } diff --git a/packages/contracts-bedrock/src/L2/GasPriceOracle.sol b/packages/contracts-bedrock/src/L2/GasPriceOracle.sol index 79c3eb4315032..862e4bb079138 100644 --- a/packages/contracts-bedrock/src/L2/GasPriceOracle.sol +++ b/packages/contracts-bedrock/src/L2/GasPriceOracle.sol @@ -1,13 +1,16 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { ISemver } from "src/universal/ISemver.sol"; +// Libraries +import { LibZip } from "@solady/utils/LibZip.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; -import { L1Block } from "src/L2/L1Block.sol"; import { Constants } from "src/libraries/Constants.sol"; -import { LibZip } from "@solady/utils/LibZip.sol"; -/// @custom:proxied +// Interfaces +import { ISemver } from "src/universal/interfaces/ISemver.sol"; +import { IL1Block } from "src/L2/interfaces/IL1Block.sol"; + +/// @custom:proxied true /// @custom:predeploy 0x420000000000000000000000000000000000000F /// @title GasPriceOracle /// @notice This contract maintains the variables responsible for computing the L1 portion of the @@ -26,8 +29,8 @@ contract GasPriceOracle is ISemver { uint256 public constant DECIMALS = 6; /// @notice Semantic version. - /// @custom:semver 1.3.0 - string public constant version = "1.3.0"; + /// @custom:semver 1.3.1-beta.2 + string public constant version = "1.3.1-beta.2"; /// @notice This is the intercept value for the linear regression used to estimate the final size of the /// compressed transaction. @@ -114,7 +117,7 @@ contract GasPriceOracle is ISemver { /// @return Current fee overhead. function overhead() public view returns (uint256) { require(!isEcotone, "GasPriceOracle: overhead() is deprecated"); - return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).l1FeeOverhead(); + return IL1Block(Predeploys.L1_BLOCK_ATTRIBUTES).l1FeeOverhead(); } /// @custom:legacy @@ -122,31 +125,31 @@ contract GasPriceOracle is ISemver { /// @return Current fee scalar. function scalar() public view returns (uint256) { require(!isEcotone, "GasPriceOracle: scalar() is deprecated"); - return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).l1FeeScalar(); + return IL1Block(Predeploys.L1_BLOCK_ATTRIBUTES).l1FeeScalar(); } /// @notice Retrieves the latest known L1 base fee. /// @return Latest known L1 base fee. function l1BaseFee() public view returns (uint256) { - return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).basefee(); + return IL1Block(Predeploys.L1_BLOCK_ATTRIBUTES).basefee(); } /// @notice Retrieves the current blob base fee. /// @return Current blob base fee. function blobBaseFee() public view returns (uint256) { - return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).blobBaseFee(); + return IL1Block(Predeploys.L1_BLOCK_ATTRIBUTES).blobBaseFee(); } /// @notice Retrieves the current base fee scalar. /// @return Current base fee scalar. function baseFeeScalar() public view returns (uint32) { - return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).baseFeeScalar(); + return IL1Block(Predeploys.L1_BLOCK_ATTRIBUTES).baseFeeScalar(); } /// @notice Retrieves the current blob base fee scalar. /// @return Current blob base fee scalar. function blobBaseFeeScalar() public view returns (uint32) { - return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).blobBaseFeeScalar(); + return IL1Block(Predeploys.L1_BLOCK_ATTRIBUTES).blobBaseFeeScalar(); } /// @custom:legacy @@ -173,7 +176,7 @@ contract GasPriceOracle is ISemver { if (isEcotone) { return l1GasUsed; } - return l1GasUsed + L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).l1FeeOverhead(); + return l1GasUsed + IL1Block(Predeploys.L1_BLOCK_ATTRIBUTES).l1FeeOverhead(); } /// @notice Computation of the L1 portion of the fee for Bedrock. @@ -181,8 +184,8 @@ contract GasPriceOracle is ISemver { /// @return L1 fee that should be paid for the tx function _getL1FeeBedrock(bytes memory _data) internal view returns (uint256) { uint256 l1GasUsed = _getCalldataGas(_data); - uint256 fee = (l1GasUsed + L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).l1FeeOverhead()) * l1BaseFee() - * L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).l1FeeScalar(); + uint256 fee = (l1GasUsed + IL1Block(Predeploys.L1_BLOCK_ATTRIBUTES).l1FeeOverhead()) * l1BaseFee() + * IL1Block(Predeploys.L1_BLOCK_ATTRIBUTES).l1FeeScalar(); return fee / (10 ** DECIMALS); } diff --git a/packages/contracts-bedrock/src/L2/L1Block.sol b/packages/contracts-bedrock/src/L2/L1Block.sol index 8cfbb391f0f58..c61f45b836290 100644 --- a/packages/contracts-bedrock/src/L2/L1Block.sol +++ b/packages/contracts-bedrock/src/L2/L1Block.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { ISemver } from "src/universal/ISemver.sol"; +import { ISemver } from "src/universal/interfaces/ISemver.sol"; import { Constants } from "src/libraries/Constants.sol"; import { GasPayingToken, IGasToken } from "src/libraries/GasPayingToken.sol"; import "src/libraries/L1BlockErrors.sol"; -/// @custom:proxied +/// @custom:proxied true /// @custom:predeploy 0x4200000000000000000000000000000000000015 /// @title L1Block /// @notice The L1Block predeploy gives users access to information about the last known L1 block. @@ -57,9 +57,9 @@ contract L1Block is ISemver, IGasToken { /// @notice The latest L1 blob base fee. uint256 public blobBaseFee; - /// @custom:semver 1.4.1-beta.1 + /// @custom:semver 1.5.1-beta.2 function version() public pure virtual returns (string memory) { - return "1.4.1-beta.1"; + return "1.5.1-beta.2"; } /// @notice Returns the gas paying token, its decimals, name and symbol. @@ -133,7 +133,23 @@ contract L1Block is ISemver, IGasToken { /// 7. _blobBaseFee L1 blob base fee. /// 8. _hash L1 blockhash. /// 9. _batcherHash Versioned hash to authenticate batcher by. - function setL1BlockValuesEcotone() external { + function setL1BlockValuesEcotone() public { + _setL1BlockValuesEcotone(); + } + + /// @notice Updates the L1 block values for an Ecotone upgraded chain. + /// Params are packed and passed in as raw msg.data instead of ABI to reduce calldata size. + /// Params are expected to be in the following order: + /// 1. _baseFeeScalar L1 base fee scalar + /// 2. _blobBaseFeeScalar L1 blob base fee scalar + /// 3. _sequenceNumber Number of L2 blocks since epoch start. + /// 4. _timestamp L1 timestamp. + /// 5. _number L1 blocknumber. + /// 6. _basefee L1 base fee. + /// 7. _blobBaseFee L1 blob base fee. + /// 8. _hash L1 blockhash. + /// 9. _batcherHash Versioned hash to authenticate batcher by. + function _setL1BlockValuesEcotone() internal { address depositor = DEPOSITOR_ACCOUNT(); assembly { // Revert if the caller is not the depositor account. diff --git a/packages/contracts-bedrock/src/L2/L1BlockInterop.sol b/packages/contracts-bedrock/src/L2/L1BlockIsthmus.sol similarity index 69% rename from packages/contracts-bedrock/src/L2/L1BlockInterop.sol rename to packages/contracts-bedrock/src/L2/L1BlockIsthmus.sol index 8dbf986fb7e60..c9643659030e3 100644 --- a/packages/contracts-bedrock/src/L2/L1BlockInterop.sol +++ b/packages/contracts-bedrock/src/L2/L1BlockIsthmus.sol @@ -1,13 +1,17 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Contracts import { L1Block } from "src/L2/L1Block.sol"; + +// Libraries import { EnumerableSet } from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; import { GasPayingToken } from "src/libraries/GasPayingToken.sol"; import { StaticConfig } from "src/libraries/StaticConfig.sol"; +import { Predeploys } from "src/libraries/Predeploys.sol"; import "src/libraries/L1BlockErrors.sol"; -/// @notice Enum representing different types of configurations that can be set on L1BlockInterop. +/// @notice Enum representing different types of configurations that can be set on L1BlockIsthmus. /// @custom:value SET_GAS_PAYING_TOKEN Represents the config type for setting the gas paying token. /// @custom:value ADD_DEPENDENCY Represents the config type for adding a chain to the interop dependency set. /// @custom:value REMOVE_DEPENDENCY Represents the config type for removing a chain from the interop dependency set. @@ -17,11 +21,11 @@ enum ConfigType { REMOVE_DEPENDENCY } -/// @custom:proxied +/// @custom:proxied true /// @custom:predeploy 0x4200000000000000000000000000000000000015 -/// @title L1BlockInterop -/// @notice Interop extenstions of L1Block. -contract L1BlockInterop is L1Block { +/// @title L1BlockIsthmus +/// @notice Isthmus extenstions of L1Block. +contract L1BlockIsthmus is L1Block { using EnumerableSet for EnumerableSet.UintSet; /// @notice Event emitted when a new dependency is added to the interop dependency set. @@ -33,9 +37,23 @@ contract L1BlockInterop is L1Block { /// @notice The interop dependency set, containing the chain IDs in it. EnumerableSet.UintSet dependencySet; - /// @custom:semver +interop + /// @notice Storage slot that the isDeposit is stored at. + /// This is a custom slot that is not part of the standard storage layout. + /// keccak256(abi.encode(uint256(keccak256("l1Block.identifier.isDeposit")) - 1)) & ~bytes32(uint256(0xff)) + uint256 internal constant IS_DEPOSIT_SLOT = 0x921bd3a089295c6e5540e8fba8195448d253efd6f2e3e495b499b627dc36a300; + + /// @custom:semver +isthmus function version() public pure override returns (string memory) { - return string.concat(super.version(), "+interop"); + return string.concat(super.version(), "+isthmus"); + } + + /// @notice Returns whether the call was triggered from a a deposit or not. + /// @notice This function is only callable by the CrossL2Inbox contract. + function isDeposit() external view returns (bool isDeposit_) { + if (msg.sender != Predeploys.CROSS_L2_INBOX) revert NotCrossL2Inbox(); + assembly { + isDeposit_ := sload(IS_DEPOSIT_SLOT) + } } /// @notice Returns true if a chain ID is in the interop dependency set and false otherwise. @@ -52,6 +70,29 @@ contract L1BlockInterop is L1Block { return uint8(dependencySet.length()); } + /// @notice Updates the `isDeposit` flag and sets the L1 block values for an Isthmus upgraded chain. + /// It updates the L1 block values through the `setL1BlockValuesEcotone` function. + /// It forwards the calldata to the internally-used `setL1BlockValuesEcotone` function. + function setL1BlockValuesIsthmus() external { + // Set the isDeposit flag to true. + assembly { + sstore(IS_DEPOSIT_SLOT, 1) + } + + _setL1BlockValuesEcotone(); + } + + /// @notice Resets the isDeposit flag. + /// Should only be called by the depositor account after the deposits are complete. + function depositsComplete() external { + if (msg.sender != DEPOSITOR_ACCOUNT()) revert NotDepositor(); + + // Set the isDeposit flag to false. + assembly { + sstore(IS_DEPOSIT_SLOT, 0) + } + } + /// @notice Sets static configuration options for the L2 system. Can only be called by the special /// depositor account. /// @param _type The type of configuration to set. diff --git a/packages/contracts-bedrock/src/L2/L1FeeVault.sol b/packages/contracts-bedrock/src/L2/L1FeeVault.sol index b8445dac5f4cc..d62db2a25c3be 100644 --- a/packages/contracts-bedrock/src/L2/L1FeeVault.sol +++ b/packages/contracts-bedrock/src/L2/L1FeeVault.sol @@ -1,17 +1,17 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { ISemver } from "src/universal/ISemver.sol"; +import { ISemver } from "src/universal/interfaces/ISemver.sol"; import { FeeVault } from "src/universal/FeeVault.sol"; -/// @custom:proxied +/// @custom:proxied true /// @custom:predeploy 0x420000000000000000000000000000000000001A /// @title L1FeeVault /// @notice The L1FeeVault accumulates the L1 portion of the transaction fees. contract L1FeeVault is FeeVault, ISemver { /// @notice Semantic version. - /// @custom:semver 1.5.0-beta.1 - string public constant version = "1.5.0-beta.1"; + /// @custom:semver 1.5.0-beta.2 + string public constant version = "1.5.0-beta.2"; /// @notice Constructs the L1FeeVault contract. /// @param _recipient Wallet that will receive the fees. diff --git a/packages/contracts-bedrock/src/L2/L2CrossDomainMessenger.sol b/packages/contracts-bedrock/src/L2/L2CrossDomainMessenger.sol index d504b2d40d327..bbfc82578ab64 100644 --- a/packages/contracts-bedrock/src/L2/L2CrossDomainMessenger.sol +++ b/packages/contracts-bedrock/src/L2/L2CrossDomainMessenger.sol @@ -1,24 +1,29 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Contracts +import { CrossDomainMessenger } from "src/universal/CrossDomainMessenger.sol"; + +// Libraries import { AddressAliasHelper } from "src/vendor/AddressAliasHelper.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; -import { CrossDomainMessenger } from "src/universal/CrossDomainMessenger.sol"; -import { ISemver } from "src/universal/ISemver.sol"; -import { L2ToL1MessagePasser } from "src/L2/L2ToL1MessagePasser.sol"; import { Constants } from "src/libraries/Constants.sol"; -import { L1Block } from "src/L2/L1Block.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; -/// @custom:proxied +// Interfaces +import { ISemver } from "src/universal/interfaces/ISemver.sol"; +import { IL2ToL1MessagePasser } from "src/L2/interfaces/IL2ToL1MessagePasser.sol"; +import { IL1Block } from "src/L2/interfaces/IL1Block.sol"; + +/// @custom:proxied true /// @custom:predeploy 0x4200000000000000000000000000000000000007 /// @title L2CrossDomainMessenger /// @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. contract L2CrossDomainMessenger is CrossDomainMessenger, ISemver { - /// @custom:semver 2.1.0 - string public constant version = "2.1.0"; + /// @custom:semver 2.1.1-beta.3 + string public constant version = "2.1.1-beta.3"; /// @notice Constructs the L2CrossDomainMessenger contract. constructor() CrossDomainMessenger() { @@ -41,14 +46,14 @@ contract L2CrossDomainMessenger is CrossDomainMessenger, ISemver { /// @inheritdoc CrossDomainMessenger function _sendMessage(address _to, uint64 _gasLimit, uint256 _value, bytes memory _data) internal override { - L2ToL1MessagePasser(payable(Predeploys.L2_TO_L1_MESSAGE_PASSER)).initiateWithdrawal{ value: _value }( + IL2ToL1MessagePasser(payable(Predeploys.L2_TO_L1_MESSAGE_PASSER)).initiateWithdrawal{ value: _value }( _to, _gasLimit, _data ); } /// @inheritdoc CrossDomainMessenger function gasPayingToken() internal view override returns (address addr_, uint8 decimals_) { - (addr_, decimals_) = L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).gasPayingToken(); + (addr_, decimals_) = IL1Block(Predeploys.L1_BLOCK_ATTRIBUTES).gasPayingToken(); } /// @inheritdoc CrossDomainMessenger diff --git a/packages/contracts-bedrock/src/L2/L2ERC721Bridge.sol b/packages/contracts-bedrock/src/L2/L2ERC721Bridge.sol index b0d5522fcc714..4f3231c677f05 100644 --- a/packages/contracts-bedrock/src/L2/L2ERC721Bridge.sol +++ b/packages/contracts-bedrock/src/L2/L2ERC721Bridge.sol @@ -1,15 +1,22 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Contracts import { ERC721Bridge } from "src/universal/ERC721Bridge.sol"; + +// Libraries import { ERC165Checker } from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; -import { L1ERC721Bridge } from "src/L1/L1ERC721Bridge.sol"; -import { IOptimismMintableERC721 } from "src/universal/IOptimismMintableERC721.sol"; -import { CrossDomainMessenger } from "src/universal/CrossDomainMessenger.sol"; -import { ISemver } from "src/universal/ISemver.sol"; import { Constants } from "src/libraries/Constants.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; +// Interfaces +import { IL1ERC721Bridge } from "src/L1/interfaces/IL1ERC721Bridge.sol"; +import { IOptimismMintableERC721 } from "src/universal/interfaces/IOptimismMintableERC721.sol"; +import { ICrossDomainMessenger } from "src/universal/interfaces/ICrossDomainMessenger.sol"; +import { ISemver } from "src/universal/interfaces/ISemver.sol"; + +/// @custom:proxied true +/// @custom:predeploy 0x4200000000000000000000000000000000000014 /// @title L2ERC721Bridge /// @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 @@ -20,8 +27,8 @@ import { Predeploys } from "src/libraries/Predeploys.sol"; /// wait for the one-week challenge period to elapse before their Optimism-native NFT /// can be refunded on L2. contract L2ERC721Bridge is ERC721Bridge, ISemver { - /// @custom:semver 1.7.1+beta.1 - string public constant version = "1.7.1+beta.1"; + /// @custom:semver 1.7.1-beta.2 + string public constant version = "1.7.1-beta.2"; /// @notice Constructs the L2ERC721Bridge contract. constructor() ERC721Bridge() { @@ -32,7 +39,7 @@ contract L2ERC721Bridge is ERC721Bridge, ISemver { /// @param _l1ERC721Bridge Address of the ERC721 bridge contract on the other network. function initialize(address payable _l1ERC721Bridge) public initializer { __ERC721Bridge_init({ - _messenger: CrossDomainMessenger(Predeploys.L2_CROSS_DOMAIN_MESSENGER), + _messenger: ICrossDomainMessenger(Predeploys.L2_CROSS_DOMAIN_MESSENGER), _otherBridge: ERC721Bridge(_l1ERC721Bridge) }); } @@ -112,7 +119,7 @@ contract L2ERC721Bridge is ERC721Bridge, ISemver { IOptimismMintableERC721(_localToken).burn(_from, _tokenId); bytes memory message = abi.encodeWithSelector( - L1ERC721Bridge.finalizeBridgeERC721.selector, remoteToken, _localToken, _from, _to, _tokenId, _extraData + IL1ERC721Bridge.finalizeBridgeERC721.selector, remoteToken, _localToken, _from, _to, _tokenId, _extraData ); // Send message to L1 bridge diff --git a/packages/contracts-bedrock/src/L2/L2StandardBridge.sol b/packages/contracts-bedrock/src/L2/L2StandardBridge.sol index b11314bcc6260..1c7e2e307cc36 100644 --- a/packages/contracts-bedrock/src/L2/L2StandardBridge.sol +++ b/packages/contracts-bedrock/src/L2/L2StandardBridge.sol @@ -1,14 +1,19 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { Predeploys } from "src/libraries/Predeploys.sol"; +// Contracts import { StandardBridge } from "src/universal/StandardBridge.sol"; -import { ISemver } from "src/universal/ISemver.sol"; import { OptimismMintableERC20 } from "src/universal/OptimismMintableERC20.sol"; -import { CrossDomainMessenger } from "src/universal/CrossDomainMessenger.sol"; -import { L1Block } from "src/L2/L1Block.sol"; -/// @custom:proxied +// Libraries +import { Predeploys } from "src/libraries/Predeploys.sol"; + +// Interfaces +import { ISemver } from "src/universal/interfaces/ISemver.sol"; +import { ICrossDomainMessenger } from "src/universal/interfaces/ICrossDomainMessenger.sol"; +import { IL1Block } from "src/L2/interfaces/IL1Block.sol"; + +/// @custom:proxied true /// @custom:predeploy 0x4200000000000000000000000000000000000010 /// @title L2StandardBridge /// @notice The L2StandardBridge is responsible for transfering ETH and ERC20 tokens between L1 and @@ -53,9 +58,9 @@ contract L2StandardBridge is StandardBridge, ISemver { ); /// @notice Semantic version. - /// @custom:semver 1.11.0 + /// @custom:semver 1.11.1-beta.2 function version() public pure virtual returns (string memory) { - return "1.11.0"; + return "1.11.1-beta.2"; } /// @notice Constructs the L2StandardBridge contract. @@ -67,7 +72,7 @@ contract L2StandardBridge is StandardBridge, ISemver { /// @param _otherBridge Contract for the corresponding bridge on the other chain. function initialize(StandardBridge _otherBridge) public initializer { __StandardBridge_init({ - _messenger: CrossDomainMessenger(Predeploys.L2_CROSS_DOMAIN_MESSENGER), + _messenger: ICrossDomainMessenger(Predeploys.L2_CROSS_DOMAIN_MESSENGER), _otherBridge: _otherBridge }); } @@ -81,7 +86,7 @@ contract L2StandardBridge is StandardBridge, ISemver { /// @inheritdoc StandardBridge function gasPayingToken() internal view override returns (address addr_, uint8 decimals_) { - (addr_, decimals_) = L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).gasPayingToken(); + (addr_, decimals_) = IL1Block(Predeploys.L1_BLOCK_ATTRIBUTES).gasPayingToken(); } /// @custom:legacy diff --git a/packages/contracts-bedrock/src/L2/L2StandardBridgeInterop.sol b/packages/contracts-bedrock/src/L2/L2StandardBridgeInterop.sol index 818ee0f9a7414..be6c9e4c878d6 100644 --- a/packages/contracts-bedrock/src/L2/L2StandardBridgeInterop.sol +++ b/packages/contracts-bedrock/src/L2/L2StandardBridgeInterop.sol @@ -1,11 +1,16 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { Predeploys } from "src/libraries/Predeploys.sol"; +// Contracts import { L2StandardBridge } from "src/L2/L2StandardBridge.sol"; + +// Libraries +import { Predeploys } from "src/libraries/Predeploys.sol"; + +// Interfaces import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { IERC20Metadata } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; -import { IOptimismERC20Factory } from "src/L2/IOptimismERC20Factory.sol"; +import { IOptimismERC20Factory } from "src/L2/interfaces/IOptimismERC20Factory.sol"; /// @notice Thrown when the decimals of the tokens are not the same. error InvalidDecimals(); @@ -27,7 +32,7 @@ interface MintableAndBurnable is IERC20 { function burn(address, uint256) external; } -/// @custom:proxied +/// @custom:proxied true /// @custom:predeploy 0x4200000000000000000000000000000000000010 /// @title L2StandardBridgeInterop /// @notice The L2StandardBridgeInterop is an extension of the L2StandardBridge that allows for diff --git a/packages/contracts-bedrock/src/L2/L2ToL1MessagePasser.sol b/packages/contracts-bedrock/src/L2/L2ToL1MessagePasser.sol index 8c764e9992710..94b8213983e13 100644 --- a/packages/contracts-bedrock/src/L2/L2ToL1MessagePasser.sol +++ b/packages/contracts-bedrock/src/L2/L2ToL1MessagePasser.sol @@ -5,9 +5,9 @@ import { Types } from "src/libraries/Types.sol"; import { Hashing } from "src/libraries/Hashing.sol"; import { Encoding } from "src/libraries/Encoding.sol"; import { Burn } from "src/libraries/Burn.sol"; -import { ISemver } from "src/universal/ISemver.sol"; +import { ISemver } from "src/universal/interfaces/ISemver.sol"; -/// @custom:proxied +/// @custom:proxied true /// @custom:predeploy 0x4200000000000000000000000000000000000016 /// @title L2ToL1MessagePasser /// @notice The L2ToL1MessagePasser is a dedicated contract where messages that are being sent from @@ -48,8 +48,8 @@ contract L2ToL1MessagePasser is ISemver { /// @param amount Amount of ETh that was burned. event WithdrawerBalanceBurnt(uint256 indexed amount); - /// @custom:semver 1.1.0 - string public constant version = "1.1.0"; + /// @custom:semver 1.1.1-beta.1 + string public constant version = "1.1.1-beta.1"; /// @notice Allows users to withdraw ETH by sending directly to this contract. receive() external payable { diff --git a/packages/contracts-bedrock/src/L2/L2ToL2CrossDomainMessenger.sol b/packages/contracts-bedrock/src/L2/L2ToL2CrossDomainMessenger.sol index 46eb76b21824d..4570e8191ca63 100644 --- a/packages/contracts-bedrock/src/L2/L2ToL2CrossDomainMessenger.sol +++ b/packages/contracts-bedrock/src/L2/L2ToL2CrossDomainMessenger.sol @@ -4,8 +4,8 @@ pragma solidity 0.8.25; import { Encoding } from "src/libraries/Encoding.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; import { CrossL2Inbox } from "src/L2/CrossL2Inbox.sol"; -import { IL2ToL2CrossDomainMessenger } from "src/L2/IL2ToL2CrossDomainMessenger.sol"; -import { ISemver } from "src/universal/ISemver.sol"; +import { IL2ToL2CrossDomainMessenger } from "src/L2/interfaces/IL2ToL2CrossDomainMessenger.sol"; +import { ISemver } from "src/universal/interfaces/ISemver.sol"; import { SafeCall } from "src/libraries/SafeCall.sol"; import { TransientReentrancyAware } from "src/libraries/TransientContext.sol"; @@ -36,7 +36,7 @@ error MessageAlreadyRelayed(); /// @notice Thrown when a reentrant call is detected. error ReentrantCall(); -/// @custom:proxied +/// @custom:proxied true /// @custom:predeploy 0x4200000000000000000000000000000000000023 /// @title L2ToL2CrossDomainMessenger /// @notice The L2ToL2CrossDomainMessenger is a higher level abstraction on top of the CrossL2Inbox that provides @@ -57,8 +57,8 @@ contract L2ToL2CrossDomainMessenger is IL2ToL2CrossDomainMessenger, ISemver, Tra uint16 public constant messageVersion = uint16(0); /// @notice Semantic version. - /// @custom:semver 1.0.0-beta.3 - string public constant version = "1.0.0-beta.3"; + /// @custom:semver 1.0.0-beta.4 + string public constant version = "1.0.0-beta.4"; /// @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. diff --git a/packages/contracts-bedrock/src/L2/OptimismSuperchainERC20.sol b/packages/contracts-bedrock/src/L2/OptimismSuperchainERC20.sol index 9b0ba5cad8b00..81cef632bfbe7 100644 --- a/packages/contracts-bedrock/src/L2/OptimismSuperchainERC20.sol +++ b/packages/contracts-bedrock/src/L2/OptimismSuperchainERC20.sol @@ -1,29 +1,19 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.25; -import { IOptimismSuperchainERC20Extension } from "src/L2/IOptimismSuperchainERC20.sol"; -import { ERC20 } from "@solady/tokens/ERC20.sol"; -import { IL2ToL2CrossDomainMessenger } from "src/L2/IL2ToL2CrossDomainMessenger.sol"; -import { ISemver } from "src/universal/ISemver.sol"; +import { IOptimismSuperchainERC20Extension } from "src/L2/interfaces/IOptimismSuperchainERC20.sol"; +import { IL2ToL2CrossDomainMessenger } from "src/L2/interfaces/IL2ToL2CrossDomainMessenger.sol"; +import { ISemver } from "src/universal/interfaces/ISemver.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; +import { ERC20 } from "@solady/tokens/ERC20.sol"; +import { SuperchainERC20 } from "src/L2/SuperchainERC20.sol"; import { Initializable } from "@openzeppelin/contracts-v5/proxy/utils/Initializable.sol"; import { ERC165 } from "@openzeppelin/contracts-v5/utils/introspection/ERC165.sol"; -/// @notice Thrown when attempting to relay a message and the function caller (msg.sender) is not -/// L2ToL2CrossDomainMessenger. -error CallerNotL2ToL2CrossDomainMessenger(); - -/// @notice Thrown when attempting to relay a message and the cross domain message sender is not this -/// OptimismSuperchainERC20. -error InvalidCrossDomainSender(); - /// @notice Thrown when attempting to mint or burn tokens and the function caller is not the StandardBridge. error OnlyBridge(); -/// @notice Thrown when attempting to mint or burn tokens and the account is the zero address. -error ZeroAddress(); - -/// @custom:proxied +/// @custom:proxied true /// @title OptimismSuperchainERC20 /// @notice OptimismSuperchainERC20 is a standard extension of the base ERC20 token contract that unifies ERC20 token /// bridging to make it fungible across the Superchain. This construction allows the L2StandardBridge to burn @@ -31,10 +21,13 @@ error ZeroAddress(); /// token, turning it fungible and interoperable across the superchain. Likewise, it also enables the inverse /// conversion path. /// Moreover, it builds on top of the L2ToL2CrossDomainMessenger for both replay protection and domain binding. -contract OptimismSuperchainERC20 is IOptimismSuperchainERC20Extension, ERC20, ISemver, Initializable, ERC165 { - /// @notice Address of the L2ToL2CrossDomainMessenger Predeploy. - address internal constant MESSENGER = Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER; - +contract OptimismSuperchainERC20 is + IOptimismSuperchainERC20Extension, + SuperchainERC20, + ISemver, + Initializable, + ERC165 +{ /// @notice Address of the StandardBridge Predeploy. address internal constant BRIDGE = Predeploys.L2_STANDARD_BRIDGE; @@ -57,7 +50,7 @@ contract OptimismSuperchainERC20 is IOptimismSuperchainERC20Extension, ERC20, IS } /// @notice Returns the storage for the OptimismSuperchainERC20Metadata. - function _getMetadataStorage() private pure returns (OptimismSuperchainERC20Metadata storage _storage) { + function _getStorage() private pure returns (OptimismSuperchainERC20Metadata storage _storage) { assembly { _storage.slot := OPTIMISM_SUPERCHAIN_ERC20_METADATA_SLOT } @@ -70,8 +63,8 @@ contract OptimismSuperchainERC20 is IOptimismSuperchainERC20Extension, ERC20, IS } /// @notice Semantic version. - /// @custom:semver 1.0.0-beta.1 - string public constant version = "1.0.0-beta.1"; + /// @custom:semver 1.0.0-beta.2 + string public constant version = "1.0.0-beta.2"; /// @notice Constructs the OptimismSuperchainERC20 contract. constructor() { @@ -92,7 +85,7 @@ contract OptimismSuperchainERC20 is IOptimismSuperchainERC20Extension, ERC20, IS external initializer { - OptimismSuperchainERC20Metadata storage _storage = _getMetadataStorage(); + OptimismSuperchainERC20Metadata storage _storage = _getStorage(); _storage.remoteToken = _remoteToken; _storage.name = _name; _storage.symbol = _symbol; @@ -121,54 +114,19 @@ contract OptimismSuperchainERC20 is IOptimismSuperchainERC20Extension, ERC20, IS emit Burn(_from, _amount); } - /// @notice Sends tokens to some target address on another chain. - /// @param _to Address to send tokens to. - /// @param _amount Amount of tokens to send. - /// @param _chainId Chain ID of the destination chain. - function sendERC20(address _to, uint256 _amount, uint256 _chainId) external { - if (_to == address(0)) revert ZeroAddress(); - - _burn(msg.sender, _amount); - - bytes memory _message = abi.encodeCall(this.relayERC20, (msg.sender, _to, _amount)); - IL2ToL2CrossDomainMessenger(MESSENGER).sendMessage(_chainId, address(this), _message); - - emit SendERC20(msg.sender, _to, _amount, _chainId); - } - - /// @notice Relays tokens received from another chain. - /// @param _from Address of the msg.sender of sendERC20 on the source chain. - /// @param _to Address to relay tokens to. - /// @param _amount Amount of tokens to relay. - function relayERC20(address _from, address _to, uint256 _amount) external { - if (_to == address(0)) revert ZeroAddress(); - - if (msg.sender != MESSENGER) revert CallerNotL2ToL2CrossDomainMessenger(); - - if (IL2ToL2CrossDomainMessenger(MESSENGER).crossDomainMessageSender() != address(this)) { - revert InvalidCrossDomainSender(); - } - - uint256 source = IL2ToL2CrossDomainMessenger(MESSENGER).crossDomainMessageSource(); - - _mint(_to, _amount); - - emit RelayERC20(_from, _to, _amount, source); - } - /// @notice Returns the address of the corresponding version of this token on the remote chain. function remoteToken() public view override returns (address) { - return _getMetadataStorage().remoteToken; + return _getStorage().remoteToken; } /// @notice Returns the name of the token. function name() public view virtual override returns (string memory) { - return _getMetadataStorage().name; + return _getStorage().name; } /// @notice Returns the symbol of the token. function symbol() public view virtual override returns (string memory) { - return _getMetadataStorage().symbol; + return _getStorage().symbol; } /// @notice Returns the number of decimals used to get its user representation. @@ -178,7 +136,7 @@ contract OptimismSuperchainERC20 is IOptimismSuperchainERC20Extension, ERC20, IS /// no way affects any of the arithmetic of the contract, including /// {IERC20-balanceOf} and {IERC20-transfer}. function decimals() public view override returns (uint8) { - return _getMetadataStorage().decimals; + return _getStorage().decimals; } /// @notice ERC165 interface check function. diff --git a/packages/contracts-bedrock/src/L2/OptimismSuperchainERC20Beacon.sol b/packages/contracts-bedrock/src/L2/OptimismSuperchainERC20Beacon.sol new file mode 100644 index 0000000000000..d1160819a2ece --- /dev/null +++ b/packages/contracts-bedrock/src/L2/OptimismSuperchainERC20Beacon.sol @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +import { IBeacon } from "@openzeppelin/contracts/proxy/beacon/IBeacon.sol"; +import { ISemver } from "src/universal/interfaces/ISemver.sol"; + +/// @custom:proxied +/// @custom:predeployed 0x4200000000000000000000000000000000000027 +/// @title OptimismSuperchainERC20Beacon +/// @notice OptimismSuperchainERC20Beacon is the beacon proxy for the OptimismSuperchainERC20 implementation. +contract OptimismSuperchainERC20Beacon is IBeacon, ISemver { + /// @notice Address of the OptimismSuperchainERC20 implementation. + address internal immutable IMPLEMENTATION; + + /// @notice Semantic version. + /// @custom:semver 1.0.0-beta.1 + string public constant version = "1.0.0-beta.1"; + + constructor(address _implementation) { + IMPLEMENTATION = _implementation; + } + + /// @inheritdoc IBeacon + function implementation() external view override returns (address) { + return IMPLEMENTATION; + } +} diff --git a/packages/contracts-bedrock/src/L2/OptimismSuperchainERC20Factory.sol b/packages/contracts-bedrock/src/L2/OptimismSuperchainERC20Factory.sol new file mode 100644 index 0000000000000..4265101597208 --- /dev/null +++ b/packages/contracts-bedrock/src/L2/OptimismSuperchainERC20Factory.sol @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.25; + +import { IOptimismERC20Factory } from "src/L2/interfaces/IOptimismERC20Factory.sol"; +import { ISemver } from "src/universal/interfaces/ISemver.sol"; +import { OptimismSuperchainERC20 } from "src/L2/OptimismSuperchainERC20.sol"; +import { Predeploys } from "src/libraries/Predeploys.sol"; +import { BeaconProxy } from "@openzeppelin/contracts-v5/proxy/beacon/BeaconProxy.sol"; +import { CREATE3 } from "@rari-capital/solmate/src/utils/CREATE3.sol"; + +/// @custom:proxied +/// @custom:predeployed 0x4200000000000000000000000000000000000026 +/// @title OptimismSuperchainERC20Factory +/// @notice OptimismSuperchainERC20Factory is a factory contract that deploys OptimismSuperchainERC20 Beacon Proxies +/// using CREATE3. +contract OptimismSuperchainERC20Factory is IOptimismERC20Factory, ISemver { + /// @notice Mapping of the deployed OptimismSuperchainERC20 to the remote token address. + /// This is used to keep track of the token deployments. + mapping(address superchainToken => address remoteToken) public deployments; + + /// @notice Emitted when an OptimismSuperchainERC20 is deployed. + /// @param superchainToken Address of the SuperchainERC20 deployment. + /// @param remoteToken Address of the corresponding token on the remote chain. + /// @param deployer Address of the account that deployed the token. + event OptimismSuperchainERC20Created( + address indexed superchainToken, address indexed remoteToken, address deployer + ); + + /// @notice Semantic version. + /// @custom:semver 1.0.0-beta.1 + string public constant version = "1.0.0-beta.1"; + + /// @notice Deploys a OptimismSuperchainERC20 Beacon Proxy using CREATE3. + /// @param _remoteToken Address of the remote token. + /// @param _name Name of the OptimismSuperchainERC20. + /// @param _symbol Symbol of the OptimismSuperchainERC20. + /// @param _decimals Decimals of the OptimismSuperchainERC20. + /// @return _superchainERC20 Address of the OptimismSuperchainERC20 deployment. + function deploy( + address _remoteToken, + string memory _name, + string memory _symbol, + uint8 _decimals + ) + external + returns (address _superchainERC20) + { + bytes memory initCallData = + abi.encodeCall(OptimismSuperchainERC20.initialize, (_remoteToken, _name, _symbol, _decimals)); + + bytes memory creationCode = bytes.concat( + type(BeaconProxy).creationCode, abi.encode(Predeploys.OPTIMISM_SUPERCHAIN_ERC20_BEACON, initCallData) + ); + + bytes32 salt = keccak256(abi.encode(_remoteToken, _name, _symbol, _decimals)); + _superchainERC20 = CREATE3.deploy({ salt: salt, creationCode: creationCode, value: 0 }); + + deployments[_superchainERC20] = _remoteToken; + + emit OptimismSuperchainERC20Created(_superchainERC20, _remoteToken, msg.sender); + } +} diff --git a/packages/contracts-bedrock/src/L2/SequencerFeeVault.sol b/packages/contracts-bedrock/src/L2/SequencerFeeVault.sol index 7216d9e3430e9..fecbb7e1b7cd9 100644 --- a/packages/contracts-bedrock/src/L2/SequencerFeeVault.sol +++ b/packages/contracts-bedrock/src/L2/SequencerFeeVault.sol @@ -1,17 +1,17 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { ISemver } from "src/universal/ISemver.sol"; +import { ISemver } from "src/universal/interfaces/ISemver.sol"; import { FeeVault } from "src/universal/FeeVault.sol"; -/// @custom:proxied +/// @custom:proxied true /// @custom:predeploy 0x4200000000000000000000000000000000000011 /// @title SequencerFeeVault /// @notice The SequencerFeeVault is the contract that holds any fees paid to the Sequencer during /// transaction processing and block production. contract SequencerFeeVault is FeeVault, ISemver { - /// @custom:semver 1.5.0-beta.1 - string public constant version = "1.5.0-beta.1"; + /// @custom:semver 1.5.0-beta.2 + string public constant version = "1.5.0-beta.2"; /// @notice Constructs the SequencerFeeVault contract. /// @param _recipient Wallet that will receive the fees. diff --git a/packages/contracts-bedrock/src/L2/SuperchainERC20.sol b/packages/contracts-bedrock/src/L2/SuperchainERC20.sol new file mode 100644 index 0000000000000..e20b375ff891e --- /dev/null +++ b/packages/contracts-bedrock/src/L2/SuperchainERC20.sol @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.25; + +import { ISuperchainERC20Extensions, ISuperchainERC20Errors } from "src/L2/interfaces/ISuperchainERC20.sol"; +import { ERC20 } from "@solady/tokens/ERC20.sol"; +import { IL2ToL2CrossDomainMessenger } from "src/L2/interfaces/IL2ToL2CrossDomainMessenger.sol"; +import { Predeploys } from "src/libraries/Predeploys.sol"; + +/// @title SuperchainERC20 +/// @notice SuperchainERC20 is a standard extension of the base ERC20 token contract that unifies ERC20 token +/// bridging to make it fungible across the Superchain. It builds on top of the L2ToL2CrossDomainMessenger for +/// both replay protection and domain binding. +abstract contract SuperchainERC20 is ISuperchainERC20Extensions, ISuperchainERC20Errors, ERC20 { + /// @notice Address of the L2ToL2CrossDomainMessenger Predeploy. + address internal constant MESSENGER = Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER; + + /// @notice Sends tokens to some target address on another chain. + /// @param _to Address to send tokens to. + /// @param _amount Amount of tokens to send. + /// @param _chainId Chain ID of the destination chain. + function sendERC20(address _to, uint256 _amount, uint256 _chainId) external virtual { + if (_to == address(0)) revert ZeroAddress(); + + _burn(msg.sender, _amount); + + bytes memory _message = abi.encodeCall(this.relayERC20, (msg.sender, _to, _amount)); + IL2ToL2CrossDomainMessenger(MESSENGER).sendMessage(_chainId, address(this), _message); + + emit SendERC20(msg.sender, _to, _amount, _chainId); + } + + /// @notice Relays tokens received from another chain. + /// @param _from Address of the msg.sender of sendERC20 on the source chain. + /// @param _to Address to relay tokens to. + /// @param _amount Amount of tokens to relay. + function relayERC20(address _from, address _to, uint256 _amount) external virtual { + if (msg.sender != MESSENGER) revert CallerNotL2ToL2CrossDomainMessenger(); + + if (IL2ToL2CrossDomainMessenger(MESSENGER).crossDomainMessageSender() != address(this)) { + revert InvalidCrossDomainSender(); + } + + uint256 source = IL2ToL2CrossDomainMessenger(MESSENGER).crossDomainMessageSource(); + + _mint(_to, _amount); + + emit RelayERC20(_from, _to, _amount, source); + } +} diff --git a/packages/contracts-bedrock/src/L2/SuperchainWETH.sol b/packages/contracts-bedrock/src/L2/SuperchainWETH.sol index 7080460254fc6..a672918ffea15 100644 --- a/packages/contracts-bedrock/src/L2/SuperchainWETH.sol +++ b/packages/contracts-bedrock/src/L2/SuperchainWETH.sol @@ -1,14 +1,19 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { WETH98 } from "src/dispute/weth/WETH98.sol"; +// Contracts +import { WETH98 } from "src/universal/WETH98.sol"; + +// Libraries import { Unauthorized, NotCustomGasToken } from "src/libraries/errors/CommonErrors.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; -import { L1Block } from "src/L2/L1Block.sol"; -import { IL2ToL2CrossDomainMessenger } from "src/L2/IL2ToL2CrossDomainMessenger.sol"; -import { ETHLiquidity } from "src/L2/ETHLiquidity.sol"; -import { ISuperchainERC20Extensions } from "src/L2/ISuperchainERC20.sol"; -import { ISemver } from "src/universal/ISemver.sol"; + +// Interfaces +import { ISemver } from "src/universal/interfaces/ISemver.sol"; +import { IL2ToL2CrossDomainMessenger } from "src/L2/interfaces/IL2ToL2CrossDomainMessenger.sol"; +import { ISuperchainERC20Extensions } from "src/L2/interfaces/ISuperchainERC20.sol"; +import { IL1Block } from "src/L2/interfaces/IL1Block.sol"; +import { IETHLiquidity } from "src/L2/interfaces/IETHLiquidity.sol"; /// @title SuperchainWETH /// @notice SuperchainWETH is a version of WETH that can be freely transfrered between chains @@ -16,18 +21,18 @@ import { ISemver } from "src/universal/ISemver.sol"; /// do not use a custom gas token. contract SuperchainWETH is WETH98, ISuperchainERC20Extensions, ISemver { /// @notice Semantic version. - /// @custom:semver 1.0.0-beta.1 - string public constant version = "1.0.0-beta.1"; + /// @custom:semver 1.0.0-beta.4 + string public constant version = "1.0.0-beta.4"; /// @inheritdoc WETH98 function deposit() public payable override { - if (L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).isCustomGasToken()) revert NotCustomGasToken(); + if (IL1Block(Predeploys.L1_BLOCK_ATTRIBUTES).isCustomGasToken()) revert NotCustomGasToken(); super.deposit(); } /// @inheritdoc WETH98 function withdraw(uint256 wad) public override { - if (L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).isCustomGasToken()) revert NotCustomGasToken(); + if (IL1Block(Predeploys.L1_BLOCK_ATTRIBUTES).isCustomGasToken()) revert NotCustomGasToken(); super.withdraw(wad); } @@ -37,8 +42,8 @@ contract SuperchainWETH is WETH98, ISuperchainERC20Extensions, ISemver { _burn(msg.sender, wad); // Burn to ETHLiquidity contract. - if (!L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).isCustomGasToken()) { - ETHLiquidity(Predeploys.ETH_LIQUIDITY).burn{ value: wad }(); + if (!IL1Block(Predeploys.L1_BLOCK_ATTRIBUTES).isCustomGasToken()) { + IETHLiquidity(Predeploys.ETH_LIQUIDITY).burn{ value: wad }(); } // Send message to other chain. @@ -60,8 +65,8 @@ contract SuperchainWETH is WETH98, ISuperchainERC20Extensions, ISemver { if (messenger.crossDomainMessageSender() != address(this)) revert Unauthorized(); // Mint from ETHLiquidity contract. - if (!L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).isCustomGasToken()) { - ETHLiquidity(Predeploys.ETH_LIQUIDITY).mint(wad); + if (!IL1Block(Predeploys.L1_BLOCK_ATTRIBUTES).isCustomGasToken()) { + IETHLiquidity(Predeploys.ETH_LIQUIDITY).mint(wad); } // Get source chain ID. diff --git a/packages/contracts-bedrock/src/L2/WETH.sol b/packages/contracts-bedrock/src/L2/WETH.sol index 42b957f45e959..fb24f07473385 100644 --- a/packages/contracts-bedrock/src/L2/WETH.sol +++ b/packages/contracts-bedrock/src/L2/WETH.sol @@ -1,26 +1,31 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { WETH98 } from "src/dispute/weth/WETH98.sol"; +// Contracts +import { WETH98 } from "src/universal/WETH98.sol"; + +// Libraries import { Predeploys } from "src/libraries/Predeploys.sol"; -import { L1Block } from "src/L2/L1Block.sol"; -import { ISemver } from "src/universal/ISemver.sol"; + +// Interfaces +import { ISemver } from "src/universal/interfaces/ISemver.sol"; +import { IL1Block } from "src/L2/interfaces/IL1Block.sol"; /// @title WETH contract that reads the name and symbol from the L1Block contract. /// Allows for nice rendering of token names for chains using custom gas token. contract WETH is WETH98, ISemver { - /// @custom:semver 1.0.0 - string public constant version = "1.0.0"; + /// @custom:semver 1.1.0-beta.2 + string public constant version = "1.1.0-beta.2"; /// @notice Returns the name of the wrapped native asset. Will be "Wrapped Ether" /// if the native asset is Ether. function name() external view override returns (string memory name_) { - name_ = string.concat("Wrapped ", L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).gasPayingTokenName()); + name_ = string.concat("Wrapped ", IL1Block(Predeploys.L1_BLOCK_ATTRIBUTES).gasPayingTokenName()); } /// @notice Returns the symbol of the wrapped native asset. Will be "WETH" if the /// native asset is Ether. function symbol() external view override returns (string memory symbol_) { - symbol_ = string.concat("W", L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).gasPayingTokenSymbol()); + symbol_ = string.concat("W", IL1Block(Predeploys.L1_BLOCK_ATTRIBUTES).gasPayingTokenSymbol()); } } diff --git a/packages/contracts-bedrock/src/L2/interfaces/IBaseFeeVault.sol b/packages/contracts-bedrock/src/L2/interfaces/IBaseFeeVault.sol new file mode 100644 index 0000000000000..9843189bdb140 --- /dev/null +++ b/packages/contracts-bedrock/src/L2/interfaces/IBaseFeeVault.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { IFeeVault } from "src/universal/interfaces/IFeeVault.sol"; + +interface IBaseFeeVault is IFeeVault { + function version() external view returns (string memory); + + function __constructor__( + address _recipient, + uint256 _minWithdrawalAmount, + WithdrawalNetwork _withdrawalNetwork + ) + external; +} diff --git a/packages/contracts-bedrock/src/L2/ICrossL2Inbox.sol b/packages/contracts-bedrock/src/L2/interfaces/ICrossL2Inbox.sol similarity index 100% rename from packages/contracts-bedrock/src/L2/ICrossL2Inbox.sol rename to packages/contracts-bedrock/src/L2/interfaces/ICrossL2Inbox.sol diff --git a/packages/contracts-bedrock/src/L2/interfaces/IDependencySet.sol b/packages/contracts-bedrock/src/L2/interfaces/IDependencySet.sol new file mode 100644 index 0000000000000..fb294bee8d197 --- /dev/null +++ b/packages/contracts-bedrock/src/L2/interfaces/IDependencySet.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/// @title IDependencySet +/// @notice Interface for L1Block with only `isInDependencySet(uint256)` method. +interface IDependencySet { + /// @notice Returns true if the chain associated with input chain ID is in the interop dependency set. + /// Every chain is in the interop dependency set of itself. + /// @param _chainId Input chain ID. + /// @return True if the input chain ID corresponds to a chain in the interop dependency set, and false otherwise. + function isInDependencySet(uint256 _chainId) external view returns (bool); +} diff --git a/packages/contracts-bedrock/src/L2/interfaces/IETHLiquidity.sol b/packages/contracts-bedrock/src/L2/interfaces/IETHLiquidity.sol new file mode 100644 index 0000000000000..de463f543b711 --- /dev/null +++ b/packages/contracts-bedrock/src/L2/interfaces/IETHLiquidity.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +interface IETHLiquidity { + error NotCustomGasToken(); + error Unauthorized(); + + event LiquidityBurned(address indexed caller, uint256 value); + event LiquidityMinted(address indexed caller, uint256 value); + + function burn() external payable; + function mint(uint256 _amount) external; + function version() external view returns (string memory); +} diff --git a/packages/contracts-bedrock/src/L2/interfaces/IGasPriceOracle.sol b/packages/contracts-bedrock/src/L2/interfaces/IGasPriceOracle.sol new file mode 100644 index 0000000000000..4ab0ef854c8ab --- /dev/null +++ b/packages/contracts-bedrock/src/L2/interfaces/IGasPriceOracle.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +interface IGasPriceOracle { + function DECIMALS() external view returns (uint256); + function baseFee() external view returns (uint256); + function baseFeeScalar() external view returns (uint32); + function blobBaseFee() external view returns (uint256); + function blobBaseFeeScalar() external view returns (uint32); + function decimals() external pure returns (uint256); + function gasPrice() external view returns (uint256); + function getL1Fee(bytes memory _data) external view returns (uint256); + function getL1FeeUpperBound(uint256 _unsignedTxSize) external view returns (uint256); + function getL1GasUsed(bytes memory _data) external view returns (uint256); + function isEcotone() external view returns (bool); + function isFjord() external view returns (bool); + function l1BaseFee() external view returns (uint256); + function overhead() external view returns (uint256); + function scalar() external view returns (uint256); + function setEcotone() external; + function setFjord() external; + function version() external view returns (string memory); +} diff --git a/packages/contracts-bedrock/src/L2/interfaces/IL1Block.sol b/packages/contracts-bedrock/src/L2/interfaces/IL1Block.sol new file mode 100644 index 0000000000000..6ef4c2984ae40 --- /dev/null +++ b/packages/contracts-bedrock/src/L2/interfaces/IL1Block.sol @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +interface IL1Block { + error NotDepositor(); + + event GasPayingTokenSet(address indexed token, uint8 indexed decimals, bytes32 name, bytes32 symbol); + + function DEPOSITOR_ACCOUNT() external pure returns (address addr_); + function baseFeeScalar() external view returns (uint32); + function basefee() external view returns (uint256); + function batcherHash() external view returns (bytes32); + function blobBaseFee() external view returns (uint256); + function blobBaseFeeScalar() external view returns (uint32); + function gasPayingToken() external view returns (address addr_, uint8 decimals_); + function gasPayingTokenName() external view returns (string memory name_); + function gasPayingTokenSymbol() external view returns (string memory symbol_); + function hash() external view returns (bytes32); + function isCustomGasToken() external view returns (bool); + function l1FeeOverhead() external view returns (uint256); + function l1FeeScalar() external view returns (uint256); + function number() external view returns (uint64); + function sequenceNumber() external view returns (uint64); + function setGasPayingToken(address _token, uint8 _decimals, bytes32 _name, bytes32 _symbol) external; + function setL1BlockValues( + uint64 _number, + uint64 _timestamp, + uint256 _basefee, + bytes32 _hash, + uint64 _sequenceNumber, + bytes32 _batcherHash, + uint256 _l1FeeOverhead, + uint256 _l1FeeScalar + ) + external; + function setL1BlockValuesEcotone() external; + function timestamp() external view returns (uint64); + function version() external pure returns (string memory); +} diff --git a/packages/contracts-bedrock/src/L2/interfaces/IL1BlockIsthmus.sol b/packages/contracts-bedrock/src/L2/interfaces/IL1BlockIsthmus.sol new file mode 100644 index 0000000000000..7ff15eda51b08 --- /dev/null +++ b/packages/contracts-bedrock/src/L2/interfaces/IL1BlockIsthmus.sol @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +enum ConfigType { + SET_GAS_PAYING_TOKEN, + ADD_DEPENDENCY, + REMOVE_DEPENDENCY +} + +interface IL1BlockIsthmus { + error AlreadyDependency(); + error CantRemovedDependency(); + error DependencySetSizeTooLarge(); + error NotCrossL2Inbox(); + error NotDependency(); + error NotDepositor(); + + event DependencyAdded(uint256 indexed chainId); + event DependencyRemoved(uint256 indexed chainId); + event GasPayingTokenSet(address indexed token, uint8 indexed decimals, bytes32 name, bytes32 symbol); + + function DEPOSITOR_ACCOUNT() external pure returns (address addr_); + function baseFeeScalar() external view returns (uint32); + function basefee() external view returns (uint256); + function batcherHash() external view returns (bytes32); + function blobBaseFee() external view returns (uint256); + function blobBaseFeeScalar() external view returns (uint32); + function dependencySetSize() external view returns (uint8); + function depositsComplete() external; + function gasPayingToken() external view returns (address addr_, uint8 decimals_); + function gasPayingTokenName() external view returns (string memory name_); + function gasPayingTokenSymbol() external view returns (string memory symbol_); + function hash() external view returns (bytes32); + function isCustomGasToken() external view returns (bool); + function isDeposit() external view returns (bool isDeposit_); + function isInDependencySet(uint256 _chainId) external view returns (bool); + function l1FeeOverhead() external view returns (uint256); + function l1FeeScalar() external view returns (uint256); + function number() external view returns (uint64); + function sequenceNumber() external view returns (uint64); + function setConfig(ConfigType _type, bytes memory _value) external; + function setGasPayingToken(address _token, uint8 _decimals, bytes32 _name, bytes32 _symbol) external; + function setL1BlockValues( + uint64 _number, + uint64 _timestamp, + uint256 _basefee, + bytes32 _hash, + uint64 _sequenceNumber, + bytes32 _batcherHash, + uint256 _l1FeeOverhead, + uint256 _l1FeeScalar + ) + external; + function setL1BlockValuesEcotone() external; + function setL1BlockValuesIsthmus() external; + function timestamp() external view returns (uint64); + function version() external pure returns (string memory); +} diff --git a/packages/contracts-bedrock/src/L2/interfaces/IL1FeeVault.sol b/packages/contracts-bedrock/src/L2/interfaces/IL1FeeVault.sol new file mode 100644 index 0000000000000..89ac3b782fcaa --- /dev/null +++ b/packages/contracts-bedrock/src/L2/interfaces/IL1FeeVault.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { IFeeVault } from "src/universal/interfaces/IFeeVault.sol"; + +interface IL1FeeVault is IFeeVault { + function version() external view returns (string memory); + + function __constructor__( + address _recipient, + uint256 _minWithdrawalAmount, + WithdrawalNetwork _withdrawalNetwork + ) + external; +} diff --git a/packages/contracts-bedrock/src/L2/interfaces/IL2CrossDomainMessenger.sol b/packages/contracts-bedrock/src/L2/interfaces/IL2CrossDomainMessenger.sol new file mode 100644 index 0000000000000..1cb49f674ec0b --- /dev/null +++ b/packages/contracts-bedrock/src/L2/interfaces/IL2CrossDomainMessenger.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { ICrossDomainMessenger } from "src/universal/interfaces/ICrossDomainMessenger.sol"; + +interface IL2CrossDomainMessenger is ICrossDomainMessenger { + function MESSAGE_VERSION() external view returns (uint16); + function initialize(ICrossDomainMessenger _l1CrossDomainMessenger) external; + function l1CrossDomainMessenger() external view returns (ICrossDomainMessenger); + function version() external view returns (string memory); + + function __constructor__() external; +} diff --git a/packages/contracts-bedrock/src/L2/interfaces/IL2ERC721Bridge.sol b/packages/contracts-bedrock/src/L2/interfaces/IL2ERC721Bridge.sol new file mode 100644 index 0000000000000..a760ce1d803c9 --- /dev/null +++ b/packages/contracts-bedrock/src/L2/interfaces/IL2ERC721Bridge.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { IERC721Bridge } from "src/universal/interfaces/IERC721Bridge.sol"; + +interface IL2ERC721Bridge is IERC721Bridge { + function finalizeBridgeERC721( + address _localToken, + address _remoteToken, + address _from, + address _to, + uint256 _tokenId, + bytes memory _extraData + ) + external; + function initialize(address payable _l1ERC721Bridge) external; + function version() external view returns (string memory); + + function __constructor__() external; +} diff --git a/packages/contracts-bedrock/src/L2/interfaces/IL2StandardBridge.sol b/packages/contracts-bedrock/src/L2/interfaces/IL2StandardBridge.sol new file mode 100644 index 0000000000000..9f9ce1a85621d --- /dev/null +++ b/packages/contracts-bedrock/src/L2/interfaces/IL2StandardBridge.sol @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { IStandardBridge } from "src/universal/interfaces/IStandardBridge.sol"; + +interface IL2StandardBridge is IStandardBridge { + event DepositFinalized( + address indexed l1Token, + address indexed l2Token, + address indexed from, + address to, + uint256 amount, + bytes extraData + ); + event WithdrawalInitiated( + address indexed l1Token, + address indexed l2Token, + address indexed from, + address to, + uint256 amount, + bytes extraData + ); + + receive() external payable; + + function initialize(IStandardBridge _otherBridge) external; + function l1TokenBridge() external view returns (address); + function version() external pure returns (string memory); + function withdraw( + address _l2Token, + uint256 _amount, + uint32 _minGasLimit, + bytes memory _extraData + ) + external + payable; + function withdrawTo( + address _l2Token, + address _to, + uint256 _amount, + uint32 _minGasLimit, + bytes memory _extraData + ) + external + payable; + + function __constructor__() external; +} diff --git a/packages/contracts-bedrock/src/L2/interfaces/IL2StandardBridgeInterop.sol b/packages/contracts-bedrock/src/L2/interfaces/IL2StandardBridgeInterop.sol new file mode 100644 index 0000000000000..227b48881fa6a --- /dev/null +++ b/packages/contracts-bedrock/src/L2/interfaces/IL2StandardBridgeInterop.sol @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import { IStandardBridge } from "src/universal/interfaces/IStandardBridge.sol"; +import { ICrossDomainMessenger } from "src/universal/interfaces/ICrossDomainMessenger.sol"; + +interface IMintableAndBurnable is IERC20 { + function mint(address, uint256) external; + function burn(address, uint256) external; +} + +interface IL2StandardBridgeInterop is IStandardBridge { + error InvalidDecimals(); + error InvalidLegacyERC20Address(); + error InvalidSuperchainERC20Address(); + error InvalidTokenPair(); + + event Converted(address indexed from, address indexed to, address indexed caller, uint256 amount); + + receive() external payable; + + event DepositFinalized( + address indexed l1Token, + address indexed l2Token, + address indexed from, + address to, + uint256 amount, + bytes extraData + ); + event WithdrawalInitiated( + address indexed l1Token, + address indexed l2Token, + address indexed from, + address to, + uint256 amount, + bytes extraData + ); + + function MESSENGER() external view returns (ICrossDomainMessenger); + function OTHER_BRIDGE() external view returns (IStandardBridge); + function bridgeERC20( + address _localToken, + address _remoteToken, + uint256 _amount, + uint32 _minGasLimit, + bytes memory _extraData + ) + external; + function bridgeERC20To( + address _localToken, + address _remoteToken, + address _to, + uint256 _amount, + uint32 _minGasLimit, + bytes memory _extraData + ) + external; + function bridgeETH(uint32 _minGasLimit, bytes memory _extraData) external payable; + function bridgeETHTo(address _to, uint32 _minGasLimit, bytes memory _extraData) external payable; + function deposits(address, address) external view returns (uint256); + function finalizeBridgeERC20( + address _localToken, + address _remoteToken, + address _from, + address _to, + uint256 _amount, + bytes memory _extraData + ) + external; + function finalizeBridgeETH(address _from, address _to, uint256 _amount, bytes memory _extraData) external payable; + function messenger() external view returns (ICrossDomainMessenger); + function otherBridge() external view returns (IStandardBridge); + function paused() external view returns (bool); + + function initialize(IStandardBridge _otherBridge) external; + function l1TokenBridge() external view returns (address); + function withdraw( + address _l2Token, + uint256 _amount, + uint32 _minGasLimit, + bytes memory _extraData + ) + external + payable; + function withdrawTo( + address _l2Token, + address _to, + uint256 _amount, + uint32 _minGasLimit, + bytes memory _extraData + ) + external + payable; + + function convert(address _from, address _to, uint256 _amount) external; + function version() external pure returns (string memory); +} diff --git a/packages/contracts-bedrock/src/L2/interfaces/IL2ToL1MessagePasser.sol b/packages/contracts-bedrock/src/L2/interfaces/IL2ToL1MessagePasser.sol new file mode 100644 index 0000000000000..751cf51a40db3 --- /dev/null +++ b/packages/contracts-bedrock/src/L2/interfaces/IL2ToL1MessagePasser.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +interface IL2ToL1MessagePasser { + event MessagePassed( + uint256 indexed nonce, + address indexed sender, + address indexed target, + uint256 value, + uint256 gasLimit, + bytes data, + bytes32 withdrawalHash + ); + event WithdrawerBalanceBurnt(uint256 indexed amount); + + receive() external payable; + + function MESSAGE_VERSION() external view returns (uint16); + function burn() external; + function initiateWithdrawal(address _target, uint256 _gasLimit, bytes memory _data) external payable; + function messageNonce() external view returns (uint256); + function sentMessages(bytes32) external view returns (bool); + function version() external view returns (string memory); +} diff --git a/packages/contracts-bedrock/src/L2/IL2ToL2CrossDomainMessenger.sol b/packages/contracts-bedrock/src/L2/interfaces/IL2ToL2CrossDomainMessenger.sol similarity index 72% rename from packages/contracts-bedrock/src/L2/IL2ToL2CrossDomainMessenger.sol rename to packages/contracts-bedrock/src/L2/interfaces/IL2ToL2CrossDomainMessenger.sol index 8b6b9d617cf1e..cb8d1952de656 100644 --- a/packages/contracts-bedrock/src/L2/IL2ToL2CrossDomainMessenger.sol +++ b/packages/contracts-bedrock/src/L2/interfaces/IL2ToL2CrossDomainMessenger.sol @@ -4,6 +4,19 @@ pragma solidity ^0.8.0; /// @title IL2ToL2CrossDomainMessenger /// @notice Interface for the L2ToL2CrossDomainMessenger contract. interface IL2ToL2CrossDomainMessenger { + /// @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. + /// @param _msgHash message hash to check. + /// @return Returns true if the message corresponding to the `_msgHash` was successfully relayed. + function successfulMessages(bytes32 _msgHash) external view returns (bool); + + /// @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. + /// @return Nonce of the next message to be sent, with added message version. + function messageNonce() external view returns (uint256); + /// @notice Retrieves the sender of the current cross domain message. /// @return _sender Address of the sender of the current cross domain message. function crossDomainMessageSender() external view returns (address _sender); diff --git a/packages/contracts-bedrock/src/L2/IOptimismERC20Factory.sol b/packages/contracts-bedrock/src/L2/interfaces/IOptimismERC20Factory.sol similarity index 100% rename from packages/contracts-bedrock/src/L2/IOptimismERC20Factory.sol rename to packages/contracts-bedrock/src/L2/interfaces/IOptimismERC20Factory.sol diff --git a/packages/contracts-bedrock/src/L2/IOptimismSuperchainERC20.sol b/packages/contracts-bedrock/src/L2/interfaces/IOptimismSuperchainERC20.sol similarity index 78% rename from packages/contracts-bedrock/src/L2/IOptimismSuperchainERC20.sol rename to packages/contracts-bedrock/src/L2/interfaces/IOptimismSuperchainERC20.sol index 9b9594e75d781..5f537c1f51ec1 100644 --- a/packages/contracts-bedrock/src/L2/IOptimismSuperchainERC20.sol +++ b/packages/contracts-bedrock/src/L2/interfaces/IOptimismSuperchainERC20.sol @@ -1,14 +1,15 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import { ISuperchainERC20Extensions } from "./ISuperchainERC20.sol"; +// Interfaces +import { IERC20Solady } from "src/vendor/interfaces/IERC20Solady.sol"; +import { ISuperchainERC20Extensions, ISuperchainERC20Errors } from "src/L2/interfaces/ISuperchainERC20.sol"; /// @title IOptimismSuperchainERC20Extension /// @notice This interface is available on the OptimismSuperchainERC20 contract. /// We declare it as a separate interface so that it can be used in /// custom implementations of SuperchainERC20. -interface IOptimismSuperchainERC20Extension is ISuperchainERC20Extensions { +interface IOptimismSuperchainERC20Extension is ISuperchainERC20Extensions, ISuperchainERC20Errors { /// @notice Emitted whenever tokens are minted for an account. /// @param account Address of the account tokens are being minted for. /// @param amount Amount of tokens minted. @@ -34,5 +35,5 @@ interface IOptimismSuperchainERC20Extension is ISuperchainERC20Extensions { } /// @title IOptimismSuperchainERC20 -/// @notice Combines the ERC20 interface with the OptimismSuperchainERC20Extension interface. -interface IOptimismSuperchainERC20 is IERC20, IOptimismSuperchainERC20Extension { } +/// @notice Combines Solady's ERC20 interface with the OptimismSuperchainERC20Extension interface. +interface IOptimismSuperchainERC20 is IERC20Solady, IOptimismSuperchainERC20Extension { } diff --git a/packages/contracts-bedrock/src/L2/interfaces/ISequencerFeeVault.sol b/packages/contracts-bedrock/src/L2/interfaces/ISequencerFeeVault.sol new file mode 100644 index 0000000000000..1987d07bb7f76 --- /dev/null +++ b/packages/contracts-bedrock/src/L2/interfaces/ISequencerFeeVault.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { IFeeVault } from "src/universal/interfaces/IFeeVault.sol"; + +interface ISequencerFeeVault is IFeeVault { + function version() external view returns (string memory); + function l1FeeWallet() external view returns (address); + + function __constructor__( + address _recipient, + uint256 _minWithdrawalAmount, + WithdrawalNetwork _withdrawalNetwork + ) + external; +} diff --git a/packages/contracts-bedrock/src/L2/ISuperchainERC20.sol b/packages/contracts-bedrock/src/L2/interfaces/ISuperchainERC20.sol similarity index 67% rename from packages/contracts-bedrock/src/L2/ISuperchainERC20.sol rename to packages/contracts-bedrock/src/L2/interfaces/ISuperchainERC20.sol index 76488cdf32ea2..fee6a2c2f7bd6 100644 --- a/packages/contracts-bedrock/src/L2/ISuperchainERC20.sol +++ b/packages/contracts-bedrock/src/L2/interfaces/ISuperchainERC20.sol @@ -1,7 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +// Interfaces +import { IERC20Solady } from "src/vendor/interfaces/IERC20Solady.sol"; /// @title ISuperchainERC20Extensions /// @notice Interface for the extensions to the ERC20 standard that are used by SuperchainERC20. @@ -35,6 +36,21 @@ interface ISuperchainERC20Extensions { function relayERC20(address _from, address _to, uint256 _amount) external; } +/// @title ISuperchainERC20Errors +/// @notice Interface containing the errors added in the SuperchainERC20 implementation. +interface ISuperchainERC20Errors { + /// @notice Thrown when attempting to relay a message and the function caller (msg.sender) is not + /// L2ToL2CrossDomainMessenger. + error CallerNotL2ToL2CrossDomainMessenger(); + + /// @notice Thrown when attempting to relay a message and the cross domain message sender is not this + /// SuperchainERC20. + error InvalidCrossDomainSender(); + + /// @notice Thrown when attempting to perform an operation and the account is the zero address. + error ZeroAddress(); +} + /// @title ISuperchainERC20 -/// @notice Combines the ERC20 interface with the SuperchainERC20Extensions interface. -interface ISuperchainERC20 is IERC20, ISuperchainERC20Extensions { } +/// @notice Combines Solady's ERC20 interface with the SuperchainERC20Extensions interface. +interface ISuperchainERC20 is IERC20Solady, ISuperchainERC20Extensions, ISuperchainERC20Errors { } diff --git a/packages/contracts-bedrock/src/L2/interfaces/ISuperchainWETH.sol b/packages/contracts-bedrock/src/L2/interfaces/ISuperchainWETH.sol new file mode 100644 index 0000000000000..7c755e11e8693 --- /dev/null +++ b/packages/contracts-bedrock/src/L2/interfaces/ISuperchainWETH.sol @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +interface ISuperchainWETH { + error NotCustomGasToken(); + error Unauthorized(); + + event Approval(address indexed src, address indexed guy, uint256 wad); + event Deposit(address indexed dst, uint256 wad); + event RelayERC20(address indexed from, address indexed to, uint256 amount, uint256 source); + event SendERC20(address indexed from, address indexed to, uint256 amount, uint256 destination); + event Transfer(address indexed src, address indexed dst, uint256 wad); + event Withdrawal(address indexed src, uint256 wad); + + fallback() external payable; + + receive() external payable; + + function allowance(address, address) external view returns (uint256); + function approve(address guy, uint256 wad) external returns (bool); + function balanceOf(address) external view returns (uint256); + function decimals() external view returns (uint8); + function deposit() external payable; + function name() external view returns (string memory); + function relayERC20(address from, address dst, uint256 wad) external; + function sendERC20(address dst, uint256 wad, uint256 chainId) external; + function symbol() external view returns (string memory); + function totalSupply() external view returns (uint256); + function transfer(address dst, uint256 wad) external returns (bool); + function transferFrom(address src, address dst, uint256 wad) external returns (bool); + function version() external view returns (string memory); + function withdraw(uint256 wad) external; +} diff --git a/packages/contracts-bedrock/src/cannon/MIPS.sol b/packages/contracts-bedrock/src/cannon/MIPS.sol index 3ecbf2a2751e8..f1d216c8e6def 100644 --- a/packages/contracts-bedrock/src/cannon/MIPS.sol +++ b/packages/contracts-bedrock/src/cannon/MIPS.sol @@ -1,13 +1,14 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { ISemver } from "src/universal/ISemver.sol"; +import { ISemver } from "src/universal/interfaces/ISemver.sol"; import { IPreimageOracle } from "./interfaces/IPreimageOracle.sol"; import { PreimageKeyLib } from "./PreimageKeyLib.sol"; import { MIPSInstructions as ins } from "src/cannon/libraries/MIPSInstructions.sol"; import { MIPSSyscalls as sys } from "src/cannon/libraries/MIPSSyscalls.sol"; import { MIPSState as st } from "src/cannon/libraries/MIPSState.sol"; import { MIPSMemory } from "src/cannon/libraries/MIPSMemory.sol"; +import { InvalidRMWInstruction } from "src/cannon/libraries/CannonErrors.sol"; /// @title MIPS /// @notice The MIPS contract emulates a single MIPS instruction. @@ -44,8 +45,8 @@ contract MIPS is ISemver { } /// @notice The semantic version of the MIPS contract. - /// @custom:semver 1.1.0-rc.1 - string public constant version = "1.1.0-rc.1"; + /// @custom:semver 1.1.1-beta.4 + string public constant version = "1.1.1-beta.4"; /// @notice The preimage oracle contract. IPreimageOracle internal immutable ORACLE; @@ -178,7 +179,7 @@ contract MIPS is ISemver { proofOffset: MIPSMemory.memoryProofOffset(STEP_PROOF_OFFSET, 1), memRoot: state.memRoot }); - (v0, v1, state.preimageOffset, state.memRoot) = sys.handleSysRead(args); + (v0, v1, state.preimageOffset, state.memRoot,,) = sys.handleSysRead(args); } else if (syscall_no == sys.SYS_WRITE) { (v0, v1, state.preimageKey, state.preimageOffset) = sys.handleSysWrite({ _a0: a0, @@ -291,23 +292,59 @@ contract MIPS is ISemver { return handleSyscall(_localContext); } + // Handle RMW (read-modify-write) ops + if (opcode == ins.OP_LOAD_LINKED || opcode == ins.OP_STORE_CONDITIONAL) { + return handleRMWOps(state, insn, opcode); + } + // Exec the rest of the step logic st.CpuScalars memory cpu = getCpuScalars(state); - (state.memRoot) = ins.execMipsCoreStepLogic({ - _cpu: cpu, - _registers: state.registers, - _memRoot: state.memRoot, - _memProofOffset: MIPSMemory.memoryProofOffset(STEP_PROOF_OFFSET, 1), - _insn: insn, - _opcode: opcode, - _fun: fun + ins.CoreStepLogicParams memory coreStepArgs = ins.CoreStepLogicParams({ + cpu: cpu, + registers: state.registers, + memRoot: state.memRoot, + memProofOffset: MIPSMemory.memoryProofOffset(STEP_PROOF_OFFSET, 1), + insn: insn, + opcode: opcode, + fun: fun }); + (state.memRoot,,) = ins.execMipsCoreStepLogic(coreStepArgs); setStateCpuScalars(state, cpu); return outputState(); } } + function handleRMWOps(State memory _state, uint32 _insn, uint32 _opcode) internal returns (bytes32) { + unchecked { + uint32 baseReg = (_insn >> 21) & 0x1F; + uint32 base = _state.registers[baseReg]; + uint32 rtReg = (_insn >> 16) & 0x1F; + uint32 offset = ins.signExtendImmediate(_insn); + + uint32 effAddr = (base + offset) & 0xFFFFFFFC; + uint256 memProofOffset = MIPSMemory.memoryProofOffset(STEP_PROOF_OFFSET, 1); + uint32 mem = MIPSMemory.readMem(_state.memRoot, effAddr, memProofOffset); + + uint32 retVal; + if (_opcode == ins.OP_LOAD_LINKED) { + retVal = mem; + } else if (_opcode == ins.OP_STORE_CONDITIONAL) { + uint32 val = _state.registers[rtReg]; + _state.memRoot = MIPSMemory.writeMem(effAddr, memProofOffset, val); + retVal = 1; // 1 for success + } else { + revert InvalidRMWInstruction(); + } + + st.CpuScalars memory cpu = getCpuScalars(_state); + ins.handleRd(cpu, _state.registers, rtReg, retVal, true); + setStateCpuScalars(_state, cpu); + + return outputState(); + } + } + function getCpuScalars(State memory _state) internal pure returns (st.CpuScalars memory) { return st.CpuScalars({ pc: _state.pc, nextPC: _state.nextPC, lo: _state.lo, hi: _state.hi }); } diff --git a/packages/contracts-bedrock/src/cannon/MIPS2.sol b/packages/contracts-bedrock/src/cannon/MIPS2.sol index 142af042b99ac..487ea0aac6dfb 100644 --- a/packages/contracts-bedrock/src/cannon/MIPS2.sol +++ b/packages/contracts-bedrock/src/cannon/MIPS2.sol @@ -1,13 +1,16 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { ISemver } from "src/universal/ISemver.sol"; +import { ISemver } from "src/universal/interfaces/ISemver.sol"; import { IPreimageOracle } from "./interfaces/IPreimageOracle.sol"; import { MIPSMemory } from "src/cannon/libraries/MIPSMemory.sol"; import { MIPSSyscalls as sys } from "src/cannon/libraries/MIPSSyscalls.sol"; import { MIPSState as st } from "src/cannon/libraries/MIPSState.sol"; import { MIPSInstructions as ins } from "src/cannon/libraries/MIPSInstructions.sol"; import { VMStatuses } from "src/dispute/lib/Types.sol"; +import { + InvalidMemoryProof, InvalidRMWInstruction, InvalidSecondMemoryProof +} from "src/cannon/libraries/CannonErrors.sol"; /// @title MIPS2 /// @notice The MIPS2 contract emulates a single MIPS instruction. @@ -32,13 +35,16 @@ contract MIPS2 is ISemver { } /// @notice Stores the VM state. - /// Total state size: 32 + 32 + 4 + 4 + 1 + 1 + 8 + 8 + 4 + 1 + 32 + 32 + 4 = 163 bytes + /// Total state size: 32 + 32 + 4 + 4 + 1 + 4 + 4 + 1 + 1 + 8 + 8 + 4 + 1 + 32 + 32 + 4 = 172 bytes /// If nextPC != pc + 4, then the VM is executing a branch/jump delay slot. struct State { bytes32 memRoot; bytes32 preimageKey; uint32 preimageOffset; uint32 heap; + bool llReservationActive; + uint32 llAddress; + uint32 llOwnerThread; uint8 exitCode; bool exited; uint64 step; @@ -51,8 +57,8 @@ contract MIPS2 is ISemver { } /// @notice The semantic version of the MIPS2 contract. - /// @custom:semver 1.0.0-beta.4 - string public constant version = "1.0.0-beta.4"; + /// @custom:semver 1.0.0-beta.11 + string public constant version = "1.0.0-beta.11"; /// @notice The preimage oracle contract. IPreimageOracle internal immutable ORACLE; @@ -70,13 +76,19 @@ contract MIPS2 is ISemver { uint256 internal constant STATE_MEM_OFFSET = 0x80; // ThreadState memory offset allocated during step - uint256 internal constant TC_MEM_OFFSET = 0x220; + uint256 internal constant TC_MEM_OFFSET = 0x280; /// @param _oracle The address of the preimage oracle contract. constructor(IPreimageOracle _oracle) { ORACLE = _oracle; } + /// @notice Getter for the pre-image oracle contract. + /// @return oracle_ The IPreimageOracle contract. + function oracle() external view returns (IPreimageOracle oracle_) { + oracle_ = ORACLE; + } + /// @notice Executes a single step of the multi-threaded vm. /// Will revert if any required input state is missing. /// @param _stateData The encoded state witness data. @@ -91,7 +103,7 @@ contract MIPS2 is ISemver { unchecked { State memory state; ThreadState memory thread; - + uint32 exited; assembly { if iszero(eq(state, STATE_MEM_OFFSET)) { // expected state mem offset check @@ -101,8 +113,8 @@ contract MIPS2 is ISemver { // expected thread mem offset check revert(0, 0) } - if iszero(eq(mload(0x40), shl(5, 60))) { - // 4 + 13 state slots + 43 thread slots = 60 expected memory check + if iszero(eq(mload(0x40), shl(5, 63))) { + // 4 + 16 state slots + 43 thread slots = 63 expected memory check revert(0, 0) } if iszero(eq(_stateData.offset, 132)) { @@ -129,8 +141,12 @@ contract MIPS2 is ISemver { c, m := putField(c, m, 32) // preimageKey c, m := putField(c, m, 4) // preimageOffset c, m := putField(c, m, 4) // heap + c, m := putField(c, m, 1) // llReservationActive + c, m := putField(c, m, 4) // llAddress + c, m := putField(c, m, 4) // llOwnerThread c, m := putField(c, m, 1) // exitCode c, m := putField(c, m, 1) // exited + exited := mload(sub(m, 32)) c, m := putField(c, m, 8) // step c, m := putField(c, m, 8) // stepsSinceLastContextSwitch c, m := putField(c, m, 4) // wakeup @@ -139,6 +155,7 @@ contract MIPS2 is ISemver { c, m := putField(c, m, 32) // rightThreadStack c, m := putField(c, m, 4) // nextThreadID } + st.assertExitedIsValid(exited); if (state.exited) { // thread state is unchanged @@ -158,7 +175,7 @@ contract MIPS2 is ISemver { // Don't allow regular execution until we resolved if we have woken up any thread. if (state.wakeup != sys.FUTEX_EMPTY_ADDR) { if (state.wakeup == thread.futexAddr) { - // completed wake traverssal + // completed wake traversal // resume execution on woken up thread state.wakeup = sys.FUTEX_EMPTY_ADDR; return outputState(); @@ -185,7 +202,7 @@ contract MIPS2 is ISemver { // check timeout first if (state.step > thread.futexTimeoutStep) { // timeout! Allow execution - return onWaitComplete(state, thread, true); + return onWaitComplete(thread, true); } else { uint32 mem = MIPSMemory.readMem( state.memRoot, thread.futexAddr & 0xFFffFFfc, MIPSMemory.memoryProofOffset(MEM_PROOF_OFFSET, 1) @@ -197,12 +214,12 @@ contract MIPS2 is ISemver { } else { // wake thread up, the value at its address changed! // Userspace can turn thread back to sleep if it was too sporadic. - return onWaitComplete(state, thread, false); + return onWaitComplete(thread, false); } } } - if (state.stepsSinceLastContextSwitch == sys.SCHED_QUANTUM) { + if (state.stepsSinceLastContextSwitch >= sys.SCHED_QUANTUM) { preemptThread(state, thread); return outputState(); } @@ -219,19 +236,95 @@ contract MIPS2 is ISemver { return handleSyscall(_localContext); } + // Handle RMW (read-modify-write) ops + if (opcode == ins.OP_LOAD_LINKED || opcode == ins.OP_STORE_CONDITIONAL) { + return handleRMWOps(state, thread, insn, opcode); + } + // Exec the rest of the step logic st.CpuScalars memory cpu = getCpuScalars(thread); - (state.memRoot) = ins.execMipsCoreStepLogic({ - _cpu: cpu, - _registers: thread.registers, - _memRoot: state.memRoot, - _memProofOffset: MIPSMemory.memoryProofOffset(MEM_PROOF_OFFSET, 1), - _insn: insn, - _opcode: opcode, - _fun: fun + ins.CoreStepLogicParams memory coreStepArgs = ins.CoreStepLogicParams({ + cpu: cpu, + registers: thread.registers, + memRoot: state.memRoot, + memProofOffset: MIPSMemory.memoryProofOffset(MEM_PROOF_OFFSET, 1), + insn: insn, + opcode: opcode, + fun: fun }); + bool memUpdated; + uint32 memAddr; + (state.memRoot, memUpdated, memAddr) = ins.execMipsCoreStepLogic(coreStepArgs); setStateCpuScalars(thread, cpu); updateCurrentThreadRoot(); + if (memUpdated) { + handleMemoryUpdate(state, memAddr); + } + + return outputState(); + } + } + + function handleMemoryUpdate(State memory _state, uint32 _memAddr) internal pure { + if (_memAddr == _state.llAddress) { + // Reserved address was modified, clear the reservation + clearLLMemoryReservation(_state); + } + } + + function clearLLMemoryReservation(State memory _state) internal pure { + _state.llReservationActive = false; + _state.llAddress = 0; + _state.llOwnerThread = 0; + } + + function handleRMWOps( + State memory _state, + ThreadState memory _thread, + uint32 _insn, + uint32 _opcode + ) + internal + returns (bytes32) + { + unchecked { + uint32 baseReg = (_insn >> 21) & 0x1F; + uint32 base = _thread.registers[baseReg]; + uint32 rtReg = (_insn >> 16) & 0x1F; + uint32 offset = ins.signExtendImmediate(_insn); + + uint32 effAddr = (base + offset) & 0xFFFFFFFC; + uint256 memProofOffset = MIPSMemory.memoryProofOffset(MEM_PROOF_OFFSET, 1); + uint32 mem = MIPSMemory.readMem(_state.memRoot, effAddr, memProofOffset); + + uint32 retVal = 0; + uint32 threadId = _thread.threadID; + if (_opcode == ins.OP_LOAD_LINKED) { + retVal = mem; + _state.llReservationActive = true; + _state.llAddress = effAddr; + _state.llOwnerThread = threadId; + } else if (_opcode == ins.OP_STORE_CONDITIONAL) { + // Check if our memory reservation is still intact + if (_state.llReservationActive && _state.llOwnerThread == threadId && _state.llAddress == effAddr) { + // Complete atomic update: set memory and return 1 for success + clearLLMemoryReservation(_state); + uint32 val = _thread.registers[rtReg]; + _state.memRoot = MIPSMemory.writeMem(effAddr, memProofOffset, val); + retVal = 1; + } else { + // Atomic update failed, return 0 for failure + retVal = 0; + } + } else { + revert InvalidRMWInstruction(); + } + + st.CpuScalars memory cpu = getCpuScalars(_thread); + ins.handleRd(cpu, _thread.registers, rtReg, retVal, true); + setStateCpuScalars(_thread, cpu); + updateCurrentThreadRoot(); + return outputState(); } } @@ -310,7 +403,8 @@ contract MIPS2 is ISemver { proofOffset: MIPSMemory.memoryProofOffset(MEM_PROOF_OFFSET, 1), memRoot: state.memRoot }); - (v0, v1, state.preimageOffset, state.memRoot) = sys.handleSysRead(args); + // Encapsulate execution to avoid stack-too-deep error + (v0, v1) = execSysRead(state, args); } else if (syscall_no == sys.SYS_WRITE) { (v0, v1, state.preimageKey, state.preimageOffset) = sys.handleSysWrite({ _a0: a0, @@ -337,15 +431,15 @@ contract MIPS2 is ISemver { return outputState(); } else if (syscall_no == sys.SYS_FUTEX) { // args: a0 = addr, a1 = op, a2 = val, a3 = timeout + uint32 effAddr = a0 & 0xFFffFFfc; if (a1 == sys.FUTEX_WAIT_PRIVATE) { - thread.futexAddr = a0; - uint32 mem = MIPSMemory.readMem( - state.memRoot, a0 & 0xFFffFFfc, MIPSMemory.memoryProofOffset(MEM_PROOF_OFFSET, 1) - ); + uint32 mem = + MIPSMemory.readMem(state.memRoot, effAddr, MIPSMemory.memoryProofOffset(MEM_PROOF_OFFSET, 1)); if (mem != a2) { v0 = sys.SYS_ERROR_SIGNAL; v1 = sys.EAGAIN; } else { + thread.futexAddr = effAddr; thread.futexVal = a2; thread.futexTimeoutStep = a3 == 0 ? sys.FUTEX_NO_TIMEOUT : state.step + sys.FUTEX_TIMEOUT_STEPS; // Leave cpu scalars as-is. This instruction will be completed by `onWaitComplete` @@ -355,7 +449,7 @@ contract MIPS2 is ISemver { } else if (a1 == sys.FUTEX_WAKE_PRIVATE) { // Trigger thread traversal starting from the left stack until we find one waiting on the wakeup // address - state.wakeup = a0; + state.wakeup = effAddr; // Don't indicate to the program that we've woken up a waiting thread, as there are no guarantees. // The woken up thread should indicate this in userspace. v0 = 0; @@ -381,9 +475,50 @@ contract MIPS2 is ISemver { } else if (syscall_no == sys.SYS_OPEN) { v0 = sys.SYS_ERROR_SIGNAL; v1 = sys.EBADF; - } else if (syscall_no == sys.SYS_CLOCK_GETTIME) { + } else if (syscall_no == sys.SYS_CLOCKGETTIME) { + if (a0 == sys.CLOCK_GETTIME_REALTIME_FLAG || a0 == sys.CLOCK_GETTIME_MONOTONIC_FLAG) { + v0 = 0; + v1 = 0; + uint32 secs = 0; + uint32 nsecs = 0; + if (a0 == sys.CLOCK_GETTIME_MONOTONIC_FLAG) { + secs = uint32(state.step / sys.HZ); + nsecs = uint32((state.step % sys.HZ) * (1_000_000_000 / sys.HZ)); + } + uint32 effAddr = a1 & 0xFFffFFfc; + // First verify the effAddr path + if ( + !MIPSMemory.isValidProof( + state.memRoot, effAddr, MIPSMemory.memoryProofOffset(MEM_PROOF_OFFSET, 1) + ) + ) { + revert InvalidMemoryProof(); + } + // Recompute the new root after updating effAddr + state.memRoot = + MIPSMemory.writeMem(effAddr, MIPSMemory.memoryProofOffset(MEM_PROOF_OFFSET, 1), secs); + handleMemoryUpdate(state, effAddr); + // Verify the second memory proof against the newly computed root + if ( + !MIPSMemory.isValidProof( + state.memRoot, effAddr + 4, MIPSMemory.memoryProofOffset(MEM_PROOF_OFFSET, 2) + ) + ) { + revert InvalidSecondMemoryProof(); + } + state.memRoot = + MIPSMemory.writeMem(effAddr + 4, MIPSMemory.memoryProofOffset(MEM_PROOF_OFFSET, 2), nsecs); + handleMemoryUpdate(state, effAddr + 4); + } else { + v0 = sys.SYS_ERROR_SIGNAL; + v1 = sys.EINVAL; + } + } else if (syscall_no == sys.SYS_GETPID) { + v0 = 0; + v1 = 0; + } else if (syscall_no == sys.SYS_MUNMAP) { // ignored - } else if (syscall_no == sys.SYS_GET_AFFINITY) { + } else if (syscall_no == sys.SYS_GETAFFINITY) { // ignored } else if (syscall_no == sys.SYS_MADVISE) { // ignored @@ -441,10 +576,6 @@ contract MIPS2 is ISemver { // ignored } else if (syscall_no == sys.SYS_TIMERDELETE) { // ignored - } else if (syscall_no == sys.SYS_CLOCKGETTIME) { - // ignored - } else if (syscall_no == sys.SYS_MUNMAP) { - // ignored } else { revert("MIPS2: unimplemented syscall"); } @@ -458,9 +589,26 @@ contract MIPS2 is ISemver { } } + function execSysRead( + State memory _state, + sys.SysReadParams memory _args + ) + internal + view + returns (uint32 v0, uint32 v1) + { + bool memUpdated; + uint32 memAddr; + (v0, v1, _state.preimageOffset, _state.memRoot, memUpdated, memAddr) = sys.handleSysRead(_args); + if (memUpdated) { + handleMemoryUpdate(_state, memAddr); + } + } + /// @notice Computes the hash of the MIPS state. /// @return out_ The hashed MIPS state. function outputState() internal returns (bytes32 out_) { + uint32 exited; assembly { // copies 'size' bytes, right-aligned in word at 'from', to 'to', incl. trailing data function copyMem(from, to, size) -> fromOut, toOut { @@ -481,9 +629,12 @@ contract MIPS2 is ISemver { from, to := copyMem(from, to, 32) // preimageKey from, to := copyMem(from, to, 4) // preimageOffset from, to := copyMem(from, to, 4) // heap + from, to := copyMem(from, to, 1) // llReservationActive + from, to := copyMem(from, to, 4) // llAddress + from, to := copyMem(from, to, 4) // llOwnerThread let exitCode := mload(from) from, to := copyMem(from, to, 1) // exitCode - let exited := mload(from) + exited := mload(from) from, to := copyMem(from, to, 1) // exited from, to := copyMem(from, to, 8) // step from, to := copyMem(from, to, 8) // stepsSinceLastContextSwitch @@ -518,6 +669,8 @@ contract MIPS2 is ISemver { out_ := keccak256(start, sub(to, start)) out_ := or(and(not(shl(248, 0xFF)), out_), shl(248, status)) } + + st.assertExitedIsValid(exited); } /// @notice Updates the current thread stack root via inner thread root in calldata @@ -537,14 +690,8 @@ contract MIPS2 is ISemver { } /// @notice Completes the FUTEX_WAIT syscall. - function onWaitComplete( - State memory _state, - ThreadState memory _thread, - bool _isTimedOut - ) - internal - returns (bytes32 out_) - { + function onWaitComplete(ThreadState memory _thread, bool _isTimedOut) internal returns (bytes32 out_) { + // Note: no need to reset State.wakeup. If we're here, the wakeup field has already been reset // Clear the futex state _thread.futexAddr = sys.FUTEX_EMPTY_ADDR; _thread.futexVal = 0; @@ -558,7 +705,6 @@ contract MIPS2 is ISemver { sys.handleSyscallUpdates(cpu, _thread.registers, v0, v1); setStateCpuScalars(_thread, cpu); - _state.wakeup = sys.FUTEX_EMPTY_ADDR; updateCurrentThreadRoot(); out_ = outputState(); } diff --git a/packages/contracts-bedrock/src/cannon/PreimageOracle.sol b/packages/contracts-bedrock/src/cannon/PreimageOracle.sol index e144e43d8d4cd..c3fbc2b498adb 100644 --- a/packages/contracts-bedrock/src/cannon/PreimageOracle.sol +++ b/packages/contracts-bedrock/src/cannon/PreimageOracle.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.15; import { IPreimageOracle } from "./interfaces/IPreimageOracle.sol"; -import { ISemver } from "src/universal/ISemver.sol"; +import { ISemver } from "src/universal/interfaces/ISemver.sol"; import { PreimageKeyLib } from "./PreimageKeyLib.sol"; import { LibKeccak } from "@lib-keccak/LibKeccak.sol"; import "src/cannon/libraries/CannonErrors.sol"; @@ -31,8 +31,8 @@ contract PreimageOracle is IPreimageOracle, ISemver { uint256 public constant PRECOMPILE_CALL_RESERVED_GAS = 100_000; /// @notice The semantic version of the Preimage Oracle contract. - /// @custom:semver 1.1.2-rc.1 - string public constant version = "1.1.2-rc.1"; + /// @custom:semver 1.1.3-beta.2 + string public constant version = "1.1.3-beta.2"; //////////////////////////////////////////////////////////////// // Authorized Preimage Parts // diff --git a/packages/contracts-bedrock/src/cannon/interfaces/IMIPS.sol b/packages/contracts-bedrock/src/cannon/interfaces/IMIPS.sol index 97b3dc8ef2833..75f4e50f3ba31 100644 --- a/packages/contracts-bedrock/src/cannon/interfaces/IMIPS.sol +++ b/packages/contracts-bedrock/src/cannon/interfaces/IMIPS.sol @@ -1,12 +1,17 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.15; +pragma solidity ^0.8.0; -import { ISemver } from "src/universal/ISemver.sol"; +import { ISemver } from "src/universal/interfaces/ISemver.sol"; import { IPreimageOracle } from "src/cannon/interfaces/IPreimageOracle.sol"; /// @title IMIPS /// @notice Interface for the MIPS contract. interface IMIPS is ISemver { + error InvalidMemoryProof(); + error InvalidRMWInstruction(); + function oracle() external view returns (IPreimageOracle oracle_); function step(bytes memory _stateData, bytes memory _proof, bytes32 _localContext) external returns (bytes32); + + function __constructor__(IPreimageOracle _oracle) external; } diff --git a/packages/contracts-bedrock/src/cannon/interfaces/IMIPS2.sol b/packages/contracts-bedrock/src/cannon/interfaces/IMIPS2.sol index 540033433329e..8f57c0f636952 100644 --- a/packages/contracts-bedrock/src/cannon/interfaces/IMIPS2.sol +++ b/packages/contracts-bedrock/src/cannon/interfaces/IMIPS2.sol @@ -1,10 +1,19 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.15; +pragma solidity ^0.8.0; -import { ISemver } from "src/universal/ISemver.sol"; +import { ISemver } from "src/universal/interfaces/ISemver.sol"; +import { IPreimageOracle } from "src/cannon/interfaces/IPreimageOracle.sol"; /// @title IMIPS2 /// @notice Interface for the MIPS2 contract. interface IMIPS2 is ISemver { + error InvalidExitedValue(); + error InvalidMemoryProof(); + error InvalidSecondMemoryProof(); + error InvalidRMWInstruction(); + + function oracle() external view returns (IPreimageOracle oracle_); function step(bytes memory _stateData, bytes memory _proof, bytes32 _localContext) external returns (bytes32); + + function __constructor__(IPreimageOracle _oracle) external; } diff --git a/packages/contracts-bedrock/src/cannon/interfaces/IPreimageOracle.sol b/packages/contracts-bedrock/src/cannon/interfaces/IPreimageOracle.sol index 9f923fcfe8fc0..79ee56f821c93 100644 --- a/packages/contracts-bedrock/src/cannon/interfaces/IPreimageOracle.sol +++ b/packages/contracts-bedrock/src/cannon/interfaces/IPreimageOracle.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.15; +pragma solidity ^0.8.0; /// @title IPreimageOracle /// @notice Interface for a preimage oracle. diff --git a/packages/contracts-bedrock/src/cannon/libraries/CannonErrors.sol b/packages/contracts-bedrock/src/cannon/libraries/CannonErrors.sol index e45cbaf9d8de6..3649852cec6f2 100644 --- a/packages/contracts-bedrock/src/cannon/libraries/CannonErrors.sol +++ b/packages/contracts-bedrock/src/cannon/libraries/CannonErrors.sol @@ -54,3 +54,12 @@ error BondTransferFailed(); /// @notice Thrown when the value of the exited boolean is not 0 or 1. error InvalidExitedValue(); + +/// @notice Thrown when reading an invalid memory +error InvalidMemoryProof(); + +/// @notice Thrown when the second memory location is invalid +error InvalidSecondMemoryProof(); + +/// @notice Thrown when an RMW instruction is expected, but a different instruction is provided. +error InvalidRMWInstruction(); diff --git a/packages/contracts-bedrock/src/cannon/libraries/MIPSInstructions.sol b/packages/contracts-bedrock/src/cannon/libraries/MIPSInstructions.sol index 0652bea0d0e1f..a2402531c82d1 100644 --- a/packages/contracts-bedrock/src/cannon/libraries/MIPSInstructions.sol +++ b/packages/contracts-bedrock/src/cannon/libraries/MIPSInstructions.sol @@ -5,6 +5,26 @@ import { MIPSMemory } from "src/cannon/libraries/MIPSMemory.sol"; import { MIPSState as st } from "src/cannon/libraries/MIPSState.sol"; library MIPSInstructions { + uint32 internal constant OP_LOAD_LINKED = 0x30; + uint32 internal constant OP_STORE_CONDITIONAL = 0x38; + + struct CoreStepLogicParams { + /// @param opcode The opcode value parsed from insn_. + st.CpuScalars cpu; + /// @param registers The CPU registers. + uint32[32] registers; + /// @param memRoot The current merkle root of the memory. + bytes32 memRoot; + /// @param memProofOffset The offset in calldata specify where the memory merkle proof is located. + uint256 memProofOffset; + /// @param insn The current 32-bit instruction at the pc. + uint32 insn; + /// @param cpu The CPU scalar fields. + uint32 opcode; + /// @param fun The function value parsed from insn_. + uint32 fun; + } + /// @param _pc The program counter. /// @param _memRoot The current memory root. /// @param _insnProofOffset The calldata offset of the memory proof for the current instruction. @@ -30,91 +50,80 @@ library MIPSInstructions { } /// @notice Execute core MIPS step logic. - /// @notice _cpu The CPU scalar fields. - /// @notice _registers The CPU registers. - /// @notice _memRoot The current merkle root of the memory. - /// @notice _memProofOffset The offset in calldata specify where the memory merkle proof is located. - /// @param _insn The current 32-bit instruction at the pc. - /// @param _opcode The opcode value parsed from insn_. - /// @param _fun The function value parsed from insn_. /// @return newMemRoot_ The updated merkle root of memory after any modifications, may be unchanged. - function execMipsCoreStepLogic( - st.CpuScalars memory _cpu, - uint32[32] memory _registers, - bytes32 _memRoot, - uint256 _memProofOffset, - uint32 _insn, - uint32 _opcode, - uint32 _fun - ) + /// @return memUpdated_ True if memory was modified. + /// @return memAddr_ Holds the memory address that was updated if memUpdated_ is true. + function execMipsCoreStepLogic(CoreStepLogicParams memory _args) internal pure - returns (bytes32 newMemRoot_) + returns (bytes32 newMemRoot_, bool memUpdated_, uint32 memAddr_) { unchecked { - newMemRoot_ = _memRoot; + newMemRoot_ = _args.memRoot; + memUpdated_ = false; + memAddr_ = 0; // j-type j/jal - if (_opcode == 2 || _opcode == 3) { + if (_args.opcode == 2 || _args.opcode == 3) { // Take top 4 bits of the next PC (its 256 MB region), and concatenate with the 26-bit offset - uint32 target = (_cpu.nextPC & 0xF0000000) | (_insn & 0x03FFFFFF) << 2; - handleJump(_cpu, _registers, _opcode == 2 ? 0 : 31, target); - return newMemRoot_; + uint32 target = (_args.cpu.nextPC & 0xF0000000) | (_args.insn & 0x03FFFFFF) << 2; + handleJump(_args.cpu, _args.registers, _args.opcode == 2 ? 0 : 31, target); + return (newMemRoot_, memUpdated_, memAddr_); } // register fetch uint32 rs = 0; // source register 1 value uint32 rt = 0; // source register 2 / temp value - uint32 rtReg = (_insn >> 16) & 0x1F; + uint32 rtReg = (_args.insn >> 16) & 0x1F; // R-type or I-type (stores rt) - rs = _registers[(_insn >> 21) & 0x1F]; + rs = _args.registers[(_args.insn >> 21) & 0x1F]; uint32 rdReg = rtReg; - if (_opcode == 0 || _opcode == 0x1c) { + if (_args.opcode == 0 || _args.opcode == 0x1c) { // R-type (stores rd) - rt = _registers[rtReg]; - rdReg = (_insn >> 11) & 0x1F; - } else if (_opcode < 0x20) { + rt = _args.registers[rtReg]; + rdReg = (_args.insn >> 11) & 0x1F; + } else if (_args.opcode < 0x20) { // rt is SignExtImm // don't sign extend for andi, ori, xori - if (_opcode == 0xC || _opcode == 0xD || _opcode == 0xe) { + if (_args.opcode == 0xC || _args.opcode == 0xD || _args.opcode == 0xe) { // ZeroExtImm - rt = _insn & 0xFFFF; + rt = _args.insn & 0xFFFF; } else { // SignExtImm - rt = signExtend(_insn & 0xFFFF, 16); + rt = signExtend(_args.insn & 0xFFFF, 16); } - } else if (_opcode >= 0x28 || _opcode == 0x22 || _opcode == 0x26) { + } else if (_args.opcode >= 0x28 || _args.opcode == 0x22 || _args.opcode == 0x26) { // store rt value with store - rt = _registers[rtReg]; + rt = _args.registers[rtReg]; // store actual rt with lwl and lwr rdReg = rtReg; } - if ((_opcode >= 4 && _opcode < 8) || _opcode == 1) { + if ((_args.opcode >= 4 && _args.opcode < 8) || _args.opcode == 1) { handleBranch({ - _cpu: _cpu, - _registers: _registers, - _opcode: _opcode, - _insn: _insn, + _cpu: _args.cpu, + _registers: _args.registers, + _opcode: _args.opcode, + _insn: _args.insn, _rtReg: rtReg, _rs: rs }); - return newMemRoot_; + return (newMemRoot_, memUpdated_, memAddr_); } uint32 storeAddr = 0xFF_FF_FF_FF; // memory fetch (all I-type) // we do the load for stores also uint32 mem = 0; - if (_opcode >= 0x20) { + if (_args.opcode >= 0x20) { // M[R[rs]+SignExtImm] - rs += signExtend(_insn & 0xFFFF, 16); + rs += signExtend(_args.insn & 0xFFFF, 16); uint32 addr = rs & 0xFFFFFFFC; - mem = MIPSMemory.readMem(_memRoot, addr, _memProofOffset); - if (_opcode >= 0x28 && _opcode != 0x30) { + mem = MIPSMemory.readMem(_args.memRoot, addr, _args.memProofOffset); + if (_args.opcode >= 0x28) { // store storeAddr = addr; // store opcodes don't write back to a register @@ -124,49 +133,58 @@ library MIPSInstructions { // ALU // Note: swr outputs more than 4 bytes without the mask 0xffFFffFF - uint32 val = executeMipsInstruction(_insn, _opcode, _fun, rs, rt, mem) & 0xffFFffFF; + uint32 val = executeMipsInstruction(_args.insn, _args.opcode, _args.fun, rs, rt, mem) & 0xffFFffFF; - if (_opcode == 0 && _fun >= 8 && _fun < 0x1c) { - if (_fun == 8 || _fun == 9) { + if (_args.opcode == 0 && _args.fun >= 8 && _args.fun < 0x1c) { + if (_args.fun == 8 || _args.fun == 9) { // jr/jalr - handleJump(_cpu, _registers, _fun == 8 ? 0 : rdReg, rs); - return newMemRoot_; + handleJump(_args.cpu, _args.registers, _args.fun == 8 ? 0 : rdReg, rs); + return (newMemRoot_, memUpdated_, memAddr_); } - if (_fun == 0xa) { + if (_args.fun == 0xa) { // movz - handleRd(_cpu, _registers, rdReg, rs, rt == 0); - return newMemRoot_; + handleRd(_args.cpu, _args.registers, rdReg, rs, rt == 0); + return (newMemRoot_, memUpdated_, memAddr_); } - if (_fun == 0xb) { + if (_args.fun == 0xb) { // movn - handleRd(_cpu, _registers, rdReg, rs, rt != 0); - return newMemRoot_; + handleRd(_args.cpu, _args.registers, rdReg, rs, rt != 0); + return (newMemRoot_, memUpdated_, memAddr_); } // lo and hi registers // can write back - if (_fun >= 0x10 && _fun < 0x1c) { - handleHiLo({ _cpu: _cpu, _registers: _registers, _fun: _fun, _rs: rs, _rt: rt, _storeReg: rdReg }); - - return newMemRoot_; + if (_args.fun >= 0x10 && _args.fun < 0x1c) { + handleHiLo({ + _cpu: _args.cpu, + _registers: _args.registers, + _fun: _args.fun, + _rs: rs, + _rt: rt, + _storeReg: rdReg + }); + return (newMemRoot_, memUpdated_, memAddr_); } } - // stupid sc, write a 1 to rt - if (_opcode == 0x38 && rtReg != 0) { - _registers[rtReg] = 1; - } - // write memory if (storeAddr != 0xFF_FF_FF_FF) { - newMemRoot_ = MIPSMemory.writeMem(storeAddr, _memProofOffset, val); + newMemRoot_ = MIPSMemory.writeMem(storeAddr, _args.memProofOffset, val); + memUpdated_ = true; + memAddr_ = storeAddr; } // write back the value to destination register - handleRd(_cpu, _registers, rdReg, val, true); + handleRd(_args.cpu, _args.registers, rdReg, val, true); - return newMemRoot_; + return (newMemRoot_, memUpdated_, memAddr_); + } + } + + function signExtendImmediate(uint32 _insn) internal pure returns (uint32 offset_) { + unchecked { + return signExtend(_insn & 0xFFFF, 16); } } @@ -417,14 +435,6 @@ library MIPSInstructions { uint32 val = _rt << (24 - (_rs & 3) * 8); uint32 mask = uint32(0xFFFFFFFF) << (24 - (_rs & 3) * 8); return (_mem & ~mask) | val; - } - // ll - else if (_opcode == 0x30) { - return _mem; - } - // sc - else if (_opcode == 0x38) { - return _rt; } else { revert("invalid instruction"); } diff --git a/packages/contracts-bedrock/src/cannon/libraries/MIPSMemory.sol b/packages/contracts-bedrock/src/cannon/libraries/MIPSMemory.sol index 12106ed23ecc1..e88f51438ef48 100644 --- a/packages/contracts-bedrock/src/cannon/libraries/MIPSMemory.sol +++ b/packages/contracts-bedrock/src/cannon/libraries/MIPSMemory.sol @@ -1,6 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +import "src/cannon/libraries/CannonErrors.sol"; + library MIPSMemory { /// @notice Reads a 32-bit value from memory. /// @param _memRoot The current memory root @@ -8,6 +10,28 @@ library MIPSMemory { /// @param _proofOffset The offset of the memory proof in calldata. /// @return out_ The hashed MIPS state. function readMem(bytes32 _memRoot, uint32 _addr, uint256 _proofOffset) internal pure returns (uint32 out_) { + bool valid; + (out_, valid) = readMemUnchecked(_memRoot, _addr, _proofOffset); + if (!valid) { + revert InvalidMemoryProof(); + } + } + + /// @notice Reads a 32-bit value from memory. + /// @param _memRoot The current memory root + /// @param _addr The address to read from. + /// @param _proofOffset The offset of the memory proof in calldata. + /// @return out_ The hashed MIPS state. + /// valid_ Whether the proof is valid. + function readMemUnchecked( + bytes32 _memRoot, + uint32 _addr, + uint256 _proofOffset + ) + internal + pure + returns (uint32 out_, bool valid_) + { unchecked { validateMemoryProofAvailability(_proofOffset); assembly { @@ -38,14 +62,12 @@ library MIPSMemory { } // Verify the root matches. - if iszero(eq(node, _memRoot)) { - mstore(0, 0x0badf00d) - revert(0, 32) + valid_ := eq(node, _memRoot) + if valid_ { + // Bits to shift = (32 - 4 - (addr % 32)) * 8 + let shamt := shl(3, sub(sub(32, 4), and(_addr, 31))) + out_ := and(shr(shamt, leaf), 0xFFffFFff) } - - // Bits to shift = (32 - 4 - (addr % 32)) * 8 - let shamt := shl(3, sub(sub(32, 4), and(_addr, 31))) - out_ := and(shr(shamt, leaf), 0xFFffFFff) } } } @@ -97,6 +119,15 @@ library MIPSMemory { } } + /// @notice Verifies a memory proof. + /// @param _memRoot The expected memory root + /// @param _addr The _addr proven. + /// @param _proofOffset The offset of the memory proof in calldata. + /// @return valid_ True iff it is a valid proof. + function isValidProof(bytes32 _memRoot, uint32 _addr, uint256 _proofOffset) internal pure returns (bool valid_) { + (, valid_) = readMemUnchecked(_memRoot, _addr, _proofOffset); + } + /// @notice Computes the offset of a memory proof in the calldata. /// @param _proofDataOffset The offset of the set of all memory proof data within calldata (proof.offset) /// Equal to the offset of the first memory proof (at _proofIndex 0). diff --git a/packages/contracts-bedrock/src/cannon/libraries/MIPSState.sol b/packages/contracts-bedrock/src/cannon/libraries/MIPSState.sol index d4431765c5b0c..2f76a2e0dda5d 100644 --- a/packages/contracts-bedrock/src/cannon/libraries/MIPSState.sol +++ b/packages/contracts-bedrock/src/cannon/libraries/MIPSState.sol @@ -1,6 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +import { InvalidExitedValue } from "src/cannon/libraries/CannonErrors.sol"; + library MIPSState { struct CpuScalars { uint32 pc; @@ -8,4 +10,10 @@ library MIPSState { uint32 lo; uint32 hi; } + + function assertExitedIsValid(uint32 exited) internal pure { + if (exited > 1) { + revert InvalidExitedValue(); + } + } } diff --git a/packages/contracts-bedrock/src/cannon/libraries/MIPSSyscalls.sol b/packages/contracts-bedrock/src/cannon/libraries/MIPSSyscalls.sol index f12f9b789a234..a835b6feef586 100644 --- a/packages/contracts-bedrock/src/cannon/libraries/MIPSSyscalls.sol +++ b/packages/contracts-bedrock/src/cannon/libraries/MIPSSyscalls.sol @@ -41,9 +41,10 @@ library MIPSSyscalls { uint32 internal constant SYS_FUTEX = 4238; uint32 internal constant SYS_OPEN = 4005; uint32 internal constant SYS_NANOSLEEP = 4166; + uint32 internal constant SYS_CLOCKGETTIME = 4263; + uint32 internal constant SYS_GETPID = 4020; // unused syscalls - uint32 internal constant SYS_CLOCK_GETTIME = 4263; - uint32 internal constant SYS_GET_AFFINITY = 4240; + uint32 internal constant SYS_MUNMAP = 4091; uint32 internal constant SYS_GETAFFINITY = 4240; uint32 internal constant SYS_MADVISE = 4218; uint32 internal constant SYS_RTSIGPROCMASK = 4195; @@ -69,13 +70,12 @@ library MIPSSyscalls { uint32 internal constant SYS_LLSEEK = 4140; uint32 internal constant SYS_MINCORE = 4217; uint32 internal constant SYS_TGKILL = 4266; + // profiling-related syscalls - ignored uint32 internal constant SYS_SETITIMER = 4104; uint32 internal constant SYS_TIMERCREATE = 4257; uint32 internal constant SYS_TIMERSETTIME = 4258; uint32 internal constant SYS_TIMERDELETE = 4261; - uint32 internal constant SYS_CLOCKGETTIME = 4263; - uint32 internal constant SYS_MUNMAP = 4091; uint32 internal constant FD_STDIN = 0; uint32 internal constant FD_STDOUT = 1; @@ -98,6 +98,9 @@ library MIPSSyscalls { uint32 internal constant FUTEX_EMPTY_ADDR = 0xFF_FF_FF_FF; uint32 internal constant SCHED_QUANTUM = 100_000; + uint32 internal constant HZ = 10_000_000; + uint32 internal constant CLOCK_GETTIME_REALTIME_FLAG = 0; + uint32 internal constant CLOCK_GETTIME_MONOTONIC_FLAG = 1; /// @notice Start of the data segment. uint32 internal constant PROGRAM_BREAK = 0x40000000; uint32 internal constant HEAP_END = 0x60000000; @@ -199,13 +202,22 @@ library MIPSSyscalls { function handleSysRead(SysReadParams memory _args) internal view - returns (uint32 v0_, uint32 v1_, uint32 newPreimageOffset_, bytes32 newMemRoot_) + returns ( + uint32 v0_, + uint32 v1_, + uint32 newPreimageOffset_, + bytes32 newMemRoot_, + bool memUpdated_, + uint32 memAddr_ + ) { unchecked { v0_ = uint32(0); v1_ = uint32(0); newMemRoot_ = _args.memRoot; newPreimageOffset_ = _args.preimageOffset; + memUpdated_ = false; + memAddr_ = 0; // args: _a0 = fd, _a1 = addr, _a2 = count // returns: v0_ = read, v1_ = err code @@ -214,9 +226,10 @@ library MIPSSyscalls { } // pre-image oracle read else if (_args.a0 == FD_PREIMAGE_READ) { + uint32 effAddr = _args.a1 & 0xFFffFFfc; // verify proof is correct, and get the existing memory. // mask the addr to align it to 4 bytes - uint32 mem = MIPSMemory.readMem(_args.memRoot, _args.a1 & 0xFFffFFfc, _args.proofOffset); + uint32 mem = MIPSMemory.readMem(_args.memRoot, effAddr, _args.proofOffset); // If the preimage key is a local key, localize it in the context of the caller. if (uint8(_args.preimageKey[0]) == 1) { _args.preimageKey = PreimageKeyLib.localize(_args.preimageKey, _args.localContext); @@ -243,7 +256,9 @@ library MIPSSyscalls { } // Write memory back - newMemRoot_ = MIPSMemory.writeMem(_args.a1 & 0xFFffFFfc, _args.proofOffset, mem); + newMemRoot_ = MIPSMemory.writeMem(effAddr, _args.proofOffset, mem); + memUpdated_ = true; + memAddr_ = effAddr; newPreimageOffset_ += uint32(datLen); v0_ = uint32(datLen); } @@ -257,7 +272,7 @@ library MIPSSyscalls { v1_ = EBADF; } - return (v0_, v1_, newPreimageOffset_, newMemRoot_); + return (v0_, v1_, newPreimageOffset_, newMemRoot_, memUpdated_, memAddr_); } } diff --git a/packages/contracts-bedrock/src/dispute/AnchorStateRegistry.sol b/packages/contracts-bedrock/src/dispute/AnchorStateRegistry.sol index 244dc5f60473f..5486d83f76847 100644 --- a/packages/contracts-bedrock/src/dispute/AnchorStateRegistry.sol +++ b/packages/contracts-bedrock/src/dispute/AnchorStateRegistry.sol @@ -1,25 +1,28 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Contracts 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 { SuperchainConfig } from "src/L1/SuperchainConfig.sol"; +// Libraries import "src/dispute/lib/Types.sol"; import { Unauthorized } from "src/libraries/errors/CommonErrors.sol"; import { UnregisteredGame, InvalidGameStatus } from "src/dispute/lib/Errors.sol"; +// Interfaces +import { ISemver } from "src/universal/interfaces/ISemver.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 { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol"; + +/// @custom:proxied true /// @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 { +contract AnchorStateRegistry is Initializable, ISemver { /// @notice Describes an initial anchor state for a game type. struct StartingAnchorRoot { GameType gameType; @@ -27,17 +30,17 @@ contract AnchorStateRegistry is Initializable, IAnchorStateRegistry, ISemver { } /// @notice Semantic version. - /// @custom:semver 2.0.0-rc.1 - string public constant version = "2.0.0-rc.1"; + /// @custom:semver 2.0.1-beta.3 + string public constant version = "2.0.1-beta.3"; /// @notice DisputeGameFactory address. IDisputeGameFactory internal immutable DISPUTE_GAME_FACTORY; - /// @inheritdoc IAnchorStateRegistry + /// @notice Returns the anchor state for the given game type. mapping(GameType => OutputRoot) public anchors; /// @notice Address of the SuperchainConfig contract. - SuperchainConfig public superchainConfig; + ISuperchainConfig public superchainConfig; /// @param _disputeGameFactory DisputeGameFactory address. constructor(IDisputeGameFactory _disputeGameFactory) { @@ -50,7 +53,7 @@ contract AnchorStateRegistry is Initializable, IAnchorStateRegistry, ISemver { /// @param _superchainConfig The address of the SuperchainConfig contract. function initialize( StartingAnchorRoot[] memory _startingAnchorRoots, - SuperchainConfig _superchainConfig + ISuperchainConfig _superchainConfig ) public initializer @@ -62,12 +65,15 @@ contract AnchorStateRegistry is Initializable, IAnchorStateRegistry, ISemver { superchainConfig = _superchainConfig; } - /// @inheritdoc IAnchorStateRegistry + /// @notice Returns the DisputeGameFactory address. + /// @return DisputeGameFactory address. function disputeGameFactory() external view returns (IDisputeGameFactory) { return DISPUTE_GAME_FACTORY; } - /// @inheritdoc IAnchorStateRegistry + /// @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 { // Grab the game and game data. IFaultDisputeGame game = IFaultDisputeGame(msg.sender); @@ -95,7 +101,8 @@ contract AnchorStateRegistry is Initializable, IAnchorStateRegistry, ISemver { anchors[gameType] = OutputRoot({ l2BlockNumber: game.l2BlockNumber(), root: Hash.wrap(game.rootClaim().raw()) }); } - /// @inheritdoc IAnchorStateRegistry + /// @notice Sets the anchor state given the game. + /// @param _game The game to set the anchor state for. function setAnchorState(IFaultDisputeGame _game) external { if (msg.sender != superchainConfig.guardian()) revert Unauthorized(); diff --git a/packages/contracts-bedrock/src/dispute/weth/DelayedWETH.sol b/packages/contracts-bedrock/src/dispute/DelayedWETH.sol similarity index 64% rename from packages/contracts-bedrock/src/dispute/weth/DelayedWETH.sol rename to packages/contracts-bedrock/src/dispute/DelayedWETH.sol index 96cc0cf55e3b4..42b6022d12fe4 100644 --- a/packages/contracts-bedrock/src/dispute/weth/DelayedWETH.sol +++ b/packages/contracts-bedrock/src/dispute/DelayedWETH.sol @@ -1,15 +1,15 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Contracts import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; -import { ISemver } from "src/universal/ISemver.sol"; +import { WETH98 } from "src/universal/WETH98.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"; +// Interfaces +import { ISemver } from "src/universal/interfaces/ISemver.sol"; +import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol"; +/// @custom:proxied true /// @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 @@ -19,41 +19,55 @@ import { SuperchainConfig } from "src/L1/SuperchainConfig.sol"; /// 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 { +contract DelayedWETH is OwnableUpgradeable, WETH98, ISemver { + /// @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 Semantic version. - /// @custom:semver 1.1.0-rc.1 - string public constant version = "1.1.0-rc.1"; + /// @custom:semver 1.2.0-beta.2 + string public constant version = "1.2.0-beta.2"; - /// @inheritdoc IDelayedWETH + /// @notice Returns a withdrawal request for the given address. 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; + ISuperchainConfig public config; /// @param _delay The delay for withdrawals in seconds. constructor(uint256 _delay) { DELAY_SECONDS = _delay; - initialize({ _owner: address(0), _config: SuperchainConfig(address(0)) }); + initialize({ _owner: address(0), _config: ISuperchainConfig(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 { + function initialize(address _owner, ISuperchainConfig _config) public initializer { __Ownable_init(); _transferOwnership(_owner); config = _config; } - /// @inheritdoc IDelayedWETH + /// @notice Returns the withdrawal delay in seconds. + /// @return The withdrawal delay in seconds. function delay() external view returns (uint256) { return DELAY_SECONDS; } - /// @inheritdoc IDelayedWETH + /// @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 { // 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 @@ -65,12 +79,15 @@ contract DelayedWETH is OwnableUpgradeable, WETH98, IDelayedWETH, ISemver { wd.amount += _wad; } - /// @inheritdoc IWETH - function withdraw(uint256 _wad) public override(WETH98, IWETH) { + /// @notice Withdraws an amount of ETH. + /// @param _wad The amount of ETH to withdraw. + function withdraw(uint256 _wad) public override { withdraw(msg.sender, _wad); } - /// @inheritdoc IDelayedWETH + /// @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) public { require(!config.paused(), "DelayedWETH: contract is paused"); WithdrawalRequest storage wd = withdrawals[msg.sender][_guy]; @@ -81,7 +98,8 @@ contract DelayedWETH is OwnableUpgradeable, WETH98, IDelayedWETH, ISemver { super.withdraw(_wad); } - /// @inheritdoc IDelayedWETH + /// @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 { require(msg.sender == owner(), "DelayedWETH: not owner"); uint256 amount = _wad < address(this).balance ? _wad : address(this).balance; @@ -89,7 +107,9 @@ contract DelayedWETH is OwnableUpgradeable, WETH98, IDelayedWETH, ISemver { require(success, "DelayedWETH: recover failed"); } - /// @inheritdoc IDelayedWETH + /// @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 { require(msg.sender == owner(), "DelayedWETH: not owner"); allowance[_guy][msg.sender] = _wad; diff --git a/packages/contracts-bedrock/src/dispute/DisputeGameFactory.sol b/packages/contracts-bedrock/src/dispute/DisputeGameFactory.sol index 55d25abb9224e..dee8dd75ec600 100644 --- a/packages/contracts-bedrock/src/dispute/DisputeGameFactory.sol +++ b/packages/contracts-bedrock/src/dispute/DisputeGameFactory.sol @@ -1,33 +1,62 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { LibClone } from "@solady/utils/LibClone.sol"; +// Contracts import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; -import { ISemver } from "src/universal/ISemver.sol"; - -import { IDisputeGame } from "src/dispute/interfaces/IDisputeGame.sol"; -import { IDisputeGameFactory } from "src/dispute/interfaces/IDisputeGameFactory.sol"; +// Libraries +import { LibClone } from "@solady/utils/LibClone.sol"; import "src/dispute/lib/Types.sol"; import "src/dispute/lib/Errors.sol"; +// Interfaces +import { ISemver } from "src/universal/interfaces/ISemver.sol"; +import { IDisputeGame } from "src/dispute/interfaces/IDisputeGame.sol"; + +/// @custom:proxied true /// @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 to make offchain discoverability of playable /// dispute games easier. -contract DisputeGameFactory is OwnableUpgradeable, IDisputeGameFactory, ISemver { +contract DisputeGameFactory is OwnableUpgradeable, ISemver { /// @dev Allows for the creation of clone proxies with immutable arguments. using LibClone for address; + /// @notice Emitted when a new dispute game is created + /// @param disputeProxy The address of the dispute game proxy + /// @param gameType The type of the dispute game proxy's implementation + /// @param rootClaim The root claim of the dispute game + event DisputeGameCreated(address indexed disputeProxy, GameType indexed gameType, Claim indexed rootClaim); + + /// @notice Emitted when a new game implementation added to the factory + /// @param impl The implementation contract for the given `GameType`. + /// @param gameType The type of the DisputeGame. + event ImplementationSet(address indexed impl, GameType indexed gameType); + + /// @notice Emitted when a game type's initialization bond is updated + /// @param gameType The type of the DisputeGame. + /// @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 Semantic version. - /// @custom:semver 1.0.0 - string public constant version = "1.0.0"; + /// @custom:semver 1.0.1-beta.2 + string public constant version = "1.0.1-beta.2"; - /// @inheritdoc IDisputeGameFactory + /// @notice `gameImpls` is a mapping that maps `GameType`s to their respective + /// `IDisputeGame` implementations. mapping(GameType => IDisputeGame) public gameImpls; - /// @inheritdoc IDisputeGameFactory + /// @notice Returns the required bonds for initializing a dispute game of the given type. mapping(GameType => uint256) public initBonds; /// @notice Mapping of a hash of `gameType || rootClaim || extraData` to the deployed `IDisputeGame` clone (where @@ -50,12 +79,21 @@ contract DisputeGameFactory is OwnableUpgradeable, IDisputeGameFactory, ISemver _transferOwnership(_owner); } - /// @inheritdoc IDisputeGameFactory + /// @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_) { gameCount_ = _disputeGameList.length; } - /// @inheritdoc IDisputeGameFactory + /// @notice `games` queries an internal mapping that maps the hash of + /// `gameType ++ rootClaim ++ extraData` to the deployed `DisputeGame` clone. + /// @dev `++` equates to concatenation. + /// @param _gameType The type of the DisputeGame - used to decide the proxy implementation + /// @param _rootClaim The root claim of the DisputeGame. + /// @param _extraData Any extra data that should be provided to the created dispute game. + /// @return proxy_ The clone of the `DisputeGame` created with the given parameters. + /// Returns `address(0)` if nonexistent. + /// @return timestamp_ The timestamp of the creation of the dispute game. function games( GameType _gameType, Claim _rootClaim, @@ -70,7 +108,13 @@ contract DisputeGameFactory is OwnableUpgradeable, IDisputeGameFactory, ISemver (proxy_, timestamp_) = (IDisputeGame(proxy), timestamp); } - /// @inheritdoc IDisputeGameFactory + /// @notice `gameAtIndex` returns the dispute game contract address and its creation timestamp + /// at the given index. Each created dispute game increments the underlying index. + /// @param _index The index of the dispute game. + /// @return gameType_ The type of the DisputeGame - used to decide the proxy implementation. + /// @return timestamp_ The timestamp of the creation of the dispute game. + /// @return proxy_ The clone of the `DisputeGame` created with the given parameters. + /// Returns `address(0)` if nonexistent. function gameAtIndex(uint256 _index) external view @@ -80,7 +124,11 @@ contract DisputeGameFactory is OwnableUpgradeable, IDisputeGameFactory, ISemver (gameType_, timestamp_, proxy_) = (gameType, timestamp, IDisputeGame(proxy)); } - /// @inheritdoc IDisputeGameFactory + /// @notice Creates a new DisputeGame proxy contract. + /// @param _gameType The type of the DisputeGame - used to decide the proxy implementation. + /// @param _rootClaim The root claim of the DisputeGame. + /// @param _extraData Any extra data that should be provided to the created dispute game. + /// @return proxy_ The address of the created DisputeGame proxy. function create( GameType _gameType, Claim _rootClaim, @@ -131,7 +179,13 @@ contract DisputeGameFactory is OwnableUpgradeable, IDisputeGameFactory, ISemver emit DisputeGameCreated(address(proxy_), _gameType, _rootClaim); } - /// @inheritdoc IDisputeGameFactory + /// @notice Returns a unique identifier for the given dispute game parameters. + /// @dev Hashes the concatenation of `gameType . rootClaim . extraData` + /// without expanding memory. + /// @param _gameType The type of the DisputeGame. + /// @param _rootClaim The root claim of the DisputeGame. + /// @param _extraData Any extra data that should be provided to the created dispute game. + /// @return uuid_ The unique identifier for the given dispute game parameters. function getGameUUID( GameType _gameType, Claim _rootClaim, @@ -144,7 +198,11 @@ contract DisputeGameFactory is OwnableUpgradeable, IDisputeGameFactory, ISemver uuid_ = Hash.wrap(keccak256(abi.encode(_gameType, _rootClaim, _extraData))); } - /// @inheritdoc IDisputeGameFactory + /// @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, @@ -195,13 +253,19 @@ contract DisputeGameFactory is OwnableUpgradeable, IDisputeGameFactory, ISemver } } - /// @inheritdoc IDisputeGameFactory + /// @notice Sets the implementation contract for a specific `GameType`. + /// @dev May only be called by the `owner`. + /// @param _gameType The type of the DisputeGame. + /// @param _impl The implementation contract for the given `GameType`. function setImplementation(GameType _gameType, IDisputeGame _impl) external onlyOwner { gameImpls[_gameType] = _impl; emit ImplementationSet(address(_impl), _gameType); } - /// @inheritdoc IDisputeGameFactory + /// @notice Sets the bond (in wei) for initializing a game type. + /// @dev May only be called by the `owner`. + /// @param _gameType The type of the DisputeGame. + /// @param _initBond The bond (in wei) for initializing a game type. function setInitBond(GameType _gameType, uint256 _initBond) external onlyOwner { initBonds[_gameType] = _initBond; emit InitBondUpdated(_gameType, _initBond); diff --git a/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol b/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol index d9153a0b76010..a11cdd9be0c86 100644 --- a/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol +++ b/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol @@ -1,29 +1,63 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { FixedPointMathLib } from "@solady/utils/FixedPointMathLib.sol"; +// Libraries import { Math } from "@openzeppelin/contracts/utils/math/Math.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 { FixedPointMathLib } from "@solady/utils/FixedPointMathLib.sol"; import { Clone } from "@solady/utils/Clone.sol"; -import { Types } from "src/libraries/Types.sol"; -import { ISemver } from "src/universal/ISemver.sol"; - import { Types } from "src/libraries/Types.sol"; import { Hashing } from "src/libraries/Hashing.sol"; import { RLPReader } from "src/libraries/rlp/RLPReader.sol"; import "src/dispute/lib/Types.sol"; import "src/dispute/lib/Errors.sol"; +// Interfaces +import { ISemver } from "src/universal/interfaces/ISemver.sol"; +import { IDelayedWETH } from "src/dispute/interfaces/IDelayedWETH.sol"; +import { IDisputeGame } from "src/dispute/interfaces/IDisputeGame.sol"; +import { IBigStepper, IPreimageOracle } from "src/dispute/interfaces/IBigStepper.sol"; +import { IAnchorStateRegistry } from "src/dispute/interfaces/IAnchorStateRegistry.sol"; + /// @title FaultDisputeGame /// @notice An implementation of the `IFaultDisputeGame` interface. -contract FaultDisputeGame is IFaultDisputeGame, Clone, ISemver { +contract FaultDisputeGame is Clone, ISemver { + //////////////////////////////////////////////////////////////// + // Structs // + //////////////////////////////////////////////////////////////// + + /// @notice The `ClaimData` struct represents the data associated with a Claim. + struct ClaimData { + uint32 parentIndex; + address counteredBy; + address claimant; + uint128 bond; + Claim claim; + Position position; + Clock clock; + } + + /// @notice The `ResolutionCheckpoint` struct represents the data associated with an in-progress claim resolution. + struct ResolutionCheckpoint { + bool initialCheckpointComplete; + uint32 subgameIndex; + Position leftmostPosition; + address counteredBy; + } + + //////////////////////////////////////////////////////////////// + // Events // + //////////////////////////////////////////////////////////////// + + /// @notice Emitted when the game is resolved. + /// @param status The status of the game after resolution. + event Resolved(GameStatus indexed status); + + /// @notice Emitted when a new claim is added to the DAG by `claimant` + /// @param parentIndex The index within the `claimData` array of the parent claim + /// @param claim The claim being added + /// @param claimant The address of the claimant + event Move(uint256 indexed parentIndex, Claim indexed claim, address indexed claimant); + //////////////////////////////////////////////////////////////// // State Vars // //////////////////////////////////////////////////////////////// @@ -70,8 +104,8 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, ISemver { uint256 internal constant HEADER_BLOCK_NUMBER_INDEX = 8; /// @notice Semantic version. - /// @custom:semver 1.3.0-rc.1 - string public constant version = "1.3.0-rc.1"; + /// @custom:semver 1.3.1-beta.3 + string public constant version = "1.3.1-beta.3"; /// @notice The starting timestamp of the game Timestamp public createdAt; @@ -79,7 +113,7 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, ISemver { /// @notice The timestamp of the game's global resolution. Timestamp public resolvedAt; - /// @inheritdoc IDisputeGame + /// @notice Returns the current status of the game. GameStatus public status; /// @notice Flag for the `initialize` function to prevent re-initialization. @@ -178,7 +212,8 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, ISemver { L2_CHAIN_ID = _l2ChainId; } - /// @inheritdoc IInitializable + /// @notice Initializes the contract. + /// @dev This function may only be called once. function initialize() public payable virtual { // SAFETY: Any revert in this function will bubble up to the DisputeGameFactory and // prevent the game from being created. @@ -255,7 +290,17 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, ISemver { // `IFaultDisputeGame` impl // //////////////////////////////////////////////////////////////// - /// @inheritdoc IFaultDisputeGame + /// @notice Perform an instruction step via an on-chain fault proof processor. + /// @dev This function should point to a fault proof processor in order to execute + /// a step in the fault proof program on-chain. The interface of the fault proof + /// processor contract should adhere to the `IBigStepper` interface. + /// @param _claimIndex The index of the challenged claim within `claimData`. + /// @param _isAttack Whether or not the step is an attack or a defense. + /// @param _stateData The stateData of the step is the preimage of the claim at the given + /// prestate, which is at `_stateIndex` if the move is an attack and `_claimIndex` if + /// the move is a defense. If the step is an attack on the first instruction, it is + /// the absolute prestate of the fault proof VM. + /// @param _proof Proof to access memory nodes in the VM's merkle state tree. function step( uint256 _claimIndex, bool _isAttack, @@ -452,17 +497,28 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, ISemver { emit Move(_challengeIndex, _claim, msg.sender); } - /// @inheritdoc IFaultDisputeGame + /// @notice Attack a disagreed upon `Claim`. + /// @param _disputed The `Claim` being attacked. + /// @param _parentIndex Index of the `Claim` to attack in the `claimData` array. This must match the `_disputed` + /// claim. + /// @param _claim The `Claim` at the relative attack position. function attack(Claim _disputed, uint256 _parentIndex, Claim _claim) external payable { move(_disputed, _parentIndex, _claim, true); } - /// @inheritdoc IFaultDisputeGame + /// @notice Defend an agreed upon `Claim`. + /// @notice _disputed The `Claim` being defended. + /// @param _parentIndex Index of the claim to defend in the `claimData` array. This must match the `_disputed` + /// claim. + /// @param _claim The `Claim` at the relative defense position. function defend(Claim _disputed, uint256 _parentIndex, Claim _claim) external payable { move(_disputed, _parentIndex, _claim, false); } - /// @inheritdoc IFaultDisputeGame + /// @notice Posts the requested local data to the VM's `PreimageOralce`. + /// @param _ident The local identifier of the data to post. + /// @param _execLeafIdx The index of the leaf claim in an execution subgame that requires the local data for a step. + /// @param _partOffset The offset of the data to post. function addLocalData(uint256 _ident, uint256 _execLeafIdx, uint256 _partOffset) external { // INVARIANT: Local data can only be added if the game is currently in progress. if (status != GameStatus.IN_PROGRESS) revert GameNotInProgress(); @@ -501,7 +557,10 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, ISemver { } } - /// @inheritdoc IFaultDisputeGame + /// @notice Returns the number of children that still need to be resolved in order to fully resolve a subgame rooted + /// at `_claimIndex`. + /// @param _claimIndex The subgame root claim's index within `claimData`. + /// @return numRemainingChildren_ The number of children that still need to be checked to resolve the subgame. function getNumToResolve(uint256 _claimIndex) public view returns (uint256 numRemainingChildren_) { ResolutionCheckpoint storage checkpoint = resolutionCheckpoints[_claimIndex]; uint256[] storage challengeIndices = subgames[_claimIndex]; @@ -510,17 +569,17 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, ISemver { numRemainingChildren_ = challengeIndicesLen - checkpoint.subgameIndex; } - /// @inheritdoc IFaultDisputeGame + /// @notice The l2BlockNumber of the disputed output root in the `L2OutputOracle`. function l2BlockNumber() public pure returns (uint256 l2BlockNumber_) { l2BlockNumber_ = _getArgUint256(0x54); } - /// @inheritdoc IFaultDisputeGame + /// @notice Only the starting block number of the game. function startingBlockNumber() external view returns (uint256 startingBlockNumber_) { startingBlockNumber_ = startingOutputRoot.l2BlockNumber; } - /// @inheritdoc IFaultDisputeGame + /// @notice Starting output root and block number of the game. function startingRootHash() external view returns (Hash startingRootHash_) { startingRootHash_ = startingOutputRoot.root; } @@ -577,7 +636,12 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, ISemver { // `IDisputeGame` impl // //////////////////////////////////////////////////////////////// - /// @inheritdoc IDisputeGame + /// @notice If all necessary information has been gathered, this function should mark the game + /// status as either `CHALLENGER_WINS` or `DEFENDER_WINS` and return the status of + /// the resolved game. It is at this stage that the bonds should be awarded to the + /// necessary parties. + /// @dev May only be called if the `status` is `IN_PROGRESS`. + /// @return status_ The status of the game after resolution. function resolve() external returns (GameStatus status_) { // INVARIANT: Resolution cannot occur unless the game is currently in progress. if (status != GameStatus.IN_PROGRESS) revert GameNotInProgress(); @@ -596,7 +660,17 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, ISemver { ANCHOR_STATE_REGISTRY.tryUpdateAnchorState(); } - /// @inheritdoc IFaultDisputeGame + /// @notice Resolves the subgame rooted at the given claim index. `_numToResolve` specifies how many children of + /// the subgame will be checked in this call. If `_numToResolve` is less than the number of children, an + /// internal cursor will be updated and this function may be called again to complete resolution of the + /// subgame. + /// @dev This function must be called bottom-up in the DAG + /// A subgame is a tree of claims that has a maximum depth of 1. + /// A subgame root claims is valid if, and only if, all of its child claims are invalid. + /// At the deepest level in the DAG, a claim is invalid if there's a successful step against it. + /// @param _claimIndex The index of the subgame root claim to resolve. + /// @param _numToResolve The number of subgames to resolve in this call. If the input is `0`, and this is the first + /// page, this function will attempt to check all of the subgame's children at once. function resolveClaim(uint256 _claimIndex, uint256 _numToResolve) external { // INVARIANT: Resolution cannot occur unless the game is currently in progress. if (status != GameStatus.IN_PROGRESS) revert GameNotInProgress(); @@ -698,34 +772,51 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, ISemver { } } - /// @inheritdoc IDisputeGame - function gameType() public view override returns (GameType gameType_) { + /// @notice Getter for the game type. + /// @dev The reference impl should be entirely different depending on the type (fault, validity) + /// i.e. The game type should indicate the security model. + /// @return gameType_ The type of proof system being used. + function gameType() public view returns (GameType gameType_) { gameType_ = GAME_TYPE; } - /// @inheritdoc IDisputeGame + /// @notice Getter for the creator of the dispute game. + /// @dev `clones-with-immutable-args` argument #1 + /// @return creator_ The creator of the dispute game. function gameCreator() public pure returns (address creator_) { creator_ = _getArgAddress(0x00); } - /// @inheritdoc IDisputeGame + /// @notice Getter for the root claim. + /// @dev `clones-with-immutable-args` argument #2 + /// @return rootClaim_ The root claim of the DisputeGame. function rootClaim() public pure returns (Claim rootClaim_) { rootClaim_ = Claim.wrap(_getArgBytes32(0x14)); } - /// @inheritdoc IDisputeGame + /// @notice Getter for the parent hash of the L1 block when the dispute game was created. + /// @dev `clones-with-immutable-args` argument #3 + /// @return l1Head_ The parent hash of the L1 block when the dispute game was created. function l1Head() public pure returns (Hash l1Head_) { l1Head_ = Hash.wrap(_getArgBytes32(0x34)); } - /// @inheritdoc IDisputeGame + /// @notice Getter for the extra data. + /// @dev `clones-with-immutable-args` argument #4 + /// @return extraData_ Any extra data supplied to the dispute game contract by the creator. 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_ = _getArgBytes(0x54, 0x20); } - /// @inheritdoc IDisputeGame + /// @notice A compliant implementation of this interface should return the components of the + /// game UUID's preimage provided in the cwia payload. The preimage of the UUID is + /// constructed as `keccak256(gameType . rootClaim . extraData)` where `.` denotes + /// concatenation. + /// @return gameType_ The type of proof system being used. + /// @return rootClaim_ The root claim of the DisputeGame. + /// @return extraData_ Any extra data supplied to the dispute game contract by the creator. function gameData() external view returns (GameType gameType_, Claim rootClaim_, bytes memory extraData_) { gameType_ = gameType(); rootClaim_ = rootClaim(); diff --git a/packages/contracts-bedrock/src/dispute/PermissionedDisputeGame.sol b/packages/contracts-bedrock/src/dispute/PermissionedDisputeGame.sol index 8e67415524898..abd8a8896cc32 100644 --- a/packages/contracts-bedrock/src/dispute/PermissionedDisputeGame.sol +++ b/packages/contracts-bedrock/src/dispute/PermissionedDisputeGame.sol @@ -1,12 +1,18 @@ // 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"; +// Contracts +import { FaultDisputeGame } from "src/dispute/FaultDisputeGame.sol"; + +// Libraries import "src/dispute/lib/Types.sol"; import "src/dispute/lib/Errors.sol"; +// Interfaces +import { IDelayedWETH } from "src/dispute/interfaces/IDelayedWETH.sol"; +import { IAnchorStateRegistry } from "src/dispute/interfaces/IAnchorStateRegistry.sol"; +import { IBigStepper } from "src/dispute/interfaces/IBigStepper.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. @@ -73,7 +79,7 @@ contract PermissionedDisputeGame is FaultDisputeGame { CHALLENGER = _challenger; } - /// @inheritdoc IFaultDisputeGame + /// @inheritdoc FaultDisputeGame function step( uint256 _claimIndex, bool _isAttack, @@ -106,7 +112,7 @@ contract PermissionedDisputeGame is FaultDisputeGame { super.move(_disputed, _challengeIndex, _claim, _isAttack); } - /// @inheritdoc IInitializable + /// @notice Initializes the contract. function initialize() public payable override { // The creator of the dispute game must be the proposer EOA. if (tx.origin != PROPOSER) revert BadAuth(); diff --git a/packages/contracts-bedrock/src/dispute/interfaces/IAnchorStateRegistry.sol b/packages/contracts-bedrock/src/dispute/interfaces/IAnchorStateRegistry.sol index dd7724538e58c..28c544c0d408b 100644 --- a/packages/contracts-bedrock/src/dispute/interfaces/IAnchorStateRegistry.sol +++ b/packages/contracts-bedrock/src/dispute/interfaces/IAnchorStateRegistry.sol @@ -3,27 +3,32 @@ pragma solidity ^0.8.0; import { IFaultDisputeGame } from "src/dispute/interfaces/IFaultDisputeGame.sol"; import { IDisputeGameFactory } from "src/dispute/interfaces/IDisputeGameFactory.sol"; - +import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol"; import "src/dispute/lib/Types.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); + struct StartingAnchorRoot { + GameType gameType; + OutputRoot outputRoot; + } - /// @notice Returns the DisputeGameFactory address. - /// @return DisputeGameFactory address. - function disputeGameFactory() external view returns (IDisputeGameFactory); + error InvalidGameStatus(); + error Unauthorized(); + error UnregisteredGame(); - /// @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; + event Initialized(uint8 version); - /// @notice Sets the anchor state given the game. - /// @param _game The game to set the anchor state for. + function anchors(GameType) external view returns (Hash root, uint256 l2BlockNumber); + function disputeGameFactory() external view returns (IDisputeGameFactory); + function initialize( + StartingAnchorRoot[] memory _startingAnchorRoots, + ISuperchainConfig _superchainConfig + ) + external; function setAnchorState(IFaultDisputeGame _game) external; + function superchainConfig() external view returns (ISuperchainConfig); + function tryUpdateAnchorState() external; + function version() external view returns (string memory); + + function __constructor__(IDisputeGameFactory _disputeGameFactory) external; } diff --git a/packages/contracts-bedrock/src/dispute/interfaces/IDelayedWETH.sol b/packages/contracts-bedrock/src/dispute/interfaces/IDelayedWETH.sol index 80b90c69b8604..7a7b36052f3de 100644 --- a/packages/contracts-bedrock/src/dispute/interfaces/IDelayedWETH.sol +++ b/packages/contracts-bedrock/src/dispute/interfaces/IDelayedWETH.sol @@ -1,48 +1,30 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import { IWETH } from "src/dispute/interfaces/IWETH.sol"; +import { IWETH } from "src/universal/interfaces/IWETH.sol"; +import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.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); + fallback() external payable; + receive() external payable; - /// @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 config() external view returns (ISuperchainConfig); + function delay() external view returns (uint256); + function hold(address _guy, uint256 _wad) external; + function initialize(address _owner, ISuperchainConfig _config) external; + function owner() external view returns (address); + function recover(uint256 _wad) external; + function transferOwnership(address newOwner) external; + function renounceOwnership() external; 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; + function withdrawals(address _owner, address _guy) external view returns (uint256, uint256); + function version() external view returns (string memory); } diff --git a/packages/contracts-bedrock/src/dispute/interfaces/IDisputeGame.sol b/packages/contracts-bedrock/src/dispute/interfaces/IDisputeGame.sol index 7e9389b4ddafb..f5a650202d0ce 100644 --- a/packages/contracts-bedrock/src/dispute/interfaces/IDisputeGame.sol +++ b/packages/contracts-bedrock/src/dispute/interfaces/IDisputeGame.sol @@ -2,68 +2,19 @@ pragma solidity ^0.8.0; import { IInitializable } from "src/dispute/interfaces/IInitializable.sol"; - import "src/dispute/lib/Types.sol"; -/// @title IDisputeGame -/// @notice The generic interface for a DisputeGame contract. interface IDisputeGame is IInitializable { - /// @notice Emitted when the game is resolved. - /// @param status The status of the game after resolution. event Resolved(GameStatus indexed status); - /// @notice Returns the timestamp that the DisputeGame contract was created at. - /// @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_); - - /// @notice Getter for the game type. - /// @dev The reference impl should be entirely different depending on the type (fault, validity) - /// i.e. The game type should indicate the security model. - /// @return gameType_ The type of proof system being used. + function createdAt() external view returns (Timestamp); + function resolvedAt() external view returns (Timestamp); + function status() external view returns (GameStatus); function gameType() external view returns (GameType gameType_); - - /// @notice Getter for the creator of the dispute game. - /// @dev `clones-with-immutable-args` argument #1 - /// @return creator_ The creator of the dispute game. function gameCreator() external pure returns (address creator_); - - /// @notice Getter for the root claim. - /// @dev `clones-with-immutable-args` argument #2 - /// @return rootClaim_ The root claim of the DisputeGame. function rootClaim() external pure returns (Claim rootClaim_); - - /// @notice Getter for the parent hash of the L1 block when the dispute game was created. - /// @dev `clones-with-immutable-args` argument #3 - /// @return l1Head_ The parent hash of the L1 block when the dispute game was created. function l1Head() external pure returns (Hash l1Head_); - - /// @notice Getter for the extra data. - /// @dev `clones-with-immutable-args` argument #4 - /// @return extraData_ Any extra data supplied to the dispute game contract by the creator. function extraData() external pure returns (bytes memory extraData_); - - /// @notice If all necessary information has been gathered, this function should mark the game - /// status as either `CHALLENGER_WINS` or `DEFENDER_WINS` and return the status of - /// the resolved game. It is at this stage that the bonds should be awarded to the - /// necessary parties. - /// @dev May only be called if the `status` is `IN_PROGRESS`. - /// @return status_ The status of the game after resolution. function resolve() external returns (GameStatus status_); - - /// @notice A compliant implementation of this interface should return the components of the - /// game UUID's preimage provided in the cwia payload. The preimage of the UUID is - /// constructed as `keccak256(gameType . rootClaim . extraData)` where `.` denotes - /// concatenation. - /// @return gameType_ The type of proof system being used. - /// @return rootClaim_ The root claim of the DisputeGame. - /// @return extraData_ Any extra data supplied to the dispute game contract by the creator. function gameData() external view returns (GameType gameType_, Claim rootClaim_, bytes memory extraData_); } diff --git a/packages/contracts-bedrock/src/dispute/interfaces/IDisputeGameFactory.sol b/packages/contracts-bedrock/src/dispute/interfaces/IDisputeGameFactory.sol index 5021de04d62a8..1e70cbbb05bf1 100644 --- a/packages/contracts-bedrock/src/dispute/interfaces/IDisputeGameFactory.sol +++ b/packages/contracts-bedrock/src/dispute/interfaces/IDisputeGameFactory.sol @@ -1,30 +1,10 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import { IDisputeGame } from "./IDisputeGame.sol"; - +import { IDisputeGame } from "src/dispute/interfaces/IDisputeGame.sol"; import "src/dispute/lib/Types.sol"; -/// @title IDisputeGameFactory -/// @notice The interface for a DisputeGameFactory contract. interface IDisputeGameFactory { - /// @notice Emitted when a new dispute game is created - /// @param disputeProxy The address of the dispute game proxy - /// @param gameType The type of the dispute game proxy's implementation - /// @param rootClaim The root claim of the dispute game - event DisputeGameCreated(address indexed disputeProxy, GameType indexed gameType, Claim indexed rootClaim); - - /// @notice Emitted when a new game implementation added to the factory - /// @param impl The implementation contract for the given `GameType`. - /// @param gameType The type of the DisputeGame. - event ImplementationSet(address indexed impl, GameType indexed gameType); - - /// @notice Emitted when a game type's initialization bond is updated - /// @param gameType The type of the DisputeGame. - /// @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; @@ -33,85 +13,46 @@ interface IDisputeGameFactory { 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_); + error GameAlreadyExists(Hash uuid); + error IncorrectBondAmount(); + error NoImplementation(GameType gameType); - /// @notice `games` queries an internal mapping that maps the hash of - /// `gameType ++ rootClaim ++ extraData` to the deployed `DisputeGame` clone. - /// @dev `++` equates to concatenation. - /// @param _gameType The type of the DisputeGame - used to decide the proxy implementation - /// @param _rootClaim The root claim of the DisputeGame. - /// @param _extraData Any extra data that should be provided to the created dispute game. - /// @return proxy_ The clone of the `DisputeGame` created with the given parameters. - /// Returns `address(0)` if nonexistent. - /// @return timestamp_ The timestamp of the creation of the dispute game. - function games( + event DisputeGameCreated(address indexed disputeProxy, GameType indexed gameType, Claim indexed rootClaim); + event ImplementationSet(address indexed impl, GameType indexed gameType); + event InitBondUpdated(GameType indexed gameType, uint256 indexed newBond); + event Initialized(uint8 version); + event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); + + function create( GameType _gameType, Claim _rootClaim, - bytes calldata _extraData + bytes memory _extraData + ) + external + payable + returns (IDisputeGame proxy_); + function findLatestGames( + GameType _gameType, + uint256 _start, + uint256 _n ) external view - returns (IDisputeGame proxy_, Timestamp timestamp_); - - /// @notice `gameAtIndex` returns the dispute game contract address and its creation timestamp - /// at the given index. Each created dispute game increments the underlying index. - /// @param _index The index of the dispute game. - /// @return gameType_ The type of the DisputeGame - used to decide the proxy implementation. - /// @return timestamp_ The timestamp of the creation of the dispute game. - /// @return proxy_ The clone of the `DisputeGame` created with the given parameters. - /// Returns `address(0)` if nonexistent. + returns (GameSearchResult[] memory games_); function gameAtIndex(uint256 _index) external view returns (GameType gameType_, Timestamp timestamp_, IDisputeGame proxy_); - - /// @notice `gameImpls` is a mapping that maps `GameType`s to their respective - /// `IDisputeGame` implementations. - /// @param _gameType The type of the dispute game. - /// @return impl_ The address of the implementation of the game type. - /// Will be cloned on creation of a new dispute game with the given `gameType`. - function gameImpls(GameType _gameType) external view returns (IDisputeGame impl_); - - /// @notice Returns the required bonds for initializing a dispute game of the given type. - /// @param _gameType The type of the dispute game. - /// @return bond_ The required bond for initializing a dispute game of the given type. - function initBonds(GameType _gameType) external view returns (uint256 bond_); - - /// @notice Creates a new DisputeGame proxy contract. - /// @param _gameType The type of the DisputeGame - used to decide the proxy implementation. - /// @param _rootClaim The root claim of the DisputeGame. - /// @param _extraData Any extra data that should be provided to the created dispute game. - /// @return proxy_ The address of the created DisputeGame proxy. - function create( + function gameCount() external view returns (uint256 gameCount_); + function gameImpls(GameType) external view returns (IDisputeGame); + function games( GameType _gameType, Claim _rootClaim, - bytes calldata _extraData + bytes memory _extraData ) external - payable - returns (IDisputeGame proxy_); - - /// @notice Sets the implementation contract for a specific `GameType`. - /// @dev May only be called by the `owner`. - /// @param _gameType The type of the DisputeGame. - /// @param _impl The implementation contract for the given `GameType`. - function setImplementation(GameType _gameType, IDisputeGame _impl) external; - - /// @notice Sets the bond (in wei) for initializing a game type. - /// @dev May only be called by the `owner`. - /// @param _gameType The type of the DisputeGame. - /// @param _initBond The bond (in wei) for initializing a game type. - function setInitBond(GameType _gameType, uint256 _initBond) external; - - /// @notice Returns a unique identifier for the given dispute game parameters. - /// @dev Hashes the concatenation of `gameType . rootClaim . extraData` - /// without expanding memory. - /// @param _gameType The type of the DisputeGame. - /// @param _rootClaim The root claim of the DisputeGame. - /// @param _extraData Any extra data that should be provided to the created dispute game. - /// @return uuid_ The unique identifier for the given dispute game parameters. + view + returns (IDisputeGame proxy_, Timestamp timestamp_); function getGameUUID( GameType _gameType, Claim _rootClaim, @@ -120,18 +61,14 @@ interface IDisputeGameFactory { external pure returns (Hash uuid_); + function initBonds(GameType) external view returns (uint256); + function initialize(address _owner) external; + function owner() external view returns (address); + function renounceOwnership() external; + function setImplementation(GameType _gameType, IDisputeGame _impl) external; + function setInitBond(GameType _gameType, uint256 _initBond) external; + function transferOwnership(address newOwner) external; + function version() external view returns (string memory); - /// @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_); + function __constructor__() external; } diff --git a/packages/contracts-bedrock/src/dispute/interfaces/IFaultDisputeGame.sol b/packages/contracts-bedrock/src/dispute/interfaces/IFaultDisputeGame.sol index 43de378ac06d1..379c4fcb6a485 100644 --- a/packages/contracts-bedrock/src/dispute/interfaces/IFaultDisputeGame.sol +++ b/packages/contracts-bedrock/src/dispute/interfaces/IFaultDisputeGame.sol @@ -1,14 +1,14 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import { IDisputeGame } from "./IDisputeGame.sol"; - +import { IDisputeGame } from "src/dispute/interfaces/IDisputeGame.sol"; +import { IDelayedWETH } from "src/dispute/interfaces/IDelayedWETH.sol"; +import { IAnchorStateRegistry } from "src/dispute/interfaces/IAnchorStateRegistry.sol"; +import { IBigStepper } from "src/dispute/interfaces/IBigStepper.sol"; +import { Types } from "src/libraries/Types.sol"; import "src/dispute/lib/Types.sol"; -/// @title IFaultDisputeGame -/// @notice The interface for a fault proof backed dispute game. interface IFaultDisputeGame is IDisputeGame { - /// @notice The `ClaimData` struct represents the data associated with a Claim. struct ClaimData { uint32 parentIndex; address counteredBy; @@ -19,7 +19,6 @@ interface IFaultDisputeGame is IDisputeGame { Clock clock; } - /// @notice The `ResolutionCheckpoint` struct represents the data associated with an in-progress claim resolution. struct ResolutionCheckpoint { bool initialCheckpointComplete; uint32 subgameIndex; @@ -27,73 +26,104 @@ interface IFaultDisputeGame is IDisputeGame { address counteredBy; } - /// @notice Emitted when a new claim is added to the DAG by `claimant` - /// @param parentIndex The index within the `claimData` array of the parent claim - /// @param claim The claim being added - /// @param claimant The address of the claimant + error AlreadyInitialized(); + error AnchorRootNotFound(); + error BlockNumberMatches(); + error BondTransferFailed(); + error CannotDefendRootClaim(); + error ClaimAboveSplit(); + error ClaimAlreadyExists(); + error ClaimAlreadyResolved(); + error ClockNotExpired(); + error ClockTimeExceeded(); + error ContentLengthMismatch(); + error DuplicateStep(); + error EmptyItem(); + error GameDepthExceeded(); + error GameNotInProgress(); + error IncorrectBondAmount(); + error InvalidChallengePeriod(); + error InvalidClockExtension(); + error InvalidDataRemainder(); + error InvalidDisputedClaimIndex(); + error InvalidHeader(); + error InvalidHeaderRLP(); + error InvalidLocalIdent(); + error InvalidOutputRootProof(); + error InvalidParent(); + error InvalidPrestate(); + error InvalidSplitDepth(); + error L2BlockNumberChallenged(); + error MaxDepthTooLarge(); + error NoCreditToClaim(); + error OutOfOrderResolution(); + error UnexpectedList(); + error UnexpectedRootClaim(Claim rootClaim); + error UnexpectedString(); + error ValidStep(); + event Move(uint256 indexed parentIndex, Claim indexed claim, address indexed claimant); - /// @notice Attack a disagreed upon `Claim`. - /// @param _disputed The `Claim` being attacked. - /// @param _parentIndex Index of the `Claim` to attack in the `claimData` array. This must match the `_disputed` - /// claim. - /// @param _claim The `Claim` at the relative attack position. + function absolutePrestate() external view returns (Claim absolutePrestate_); + function addLocalData(uint256 _ident, uint256 _execLeafIdx, uint256 _partOffset) external; + function anchorStateRegistry() external view returns (IAnchorStateRegistry registry_); function attack(Claim _disputed, uint256 _parentIndex, Claim _claim) external payable; - - /// @notice Defend an agreed upon `Claim`. - /// @notice _disputed The `Claim` being defended. - /// @param _parentIndex Index of the claim to defend in the `claimData` array. This must match the `_disputed` - /// claim. - /// @param _claim The `Claim` at the relative defense position. + function challengeRootL2Block(Types.OutputRootProof memory _outputRootProof, bytes memory _headerRLP) external; + function claimCredit(address _recipient) external; + function claimData(uint256) + external + view + returns ( + uint32 parentIndex, + address counteredBy, + address claimant, + uint128 bond, + Claim claim, + Position position, + Clock clock + ); + function claimDataLen() external view returns (uint256 len_); + function claims(Hash) external view returns (bool); + function clockExtension() external view returns (Duration clockExtension_); + function credit(address) external view returns (uint256); function defend(Claim _disputed, uint256 _parentIndex, Claim _claim) external payable; - - /// @notice Perform an instruction step via an on-chain fault proof processor. - /// @dev This function should point to a fault proof processor in order to execute - /// a step in the fault proof program on-chain. The interface of the fault proof - /// processor contract should adhere to the `IBigStepper` interface. - /// @param _claimIndex The index of the challenged claim within `claimData`. - /// @param _isAttack Whether or not the step is an attack or a defense. - /// @param _stateData The stateData of the step is the preimage of the claim at the given - /// prestate, which is at `_stateIndex` if the move is an attack and `_claimIndex` if - /// the move is a defense. If the step is an attack on the first instruction, it is - /// the absolute prestate of the fault proof VM. - /// @param _proof Proof to access memory nodes in the VM's merkle state tree. - function step(uint256 _claimIndex, bool _isAttack, bytes calldata _stateData, bytes calldata _proof) external; - - /// @notice Posts the requested local data to the VM's `PreimageOralce`. - /// @param _ident The local identifier of the data to post. - /// @param _execLeafIdx The index of the leaf claim in an execution subgame that requires the local data for a step. - /// @param _partOffset The offset of the data to post. - function addLocalData(uint256 _ident, uint256 _execLeafIdx, uint256 _partOffset) external; - - /// @notice Resolves the subgame rooted at the given claim index. `_numToResolve` specifies how many children of - /// the subgame will be checked in this call. If `_numToResolve` is less than the number of children, an - /// internal cursor will be updated and this function may be called again to complete resolution of the - /// subgame. - /// @dev This function must be called bottom-up in the DAG - /// A subgame is a tree of claims that has a maximum depth of 1. - /// A subgame root claims is valid if, and only if, all of its child claims are invalid. - /// At the deepest level in the DAG, a claim is invalid if there's a successful step against it. - /// @param _claimIndex The index of the subgame root claim to resolve. - /// @param _numToResolve The number of subgames to resolve in this call. If the input is `0`, and this is the first - /// page, this function will attempt to check all of the subgame's children at once. - function resolveClaim(uint256 _claimIndex, uint256 _numToResolve) external; - - /// @notice Returns the number of children that still need to be resolved in order to fully resolve a subgame rooted - /// at `_claimIndex`. - /// @param _claimIndex The subgame root claim's index within `claimData`. - /// @return numRemainingChildren_ The number of children that still need to be checked to resolve the subgame. + function getChallengerDuration(uint256 _claimIndex) external view returns (Duration duration_); function getNumToResolve(uint256 _claimIndex) external view returns (uint256 numRemainingChildren_); - - /// @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 getRequiredBond(Position _position) external view returns (uint256 requiredBond_); + function l2BlockNumber() external pure returns (uint256 l2BlockNumber_); + function l2BlockNumberChallenged() external view returns (bool); + function l2BlockNumberChallenger() external view returns (address); + function l2ChainId() external view returns (uint256 l2ChainId_); + function maxClockDuration() external view returns (Duration maxClockDuration_); + function maxGameDepth() external view returns (uint256 maxGameDepth_); + function move(Claim _disputed, uint256 _challengeIndex, Claim _claim, bool _isAttack) external payable; + function resolutionCheckpoints(uint256) + external + view + returns (bool initialCheckpointComplete, uint32 subgameIndex, Position leftmostPosition, address counteredBy); + function resolveClaim(uint256 _claimIndex, uint256 _numToResolve) external; + function resolvedSubgames(uint256) external view returns (bool); + function splitDepth() external view returns (uint256 splitDepth_); function startingBlockNumber() external view returns (uint256 startingBlockNumber_); - - /// @notice Only the starting output root of the game. + function startingOutputRoot() external view returns (Hash root, uint256 l2BlockNumber); function startingRootHash() external view returns (Hash startingRootHash_); + function step(uint256 _claimIndex, bool _isAttack, bytes memory _stateData, bytes memory _proof) external; + function subgames(uint256, uint256) external view returns (uint256); + function version() external view returns (string memory); + function vm() external view returns (IBigStepper vm_); + function weth() external view returns (IDelayedWETH weth_); + + function __constructor__( + GameType _gameType, + Claim _absolutePrestate, + uint256 _maxGameDepth, + uint256 _splitDepth, + Duration _clockExtension, + Duration _maxClockDuration, + IBigStepper _vm, + IDelayedWETH _weth, + IAnchorStateRegistry _anchorStateRegistry, + uint256 _l2ChainId + ) + external; } diff --git a/packages/contracts-bedrock/src/dispute/interfaces/IInitializable.sol b/packages/contracts-bedrock/src/dispute/interfaces/IInitializable.sol index 5968b45f9bfb5..a3bb74b82f3a6 100644 --- a/packages/contracts-bedrock/src/dispute/interfaces/IInitializable.sol +++ b/packages/contracts-bedrock/src/dispute/interfaces/IInitializable.sol @@ -1,10 +1,6 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -/// @title IInitializable -/// @notice An interface for initializable contracts. interface IInitializable { - /// @notice Initializes the contract. - /// @dev This function may only be called once. function initialize() external payable; } diff --git a/packages/contracts-bedrock/src/dispute/interfaces/IPermissionedDisputeGame.sol b/packages/contracts-bedrock/src/dispute/interfaces/IPermissionedDisputeGame.sol new file mode 100644 index 0000000000000..5fda4e9163b25 --- /dev/null +++ b/packages/contracts-bedrock/src/dispute/interfaces/IPermissionedDisputeGame.sol @@ -0,0 +1,137 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { Types } from "src/libraries/Types.sol"; +import "src/dispute/lib/Types.sol"; + +import { IAnchorStateRegistry } from "src/dispute/interfaces/IAnchorStateRegistry.sol"; +import { IDelayedWETH } from "src/dispute/interfaces/IDelayedWETH.sol"; +import { IBigStepper } from "src/dispute/interfaces/IBigStepper.sol"; +import { IDisputeGame } from "src/dispute/interfaces/IDisputeGame.sol"; + +interface IPermissionedDisputeGame is IDisputeGame { + struct ClaimData { + uint32 parentIndex; + address counteredBy; + address claimant; + uint128 bond; + Claim claim; + Position position; + Clock clock; + } + + struct ResolutionCheckpoint { + bool initialCheckpointComplete; + uint32 subgameIndex; + Position leftmostPosition; + address counteredBy; + } + + error AlreadyInitialized(); + error AnchorRootNotFound(); + error BlockNumberMatches(); + error BondTransferFailed(); + error CannotDefendRootClaim(); + error ClaimAboveSplit(); + error ClaimAlreadyExists(); + error ClaimAlreadyResolved(); + error ClockNotExpired(); + error ClockTimeExceeded(); + error ContentLengthMismatch(); + error DuplicateStep(); + error EmptyItem(); + error GameDepthExceeded(); + error GameNotInProgress(); + error IncorrectBondAmount(); + error InvalidChallengePeriod(); + error InvalidClockExtension(); + error InvalidDataRemainder(); + error InvalidDisputedClaimIndex(); + error InvalidHeader(); + error InvalidHeaderRLP(); + error InvalidLocalIdent(); + error InvalidOutputRootProof(); + error InvalidParent(); + error InvalidPrestate(); + error InvalidSplitDepth(); + error L2BlockNumberChallenged(); + error MaxDepthTooLarge(); + error NoCreditToClaim(); + error OutOfOrderResolution(); + error UnexpectedList(); + error UnexpectedRootClaim(Claim rootClaim); + error UnexpectedString(); + error ValidStep(); + + event Move(uint256 indexed parentIndex, Claim indexed claim, address indexed claimant); + + function absolutePrestate() external view returns (Claim absolutePrestate_); + function addLocalData(uint256 _ident, uint256 _execLeafIdx, uint256 _partOffset) external; + function anchorStateRegistry() external view returns (IAnchorStateRegistry registry_); + function attack(Claim _disputed, uint256 _parentIndex, Claim _claim) external payable; + function challengeRootL2Block(Types.OutputRootProof memory _outputRootProof, bytes memory _headerRLP) external; + function claimCredit(address _recipient) external; + function claimData(uint256) + external + view + returns ( + uint32 parentIndex, + address counteredBy, + address claimant, + uint128 bond, + Claim claim, + Position position, + Clock clock + ); + function claimDataLen() external view returns (uint256 len_); + function claims(Hash) external view returns (bool); + function clockExtension() external view returns (Duration clockExtension_); + function credit(address) external view returns (uint256); + function defend(Claim _disputed, uint256 _parentIndex, Claim _claim) external payable; + function getChallengerDuration(uint256 _claimIndex) external view returns (Duration duration_); + function getNumToResolve(uint256 _claimIndex) external view returns (uint256 numRemainingChildren_); + function getRequiredBond(Position _position) external view returns (uint256 requiredBond_); + function l2BlockNumber() external pure returns (uint256 l2BlockNumber_); + function l2BlockNumberChallenged() external view returns (bool); + function l2BlockNumberChallenger() external view returns (address); + function l2ChainId() external view returns (uint256 l2ChainId_); + function maxClockDuration() external view returns (Duration maxClockDuration_); + function maxGameDepth() external view returns (uint256 maxGameDepth_); + function move(Claim _disputed, uint256 _challengeIndex, Claim _claim, bool _isAttack) external payable; + function resolutionCheckpoints(uint256) + external + view + returns (bool initialCheckpointComplete, uint32 subgameIndex, Position leftmostPosition, address counteredBy); + function resolveClaim(uint256 _claimIndex, uint256 _numToResolve) external; + function resolvedSubgames(uint256) external view returns (bool); + function splitDepth() external view returns (uint256 splitDepth_); + function startingBlockNumber() external view returns (uint256 startingBlockNumber_); + function startingOutputRoot() external view returns (Hash root, uint256 l2BlockNumber); + function startingRootHash() external view returns (Hash startingRootHash_); + function step(uint256 _claimIndex, bool _isAttack, bytes memory _stateData, bytes memory _proof) external; + function subgames(uint256, uint256) external view returns (uint256); + function version() external view returns (string memory); + function vm() external view returns (IBigStepper vm_); + function weth() external view returns (IDelayedWETH weth_); + + error BadAuth(); + + function proposer() external view returns (address proposer_); + function challenger() external view returns (address challenger_); + + function __constructor__( + GameType _gameType, + Claim _absolutePrestate, + uint256 _maxGameDepth, + uint256 _splitDepth, + Duration _clockExtension, + Duration _maxClockDuration, + IBigStepper _vm, + IDelayedWETH _weth, + IAnchorStateRegistry _anchorStateRegistry, + uint256 _l2ChainId, + address _proposer, + address _challenger + ) + external; +} diff --git a/packages/contracts-bedrock/src/governance/MintManager.sol b/packages/contracts-bedrock/src/governance/MintManager.sol index d9feae71dfb33..57abeece6b62c 100644 --- a/packages/contracts-bedrock/src/governance/MintManager.sol +++ b/packages/contracts-bedrock/src/governance/MintManager.sol @@ -1,8 +1,11 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Contracts import "@openzeppelin/contracts/access/Ownable.sol"; -import "./GovernanceToken.sol"; + +// Interfaces +import { IGovernanceToken } from "src/governance/interfaces/IGovernanceToken.sol"; /// @title MintManager /// @notice Set as `owner` of the governance token and responsible for the token inflation @@ -11,7 +14,7 @@ import "./GovernanceToken.sol"; /// token supply. Upgradable to allow changes in the inflation schedule. contract MintManager is Ownable { /// @notice The GovernanceToken that the MintManager can mint tokens - GovernanceToken public immutable governanceToken; + IGovernanceToken public immutable governanceToken; /// @notice The amount of tokens that can be minted per year. /// The value is a fixed point number with 4 decimals. @@ -32,7 +35,7 @@ contract MintManager is Ownable { /// @param _governanceToken The governance token this contract can mint tokens of. constructor(address _upgrader, address _governanceToken) { transferOwnership(_upgrader); - governanceToken = GovernanceToken(_governanceToken); + governanceToken = IGovernanceToken(_governanceToken); } /// @notice Only the token owner is allowed to mint a certain amount of the diff --git a/packages/contracts-bedrock/src/governance/interfaces/IGovernanceToken.sol b/packages/contracts-bedrock/src/governance/interfaces/IGovernanceToken.sol new file mode 100644 index 0000000000000..04a0490adc9b2 --- /dev/null +++ b/packages/contracts-bedrock/src/governance/interfaces/IGovernanceToken.sol @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { ERC20Votes } from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol"; + +interface IGovernanceToken { + event Approval(address indexed owner, address indexed spender, uint256 value); + event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate); + event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance); + event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); + event Transfer(address indexed from, address indexed to, uint256 value); + + function DOMAIN_SEPARATOR() external view returns (bytes32); + function allowance(address owner, address spender) external view returns (uint256); + function approve(address spender, uint256 amount) external returns (bool); + function balanceOf(address account) external view returns (uint256); + function burn(uint256 amount) external; + function burnFrom(address account, uint256 amount) external; + function checkpoints(address account, uint32 pos) external view returns (ERC20Votes.Checkpoint memory); + function decimals() external view returns (uint8); + function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool); + function delegate(address delegatee) external; + function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external; + function delegates(address account) external view returns (address); + function getPastTotalSupply(uint256 blockNumber) external view returns (uint256); + function getPastVotes(address account, uint256 blockNumber) external view returns (uint256); + function getVotes(address account) external view returns (uint256); + function increaseAllowance(address spender, uint256 addedValue) external returns (bool); + function mint(address _account, uint256 _amount) external; + function name() external view returns (string memory); + function nonces(address owner) external view returns (uint256); + function numCheckpoints(address account) external view returns (uint32); + function owner() external view returns (address); + function permit( + address owner, + address spender, + uint256 value, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s + ) + external; + function renounceOwnership() external; + function symbol() external view returns (string memory); + function totalSupply() external view returns (uint256); + function transfer(address to, uint256 amount) external returns (bool); + function transferFrom(address from, address to, uint256 amount) external returns (bool); + function transferOwnership(address newOwner) external; + + function __constructor__() external; +} diff --git a/packages/contracts-bedrock/src/governance/interfaces/IMintManager.sol b/packages/contracts-bedrock/src/governance/interfaces/IMintManager.sol new file mode 100644 index 0000000000000..e769f3042e537 --- /dev/null +++ b/packages/contracts-bedrock/src/governance/interfaces/IMintManager.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { IGovernanceToken } from "src/governance/interfaces/IGovernanceToken.sol"; + +interface IMintManager { + event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); + + function DENOMINATOR() external view returns (uint256); + function MINT_CAP() external view returns (uint256); + function MINT_PERIOD() external view returns (uint256); + function governanceToken() external view returns (IGovernanceToken); + function mint(address _account, uint256 _amount) external; + function mintPermittedAfter() external view returns (uint256); + function owner() external view returns (address); + function renounceOwnership() external; + function transferOwnership(address newOwner) external; + function upgrade(address _newMintManager) external; + + function __constructor__(address _upgrader, address _governanceToken) external; +} diff --git a/packages/contracts-bedrock/src/legacy/AddressManager.sol b/packages/contracts-bedrock/src/legacy/AddressManager.sol index 6029a1142c12b..daaac412e0a00 100644 --- a/packages/contracts-bedrock/src/legacy/AddressManager.sol +++ b/packages/contracts-bedrock/src/legacy/AddressManager.sol @@ -3,7 +3,7 @@ pragma solidity 0.8.15; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; -/// @custom:legacy +/// @custom:legacy true /// @title AddressManager /// @notice AddressManager is a legacy contract that was used in the old version of the Optimism /// system to manage a registry of string names to addresses. We now use a more standard diff --git a/packages/contracts-bedrock/src/legacy/DeployerWhitelist.sol b/packages/contracts-bedrock/src/legacy/DeployerWhitelist.sol index 11585791655f7..a7a6313edf4b3 100644 --- a/packages/contracts-bedrock/src/legacy/DeployerWhitelist.sol +++ b/packages/contracts-bedrock/src/legacy/DeployerWhitelist.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { ISemver } from "src/universal/ISemver.sol"; +import { ISemver } from "src/universal/interfaces/ISemver.sol"; -/// @custom:legacy -/// @custom:proxied +/// @custom:legacy true +/// @custom:proxied true /// @custom:predeployed 0x4200000000000000000000000000000000000002 /// @title DeployerWhitelist /// @notice DeployerWhitelist is a legacy contract that was originally used to act as a whitelist of @@ -41,8 +41,8 @@ contract DeployerWhitelist is ISemver { } /// @notice Semantic version. - /// @custom:semver 1.1.0 - string public constant version = "1.1.0"; + /// @custom:semver 1.1.1-beta.1 + string public constant version = "1.1.1-beta.1"; /// @notice Adds or removes an address from the deployment whitelist. /// @param _deployer Address to update permissions for. diff --git a/packages/contracts-bedrock/src/legacy/L1BlockNumber.sol b/packages/contracts-bedrock/src/legacy/L1BlockNumber.sol index 8bd2e2a8f315d..19a595a3fad3c 100644 --- a/packages/contracts-bedrock/src/legacy/L1BlockNumber.sol +++ b/packages/contracts-bedrock/src/legacy/L1BlockNumber.sol @@ -1,12 +1,15 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { L1Block } from "src/L2/L1Block.sol"; +// Libraries import { Predeploys } from "src/libraries/Predeploys.sol"; -import { ISemver } from "src/universal/ISemver.sol"; -/// @custom:legacy -/// @custom:proxied +// Interfaces +import { ISemver } from "src/universal/interfaces/ISemver.sol"; +import { IL1Block } from "src/L2/interfaces/IL1Block.sol"; + +/// @custom:legacy true +/// @custom:proxied true /// @custom:predeploy 0x4200000000000000000000000000000000000013 /// @title L1BlockNumber /// @notice L1BlockNumber is a legacy contract that fills the roll of the OVM_L1BlockNumber contract @@ -15,8 +18,8 @@ import { ISemver } from "src/universal/ISemver.sol"; /// contract instead. contract L1BlockNumber is ISemver { /// @notice Semantic version. - /// @custom:semver 1.1.0 - string public constant version = "1.1.0"; + /// @custom:semver 1.1.1-beta.2 + string public constant version = "1.1.1-beta.2"; /// @notice Returns the L1 block number. receive() external payable { @@ -39,6 +42,6 @@ contract L1BlockNumber is ISemver { /// @notice Retrieves the latest L1 block number. /// @return Latest L1 block number. function getL1BlockNumber() public view returns (uint256) { - return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).number(); + return IL1Block(Predeploys.L1_BLOCK_ATTRIBUTES).number(); } } diff --git a/packages/contracts-bedrock/src/legacy/L1ChugSplashProxy.sol b/packages/contracts-bedrock/src/legacy/L1ChugSplashProxy.sol index 4f3f7509c9fd6..28125a23f90f4 100644 --- a/packages/contracts-bedrock/src/legacy/L1ChugSplashProxy.sol +++ b/packages/contracts-bedrock/src/legacy/L1ChugSplashProxy.sol @@ -2,13 +2,9 @@ pragma solidity 0.8.15; import { Constants } from "src/libraries/Constants.sol"; +import { IL1ChugSplashDeployer } from "src/legacy/interfaces/IL1ChugSplashProxy.sol"; -/// @title IL1ChugSplashDeployer -interface IL1ChugSplashDeployer { - function isUpgrading() external view returns (bool); -} - -/// @custom:legacy +/// @custom:legacy true /// @title L1ChugSplashProxy /// @notice Basic ChugSplash proxy contract for L1. Very close to being a normal proxy but has added /// functions `setCode` and `setStorage` for changing the code or storage of the contract. diff --git a/packages/contracts-bedrock/src/legacy/LegacyMessagePasser.sol b/packages/contracts-bedrock/src/legacy/LegacyMessagePasser.sol index caf5e6a233225..b90d1263f7a96 100644 --- a/packages/contracts-bedrock/src/legacy/LegacyMessagePasser.sol +++ b/packages/contracts-bedrock/src/legacy/LegacyMessagePasser.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { ISemver } from "src/universal/ISemver.sol"; +import { ISemver } from "src/universal/interfaces/ISemver.sol"; -/// @custom:legacy -/// @custom:proxied +/// @custom:legacy true +/// @custom:proxied true /// @custom:predeploy 0x4200000000000000000000000000000000000000 /// @title LegacyMessagePasser /// @notice The LegacyMessagePasser was the low-level mechanism used to send messages from L2 to L1 @@ -14,8 +14,8 @@ contract LegacyMessagePasser is ISemver { mapping(bytes32 => bool) public sentMessages; /// @notice Semantic version. - /// @custom:semver 1.1.0 - string public constant version = "1.1.0"; + /// @custom:semver 1.1.1-beta.1 + string public constant version = "1.1.1-beta.1"; /// @notice Passes a message to L1. /// @param _message Message to pass to L1. diff --git a/packages/contracts-bedrock/src/legacy/ResolvedDelegateProxy.sol b/packages/contracts-bedrock/src/legacy/ResolvedDelegateProxy.sol index c735339a6bb80..3005456570ff6 100644 --- a/packages/contracts-bedrock/src/legacy/ResolvedDelegateProxy.sol +++ b/packages/contracts-bedrock/src/legacy/ResolvedDelegateProxy.sol @@ -3,7 +3,7 @@ pragma solidity 0.8.15; import { AddressManager } from "src/legacy/AddressManager.sol"; -/// @custom:legacy +/// @custom:legacy true /// @title ResolvedDelegateProxy /// @notice ResolvedDelegateProxy is a legacy proxy contract that makes use of the AddressManager to /// resolve the implementation address. We're maintaining this contract for backwards diff --git a/packages/contracts-bedrock/src/legacy/interfaces/IAddressManager.sol b/packages/contracts-bedrock/src/legacy/interfaces/IAddressManager.sol new file mode 100644 index 0000000000000..3fae2cbab4304 --- /dev/null +++ b/packages/contracts-bedrock/src/legacy/interfaces/IAddressManager.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { IOwnable } from "src/universal/interfaces/IOwnable.sol"; + +/// @title IAddressManager +/// @notice Interface for the AddressManager contract. +interface IAddressManager is IOwnable { + event AddressSet(string indexed name, address newAddress, address oldAddress); + + function getAddress(string memory _name) external view returns (address); + function setAddress(string memory _name, address _address) external; +} diff --git a/packages/contracts-bedrock/src/legacy/interfaces/IDeployerWhitelist.sol b/packages/contracts-bedrock/src/legacy/interfaces/IDeployerWhitelist.sol new file mode 100644 index 0000000000000..050748f1786e8 --- /dev/null +++ b/packages/contracts-bedrock/src/legacy/interfaces/IDeployerWhitelist.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { ISemver } from "src/universal/interfaces/ISemver.sol"; + +/// @title IDeployerWhitelist +/// @notice Interface for the DeployerWhitelist contract. +interface IDeployerWhitelist { + event OwnerChanged(address oldOwner, address newOwner); + event WhitelistDisabled(address oldOwner); + event WhitelistStatusChanged(address deployer, bool whitelisted); + + function enableArbitraryContractDeployment() external; + function isDeployerAllowed(address _deployer) external view returns (bool); + function owner() external view returns (address); + function setOwner(address _owner) external; + function setWhitelistedDeployer(address _deployer, bool _isWhitelisted) external; + function version() external view returns (string memory); + function whitelist(address) external view returns (bool); +} diff --git a/packages/contracts-bedrock/src/legacy/interfaces/IL1BlockNumber.sol b/packages/contracts-bedrock/src/legacy/interfaces/IL1BlockNumber.sol new file mode 100644 index 0000000000000..7634cc67c6906 --- /dev/null +++ b/packages/contracts-bedrock/src/legacy/interfaces/IL1BlockNumber.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { ISemver } from "src/universal/interfaces/ISemver.sol"; + +/// @title IL1BlockNumber +/// @notice Interface for the L1BlockNumber contract. +interface IL1BlockNumber is ISemver { + fallback() external payable; + + receive() external payable; + + function getL1BlockNumber() external view returns (uint256); +} diff --git a/packages/contracts-bedrock/src/legacy/interfaces/IL1ChugSplashProxy.sol b/packages/contracts-bedrock/src/legacy/interfaces/IL1ChugSplashProxy.sol new file mode 100644 index 0000000000000..863c89906751b --- /dev/null +++ b/packages/contracts-bedrock/src/legacy/interfaces/IL1ChugSplashProxy.sol @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/// @title IL1ChugSplashProxy +/// @notice Interface for the L1ChugSplashProxy contract. +interface IL1ChugSplashProxy { + fallback() external payable; + + receive() external payable; + + function getImplementation() external returns (address); + function getOwner() external returns (address); + function setCode(bytes memory _code) external; + function setOwner(address _owner) external; + function setStorage(bytes32 _key, bytes32 _value) external; + + function __constructor__(address _owner) external; +} + +/// @title IStaticL1ChugSplashProxy +/// @notice IStaticL1ChugSplashProxy is a static version of the ChugSplash proxy interface. +interface IStaticL1ChugSplashProxy { + function getImplementation() external view returns (address); + function getOwner() external view returns (address); +} + +/// @title IL1ChugSplashDeployer +interface IL1ChugSplashDeployer { + function isUpgrading() external view returns (bool); +} diff --git a/packages/contracts-bedrock/src/legacy/interfaces/ILegacyMessagePasser.sol b/packages/contracts-bedrock/src/legacy/interfaces/ILegacyMessagePasser.sol new file mode 100644 index 0000000000000..a5fde0fdb65de --- /dev/null +++ b/packages/contracts-bedrock/src/legacy/interfaces/ILegacyMessagePasser.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { ISemver } from "src/universal/interfaces/ISemver.sol"; + +/// @title ILegacyMessagePasser +/// @notice Interface for the LegacyMessagePasser contract. +interface ILegacyMessagePasser is ISemver { + function passMessageToL1(bytes memory _message) external; + function sentMessages(bytes32) external view returns (bool); +} diff --git a/packages/contracts-bedrock/src/legacy/interfaces/IResolvedDelegateProxy.sol b/packages/contracts-bedrock/src/legacy/interfaces/IResolvedDelegateProxy.sol new file mode 100644 index 0000000000000..abeb3817d9be9 --- /dev/null +++ b/packages/contracts-bedrock/src/legacy/interfaces/IResolvedDelegateProxy.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/// @title IResolvedDelegateProxy +/// @notice Interface for the ResolvedDelegateProxy contract. +interface IResolvedDelegateProxy { + fallback() external payable; +} diff --git a/packages/contracts-bedrock/src/libraries/Blueprint.sol b/packages/contracts-bedrock/src/libraries/Blueprint.sol new file mode 100644 index 0000000000000..a7ddf1f9009ba --- /dev/null +++ b/packages/contracts-bedrock/src/libraries/Blueprint.sol @@ -0,0 +1,169 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/// @notice Methods for working with ERC-5202 blueprint contracts. +/// https://eips.ethereum.org/EIPS/eip-5202 +library Blueprint { + /// @notice The structure of a blueprint contract per ERC-5202. + struct Preamble { + uint8 ercVersion; + bytes preambleData; + bytes initcode; + } + + /// @notice Thrown when converting a bytes array to a uint256 and the bytes array is too long. + error BytesArrayTooLong(); + + /// @notice Throw when contract deployment fails. + error DeploymentFailed(); + + /// @notice Thrown when parsing a blueprint preamble and the resulting initcode is empty. + error EmptyInitcode(); + + /// @notice Thrown when call to the identity precompile fails. + error IdentityPrecompileCallFailed(); + + /// @notice Thrown when parsing a blueprint preamble and the bytecode does not contain the expected prefix bytes. + error NotABlueprint(); + + /// @notice Thrown when parsing a blueprint preamble and the reserved bits are set. + error ReservedBitsSet(); + + /// @notice Thrown when parsing a blueprint preamble and the preamble data is not empty. + /// We do not use the preamble data, so it's expected to be empty. + error UnexpectedPreambleData(bytes data); + + /// @notice Thrown during deployment if the ERC version is not supported. + error UnsupportedERCVersion(uint8 version); + + /// @notice Takes the desired initcode for a blueprint as a parameter, and returns EVM code + /// which will deploy a corresponding blueprint contract (with no data section). Based on the + /// reference implementation in https://eips.ethereum.org/EIPS/eip-5202. + function blueprintDeployerBytecode(bytes memory _initcode) internal pure returns (bytes memory) { + // Check that the initcode is not empty. + if (_initcode.length == 0) revert EmptyInitcode(); + + bytes memory blueprintPreamble = hex"FE7100"; // ERC-5202 preamble. + bytes memory blueprintBytecode = bytes.concat(blueprintPreamble, _initcode); + + // The length of the deployed code in bytes. + bytes2 lenBytes = bytes2(uint16(blueprintBytecode.length)); + + // Copy <blueprintBytecode> to memory and `RETURN` it per EVM creation semantics. + // PUSH2 <len> RETURNDATASIZE DUP2 PUSH1 10 RETURNDATASIZE CODECOPY RETURN + bytes memory deployBytecode = bytes.concat(hex"61", lenBytes, hex"3d81600a3d39f3"); + + return bytes.concat(deployBytecode, blueprintBytecode); + } + + /// @notice Given bytecode as a sequence of bytes, parse the blueprint preamble and deconstruct + /// the bytecode into the ERC version, preamble data and initcode. Reverts if the bytecode is + /// not a valid blueprint contract according to ERC-5202. + function parseBlueprintPreamble(bytes memory _bytecode) internal view returns (Preamble memory) { + if (_bytecode.length < 2 || _bytecode[0] != 0xFE || _bytecode[1] != 0x71) { + revert NotABlueprint(); + } + + uint8 ercVersion = uint8(_bytecode[2] & 0xFC) >> 2; + uint8 nLengthBytes = uint8(_bytecode[2] & 0x03); + if (nLengthBytes == 0x03) revert ReservedBitsSet(); + + uint256 dataLength = 0; + if (nLengthBytes > 0) { + bytes memory lengthBytes = new bytes(nLengthBytes); + for (uint256 i = 0; i < nLengthBytes; i++) { + lengthBytes[i] = _bytecode[3 + i]; + } + dataLength = bytesToUint(lengthBytes); + } + + bytes memory preambleData = new bytes(dataLength); + if (nLengthBytes != 0) { + uint256 dataStart = 3 + nLengthBytes; + // This loop is very small, so not worth using the identity precompile like we do with initcode below. + for (uint256 i = 0; i < dataLength; i++) { + preambleData[i] = _bytecode[dataStart + i]; + } + } + + // Parsing the initcode byte-by-byte is too costly for long initcode, so we perform a staticcall + // to the identity precompile at address(0x04) to copy the initcode. + uint256 initcodeStart = 3 + nLengthBytes + dataLength; + uint256 initcodeLength = _bytecode.length - initcodeStart; + if (initcodeLength == 0) revert EmptyInitcode(); + + bytes memory initcode = new bytes(initcodeLength); + bool success; + assembly ("memory-safe") { + // Calculate the memory address of the input data (initcode) within _bytecode. + // - add(_bytecode, 32): Moves past the length field to the start of _bytecode's data. + // - add(..., initcodeStart): Adds the offset to reach the initcode within _bytecode. + let inputData := add(add(_bytecode, 32), initcodeStart) + + // Calculate the memory address for the output data in initcode. + let outputData := add(initcode, 32) + + // Perform the staticcall to the identity precompile. + success := staticcall(gas(), 0x04, inputData, initcodeLength, outputData, initcodeLength) + } + + if (!success) revert IdentityPrecompileCallFailed(); + return Preamble(ercVersion, preambleData, initcode); + } + + /// @notice Parses the code at the given `_target` as a blueprint and deploys the resulting initcode. + /// This version of `deployFrom` is used when the initcode requires no constructor arguments. + function deployFrom(address _target, bytes32 _salt) internal returns (address) { + return deployFrom(_target, _salt, new bytes(0)); + } + + /// @notice Parses the code at the given `_target` as a blueprint and deploys the resulting initcode + /// with the given `_data` appended, i.e. `_data` is the ABI-encoded constructor arguments. + function deployFrom(address _target, bytes32 _salt, bytes memory _data) internal returns (address newContract_) { + Preamble memory preamble = parseBlueprintPreamble(address(_target).code); + if (preamble.ercVersion != 0) revert UnsupportedERCVersion(preamble.ercVersion); + if (preamble.preambleData.length != 0) revert UnexpectedPreambleData(preamble.preambleData); + + bytes memory initcode = bytes.concat(preamble.initcode, _data); + assembly ("memory-safe") { + newContract_ := create2(0, add(initcode, 0x20), mload(initcode), _salt) + } + if (newContract_ == address(0)) revert DeploymentFailed(); + } + + /// @notice Parses the code at two target addresses as individual blueprints, concatentates them and then deploys + /// the resulting initcode with the given `_data` appended, i.e. `_data` is the ABI-encoded constructor arguments. + function deployFrom( + address _target1, + address _target2, + bytes32 _salt, + bytes memory _data + ) + internal + returns (address newContract_) + { + Preamble memory preamble1 = parseBlueprintPreamble(address(_target1).code); + if (preamble1.ercVersion != 0) revert UnsupportedERCVersion(preamble1.ercVersion); + if (preamble1.preambleData.length != 0) revert UnexpectedPreambleData(preamble1.preambleData); + + Preamble memory preamble2 = parseBlueprintPreamble(address(_target2).code); + if (preamble2.ercVersion != 0) revert UnsupportedERCVersion(preamble2.ercVersion); + if (preamble2.preambleData.length != 0) revert UnexpectedPreambleData(preamble2.preambleData); + + bytes memory initcode = bytes.concat(preamble1.initcode, preamble2.initcode, _data); + assembly ("memory-safe") { + newContract_ := create2(0, add(initcode, 0x20), mload(initcode), _salt) + } + if (newContract_ == address(0)) revert DeploymentFailed(); + } + + /// @notice Convert a bytes array to a uint256. + function bytesToUint(bytes memory _b) internal pure returns (uint256) { + if (_b.length > 32) revert BytesArrayTooLong(); + uint256 number; + for (uint256 i = 0; i < _b.length; i++) { + number = number + uint256(uint8(_b[i])) * (2 ** (8 * (_b.length - (i + 1)))); + } + return number; + } +} diff --git a/packages/contracts-bedrock/src/libraries/Constants.sol b/packages/contracts-bedrock/src/libraries/Constants.sol index e86010421d347..1cbd61d21a5e0 100644 --- a/packages/contracts-bedrock/src/libraries/Constants.sol +++ b/packages/contracts-bedrock/src/libraries/Constants.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import { ResourceMetering } from "src/L1/ResourceMetering.sol"; +import { IResourceMetering } from "src/L1/interfaces/IResourceMetering.sol"; /// @title Constants /// @notice Constants is a library for storing constants. Simple! Don't put everything in here, just @@ -39,8 +39,8 @@ library Constants { /// @notice Returns the default values for the ResourceConfig. These are the recommended values /// for a production network. - function DEFAULT_RESOURCE_CONFIG() internal pure returns (ResourceMetering.ResourceConfig memory) { - ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({ + function DEFAULT_RESOURCE_CONFIG() internal pure returns (IResourceMetering.ResourceConfig memory) { + IResourceMetering.ResourceConfig memory config = IResourceMetering.ResourceConfig({ maxResourceLimit: 20_000_000, elasticityMultiplier: 10, baseFeeMaxChangeDenominator: 8, diff --git a/packages/contracts-bedrock/src/libraries/Encoding.sol b/packages/contracts-bedrock/src/libraries/Encoding.sol index dae9486c7c630..7ab1a285841ff 100644 --- a/packages/contracts-bedrock/src/libraries/Encoding.sol +++ b/packages/contracts-bedrock/src/libraries/Encoding.sol @@ -184,8 +184,7 @@ library Encoding { /// @param _blobBaseFee L1 blob base fee. /// @param _hash L1 blockhash. /// @param _batcherHash Versioned hash to authenticate batcher by. - /// @param _dependencySet Array of the chain IDs in the interop dependency set. - function encodeSetL1BlockValuesInterop( + function encodeSetL1BlockValuesIsthmus( uint32 _baseFeeScalar, uint32 _blobBaseFeeScalar, uint64 _sequenceNumber, @@ -194,18 +193,13 @@ library Encoding { uint256 _baseFee, uint256 _blobBaseFee, bytes32 _hash, - bytes32 _batcherHash, - uint256[] memory _dependencySet + bytes32 _batcherHash ) internal pure returns (bytes memory) { - require(_dependencySet.length <= type(uint8).max, "Encoding: dependency set length is too large"); - // Check that the batcher hash is just the address with 0 padding to the left for version 0. - require(uint160(uint256(_batcherHash)) == uint256(_batcherHash), "Encoding: invalid batcher hash"); - - bytes4 functionSignature = bytes4(keccak256("setL1BlockValuesInterop()")); + bytes4 functionSignature = bytes4(keccak256("setL1BlockValuesIsthmus()")); return abi.encodePacked( functionSignature, _baseFeeScalar, @@ -216,9 +210,7 @@ library Encoding { _baseFee, _blobBaseFee, _hash, - _batcherHash, - uint8(_dependencySet.length), - _dependencySet + _batcherHash ); } } diff --git a/packages/contracts-bedrock/src/libraries/L1BlockErrors.sol b/packages/contracts-bedrock/src/libraries/L1BlockErrors.sol index c9ef3903aebe8..44e156e158c06 100644 --- a/packages/contracts-bedrock/src/libraries/L1BlockErrors.sol +++ b/packages/contracts-bedrock/src/libraries/L1BlockErrors.sol @@ -4,6 +4,9 @@ pragma solidity ^0.8.0; /// @notice Error returns when a non-depositor account tries to set L1 block values. error NotDepositor(); +/// @notice Error when a non-cross L2 Inbox sender tries to call the `isDeposit()` method. +error NotCrossL2Inbox(); + /// @notice Error when a chain ID is not in the interop dependency set. error NotDependency(); diff --git a/packages/contracts-bedrock/src/libraries/Predeploys.sol b/packages/contracts-bedrock/src/libraries/Predeploys.sol index 9dcd7f0a95d0f..c8fca4376bdef 100644 --- a/packages/contracts-bedrock/src/libraries/Predeploys.sol +++ b/packages/contracts-bedrock/src/libraries/Predeploys.sol @@ -95,10 +95,16 @@ library Predeploys { /// @notice Address of the ETHLiquidity predeploy. address internal constant ETH_LIQUIDITY = 0x4200000000000000000000000000000000000025; - /// TODO: Add correct predeploy address for OptimismSuperchainERC20Factory /// @notice Address of the OptimismSuperchainERC20Factory predeploy. address internal constant OPTIMISM_SUPERCHAIN_ERC20_FACTORY = 0x4200000000000000000000000000000000000026; + /// @notice Address of the OptimismSuperchainERC20Beacon predeploy. + address internal constant OPTIMISM_SUPERCHAIN_ERC20_BEACON = 0x4200000000000000000000000000000000000027; + + // TODO: Precalculate the address of the implementation contract + /// @notice Arbitrary address of the OptimismSuperchainERC20 implementation contract. + address internal constant OPTIMISM_SUPERCHAIN_ERC20 = 0xB9415c6cA93bdC545D4c5177512FCC22EFa38F28; + /// @notice Returns the name of the predeploy at the given address. function getName(address _addr) internal pure returns (string memory out_) { require(isPredeployNamespace(_addr), "Predeploys: address must be a predeploy"); @@ -128,6 +134,7 @@ library Predeploys { if (_addr == SUPERCHAIN_WETH) return "SuperchainWETH"; if (_addr == ETH_LIQUIDITY) return "ETHLiquidity"; if (_addr == OPTIMISM_SUPERCHAIN_ERC20_FACTORY) return "OptimismSuperchainERC20Factory"; + if (_addr == OPTIMISM_SUPERCHAIN_ERC20_BEACON) return "OptimismSuperchainERC20Beacon"; revert("Predeploys: unnamed predeploy"); } @@ -146,7 +153,8 @@ library Predeploys { || _addr == L1_FEE_VAULT || _addr == SCHEMA_REGISTRY || _addr == EAS || _addr == GOVERNANCE_TOKEN || (_useInterop && _addr == CROSS_L2_INBOX) || (_useInterop && _addr == L2_TO_L2_CROSS_DOMAIN_MESSENGER) || (_useInterop && _addr == SUPERCHAIN_WETH) || (_useInterop && _addr == ETH_LIQUIDITY) - || (_useInterop && _addr == OPTIMISM_SUPERCHAIN_ERC20_FACTORY); + || (_useInterop && _addr == OPTIMISM_SUPERCHAIN_ERC20_FACTORY) + || (_useInterop && _addr == OPTIMISM_SUPERCHAIN_ERC20_BEACON); } function isPredeployNamespace(address _addr) internal pure returns (bool) { diff --git a/packages/contracts-bedrock/src/libraries/Preinstalls.sol b/packages/contracts-bedrock/src/libraries/Preinstalls.sol index 327b34c0abf4c..db886f57f10a9 100644 --- a/packages/contracts-bedrock/src/libraries/Preinstalls.sol +++ b/packages/contracts-bedrock/src/libraries/Preinstalls.sol @@ -44,6 +44,9 @@ library Preinstalls { /// @notice Address of the EntryPoint_v070 predeploy. address internal constant EntryPoint_v070 = 0x0000000071727De22E5E9d8BAf0edAc6f37da032; + /// @notice Address of the CreateX predeploy. + address internal constant CreateX = 0xba5Ed099633D3B313e4D5F7bdc1305d3c28ba5Ed; + /// @notice Address of beacon block roots contract, introduced in the Cancun upgrade. /// See BEACON_ROOTS_ADDRESS in EIP-4788. /// This contract is introduced in L2 through an Ecotone upgrade transaction, if not already in genesis. @@ -99,6 +102,9 @@ library Preinstalls { bytes internal constant EntryPoint_v070Code = hex"60806040526004361015610024575b361561001957600080fd5b61002233612748565b005b60003560e01c806242dc5314611b0057806301ffc9a7146119ae5780630396cb60146116765780630bd28e3b146115fa5780631b2e01b814611566578063205c2878146113d157806322cdde4c1461136b57806335567e1a146112b35780635287ce12146111a557806370a0823114611140578063765e827f14610e82578063850aaf6214610dc35780639b249f6914610c74578063b760faf914610c3a578063bb9fe6bf14610a68578063c23a5cea146107c4578063dbed18e0146101a15763fc7e286d0361000e573461019c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5773ffffffffffffffffffffffffffffffffffffffff61013a61229f565b16600052600060205260a0604060002065ffffffffffff6001825492015460405192835260ff8116151560208401526dffffffffffffffffffffffffffff8160081c16604084015263ffffffff8160781c16606084015260981c166080820152f35b600080fd5b3461019c576101af36612317565b906101b86129bd565b60009160005b82811061056f57506101d08493612588565b6000805b8481106102fc5750507fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f972600080a16000809360005b81811061024757610240868660007f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d8180a2613ba7565b6001600255005b6102a261025582848a612796565b73ffffffffffffffffffffffffffffffffffffffff6102766020830161282a565b167f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d600080a2806127d6565b906000915b8083106102b957505050600101610209565b909194976102f36102ed6001926102e78c8b6102e0826102da8e8b8d61269d565b9261265a565b5191613597565b90612409565b99612416565b950191906102a7565b6020610309828789612796565b61031f61031682806127d6565b9390920161282a565b9160009273ffffffffffffffffffffffffffffffffffffffff8091165b8285106103505750505050506001016101d4565b909192939561037f83610378610366848c61265a565b516103728b898b61269d565b856129f6565b9290613dd7565b9116840361050a576104a5576103958491613dd7565b9116610440576103b5576103aa600191612416565b96019392919061033c565b60a487604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152602160448201527f41413332207061796d61737465722065787069726564206f72206e6f7420647560648201527f65000000000000000000000000000000000000000000000000000000000000006084820152fd5b608488604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601460448201527f41413334207369676e6174757265206572726f720000000000000000000000006064820152fd5b608488604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601760448201527f414132322065787069726564206f72206e6f74206475650000000000000000006064820152fd5b608489604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601460448201527f41413234207369676e6174757265206572726f720000000000000000000000006064820152fd5b61057a818487612796565b9361058585806127d6565b919095602073ffffffffffffffffffffffffffffffffffffffff6105aa82840161282a565b1697600192838a1461076657896105da575b5050505060019293949550906105d191612409565b939291016101be565b8060406105e892019061284b565b918a3b1561019c57929391906040519485937f2dd8113300000000000000000000000000000000000000000000000000000000855288604486016040600488015252606490818601918a60051b8701019680936000915b8c83106106e657505050505050838392610684927ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8560009803016024860152612709565b03818a5afa90816106d7575b506106c657602486604051907f86a9f7500000000000000000000000000000000000000000000000000000000082526004820152fd5b93945084936105d1600189806105bc565b6106e0906121bd565b88610690565b91939596977fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9c908a9294969a0301865288357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee18336030181121561019c57836107538793858394016128ec565b9a0196019301909189979695949261063f565b606483604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152601760248201527f4141393620696e76616c69642061676772656761746f720000000000000000006044820152fd5b3461019c576020807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c576107fc61229f565b33600052600082526001604060002001908154916dffffffffffffffffffffffffffff8360081c16928315610a0a5765ffffffffffff8160981c1680156109ac57421061094e5760009373ffffffffffffffffffffffffffffffffffffffff859485947fffffffffffffff000000000000000000000000000000000000000000000000ff86951690556040517fb7c918e0e249f999e965cafeb6c664271b3f4317d296461500e71da39f0cbda33391806108da8786836020909392919373ffffffffffffffffffffffffffffffffffffffff60408201951681520152565b0390a2165af16108e8612450565b50156108f057005b606490604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152601860248201527f6661696c656420746f207769746864726177207374616b6500000000000000006044820152fd5b606485604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152601b60248201527f5374616b65207769746864726177616c206973206e6f742064756500000000006044820152fd5b606486604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152601d60248201527f6d7573742063616c6c20756e6c6f636b5374616b6528292066697273740000006044820152fd5b606485604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152601460248201527f4e6f207374616b6520746f2077697468647261770000000000000000000000006044820152fd5b3461019c5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c573360005260006020526001604060002001805463ffffffff8160781c16908115610bdc5760ff1615610b7e5765ffffffffffff908142160191818311610b4f5780547fffffffffffffff000000000000ffffffffffffffffffffffffffffffffffff001678ffffffffffff00000000000000000000000000000000000000609885901b161790556040519116815233907ffa9b3c14cc825c412c9ed81b3ba365a5b459439403f18829e572ed53a4180f0a90602090a2005b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f616c726561647920756e7374616b696e670000000000000000000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f6e6f74207374616b6564000000000000000000000000000000000000000000006044820152fd5b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c57610022610c6f61229f565b612748565b3461019c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5760043567ffffffffffffffff811161019c576020610cc8610d1b9236906004016122c2565b919073ffffffffffffffffffffffffffffffffffffffff9260405194859283927f570e1a360000000000000000000000000000000000000000000000000000000084528560048501526024840191612709565b03816000857f000000000000000000000000efc2c1444ebcc4db75e7613d20c6a62ff67a167c165af1908115610db757602492600092610d86575b50604051917f6ca7b806000000000000000000000000000000000000000000000000000000008352166004820152fd5b610da991925060203d602011610db0575b610da181836121ed565b8101906126dd565b9083610d56565b503d610d97565b6040513d6000823e3d90fd5b3461019c5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c57610dfa61229f565b60243567ffffffffffffffff811161019c57600091610e1e839236906004016122c2565b90816040519283928337810184815203915af4610e39612450565b90610e7e6040519283927f99410554000000000000000000000000000000000000000000000000000000008452151560048401526040602484015260448301906123c6565b0390fd5b3461019c57610e9036612317565b610e9b9291926129bd565b610ea483612588565b60005b848110610f1c57506000927fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f972600080a16000915b858310610eec576102408585613ba7565b909193600190610f12610f0087898761269d565b610f0a888661265a565b519088613597565b0194019190610edb565b610f47610f40610f2e8385979561265a565b51610f3a84898761269d565b846129f6565b9190613dd7565b73ffffffffffffffffffffffffffffffffffffffff929183166110db5761107657610f7190613dd7565b911661101157610f8657600101929092610ea7565b60a490604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152602160448201527f41413332207061796d61737465722065787069726564206f72206e6f7420647560648201527f65000000000000000000000000000000000000000000000000000000000000006084820152fd5b608482604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601460448201527f41413334207369676e6174757265206572726f720000000000000000000000006064820152fd5b608483604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601760448201527f414132322065787069726564206f72206e6f74206475650000000000000000006064820152fd5b608484604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601460448201527f41413234207369676e6174757265206572726f720000000000000000000000006064820152fd5b3461019c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5773ffffffffffffffffffffffffffffffffffffffff61118c61229f565b1660005260006020526020604060002054604051908152f35b3461019c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5773ffffffffffffffffffffffffffffffffffffffff6111f161229f565b6000608060405161120181612155565b828152826020820152826040820152826060820152015216600052600060205260a06040600020608060405161123681612155565b6001835493848352015490602081019060ff8316151582526dffffffffffffffffffffffffffff60408201818560081c16815263ffffffff936060840193858760781c16855265ffffffffffff978891019660981c1686526040519788525115156020880152511660408601525116606084015251166080820152f35b3461019c5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5760206112ec61229f565b73ffffffffffffffffffffffffffffffffffffffff6113096122f0565b911660005260018252604060002077ffffffffffffffffffffffffffffffffffffffffffffffff821660005282526040600020547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000006040519260401b16178152f35b3461019c577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc60208136011261019c576004359067ffffffffffffffff821161019c5761012090823603011261019c576113c9602091600401612480565b604051908152f35b3461019c5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5761140861229f565b60243590336000526000602052604060002090815491828411611508576000808573ffffffffffffffffffffffffffffffffffffffff8295839561144c848a612443565b90556040805173ffffffffffffffffffffffffffffffffffffffff831681526020810185905233917fd1c19fbcd4551a5edfb66d43d2e337c04837afda3482b42bdf569a8fccdae5fb91a2165af16114a2612450565b50156114aa57005b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6661696c656420746f20776974686472617700000000000000000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f576974686472617720616d6f756e7420746f6f206c61726765000000000000006044820152fd5b3461019c5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5761159d61229f565b73ffffffffffffffffffffffffffffffffffffffff6115ba6122f0565b9116600052600160205277ffffffffffffffffffffffffffffffffffffffffffffffff604060002091166000526020526020604060002054604051908152f35b3461019c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5760043577ffffffffffffffffffffffffffffffffffffffffffffffff811680910361019c5733600052600160205260406000209060005260205260406000206116728154612416565b9055005b6020807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5760043563ffffffff9182821680920361019c5733600052600081526040600020928215611950576001840154908160781c1683106118f2576116f86dffffffffffffffffffffffffffff9182349160081c16612409565b93841561189457818511611836579065ffffffffffff61180592546040519061172082612155565b8152848101926001845260408201908816815260608201878152600160808401936000855233600052600089526040600020905181550194511515917fffffffffffffffffffffffffff0000000000000000000000000000000000000060ff72ffffffff0000000000000000000000000000006effffffffffffffffffffffffffff008954945160081b16945160781b1694169116171717835551167fffffffffffffff000000000000ffffffffffffffffffffffffffffffffffffff78ffffffffffff0000000000000000000000000000000000000083549260981b169116179055565b6040519283528201527fa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c0160403392a2005b606483604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152600e60248201527f7374616b65206f766572666c6f770000000000000000000000000000000000006044820152fd5b606483604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152601260248201527f6e6f207374616b652073706563696669656400000000000000000000000000006044820152fd5b606482604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152601c60248201527f63616e6e6f7420646563726561736520756e7374616b652074696d65000000006044820152fd5b606482604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152601a60248201527f6d757374207370656369667920756e7374616b652064656c61790000000000006044820152fd5b3461019c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c576004357fffffffff00000000000000000000000000000000000000000000000000000000811680910361019c57807f60fc6b6e0000000000000000000000000000000000000000000000000000000060209214908115611ad6575b8115611aac575b8115611a82575b8115611a58575b506040519015158152f35b7f01ffc9a70000000000000000000000000000000000000000000000000000000091501482611a4d565b7f3e84f0210000000000000000000000000000000000000000000000000000000081149150611a46565b7fcf28ef970000000000000000000000000000000000000000000000000000000081149150611a3f565b7f915074d80000000000000000000000000000000000000000000000000000000081149150611a38565b3461019c576102007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5767ffffffffffffffff60043581811161019c573660238201121561019c57611b62903690602481600401359101612268565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc36016101c0811261019c5761014060405191611b9e83612155565b1261019c5760405192611bb0846121a0565b60243573ffffffffffffffffffffffffffffffffffffffff8116810361019c578452602093604435858201526064356040820152608435606082015260a435608082015260c43560a082015260e43560c08201526101043573ffffffffffffffffffffffffffffffffffffffff8116810361019c5760e08201526101243561010082015261014435610120820152825261016435848301526101843560408301526101a43560608301526101c43560808301526101e43590811161019c57611c7c9036906004016122c2565b905a3033036120f7578351606081015195603f5a0260061c61271060a0840151890101116120ce5760009681519182611ff0575b5050505090611cca915a9003608085015101923691612268565b925a90600094845193611cdc85613ccc565b9173ffffffffffffffffffffffffffffffffffffffff60e0870151168015600014611ea957505073ffffffffffffffffffffffffffffffffffffffff855116935b5a9003019360a06060820151910151016080860151850390818111611e95575b50508302604085015192818410600014611dce5750506003811015611da157600203611d79576113c99293508093611d7481613d65565b613cf6565b5050507fdeadaa51000000000000000000000000000000000000000000000000000000008152fd5b6024857f4e487b710000000000000000000000000000000000000000000000000000000081526021600452fd5b81611dde92979396940390613c98565b506003841015611e6857507f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f60808683015192519473ffffffffffffffffffffffffffffffffffffffff865116948873ffffffffffffffffffffffffffffffffffffffff60e0890151169701519160405192835215898301528760408301526060820152a46113c9565b807f4e487b7100000000000000000000000000000000000000000000000000000000602492526021600452fd5b6064919003600a0204909301928780611d3d565b8095918051611eba575b5050611d1d565b6003861015611fc1576002860315611eb35760a088015190823b1561019c57600091611f2491836040519586809581947f7c627b210000000000000000000000000000000000000000000000000000000083528d60048401526080602484015260848301906123c6565b8b8b0260448301528b60648301520393f19081611fad575b50611fa65787893d610800808211611f9e575b506040519282828501016040528184528284013e610e7e6040519283927fad7954bc000000000000000000000000000000000000000000000000000000008452600484015260248301906123c6565b905083611f4f565b8980611eb3565b611fb89199506121bd565b6000978a611f3c565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91600092918380938c73ffffffffffffffffffffffffffffffffffffffff885116910192f115612023575b808080611cb0565b611cca929195503d6108008082116120c6575b5060405190888183010160405280825260008983013e805161205f575b5050600194909161201b565b7f1c4fada7374c0a9ee8841fc38afe82932dc0f8e69012e927f061a8bae611a20188870151918973ffffffffffffffffffffffffffffffffffffffff8551169401516120bc604051928392835260408d84015260408301906123c6565b0390a38680612053565b905088612036565b877fdeaddead000000000000000000000000000000000000000000000000000000006000526000fd5b606486604051907f08c379a00000000000000000000000000000000000000000000000000000000082526004820152601760248201527f4141393220696e7465726e616c2063616c6c206f6e6c790000000000000000006044820152fd5b60a0810190811067ffffffffffffffff82111761217157604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b610140810190811067ffffffffffffffff82111761217157604052565b67ffffffffffffffff811161217157604052565b6060810190811067ffffffffffffffff82111761217157604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761217157604052565b67ffffffffffffffff811161217157601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b9291926122748261222e565b9161228260405193846121ed565b82948184528183011161019c578281602093846000960137010152565b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361019c57565b9181601f8401121561019c5782359167ffffffffffffffff831161019c576020838186019501011161019c57565b6024359077ffffffffffffffffffffffffffffffffffffffffffffffff8216820361019c57565b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc83011261019c5760043567ffffffffffffffff9283821161019c578060238301121561019c57816004013593841161019c5760248460051b8301011161019c57602401919060243573ffffffffffffffffffffffffffffffffffffffff8116810361019c5790565b60005b8381106123b65750506000910152565b81810151838201526020016123a6565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f602093612402815180928187528780880191016123a3565b0116010190565b91908201809211610b4f57565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610b4f5760010190565b91908203918211610b4f57565b3d1561247b573d906124618261222e565b9161246f60405193846121ed565b82523d6000602084013e565b606090565b604061248e8183018361284b565b90818351918237206124a3606084018461284b565b90818451918237209260c06124bb60e083018361284b565b908186519182372091845195602087019473ffffffffffffffffffffffffffffffffffffffff833516865260208301358789015260608801526080870152608081013560a087015260a081013582870152013560e08501526101009081850152835261012083019167ffffffffffffffff918484108385111761217157838252845190206101408501908152306101608601524661018086015260608452936101a00191821183831017612171575251902090565b67ffffffffffffffff81116121715760051b60200190565b9061259282612570565b6040906125a260405191826121ed565b8381527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06125d08295612570565b019160005b8381106125e25750505050565b60209082516125f081612155565b83516125fb816121a0565b600081526000849181838201528187820152816060818184015260809282848201528260a08201528260c08201528260e082015282610100820152826101208201528652818587015281898701528501528301528286010152016125d5565b805182101561266e5760209160051b010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b919081101561266e5760051b810135907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee18136030182121561019c570190565b9081602091031261019c575173ffffffffffffffffffffffffffffffffffffffff8116810361019c5790565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b7f2da466a7b24304f47e87fa2e1e5a81b9831ce54fec19055ce277ca2f39ba42c4602073ffffffffffffffffffffffffffffffffffffffff61278a3485613c98565b936040519485521692a2565b919081101561266e5760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa18136030182121561019c570190565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561019c570180359067ffffffffffffffff821161019c57602001918160051b3603831361019c57565b3573ffffffffffffffffffffffffffffffffffffffff8116810361019c5790565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561019c570180359067ffffffffffffffff821161019c5760200191813603831361019c57565b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18236030181121561019c57016020813591019167ffffffffffffffff821161019c57813603831361019c57565b61012091813573ffffffffffffffffffffffffffffffffffffffff811680910361019c576129626129476129ba9561299b93855260208601356020860152612937604087018761289c565b9091806040880152860191612709565b612954606086018661289c565b908583036060870152612709565b6080840135608084015260a084013560a084015260c084013560c084015261298d60e085018561289c565b9084830360e0860152612709565b916129ac610100918281019061289c565b929091818503910152612709565b90565b60028054146129cc5760028055565b60046040517f3ee5aeb5000000000000000000000000000000000000000000000000000000008152fd5b926000905a93805194843573ffffffffffffffffffffffffffffffffffffffff811680910361019c5786526020850135602087015260808501356fffffffffffffffffffffffffffffffff90818116606089015260801c604088015260a086013560c088015260c086013590811661010088015260801c610120870152612a8060e086018661284b565b801561357b576034811061351d578060141161019c578060241161019c5760341161019c57602481013560801c60a0880152601481013560801c60808801523560601c60e08701525b612ad285612480565b60208301526040860151946effffffffffffffffffffffffffffff8660c08901511760608901511760808901511760a0890151176101008901511761012089015117116134bf57604087015160608801510160808801510160a08801510160c0880151016101008801510296835173ffffffffffffffffffffffffffffffffffffffff81511690612b66604085018561284b565b806131e4575b505060e0015173ffffffffffffffffffffffffffffffffffffffff1690600082156131ac575b6020612bd7918b828a01516000868a604051978896879586937f19822f7c00000000000000000000000000000000000000000000000000000000855260048501613db5565b0393f160009181613178575b50612c8b573d8c610800808311612c83575b50604051916020818401016040528083526000602084013e610e7e6040519283927f65c8fd4d000000000000000000000000000000000000000000000000000000008452600484015260606024840152600d60648401527f4141323320726576657274656400000000000000000000000000000000000000608484015260a0604484015260a48301906123c6565b915082612bf5565b9a92939495969798999a91156130f2575b509773ffffffffffffffffffffffffffffffffffffffff835116602084015190600052600160205260406000208160401c60005260205267ffffffffffffffff604060002091825492612cee84612416565b9055160361308d575a8503116130285773ffffffffffffffffffffffffffffffffffffffff60e0606093015116612d42575b509060a09184959697986040608096015260608601520135905a900301910152565b969550505a9683519773ffffffffffffffffffffffffffffffffffffffff60e08a01511680600052600060205260406000208054848110612fc3576080612dcd9a9b9c600093878094039055015192602089015183604051809d819582947f52b7512c0000000000000000000000000000000000000000000000000000000084528c60048501613db5565b039286f1978860009160009a612f36575b50612e86573d8b610800808311612e7e575b50604051916020818401016040528083526000602084013e610e7e6040519283927f65c8fd4d000000000000000000000000000000000000000000000000000000008452600484015260606024840152600d60648401527f4141333320726576657274656400000000000000000000000000000000000000608484015260a0604484015260a48301906123c6565b915082612df0565b9991929394959697989998925a900311612eab57509096959094939291906080612d20565b60a490604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152602760448201527f41413336206f766572207061796d6173746572566572696669636174696f6e4760648201527f61734c696d6974000000000000000000000000000000000000000000000000006084820152fd5b915098503d90816000823e612f4b82826121ed565b604081838101031261019c5780519067ffffffffffffffff821161019c57828101601f83830101121561019c578181015191612f868361222e565b93612f9460405195866121ed565b838552820160208483850101011161019c57602092612fba9184808701918501016123a3565b01519838612dde565b60848b604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601e60448201527f41413331207061796d6173746572206465706f73697420746f6f206c6f7700006064820152fd5b608490604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601e60448201527f41413236206f76657220766572696669636174696f6e4761734c696d697400006064820152fd5b608482604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601a60448201527f4141323520696e76616c6964206163636f756e74206e6f6e63650000000000006064820152fd5b600052600060205260406000208054808c11613113578b9003905538612c9c565b608484604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601760448201527f41413231206469646e2774207061792070726566756e640000000000000000006064820152fd5b9091506020813d6020116131a4575b81613194602093836121ed565b8101031261019c57519038612be3565b3d9150613187565b508060005260006020526040600020548a81116000146131d75750612bd7602060005b915050612b92565b6020612bd7918c036131cf565b833b61345a57604088510151602060405180927f570e1a360000000000000000000000000000000000000000000000000000000082528260048301528160008161323260248201898b612709565b039273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000efc2c1444ebcc4db75e7613d20c6a62ff67a167c1690f1908115610db75760009161343b575b5073ffffffffffffffffffffffffffffffffffffffff811680156133d6578503613371573b1561330c5760141161019c5773ffffffffffffffffffffffffffffffffffffffff9183887fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d604060e0958787602086015195510151168251913560601c82526020820152a391612b6c565b60848d604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152602060448201527f4141313520696e6974436f6465206d757374206372656174652073656e6465726064820152fd5b60848e604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152602060448201527f4141313420696e6974436f6465206d7573742072657475726e2073656e6465726064820152fd5b60848f604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601b60448201527f4141313320696e6974436f6465206661696c6564206f72204f4f4700000000006064820152fd5b613454915060203d602011610db057610da181836121ed565b3861327c565b60848d604051907f220266b6000000000000000000000000000000000000000000000000000000008252600482015260406024820152601f60448201527f414131302073656e64657220616c726561647920636f6e7374727563746564006064820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f41413934206761732076616c756573206f766572666c6f7700000000000000006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4141393320696e76616c6964207061796d6173746572416e64446174610000006044820152fd5b5050600060e087015260006080870152600060a0870152612ac9565b9092915a906060810151916040928351967fffffffff00000000000000000000000000000000000000000000000000000000886135d7606084018461284b565b600060038211613b9f575b7f8dd7712f0000000000000000000000000000000000000000000000000000000094168403613a445750505061379d6000926136b292602088015161363a8a5193849360208501528b602485015260648401906128ec565b90604483015203906136727fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0928381018352826121ed565b61379189519485927e42dc5300000000000000000000000000000000000000000000000000000000602085015261020060248501526102248401906123c6565b613760604484018b60806101a091805173ffffffffffffffffffffffffffffffffffffffff808251168652602082015160208701526040820151604087015260608201516060870152838201518487015260a082015160a087015260c082015160c087015260e08201511660e0860152610100808201519086015261012080910151908501526020810151610140850152604081015161016085015260608101516101808501520151910152565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc83820301610204840152876123c6565b039081018352826121ed565b6020918183809351910182305af1600051988652156137bf575b505050505050565b909192939495965060003d8214613a3a575b7fdeaddead00000000000000000000000000000000000000000000000000000000810361385b57608487878051917f220266b600000000000000000000000000000000000000000000000000000000835260048301526024820152600f60448201527f41413935206f7574206f662067617300000000000000000000000000000000006064820152fd5b7fdeadaa510000000000000000000000000000000000000000000000000000000091929395949650146000146138c55750506138a961389e6138b8935a90612443565b608085015190612409565b9083015183611d748295613d65565b905b3880808080806137b7565b909261395290828601518651907ff62676f440ff169a3a9afdbf812e89e7f95975ee8e5c31214ffdef631c5f479273ffffffffffffffffffffffffffffffffffffffff9580878551169401516139483d610800808211613a32575b508a519084818301018c5280825260008583013e8a805194859485528401528a8301906123c6565b0390a35a90612443565b916139636080860193845190612409565b926000905a94829488519761397789613ccc565b948260e08b0151168015600014613a1857505050875116955b5a9003019560a06060820151910151019051860390818111613a04575b5050840290850151928184106000146139de57505080611e68575090816139d89293611d7481613d65565b906138ba565b6139ee9082849397950390613c98565b50611e68575090826139ff92613cf6565b6139d8565b6064919003600a02049094019338806139ad565b90919892509751613a2a575b50613990565b955038613a24565b905038613920565b8181803e516137d1565b613b97945082935090613a8c917e42dc53000000000000000000000000000000000000000000000000000000006020613b6b9501526102006024860152610224850191612709565b613b3a604484018860806101a091805173ffffffffffffffffffffffffffffffffffffffff808251168652602082015160208701526040820151604087015260608201516060870152838201518487015260a082015160a087015260c082015160c087015260e08201511660e0860152610100808201519086015261012080910151908501526020810151610140850152604081015161016085015260608101516101808501520151910152565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc83820301610204840152846123c6565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081018952886121ed565b60008761379d565b5081356135e2565b73ffffffffffffffffffffffffffffffffffffffff168015613c3a57600080809381935af1613bd4612450565b5015613bdc57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f41413931206661696c65642073656e6420746f2062656e6566696369617279006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4141393020696e76616c69642062656e656669636961727900000000000000006044820152fd5b73ffffffffffffffffffffffffffffffffffffffff166000526000602052613cc66040600020918254612409565b80915590565b610120610100820151910151808214613cf257480180821015613ced575090565b905090565b5090565b9190917f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f6080602083015192519473ffffffffffffffffffffffffffffffffffffffff946020868851169660e089015116970151916040519283526000602084015260408301526060820152a4565b60208101519051907f67b4fa9642f42120bf031f3051d1824b0fe25627945b27b8a6a65d5761d5482e60208073ffffffffffffffffffffffffffffffffffffffff855116940151604051908152a3565b613dcd604092959493956060835260608301906128ec565b9460208201520152565b8015613e6457600060408051613dec816121d1565b828152826020820152015273ffffffffffffffffffffffffffffffffffffffff811690604065ffffffffffff91828160a01c16908115613e5c575b60d01c92825191613e37836121d1565b8583528460208401521691829101524211908115613e5457509091565b905042109091565b839150613e27565b5060009060009056fea2646970667358221220b094fd69f04977ae9458e5ba422d01cd2d20dbcfca0992ff37f19aa07deec25464736f6c63430008170033"; + bytes internal constant CreateXCode = + hex"60806040526004361061018a5760003560e01c806381503da1116100d6578063d323826a1161007f578063e96deee411610059578063e96deee414610395578063f5745aba146103a8578063f9664498146103bb57600080fd5b8063d323826a1461034f578063ddda0acb1461036f578063e437252a1461038257600080fd5b80639c36a286116100b05780639c36a28614610316578063a7db93f214610329578063c3fe107b1461033c57600080fd5b806381503da1146102d0578063890c283b146102e357806398e810771461030357600080fd5b80632f990e3f116101385780636cec2536116101125780636cec25361461027d57806374637a7a1461029d5780637f565360146102bd57600080fd5b80632f990e3f1461023757806331a7c8c81461024a57806342d654fc1461025d57600080fd5b806327fe18221161016957806327fe1822146101f15780632852527a1461020457806328ddd0461461021757600080fd5b8062d84acb1461018f57806326307668146101cb57806326a32fc7146101de575b600080fd5b6101a261019d366004612915565b6103ce565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b6101a26101d9366004612994565b6103e6565b6101a26101ec3660046129db565b610452565b6101a26101ff3660046129db565b6104de565b6101a2610212366004612a39565b610539565b34801561022357600080fd5b506101a2610232366004612a90565b6106fe565b6101a2610245366004612aa9565b61072a565b6101a2610258366004612aa9565b6107bb565b34801561026957600080fd5b506101a2610278366004612b1e565b6107c9565b34801561028957600080fd5b506101a2610298366004612a90565b610823565b3480156102a957600080fd5b506101a26102b8366004612b4a565b61084f565b6101a26102cb3660046129db565b611162565b6101a26102de366004612b74565b6111e8565b3480156102ef57600080fd5b506101a26102fe366004612bac565b611276565b6101a2610311366004612bce565b6112a3565b6101a2610324366004612994565b611505565b6101a2610337366004612c49565b6116f1565b6101a261034a366004612aa9565b611964565b34801561035b57600080fd5b506101a261036a366004612cd9565b6119ed565b6101a261037d366004612c49565b611a17565b6101a2610390366004612bce565b611e0c565b6101a26103a3366004612915565b611e95565b6101a26103b6366004612bce565b611ea4565b6101a26103c9366004612b74565b611f2d565b60006103dd8585858533611a17565b95945050505050565b6000806103f2846120db565b90508083516020850134f59150610408826123d3565b604051819073ffffffffffffffffffffffffffffffffffffffff8416907fb8fda7e00c6b06a2b54e58521bc5894fee35f1090e5a3bb6390bfe2b98b497f790600090a35092915050565b60006104d86104d260408051437fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101406020830152419282019290925260608101919091524260808201524460a08201524660c08201523360e08201526000906101000160405160208183030381529060405280519060200120905090565b836103e6565b92915050565b600081516020830134f090506104f3816123d3565b60405173ffffffffffffffffffffffffffffffffffffffff8216907f4db17dd5e4732fb6da34a148104a592783ca119a1e7bb8829eba6cbadef0b51190600090a2919050565b600080610545856120db565b905060008460601b90506040517f3d602d80600a3d3981f3363d3d373d3d3d363d7300000000000000000000000081528160148201527f5af43d82803e903d91602b57fd5bf300000000000000000000000000000000006028820152826037826000f593505073ffffffffffffffffffffffffffffffffffffffff8316610635576040517fc05cee7a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed1660048201526024015b60405180910390fd5b604051829073ffffffffffffffffffffffffffffffffffffffff8516907fb8fda7e00c6b06a2b54e58521bc5894fee35f1090e5a3bb6390bfe2b98b497f790600090a36000808473ffffffffffffffffffffffffffffffffffffffff1634876040516106a19190612d29565b60006040518083038185875af1925050503d80600081146106de576040519150601f19603f3d011682016040523d82523d6000602084013e6106e3565b606091505b50915091506106f382828961247d565b505050509392505050565b60006104d87f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed8361084f565b60006107b36107aa60408051437fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101406020830152419282019290925260608101919091524260808201524460a08201524660c08201523360e08201526000906101000160405160208183030381529060405280519060200120905090565b85858533611a17565b949350505050565b60006107b3848484336112a3565b60006040518260005260ff600b53836020527f21c35dbe1b344a2488cf3321d6ce542f8e9f305544ff09e4993a62319a497c1f6040526055600b20601452806040525061d694600052600160345350506017601e20919050565b60006104d8827f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed6107c9565b600060607f9400000000000000000000000000000000000000000000000000000000000000610887600167ffffffffffffffff612d45565b67ffffffffffffffff16841115610902576040517f3c55ab3b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed16600482015260240161062c565b836000036109c7576040517fd60000000000000000000000000000000000000000000000000000000000000060208201527fff00000000000000000000000000000000000000000000000000000000000000821660218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606087901b1660228201527f800000000000000000000000000000000000000000000000000000000000000060368201526037015b6040516020818303038152906040529150611152565b607f8411610a60576040517fd60000000000000000000000000000000000000000000000000000000000000060208201527fff0000000000000000000000000000000000000000000000000000000000000080831660218301527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606088901b16602283015260f886901b1660368201526037016109b1565b60ff8411610b1f576040517fd70000000000000000000000000000000000000000000000000000000000000060208201527fff0000000000000000000000000000000000000000000000000000000000000080831660218301527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606088901b1660228301527f8100000000000000000000000000000000000000000000000000000000000000603683015260f886901b1660378201526038016109b1565b61ffff8411610bff576040517fd80000000000000000000000000000000000000000000000000000000000000060208201527fff00000000000000000000000000000000000000000000000000000000000000821660218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606087901b1660228201527f820000000000000000000000000000000000000000000000000000000000000060368201527fffff00000000000000000000000000000000000000000000000000000000000060f086901b1660378201526039016109b1565b62ffffff8411610ce0576040517fd90000000000000000000000000000000000000000000000000000000000000060208201527fff00000000000000000000000000000000000000000000000000000000000000821660218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606087901b1660228201527f830000000000000000000000000000000000000000000000000000000000000060368201527fffffff000000000000000000000000000000000000000000000000000000000060e886901b166037820152603a016109b1565b63ffffffff8411610dc2576040517fda0000000000000000000000000000000000000000000000000000000000000060208201527fff00000000000000000000000000000000000000000000000000000000000000821660218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606087901b1660228201527f840000000000000000000000000000000000000000000000000000000000000060368201527fffffffff0000000000000000000000000000000000000000000000000000000060e086901b166037820152603b016109b1565b64ffffffffff8411610ea5576040517fdb0000000000000000000000000000000000000000000000000000000000000060208201527fff00000000000000000000000000000000000000000000000000000000000000821660218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606087901b1660228201527f850000000000000000000000000000000000000000000000000000000000000060368201527fffffffffff00000000000000000000000000000000000000000000000000000060d886901b166037820152603c016109b1565b65ffffffffffff8411610f89576040517fdc0000000000000000000000000000000000000000000000000000000000000060208201527fff00000000000000000000000000000000000000000000000000000000000000821660218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606087901b1660228201527f860000000000000000000000000000000000000000000000000000000000000060368201527fffffffffffff000000000000000000000000000000000000000000000000000060d086901b166037820152603d016109b1565b66ffffffffffffff841161106e576040517fdd0000000000000000000000000000000000000000000000000000000000000060208201527fff00000000000000000000000000000000000000000000000000000000000000821660218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606087901b1660228201527f870000000000000000000000000000000000000000000000000000000000000060368201527fffffffffffffff0000000000000000000000000000000000000000000000000060c886901b166037820152603e016109b1565b6040517fde0000000000000000000000000000000000000000000000000000000000000060208201527fff00000000000000000000000000000000000000000000000000000000000000821660218201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606087901b1660228201527f880000000000000000000000000000000000000000000000000000000000000060368201527fffffffffffffffff00000000000000000000000000000000000000000000000060c086901b166037820152603f0160405160208183030381529060405291505b5080516020909101209392505050565b60006104d86111e260408051437fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101406020830152419282019290925260608101919091524260808201524460a08201524660c08201523360e08201526000906101000160405160208183030381529060405280519060200120905090565b83611505565b600061126f61126860408051437fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101406020830152419282019290925260608101919091524260808201524460a08201524660c08201523360e08201526000906101000160405160208183030381529060405280519060200120905090565b8484610539565b9392505050565b600061126f83837f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed6119ed565b60008451602086018451f090506112b9816123d3565b60405173ffffffffffffffffffffffffffffffffffffffff8216907f4db17dd5e4732fb6da34a148104a592783ca119a1e7bb8829eba6cbadef0b51190600090a26000808273ffffffffffffffffffffffffffffffffffffffff168560200151876040516113279190612d29565b60006040518083038185875af1925050503d8060008114611364576040519150601f19603f3d011682016040523d82523d6000602084013e611369565b606091505b5091509150816113c9577f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed816040517fa57ca23900000000000000000000000000000000000000000000000000000000815260040161062c929190612d94565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed1631156114fb578373ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed73ffffffffffffffffffffffffffffffffffffffff163160405160006040518083038185875af1925050503d8060008114611495576040519150601f19603f3d011682016040523d82523d6000602084013e61149a565b606091505b509092509050816114fb577f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed816040517fc2b3f44500000000000000000000000000000000000000000000000000000000815260040161062c929190612d94565b5050949350505050565b600080611511846120db565b905060006040518060400160405280601081526020017f67363d3d37363d34f03d5260086018f30000000000000000000000000000000081525090506000828251602084016000f5905073ffffffffffffffffffffffffffffffffffffffff81166115e0576040517fc05cee7a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed16600482015260240161062c565b604051839073ffffffffffffffffffffffffffffffffffffffff8316907f2feea65dd4e9f9cbd86b74b7734210c59a1b2981b5b137bd0ee3e208200c906790600090a361162c83610823565b935060008173ffffffffffffffffffffffffffffffffffffffff1634876040516116569190612d29565b60006040518083038185875af1925050503d8060008114611693576040519150601f19603f3d011682016040523d82523d6000602084013e611698565b606091505b505090506116a681866124ff565b60405173ffffffffffffffffffffffffffffffffffffffff8616907f4db17dd5e4732fb6da34a148104a592783ca119a1e7bb8829eba6cbadef0b51190600090a25050505092915050565b6000806116fd876120db565b9050808651602088018651f59150611714826123d3565b604051819073ffffffffffffffffffffffffffffffffffffffff8416907fb8fda7e00c6b06a2b54e58521bc5894fee35f1090e5a3bb6390bfe2b98b497f790600090a36000808373ffffffffffffffffffffffffffffffffffffffff168660200151886040516117849190612d29565b60006040518083038185875af1925050503d80600081146117c1576040519150601f19603f3d011682016040523d82523d6000602084013e6117c6565b606091505b509150915081611826577f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed816040517fa57ca23900000000000000000000000000000000000000000000000000000000815260040161062c929190612d94565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed163115611958578473ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed73ffffffffffffffffffffffffffffffffffffffff163160405160006040518083038185875af1925050503d80600081146118f2576040519150601f19603f3d011682016040523d82523d6000602084013e6118f7565b606091505b50909250905081611958577f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed816040517fc2b3f44500000000000000000000000000000000000000000000000000000000815260040161062c929190612d94565b50505095945050505050565b60006107b36119e460408051437fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101406020830152419282019290925260608101919091524260808201524460a08201524660c08201523360e08201526000906101000160405160208183030381529060405280519060200120905090565b858585336116f1565b6000604051836040820152846020820152828152600b8101905060ff815360559020949350505050565b600080611a23876120db565b905060006040518060400160405280601081526020017f67363d3d37363d34f03d5260086018f30000000000000000000000000000000081525090506000828251602084016000f5905073ffffffffffffffffffffffffffffffffffffffff8116611af2576040517fc05cee7a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed16600482015260240161062c565b604051839073ffffffffffffffffffffffffffffffffffffffff8316907f2feea65dd4e9f9cbd86b74b7734210c59a1b2981b5b137bd0ee3e208200c906790600090a3611b3e83610823565b935060008173ffffffffffffffffffffffffffffffffffffffff1687600001518a604051611b6c9190612d29565b60006040518083038185875af1925050503d8060008114611ba9576040519150601f19603f3d011682016040523d82523d6000602084013e611bae565b606091505b50509050611bbc81866124ff565b60405173ffffffffffffffffffffffffffffffffffffffff8616907f4db17dd5e4732fb6da34a148104a592783ca119a1e7bb8829eba6cbadef0b51190600090a260608573ffffffffffffffffffffffffffffffffffffffff1688602001518a604051611c299190612d29565b60006040518083038185875af1925050503d8060008114611c66576040519150601f19603f3d011682016040523d82523d6000602084013e611c6b565b606091505b50909250905081611ccc577f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed816040517fa57ca23900000000000000000000000000000000000000000000000000000000815260040161062c929190612d94565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed163115611dfe578673ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed73ffffffffffffffffffffffffffffffffffffffff163160405160006040518083038185875af1925050503d8060008114611d98576040519150601f19603f3d011682016040523d82523d6000602084013e611d9d565b606091505b50909250905081611dfe577f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed816040517fc2b3f44500000000000000000000000000000000000000000000000000000000815260040161062c929190612d94565b505050505095945050505050565b60006103dd611e8c60408051437fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101406020830152419282019290925260608101919091524260808201524460a08201524660c08201523360e08201526000906101000160405160208183030381529060405280519060200120905090565b868686866116f1565b60006103dd85858585336116f1565b60006103dd611f2460408051437fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101406020830152419282019290925260608101919091524260808201524460a08201524660c08201523360e08201526000906101000160405160208183030381529060405280519060200120905090565b86868686611a17565b6000808360601b90506040517f3d602d80600a3d3981f3363d3d373d3d3d363d7300000000000000000000000081528160148201527f5af43d82803e903d91602b57fd5bf3000000000000000000000000000000000060288201526037816000f092505073ffffffffffffffffffffffffffffffffffffffff8216612016576040517fc05cee7a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed16600482015260240161062c565b60405173ffffffffffffffffffffffffffffffffffffffff8316907f4db17dd5e4732fb6da34a148104a592783ca119a1e7bb8829eba6cbadef0b51190600090a26000808373ffffffffffffffffffffffffffffffffffffffff1634866040516120809190612d29565b60006040518083038185875af1925050503d80600081146120bd576040519150601f19603f3d011682016040523d82523d6000602084013e6120c2565b606091505b50915091506120d282828861247d565b50505092915050565b60008060006120e9846125b3565b9092509050600082600281111561210257612102612e02565b1480156121205750600081600281111561211e5761211e612e02565b145b1561215e57604080513360208201524691810191909152606081018590526080016040516020818303038152906040528051906020012092506123cc565b600082600281111561217257612172612e02565b1480156121905750600181600281111561218e5761218e612e02565b145b156121b0576121a9338560009182526020526040902090565b92506123cc565b60008260028111156121c4576121c4612e02565b03612233576040517f13b3a2a100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed16600482015260240161062c565b600182600281111561224757612247612e02565b1480156122655750600081600281111561226357612263612e02565b145b1561227e576121a9468560009182526020526040902090565b600182600281111561229257612292612e02565b1480156122b0575060028160028111156122ae576122ae612e02565b145b1561231f576040517f13b3a2a100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed16600482015260240161062c565b61239a60408051437fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101406020830152419282019290925260608101919091524260808201524460a08201524660c08201523360e08201526000906101000160405160208183030381529060405280519060200120905090565b84036123a657836123c9565b604080516020810186905201604051602081830303815290604052805190602001205b92505b5050919050565b73ffffffffffffffffffffffffffffffffffffffff8116158061240b575073ffffffffffffffffffffffffffffffffffffffff81163b155b1561247a576040517fc05cee7a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed16600482015260240161062c565b50565b82158061249f575073ffffffffffffffffffffffffffffffffffffffff81163b155b156124fa577f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed826040517fa57ca23900000000000000000000000000000000000000000000000000000000815260040161062c929190612d94565b505050565b811580612520575073ffffffffffffffffffffffffffffffffffffffff8116155b80612540575073ffffffffffffffffffffffffffffffffffffffff81163b155b156125af576040517fc05cee7a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ba5ed099633d3b313e4d5f7bdc1305d3c28ba5ed16600482015260240161062c565b5050565b600080606083901c3314801561261057508260141a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167f0100000000000000000000000000000000000000000000000000000000000000145b1561262057506000905080915091565b606083901c3314801561265a57507fff00000000000000000000000000000000000000000000000000000000000000601484901a60f81b16155b1561266b5750600090506001915091565b33606084901c036126825750600090506002915091565b606083901c1580156126db57508260141a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167f0100000000000000000000000000000000000000000000000000000000000000145b156126ec5750600190506000915091565b606083901c15801561272557507fff00000000000000000000000000000000000000000000000000000000000000601484901a60f81b16155b1561273557506001905080915091565b606083901c61274a5750600190506002915091565b8260141a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167f0100000000000000000000000000000000000000000000000000000000000000036127a55750600290506000915091565b8260141a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166000036127e15750600290506001915091565b506002905080915091565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261282c57600080fd5b813567ffffffffffffffff80821115612847576128476127ec565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561288d5761288d6127ec565b816040528381528660208588010111156128a657600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000604082840312156128d857600080fd5b6040516040810181811067ffffffffffffffff821117156128fb576128fb6127ec565b604052823581526020928301359281019290925250919050565b60008060008060a0858703121561292b57600080fd5b84359350602085013567ffffffffffffffff8082111561294a57600080fd5b6129568883890161281b565b9450604087013591508082111561296c57600080fd5b506129798782880161281b565b92505061298986606087016128c6565b905092959194509250565b600080604083850312156129a757600080fd5b82359150602083013567ffffffffffffffff8111156129c557600080fd5b6129d18582860161281b565b9150509250929050565b6000602082840312156129ed57600080fd5b813567ffffffffffffffff811115612a0457600080fd5b6107b38482850161281b565b803573ffffffffffffffffffffffffffffffffffffffff81168114612a3457600080fd5b919050565b600080600060608486031215612a4e57600080fd5b83359250612a5e60208501612a10565b9150604084013567ffffffffffffffff811115612a7a57600080fd5b612a868682870161281b565b9150509250925092565b600060208284031215612aa257600080fd5b5035919050565b600080600060808486031215612abe57600080fd5b833567ffffffffffffffff80821115612ad657600080fd5b612ae28783880161281b565b94506020860135915080821115612af857600080fd5b50612b058682870161281b565b925050612b1585604086016128c6565b90509250925092565b60008060408385031215612b3157600080fd5b82359150612b4160208401612a10565b90509250929050565b60008060408385031215612b5d57600080fd5b612b6683612a10565b946020939093013593505050565b60008060408385031215612b8757600080fd5b612b9083612a10565b9150602083013567ffffffffffffffff8111156129c557600080fd5b60008060408385031215612bbf57600080fd5b50508035926020909101359150565b60008060008060a08587031215612be457600080fd5b843567ffffffffffffffff80821115612bfc57600080fd5b612c088883890161281b565b95506020870135915080821115612c1e57600080fd5b50612c2b8782880161281b565b935050612c3b86604087016128c6565b915061298960808601612a10565b600080600080600060c08688031215612c6157600080fd5b85359450602086013567ffffffffffffffff80821115612c8057600080fd5b612c8c89838a0161281b565b95506040880135915080821115612ca257600080fd5b50612caf8882890161281b565b935050612cbf87606088016128c6565b9150612ccd60a08701612a10565b90509295509295909350565b600080600060608486031215612cee57600080fd5b8335925060208401359150612b1560408501612a10565b60005b83811015612d20578181015183820152602001612d08565b50506000910152565b60008251612d3b818460208701612d05565b9190910192915050565b67ffffffffffffffff828116828216039080821115612d8d577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5092915050565b73ffffffffffffffffffffffffffffffffffffffff831681526040602082015260008251806040840152612dcf816060850160208701612d05565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016060019392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea164736f6c6343000817000a"; + bytes internal constant BeaconBlockRootsCode = hex"3373fffffffffffffffffffffffffffffffffffffffe14604d57602036146024575f5ffd5b5f35801560495762001fff810690815414603c575f5ffd5b62001fff01545f5260205ff35b5f5ffd5b62001fff42064281555f359062001fff015500"; @@ -118,6 +124,7 @@ library Preinstalls { if (_addr == Permit2) return getPermit2Code(_chainID); if (_addr == BeaconBlockRoots) return BeaconBlockRootsCode; + if (_addr == CreateX) return CreateXCode; revert("Preinstalls: unknown preinstall"); } @@ -138,6 +145,7 @@ library Preinstalls { if (_addr == SenderCreator_v070) return "SenderCreator_v070"; if (_addr == EntryPoint_v070) return "EntryPoint_v070"; if (_addr == BeaconBlockRoots) return "BeaconBlockRoots"; + if (_addr == CreateX) return "CreateX"; revert("Preinstalls: unnamed preinstall"); } diff --git a/packages/contracts-bedrock/src/libraries/SafeCall.sol b/packages/contracts-bedrock/src/libraries/SafeCall.sol index c2c4e635f0fbe..a8ae9ec8be324 100644 --- a/packages/contracts-bedrock/src/libraries/SafeCall.sol +++ b/packages/contracts-bedrock/src/libraries/SafeCall.sol @@ -67,6 +67,13 @@ library SafeCall { success_ = call({ _target: _target, _gas: gasleft(), _value: _value, _calldata: _calldata }); } + /// @notice Perform a low level call without copying any returndata + /// @param _target Address to call + /// @param _calldata Calldata to pass to the call + function call(address _target, bytes memory _calldata) internal returns (bool success_) { + success_ = call({ _target: _target, _gas: gasleft(), _value: 0, _calldata: _calldata }); + } + /// @notice Helper function to determine if there is sufficient gas remaining within the context /// to guarantee that the minimum gas requirement for a call will be met as well as /// optionally reserving a specified amount of gas for after the call has concluded. diff --git a/packages/contracts-bedrock/src/periphery/drippie/dripchecks/CheckGelatoLow.sol b/packages/contracts-bedrock/src/periphery/drippie/dripchecks/CheckGelatoLow.sol index 0ef6a0020c6a9..a5ef463f89e6e 100644 --- a/packages/contracts-bedrock/src/periphery/drippie/dripchecks/CheckGelatoLow.sol +++ b/packages/contracts-bedrock/src/periphery/drippie/dripchecks/CheckGelatoLow.sol @@ -2,11 +2,7 @@ pragma solidity 0.8.15; import { IDripCheck } from "../IDripCheck.sol"; - -interface IGelatoTreasury { - function totalDepositedAmount(address _user, address _token) external view returns (uint256); - function totalWithdrawnAmount(address _user, address _token) external view returns (uint256); -} +import { IGelatoTreasury } from "src/vendor/interfaces/IGelatoTreasury.sol"; /// @title CheckGelatoLow /// @notice DripCheck for checking if an account's Gelato ETH balance is below some threshold. diff --git a/packages/contracts-bedrock/src/periphery/faucet/authmodules/IFaucetAuthModule.sol b/packages/contracts-bedrock/src/periphery/faucet/authmodules/IFaucetAuthModule.sol index 5bef4c8c705a0..a94071dd2befc 100644 --- a/packages/contracts-bedrock/src/periphery/faucet/authmodules/IFaucetAuthModule.sol +++ b/packages/contracts-bedrock/src/periphery/faucet/authmodules/IFaucetAuthModule.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.15; +pragma solidity ^0.8.0; import { Faucet } from "../Faucet.sol"; diff --git a/packages/contracts-bedrock/src/periphery/op-nft/AttestationStation.sol b/packages/contracts-bedrock/src/periphery/op-nft/AttestationStation.sol index b9af730a71d4a..4d15862d43580 100644 --- a/packages/contracts-bedrock/src/periphery/op-nft/AttestationStation.sol +++ b/packages/contracts-bedrock/src/periphery/op-nft/AttestationStation.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { ISemver } from "src/universal/ISemver.sol"; +import { ISemver } from "src/universal/interfaces/ISemver.sol"; /// @title AttestationStation /// @author Optimism Collective @@ -29,8 +29,8 @@ contract AttestationStation is ISemver { event AttestationCreated(address indexed creator, address indexed about, bytes32 indexed key, bytes val); /// @notice Semantic version. - /// @custom:semver 1.2.0 - string public constant version = "1.2.0"; + /// @custom:semver 1.2.1-beta.1 + string public constant version = "1.2.1-beta.1"; /// @notice Allows anyone to create an attestation. /// @param _about Address that the attestation is about. diff --git a/packages/contracts-bedrock/src/periphery/op-nft/Optimist.sol b/packages/contracts-bedrock/src/periphery/op-nft/Optimist.sol index 74d04b087d865..b15c0f00044c6 100644 --- a/packages/contracts-bedrock/src/periphery/op-nft/Optimist.sol +++ b/packages/contracts-bedrock/src/periphery/op-nft/Optimist.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { ISemver } from "src/universal/ISemver.sol"; +import { ISemver } from "src/universal/interfaces/ISemver.sol"; import { ERC721BurnableUpgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721BurnableUpgradeable.sol"; import { AttestationStation } from "src/periphery/op-nft/AttestationStation.sol"; @@ -26,8 +26,8 @@ contract Optimist is ERC721BurnableUpgradeable, ISemver { OptimistAllowlist public immutable OPTIMIST_ALLOWLIST; /// @notice Semantic version. - /// @custom:semver 2.1.0 - string public constant version = "2.1.0"; + /// @custom:semver 2.1.1-beta.1 + string public constant version = "2.1.1-beta.1"; /// @param _name Token name. /// @param _symbol Token symbol. diff --git a/packages/contracts-bedrock/src/periphery/op-nft/OptimistAllowlist.sol b/packages/contracts-bedrock/src/periphery/op-nft/OptimistAllowlist.sol index b8212a37c6744..ffa46116a4c59 100644 --- a/packages/contracts-bedrock/src/periphery/op-nft/OptimistAllowlist.sol +++ b/packages/contracts-bedrock/src/periphery/op-nft/OptimistAllowlist.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { ISemver } from "src/universal/ISemver.sol"; +import { ISemver } from "src/universal/interfaces/ISemver.sol"; import { AttestationStation } from "src/periphery/op-nft/AttestationStation.sol"; import { OptimistConstants } from "src/periphery/op-nft/libraries/OptimistConstants.sol"; @@ -31,8 +31,8 @@ contract OptimistAllowlist is ISemver { address public immutable OPTIMIST_INVITER; /// @notice Semantic version. - /// @custom:semver 1.1.0 - string public constant version = "1.1.0"; + /// @custom:semver 1.1.1-beta.1 + string public constant version = "1.1.1-beta.1"; /// @param _attestationStation Address of the AttestationStation contract. /// @param _allowlistAttestor Address of the allowlist attestor. diff --git a/packages/contracts-bedrock/src/periphery/op-nft/OptimistInviter.sol b/packages/contracts-bedrock/src/periphery/op-nft/OptimistInviter.sol index 222405d77c336..ae0ab9d92657c 100644 --- a/packages/contracts-bedrock/src/periphery/op-nft/OptimistInviter.sol +++ b/packages/contracts-bedrock/src/periphery/op-nft/OptimistInviter.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.15; import { OptimistConstants } from "src/periphery/op-nft/libraries/OptimistConstants.sol"; -import { ISemver } from "src/universal/ISemver.sol"; +import { ISemver } from "src/universal/interfaces/ISemver.sol"; import { AttestationStation } from "src/periphery/op-nft/AttestationStation.sol"; import { SignatureChecker } from "@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol"; import { EIP712Upgradeable } from "@openzeppelin/contracts-upgradeable/utils/cryptography/draft-EIP712Upgradeable.sol"; @@ -88,8 +88,8 @@ contract OptimistInviter is ISemver, EIP712Upgradeable { mapping(address => uint256) public inviteCounts; /// @notice Semantic version. - /// @custom:semver 1.1.0 - string public constant version = "1.1.0"; + /// @custom:semver 1.1.1-beta.1 + string public constant version = "1.1.1-beta.1"; /// @param _inviteGranter Address of the invite granter. /// @param _attestationStation Address of the AttestationStation contract. diff --git a/packages/contracts-bedrock/src/Safe/DeputyGuardianModule.sol b/packages/contracts-bedrock/src/safe/DeputyGuardianModule.sol similarity index 82% rename from packages/contracts-bedrock/src/Safe/DeputyGuardianModule.sol rename to packages/contracts-bedrock/src/safe/DeputyGuardianModule.sol index 485af22738eb9..0882910d50721 100644 --- a/packages/contracts-bedrock/src/Safe/DeputyGuardianModule.sol +++ b/packages/contracts-bedrock/src/safe/DeputyGuardianModule.sol @@ -1,19 +1,22 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Safe import { GnosisSafe as Safe } from "safe-contracts/GnosisSafe.sol"; import { Enum } from "safe-contracts/common/Enum.sol"; -import { IFaultDisputeGame } from "src/dispute/interfaces/IFaultDisputeGame.sol"; -import { SuperchainConfig } from "src/L1/SuperchainConfig.sol"; -import { OptimismPortal2 } from "src/L1/OptimismPortal2.sol"; -import { IDisputeGame } from "src/dispute/interfaces/IDisputeGame.sol"; -import { ISemver } from "src/universal/ISemver.sol"; +// Libraries import { Unauthorized } from "src/libraries/PortalErrors.sol"; -import { AnchorStateRegistry } from "src/dispute/AnchorStateRegistry.sol"; - import "src/dispute/lib/Types.sol"; +// Interfaces +import { IAnchorStateRegistry } from "src/dispute/interfaces/IAnchorStateRegistry.sol"; +import { IFaultDisputeGame } from "src/dispute/interfaces/IFaultDisputeGame.sol"; +import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol"; +import { IOptimismPortal2 } from "src/L1/interfaces/IOptimismPortal2.sol"; +import { IDisputeGame } from "src/dispute/interfaces/IDisputeGame.sol"; +import { ISemver } from "src/universal/interfaces/ISemver.sol"; + /// @title DeputyGuardianModule /// @notice This module is intended to be enabled on the Security Council Safe, which will own the Guardian role in the /// SuperchainConfig contract. The DeputyGuardianModule should allow a Deputy Guardian to administer any of the @@ -39,17 +42,17 @@ contract DeputyGuardianModule is ISemver { Safe internal immutable SAFE; /// @notice The SuperchainConfig's address - SuperchainConfig internal immutable SUPERCHAIN_CONFIG; + ISuperchainConfig internal immutable SUPERCHAIN_CONFIG; /// @notice The deputy guardian's address address internal immutable DEPUTY_GUARDIAN; /// @notice Semantic version. - /// @custom:semver 2.0.0-rc.1 - string public constant version = "2.0.0-rc.1"; + /// @custom:semver 2.0.1-beta.3 + string public constant version = "2.0.1-beta.3"; // Constructor to initialize the Safe and baseModule instances - constructor(Safe _safe, SuperchainConfig _superchainConfig, address _deputyGuardian) { + constructor(Safe _safe, ISuperchainConfig _superchainConfig, address _deputyGuardian) { SAFE = _safe; SUPERCHAIN_CONFIG = _superchainConfig; DEPUTY_GUARDIAN = _deputyGuardian; @@ -63,7 +66,7 @@ contract DeputyGuardianModule is ISemver { /// @notice Getter function for the SuperchainConfig's address /// @return superchainConfig_ The SuperchainConfig's address - function superchainConfig() public view returns (SuperchainConfig superchainConfig_) { + function superchainConfig() public view returns (ISuperchainConfig superchainConfig_) { superchainConfig_ = SUPERCHAIN_CONFIG; } @@ -113,12 +116,12 @@ contract DeputyGuardianModule is ISemver { /// @notice Calls the Security Council Safe's `execTransactionFromModuleReturnData()`, with the arguments /// necessary to call `setAnchorState()` on the `AnchorStateRegistry` contract. /// Only the deputy guardian can call this function. - /// @param _registry The `AnchorStateRegistry` contract instance. + /// @param _registry The `IAnchorStateRegistry` contract instance. /// @param _game The `IFaultDisputeGame` contract instance. - function setAnchorState(AnchorStateRegistry _registry, IFaultDisputeGame _game) external { + function setAnchorState(IAnchorStateRegistry _registry, IFaultDisputeGame _game) external { _onlyDeputyGuardian(); - bytes memory data = abi.encodeCall(AnchorStateRegistry.setAnchorState, (_game)); + bytes memory data = abi.encodeCall(IAnchorStateRegistry.setAnchorState, (_game)); (bool success, bytes memory returnData) = SAFE.execTransactionFromModuleReturnData(address(_registry), 0, data, Enum.Operation.Call); if (!success) { @@ -131,10 +134,10 @@ contract DeputyGuardianModule is ISemver { /// Only the deputy guardian can call this function. /// @param _portal The `OptimismPortal2` contract instance. /// @param _game The `IDisputeGame` contract instance. - function blacklistDisputeGame(OptimismPortal2 _portal, IDisputeGame _game) external { + function blacklistDisputeGame(IOptimismPortal2 _portal, IDisputeGame _game) external { _onlyDeputyGuardian(); - bytes memory data = abi.encodeCall(OptimismPortal2.blacklistDisputeGame, (_game)); + bytes memory data = abi.encodeCall(IOptimismPortal2.blacklistDisputeGame, (_game)); (bool success, bytes memory returnData) = SAFE.execTransactionFromModuleReturnData(address(_portal), 0, data, Enum.Operation.Call); if (!success) { @@ -148,10 +151,10 @@ contract DeputyGuardianModule is ISemver { /// Only the deputy guardian can call this function. /// @param _portal The `OptimismPortal2` contract instance. /// @param _gameType The `GameType` to set as the respected game type. - function setRespectedGameType(OptimismPortal2 _portal, GameType _gameType) external { + function setRespectedGameType(IOptimismPortal2 _portal, GameType _gameType) external { _onlyDeputyGuardian(); - bytes memory data = abi.encodeCall(OptimismPortal2.setRespectedGameType, (_gameType)); + bytes memory data = abi.encodeCall(IOptimismPortal2.setRespectedGameType, (_gameType)); (bool success, bytes memory returnData) = SAFE.execTransactionFromModuleReturnData(address(_portal), 0, data, Enum.Operation.Call); if (!success) { diff --git a/packages/contracts-bedrock/src/Safe/LivenessGuard.sol b/packages/contracts-bedrock/src/safe/LivenessGuard.sol similarity index 96% rename from packages/contracts-bedrock/src/Safe/LivenessGuard.sol rename to packages/contracts-bedrock/src/safe/LivenessGuard.sol index 59b431de126a4..d4fe5c98c89b6 100644 --- a/packages/contracts-bedrock/src/Safe/LivenessGuard.sol +++ b/packages/contracts-bedrock/src/safe/LivenessGuard.sol @@ -3,9 +3,9 @@ pragma solidity 0.8.15; import { GnosisSafe as Safe } from "safe-contracts/GnosisSafe.sol"; import { Guard as BaseGuard } from "safe-contracts/base/GuardManager.sol"; -import { SafeSigners } from "src/Safe/SafeSigners.sol"; +import { SafeSigners } from "src/safe/SafeSigners.sol"; import { Enum } from "safe-contracts/common/Enum.sol"; -import { ISemver } from "src/universal/ISemver.sol"; +import { ISemver } from "src/universal/interfaces/ISemver.sol"; import { EnumerableSet } from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; /// @title LivenessGuard @@ -25,8 +25,8 @@ contract LivenessGuard is ISemver, BaseGuard { event OwnerRecorded(address owner); /// @notice Semantic version. - /// @custom:semver 1.0.0 - string public constant version = "1.0.0"; + /// @custom:semver 1.0.1-beta.1 + string public constant version = "1.0.1-beta.1"; /// @notice The safe account for which this contract will be the guard. Safe internal immutable SAFE; diff --git a/packages/contracts-bedrock/src/Safe/LivenessModule.sol b/packages/contracts-bedrock/src/safe/LivenessModule.sol similarity index 98% rename from packages/contracts-bedrock/src/Safe/LivenessModule.sol rename to packages/contracts-bedrock/src/safe/LivenessModule.sol index 17ec33f1a884e..cd41c6e2dd53a 100644 --- a/packages/contracts-bedrock/src/Safe/LivenessModule.sol +++ b/packages/contracts-bedrock/src/safe/LivenessModule.sol @@ -4,8 +4,8 @@ pragma solidity 0.8.15; import { GnosisSafe as Safe } from "safe-contracts/GnosisSafe.sol"; import { Enum } from "safe-contracts/common/Enum.sol"; import { OwnerManager } from "safe-contracts/base/OwnerManager.sol"; -import { LivenessGuard } from "src/Safe/LivenessGuard.sol"; -import { ISemver } from "src/universal/ISemver.sol"; +import { LivenessGuard } from "src/safe/LivenessGuard.sol"; +import { ISemver } from "src/universal/interfaces/ISemver.sol"; /// @title LivenessModule /// @notice This module is intended to be used in conjunction with the LivenessGuard. In the event @@ -53,8 +53,8 @@ contract LivenessModule is ISemver { uint256 internal constant GUARD_STORAGE_SLOT = 0x4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c8; /// @notice Semantic version. - /// @custom:semver 1.1.0 - string public constant version = "1.2.0"; + /// @custom:semver 1.2.1-beta.1 + string public constant version = "1.2.1-beta.1"; // Constructor to initialize the Safe and baseModule instances constructor( diff --git a/packages/contracts-bedrock/src/Safe/SafeSigners.sol b/packages/contracts-bedrock/src/safe/SafeSigners.sol similarity index 100% rename from packages/contracts-bedrock/src/Safe/SafeSigners.sol rename to packages/contracts-bedrock/src/safe/SafeSigners.sol diff --git a/packages/contracts-bedrock/src/universal/ERC721Bridge.sol b/packages/contracts-bedrock/src/universal/ERC721Bridge.sol index 9c5c325f71840..52217fab713cb 100644 --- a/packages/contracts-bedrock/src/universal/ERC721Bridge.sol +++ b/packages/contracts-bedrock/src/universal/ERC721Bridge.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { CrossDomainMessenger } from "src/universal/CrossDomainMessenger.sol"; -import { SuperchainConfig } from "src/L1/SuperchainConfig.sol"; +import { ICrossDomainMessenger } from "src/universal/interfaces/ICrossDomainMessenger.sol"; import { Address } from "@openzeppelin/contracts/utils/Address.sol"; import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; @@ -15,7 +14,7 @@ abstract contract ERC721Bridge is Initializable { /// @notice Messenger contract on this domain. /// @custom:network-specific - CrossDomainMessenger public messenger; + ICrossDomainMessenger public messenger; /// @notice Contract of the bridge on the other network. /// @custom:network-specific @@ -69,7 +68,7 @@ abstract contract ERC721Bridge is Initializable { /// @param _messenger Contract of the CrossDomainMessenger on this network. /// @param _otherBridge Contract of the ERC721 bridge on the other network. function __ERC721Bridge_init( - CrossDomainMessenger _messenger, + ICrossDomainMessenger _messenger, ERC721Bridge _otherBridge ) internal @@ -83,7 +82,7 @@ abstract contract ERC721Bridge is Initializable { /// Public getter is legacy and will be removed in the future. Use `messenger` instead. /// @return Messenger contract on this domain. /// @custom:legacy - function MESSENGER() external view returns (CrossDomainMessenger) { + function MESSENGER() external view returns (ICrossDomainMessenger) { return messenger; } diff --git a/packages/contracts-bedrock/src/universal/FeeVault.sol b/packages/contracts-bedrock/src/universal/FeeVault.sol index aa68c5f53b1d3..542cd88447a46 100644 --- a/packages/contracts-bedrock/src/universal/FeeVault.sol +++ b/packages/contracts-bedrock/src/universal/FeeVault.sol @@ -1,10 +1,13 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { L2ToL1MessagePasser } from "src/L2/L2ToL1MessagePasser.sol"; +// Libraries import { SafeCall } from "src/libraries/SafeCall.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; +// Interfaces +import { IL2ToL1MessagePasser } from "src/L2/interfaces/IL2ToL1MessagePasser.sol"; + /// @title FeeVault /// @notice The FeeVault contract contains the basic logic for the various different vault contracts /// used to hold fee revenue generated by the L2 system. @@ -102,7 +105,7 @@ abstract contract FeeVault { bool success = SafeCall.send(RECIPIENT, value); require(success, "FeeVault: failed to send ETH to L2 fee recipient"); } else { - L2ToL1MessagePasser(payable(Predeploys.L2_TO_L1_MESSAGE_PASSER)).initiateWithdrawal{ value: value }({ + IL2ToL1MessagePasser(payable(Predeploys.L2_TO_L1_MESSAGE_PASSER)).initiateWithdrawal{ value: value }({ _target: RECIPIENT, _gasLimit: WITHDRAWAL_MIN_GAS, _data: hex"" diff --git a/packages/contracts-bedrock/src/universal/OptimismMintableERC20.sol b/packages/contracts-bedrock/src/universal/OptimismMintableERC20.sol index 43ddd65424f89..838a21af56626 100644 --- a/packages/contracts-bedrock/src/universal/OptimismMintableERC20.sol +++ b/packages/contracts-bedrock/src/universal/OptimismMintableERC20.sol @@ -2,9 +2,11 @@ pragma solidity 0.8.15; import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import { ERC20Permit } from "@openzeppelin/contracts/token/ERC20/extensions/draft-ERC20Permit.sol"; import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; -import { ILegacyMintableERC20, IOptimismMintableERC20 } from "src/universal/IOptimismMintableERC20.sol"; -import { ISemver } from "src/universal/ISemver.sol"; +import { ILegacyMintableERC20, IOptimismMintableERC20 } from "src/universal/interfaces/IOptimismMintableERC20.sol"; +import { ISemver } from "src/universal/interfaces/ISemver.sol"; +import { Preinstalls } from "src/libraries/Preinstalls.sol"; /// @title OptimismMintableERC20 /// @notice OptimismMintableERC20 is a standard extension of the base ERC20 token contract designed @@ -12,7 +14,7 @@ import { ISemver } from "src/universal/ISemver.sol"; /// use an OptimismMintablERC20 as the L2 representation of an L1 token, or vice-versa. /// Designed to be backwards compatible with the older StandardL2ERC20 token which was only /// meant for use on L2. -contract OptimismMintableERC20 is IOptimismMintableERC20, ILegacyMintableERC20, ERC20, ISemver { +contract OptimismMintableERC20 is IOptimismMintableERC20, ILegacyMintableERC20, ERC20Permit, ISemver { /// @notice Address of the corresponding version of this token on the remote chain. address public immutable REMOTE_TOKEN; @@ -39,8 +41,16 @@ contract OptimismMintableERC20 is IOptimismMintableERC20, ILegacyMintableERC20, } /// @notice Semantic version. - /// @custom:semver 1.3.0 - string public constant version = "1.3.0"; + /// @custom:semver 1.4.0-beta.1 + string public constant version = "1.4.0-beta.1"; + + /// @notice Getter function for the permit2 address. It deterministically deployed + /// so it will always be at the same address. It is also included as a preinstall, + /// so it exists in the genesis state of chains. + /// @return Address of permit2 on this network. + function PERMIT2() public pure returns (address) { + return Preinstalls.Permit2; + } /// @param _bridge Address of the L2 standard bridge. /// @param _remoteToken Address of the corresponding L1 token. @@ -54,12 +64,35 @@ contract OptimismMintableERC20 is IOptimismMintableERC20, ILegacyMintableERC20, uint8 _decimals ) ERC20(_name, _symbol) + ERC20Permit(_name) { REMOTE_TOKEN = _remoteToken; BRIDGE = _bridge; DECIMALS = _decimals; } + /// @dev Returns the number of decimals used to get its user representation. + /// For example, if `decimals` equals `2`, a balance of `505` tokens should + /// be displayed to a user as `5.05` (`505 / 10 ** 2`). + /// NOTE: This information is only used for _display_ purposes: it in + /// no way affects any of the arithmetic of the contract, including + /// {IERC20-balanceOf} and {IERC20-transfer}. + function decimals() public view override returns (uint8) { + return DECIMALS; + } + + /// @notice Returns the allowance for a spender on the owner's tokens. + /// If the spender is the permit2 address, returns the maximum uint256 value. + /// @param _owner owner of the tokens. + /// @param _spender spender of the tokens. + /// @return Allowance for the spender. + function allowance(address _owner, address _spender) public view override returns (uint256) { + if (_spender == PERMIT2()) { + return type(uint256).max; + } + return super.allowance(_owner, _spender); + } + /// @notice Allows the StandardBridge on this network to mint tokens. /// @param _to Address to mint tokens to. /// @param _amount Amount of tokens to mint. @@ -127,14 +160,4 @@ contract OptimismMintableERC20 is IOptimismMintableERC20, ILegacyMintableERC20, function bridge() public view returns (address) { return BRIDGE; } - - /// @dev Returns the number of decimals used to get its user representation. - /// For example, if `decimals` equals `2`, a balance of `505` tokens should - /// be displayed to a user as `5.05` (`505 / 10 ** 2`). - /// NOTE: This information is only used for _display_ purposes: it in - /// no way affects any of the arithmetic of the contract, including - /// {IERC20-balanceOf} and {IERC20-transfer}. - function decimals() public view override returns (uint8) { - return DECIMALS; - } } diff --git a/packages/contracts-bedrock/src/universal/OptimismMintableERC20Factory.sol b/packages/contracts-bedrock/src/universal/OptimismMintableERC20Factory.sol index 799389542abe0..e179c6408dad1 100644 --- a/packages/contracts-bedrock/src/universal/OptimismMintableERC20Factory.sol +++ b/packages/contracts-bedrock/src/universal/OptimismMintableERC20Factory.sol @@ -2,11 +2,11 @@ pragma solidity 0.8.15; import { OptimismMintableERC20 } from "src/universal/OptimismMintableERC20.sol"; -import { ISemver } from "src/universal/ISemver.sol"; +import { ISemver } from "src/universal/interfaces/ISemver.sol"; import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; -import { IOptimismERC20Factory } from "src/L2/IOptimismERC20Factory.sol"; +import { IOptimismERC20Factory } from "src/L2/interfaces/IOptimismERC20Factory.sol"; -/// @custom:proxied +/// @custom:proxied true /// @custom:predeployed 0x4200000000000000000000000000000000000012 /// @title OptimismMintableERC20Factory /// @notice OptimismMintableERC20Factory is a factory contract that generates OptimismMintableERC20 @@ -48,8 +48,8 @@ contract OptimismMintableERC20Factory is ISemver, Initializable, IOptimismERC20F /// the OptimismMintableERC20 token contract since this contract /// is responsible for deploying OptimismMintableERC20 contracts. /// @notice Semantic version. - /// @custom:semver 1.10.0 - string public constant version = "1.10.0"; + /// @custom:semver 1.10.1-beta.3 + string public constant version = "1.10.1-beta.3"; /// @notice Constructs the OptimismMintableERC20Factory contract. constructor() { diff --git a/packages/contracts-bedrock/src/universal/OptimismMintableERC721.sol b/packages/contracts-bedrock/src/universal/OptimismMintableERC721.sol index 025b5b14bde3b..955a340722051 100644 --- a/packages/contracts-bedrock/src/universal/OptimismMintableERC721.sol +++ b/packages/contracts-bedrock/src/universal/OptimismMintableERC721.sol @@ -5,8 +5,8 @@ import { ERC721Enumerable } from "@openzeppelin/contracts/token/ERC721/extension import { ERC721 } from "@openzeppelin/contracts/token/ERC721/ERC721.sol"; import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; -import { IOptimismMintableERC721 } from "src/universal/IOptimismMintableERC721.sol"; -import { ISemver } from "src/universal/ISemver.sol"; +import { IOptimismMintableERC721 } from "src/universal/interfaces/IOptimismMintableERC721.sol"; +import { ISemver } from "src/universal/interfaces/ISemver.sol"; /// @title OptimismMintableERC721 /// @notice This contract is the remote representation for some token that lives on another network, @@ -32,8 +32,8 @@ contract OptimismMintableERC721 is ERC721Enumerable, IOptimismMintableERC721, IS } /// @notice Semantic version. - /// @custom:semver 1.3.0 - string public constant version = "1.3.0"; + /// @custom:semver 1.3.1-beta.2 + string public constant version = "1.3.1-beta.2"; /// @param _bridge Address of the bridge on this network. /// @param _remoteChainId Chain ID where the remote token is deployed. diff --git a/packages/contracts-bedrock/src/universal/OptimismMintableERC721Factory.sol b/packages/contracts-bedrock/src/universal/OptimismMintableERC721Factory.sol index 9d9cd62c48d6f..e9bc81524f865 100644 --- a/packages/contracts-bedrock/src/universal/OptimismMintableERC721Factory.sol +++ b/packages/contracts-bedrock/src/universal/OptimismMintableERC721Factory.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.15; import { OptimismMintableERC721 } from "src/universal/OptimismMintableERC721.sol"; -import { ISemver } from "src/universal/ISemver.sol"; +import { ISemver } from "src/universal/interfaces/ISemver.sol"; /// @title OptimismMintableERC721Factory /// @notice Factory contract for creating OptimismMintableERC721 contracts. @@ -23,8 +23,8 @@ contract OptimismMintableERC721Factory is ISemver { event OptimismMintableERC721Created(address indexed localToken, address indexed remoteToken, address deployer); /// @notice Semantic version. - /// @custom:semver 1.4.0 - string public constant version = "1.4.0"; + /// @custom:semver 1.4.1-beta.2 + string public constant version = "1.4.1-beta.2"; /// @notice The semver MUST be bumped any time that there is a change in /// the OptimismMintableERC721 token contract since this contract diff --git a/packages/contracts-bedrock/src/universal/ProxyAdmin.sol b/packages/contracts-bedrock/src/universal/ProxyAdmin.sol index 8558d421bb46f..e554345d42645 100644 --- a/packages/contracts-bedrock/src/universal/ProxyAdmin.sol +++ b/packages/contracts-bedrock/src/universal/ProxyAdmin.sol @@ -6,22 +6,8 @@ import { Proxy } from "src/universal/Proxy.sol"; import { AddressManager } from "src/legacy/AddressManager.sol"; import { L1ChugSplashProxy } from "src/legacy/L1ChugSplashProxy.sol"; import { Constants } from "src/libraries/Constants.sol"; - -/// @title IStaticERC1967Proxy -/// @notice IStaticERC1967Proxy is a static version of the ERC1967 proxy interface. -interface IStaticERC1967Proxy { - function implementation() external view returns (address); - - function admin() external view returns (address); -} - -/// @title IStaticL1ChugSplashProxy -/// @notice IStaticL1ChugSplashProxy is a static version of the ChugSplash proxy interface. -interface IStaticL1ChugSplashProxy { - function getImplementation() external view returns (address); - - function getOwner() external view returns (address); -} +import { IStaticERC1967Proxy } from "src/universal/interfaces/IStaticERC1967Proxy.sol"; +import { IStaticL1ChugSplashProxy } from "src/legacy/interfaces/IL1ChugSplashProxy.sol"; /// @title ProxyAdmin /// @notice This is an auxiliary contract meant to be assigned as the admin of an ERC1967 Proxy, diff --git a/packages/contracts-bedrock/src/universal/StandardBridge.sol b/packages/contracts-bedrock/src/universal/StandardBridge.sol index 140aba531e615..476d3ba54c933 100644 --- a/packages/contracts-bedrock/src/universal/StandardBridge.sol +++ b/packages/contracts-bedrock/src/universal/StandardBridge.sol @@ -6,8 +6,8 @@ import { ERC165Checker } from "@openzeppelin/contracts/utils/introspection/ERC16 import { Address } from "@openzeppelin/contracts/utils/Address.sol"; import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import { SafeCall } from "src/libraries/SafeCall.sol"; -import { IOptimismMintableERC20, ILegacyMintableERC20 } from "src/universal/IOptimismMintableERC20.sol"; -import { CrossDomainMessenger } from "src/universal/CrossDomainMessenger.sol"; +import { IOptimismMintableERC20, ILegacyMintableERC20 } from "src/universal/interfaces/IOptimismMintableERC20.sol"; +import { ICrossDomainMessenger } from "src/universal/interfaces/ICrossDomainMessenger.sol"; import { OptimismMintableERC20 } from "src/universal/OptimismMintableERC20.sol"; import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; import { Constants } from "src/libraries/Constants.sol"; @@ -38,7 +38,7 @@ abstract contract StandardBridge is Initializable { /// @notice Messenger contract on this domain. /// @custom:network-specific - CrossDomainMessenger public messenger; + ICrossDomainMessenger public messenger; /// @notice Corresponding bridge on the other domain. /// @custom:network-specific @@ -116,7 +116,7 @@ abstract contract StandardBridge is Initializable { /// @param _messenger Contract for CrossDomainMessenger on this network. /// @param _otherBridge Contract for the other StandardBridge contract. function __StandardBridge_init( - CrossDomainMessenger _messenger, + ICrossDomainMessenger _messenger, StandardBridge _otherBridge ) internal @@ -143,7 +143,7 @@ abstract contract StandardBridge is Initializable { /// Public getter is legacy and will be removed in the future. Use `messenger` instead. /// @return Contract of the messenger on this domain. /// @custom:legacy - function MESSENGER() external view returns (CrossDomainMessenger) { + function MESSENGER() external view returns (ICrossDomainMessenger) { return messenger; } diff --git a/packages/contracts-bedrock/src/universal/StorageSetter.sol b/packages/contracts-bedrock/src/universal/StorageSetter.sol index 53b8ab2affd5e..b7f7614b4ea0c 100644 --- a/packages/contracts-bedrock/src/universal/StorageSetter.sol +++ b/packages/contracts-bedrock/src/universal/StorageSetter.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { ISemver } from "src/universal/ISemver.sol"; +import { ISemver } from "src/universal/interfaces/ISemver.sol"; import { Storage } from "src/libraries/Storage.sol"; /// @title StorageSetter @@ -16,8 +16,8 @@ contract StorageSetter is ISemver { } /// @notice Semantic version. - /// @custom:semver 1.2.0 - string public constant version = "1.2.0"; + /// @custom:semver 1.2.1-beta.1 + string public constant version = "1.2.1-beta.1"; /// @notice Stores a bytes32 `_value` at `_slot`. Any storage slots that /// are packed should be set through this interface. diff --git a/packages/contracts-bedrock/src/dispute/weth/WETH98.sol b/packages/contracts-bedrock/src/universal/WETH98.sol similarity index 98% rename from packages/contracts-bedrock/src/dispute/weth/WETH98.sol rename to packages/contracts-bedrock/src/universal/WETH98.sol index 2b054c7048ebf..5665e5f9210fe 100644 --- a/packages/contracts-bedrock/src/dispute/weth/WETH98.sol +++ b/packages/contracts-bedrock/src/universal/WETH98.sol @@ -19,7 +19,7 @@ pragma solidity 0.8.15; -import { IWETH } from "src/dispute/interfaces/IWETH.sol"; +import { IWETH } from "src/universal/interfaces/IWETH.sol"; /// @title WETH98 /// @notice WETH98 is a version of WETH9 upgraded for Solidity 0.8.x. diff --git a/packages/contracts-bedrock/src/universal/interfaces/ICrossDomainMessenger.sol b/packages/contracts-bedrock/src/universal/interfaces/ICrossDomainMessenger.sol new file mode 100644 index 0000000000000..ed2fb20ea453c --- /dev/null +++ b/packages/contracts-bedrock/src/universal/interfaces/ICrossDomainMessenger.sol @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +interface ICrossDomainMessenger { + event FailedRelayedMessage(bytes32 indexed msgHash); + event Initialized(uint8 version); + event RelayedMessage(bytes32 indexed msgHash); + event SentMessage(address indexed target, address sender, bytes message, uint256 messageNonce, uint256 gasLimit); + event SentMessageExtension1(address indexed sender, uint256 value); + + function MESSAGE_VERSION() external view returns (uint16); + function MIN_GAS_CALLDATA_OVERHEAD() external view returns (uint64); + function MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR() external view returns (uint64); + function MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR() external view returns (uint64); + function OTHER_MESSENGER() external view returns (ICrossDomainMessenger); + function RELAY_CALL_OVERHEAD() external view returns (uint64); + function RELAY_CONSTANT_OVERHEAD() external view returns (uint64); + function RELAY_GAS_CHECK_BUFFER() external view returns (uint64); + function RELAY_RESERVED_GAS() external view returns (uint64); + function baseGas(bytes memory _message, uint32 _minGasLimit) external pure returns (uint64); + function failedMessages(bytes32) external view returns (bool); + function messageNonce() external view returns (uint256); + function otherMessenger() external view returns (ICrossDomainMessenger); + function paused() external view returns (bool); + function relayMessage( + uint256 _nonce, + address _sender, + address _target, + uint256 _value, + uint256 _minGasLimit, + bytes memory _message + ) + external + payable; + function sendMessage(address _target, bytes memory _message, uint32 _minGasLimit) external payable; + function successfulMessages(bytes32) external view returns (bool); + function xDomainMessageSender() external view returns (address); +} diff --git a/packages/contracts-bedrock/src/universal/interfaces/IEIP712.sol b/packages/contracts-bedrock/src/universal/interfaces/IEIP712.sol new file mode 100644 index 0000000000000..b05a49cb01ea9 --- /dev/null +++ b/packages/contracts-bedrock/src/universal/interfaces/IEIP712.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/// @title IEIP712 +interface IEIP712 { + function DOMAIN_SEPARATOR() external view returns (bytes32); +} diff --git a/packages/contracts-bedrock/src/universal/interfaces/IERC721Bridge.sol b/packages/contracts-bedrock/src/universal/interfaces/IERC721Bridge.sol new file mode 100644 index 0000000000000..ccb2d5f0a4836 --- /dev/null +++ b/packages/contracts-bedrock/src/universal/interfaces/IERC721Bridge.sol @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { ICrossDomainMessenger } from "src/universal/interfaces/ICrossDomainMessenger.sol"; + +interface IERC721Bridge { + event ERC721BridgeFinalized( + address indexed localToken, + address indexed remoteToken, + address indexed from, + address to, + uint256 tokenId, + bytes extraData + ); + event ERC721BridgeInitiated( + address indexed localToken, + address indexed remoteToken, + address indexed from, + address to, + uint256 tokenId, + bytes extraData + ); + event Initialized(uint8 version); + + function MESSENGER() external view returns (ICrossDomainMessenger); + function OTHER_BRIDGE() external view returns (IERC721Bridge); + function bridgeERC721( + address _localToken, + address _remoteToken, + uint256 _tokenId, + uint32 _minGasLimit, + bytes memory _extraData + ) + external; + function bridgeERC721To( + address _localToken, + address _remoteToken, + address _to, + uint256 _tokenId, + uint32 _minGasLimit, + bytes memory _extraData + ) + external; + function messenger() external view returns (ICrossDomainMessenger); + function otherBridge() external view returns (IERC721Bridge); + function paused() external view returns (bool); +} diff --git a/packages/contracts-bedrock/src/universal/interfaces/IFeeVault.sol b/packages/contracts-bedrock/src/universal/interfaces/IFeeVault.sol new file mode 100644 index 0000000000000..1742a0029c7d8 --- /dev/null +++ b/packages/contracts-bedrock/src/universal/interfaces/IFeeVault.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +interface IFeeVault { + enum WithdrawalNetwork { + L1, + L2 + } + + event Withdrawal(uint256 value, address to, address from); + event Withdrawal(uint256 value, address to, address from, WithdrawalNetwork withdrawalNetwork); + + receive() external payable; + + function MIN_WITHDRAWAL_AMOUNT() external view returns (uint256); + function RECIPIENT() external view returns (address); + function WITHDRAWAL_NETWORK() external view returns (WithdrawalNetwork); + function minWithdrawalAmount() external view returns (uint256 amount_); + function recipient() external view returns (address recipient_); + function totalProcessed() external view returns (uint256); + function withdraw() external; + function withdrawalNetwork() external view returns (WithdrawalNetwork network_); +} diff --git a/packages/contracts-bedrock/src/universal/IOptimismMintableERC20.sol b/packages/contracts-bedrock/src/universal/interfaces/IOptimismMintableERC20.sol similarity index 100% rename from packages/contracts-bedrock/src/universal/IOptimismMintableERC20.sol rename to packages/contracts-bedrock/src/universal/interfaces/IOptimismMintableERC20.sol diff --git a/packages/contracts-bedrock/src/universal/interfaces/IOptimismMintableERC20Factory.sol b/packages/contracts-bedrock/src/universal/interfaces/IOptimismMintableERC20Factory.sol new file mode 100644 index 0000000000000..91f6eba6c1756 --- /dev/null +++ b/packages/contracts-bedrock/src/universal/interfaces/IOptimismMintableERC20Factory.sol @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +interface IOptimismMintableERC20Factory { + event Initialized(uint8 version); + event OptimismMintableERC20Created(address indexed localToken, address indexed remoteToken, address deployer); + event StandardL2TokenCreated(address indexed remoteToken, address indexed localToken); + + function BRIDGE() external view returns (address); + function bridge() external view returns (address); + function createOptimismMintableERC20( + address _remoteToken, + string memory _name, + string memory _symbol + ) + external + returns (address); + function createOptimismMintableERC20WithDecimals( + address _remoteToken, + string memory _name, + string memory _symbol, + uint8 _decimals + ) + external + returns (address); + function createStandardL2Token( + address _remoteToken, + string memory _name, + string memory _symbol + ) + external + returns (address); + function deployments(address) external view returns (address); + function initialize(address _bridge) external; + function version() external view returns (string memory); + + function __constructor__() external; +} diff --git a/packages/contracts-bedrock/src/universal/IOptimismMintableERC721.sol b/packages/contracts-bedrock/src/universal/interfaces/IOptimismMintableERC721.sol similarity index 100% rename from packages/contracts-bedrock/src/universal/IOptimismMintableERC721.sol rename to packages/contracts-bedrock/src/universal/interfaces/IOptimismMintableERC721.sol diff --git a/packages/contracts-bedrock/src/universal/interfaces/IOwnable.sol b/packages/contracts-bedrock/src/universal/interfaces/IOwnable.sol new file mode 100644 index 0000000000000..968ad63a76522 --- /dev/null +++ b/packages/contracts-bedrock/src/universal/interfaces/IOwnable.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/// @title IOwnable +/// @notice Interface for Ownable. +interface IOwnable { + event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); + + function owner() external view returns (address); + function renounceOwnership() external; + function transferOwnership(address newOwner) external; // nosemgrep: sol-style-input-arg-fmt. +} diff --git a/packages/contracts-bedrock/src/universal/ISemver.sol b/packages/contracts-bedrock/src/universal/interfaces/ISemver.sol similarity index 100% rename from packages/contracts-bedrock/src/universal/ISemver.sol rename to packages/contracts-bedrock/src/universal/interfaces/ISemver.sol diff --git a/packages/contracts-bedrock/src/universal/interfaces/IStandardBridge.sol b/packages/contracts-bedrock/src/universal/interfaces/IStandardBridge.sol new file mode 100644 index 0000000000000..b92aae27503bc --- /dev/null +++ b/packages/contracts-bedrock/src/universal/interfaces/IStandardBridge.sol @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { ICrossDomainMessenger } from "src/universal/interfaces/ICrossDomainMessenger.sol"; + +interface IStandardBridge { + event ERC20BridgeFinalized( + address indexed localToken, + address indexed remoteToken, + address indexed from, + address to, + uint256 amount, + bytes extraData + ); + event ERC20BridgeInitiated( + address indexed localToken, + address indexed remoteToken, + address indexed from, + address to, + uint256 amount, + bytes extraData + ); + event ETHBridgeFinalized(address indexed from, address indexed to, uint256 amount, bytes extraData); + event ETHBridgeInitiated(address indexed from, address indexed to, uint256 amount, bytes extraData); + event Initialized(uint8 version); + + receive() external payable; + + function MESSENGER() external view returns (ICrossDomainMessenger); + function OTHER_BRIDGE() external view returns (IStandardBridge); + function bridgeERC20( + address _localToken, + address _remoteToken, + uint256 _amount, + uint32 _minGasLimit, + bytes memory _extraData + ) + external; + function bridgeERC20To( + address _localToken, + address _remoteToken, + address _to, + uint256 _amount, + uint32 _minGasLimit, + bytes memory _extraData + ) + external; + function bridgeETH(uint32 _minGasLimit, bytes memory _extraData) external payable; + function bridgeETHTo(address _to, uint32 _minGasLimit, bytes memory _extraData) external payable; + function deposits(address, address) external view returns (uint256); + function finalizeBridgeERC20( + address _localToken, + address _remoteToken, + address _from, + address _to, + uint256 _amount, + bytes memory _extraData + ) + external; + function finalizeBridgeETH(address _from, address _to, uint256 _amount, bytes memory _extraData) external payable; + function messenger() external view returns (ICrossDomainMessenger); + function otherBridge() external view returns (IStandardBridge); + function paused() external view returns (bool); +} diff --git a/packages/contracts-bedrock/src/universal/interfaces/IStaticERC1967Proxy.sol b/packages/contracts-bedrock/src/universal/interfaces/IStaticERC1967Proxy.sol new file mode 100644 index 0000000000000..511f2be7b4f21 --- /dev/null +++ b/packages/contracts-bedrock/src/universal/interfaces/IStaticERC1967Proxy.sol @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/// @title IStaticERC1967Proxy +/// @notice IStaticERC1967Proxy is a static version of the ERC1967 proxy interface. +interface IStaticERC1967Proxy { + function implementation() external view returns (address); + function admin() external view returns (address); +} diff --git a/packages/contracts-bedrock/src/dispute/interfaces/IWETH.sol b/packages/contracts-bedrock/src/universal/interfaces/IWETH.sol similarity index 100% rename from packages/contracts-bedrock/src/dispute/interfaces/IWETH.sol rename to packages/contracts-bedrock/src/universal/interfaces/IWETH.sol diff --git a/packages/contracts-bedrock/src/vendor/interfaces/IERC20Solady.sol b/packages/contracts-bedrock/src/vendor/interfaces/IERC20Solady.sol new file mode 100644 index 0000000000000..1e696ad23ac31 --- /dev/null +++ b/packages/contracts-bedrock/src/vendor/interfaces/IERC20Solady.sol @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +interface IERC20Solady { + /// @dev The total supply has overflowed. + error TotalSupplyOverflow(); + + /// @dev The allowance has overflowed. + error AllowanceOverflow(); + + /// @dev The allowance has underflowed. + error AllowanceUnderflow(); + + /// @dev Insufficient balance. + error InsufficientBalance(); + + /// @dev Insufficient allowance. + error InsufficientAllowance(); + + /// @dev The permit is invalid. + error InvalidPermit(); + + /// @dev The permit has expired. + error PermitExpired(); + + /// @dev Emitted when `amount` tokens is transferred from `from` to `to`. + event Transfer(address indexed from, address indexed to, uint256 amount); + + /// @dev Emitted when `amount` tokens is approved by `owner` to be used by `spender`. + event Approval(address indexed owner, address indexed spender, uint256 amount); + + /// @dev Returns the name of the token. + function name() external view returns (string memory); + + /// @dev Returns the symbol of the token. + function symbol() external view returns (string memory); + + /// @dev Returns the decimals places of the token. + function decimals() external view returns (uint8); + + /// @dev Returns the amount of tokens in existence. + function totalSupply() external view returns (uint256 result); + + /// @dev Returns the amount of tokens owned by `owner` + function balanceOf(address owner) external view returns (uint256 result); + + /// @dev Returns the amount of tokens that `spender` can spend on behalf of `owner`. + function allowance(address owner, address spender) external view returns (uint256 result); + + /// @dev Sets `amount` as the allowance of `spender` over the caller's tokens. + /// + /// Emits a {Approval} event. + function approve(address spender, uint256 amount) external returns (bool); + + /// @dev Transfer `amount` tokens from the caller to `to`. + /// + /// Requirements: + /// - `from` must at least have `amount`. + /// + /// Emits a {Transfer} event. + function transfer(address to, uint256 amount) external returns (bool); + + /// @dev Transfers `amount` tokens from `from` to `to`. + /// + /// Note: Does not update the allowance if it is the maximum uint256 value. + /// + /// Requirements: + /// - `from` must at least have `amount`. + /// - The caller must have at least `amount` of allowance to transfer the tokens of `from`. + /// + /// Emits a {Transfer} event. + function transferFrom(address from, address to, uint256 amount) external returns (bool); + + /// @dev Returns the current nonce for `owner`. + /// This value is used to compute the signature for EIP-2612 permit. + function nonces(address owner) external view returns (uint256 result); + + /// @dev Sets `value` as the allowance of `spender` over the tokens of `owner`, + /// authorized by a signed approval by `owner`. + /// + /// Emits a {Approval} event. + function permit( + address owner, + address spender, + uint256 value, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s + ) + external; + + /// @dev Returns the EIP-712 domain separator for the EIP-2612 permit. + function DOMAIN_SEPARATOR() external view returns (bytes32 result); +} diff --git a/packages/contracts-bedrock/src/vendor/interfaces/IGelatoTreasury.sol b/packages/contracts-bedrock/src/vendor/interfaces/IGelatoTreasury.sol new file mode 100644 index 0000000000000..8438948f850d9 --- /dev/null +++ b/packages/contracts-bedrock/src/vendor/interfaces/IGelatoTreasury.sol @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/// @title IGelatoTreasury +/// @notice Interface for the GelatoTreasury contract. +interface IGelatoTreasury { + function totalDepositedAmount(address _user, address _token) external view returns (uint256); + function totalWithdrawnAmount(address _user, address _token) external view returns (uint256); +} diff --git a/packages/contracts-bedrock/test/BenchmarkTest.t.sol b/packages/contracts-bedrock/test/BenchmarkTest.t.sol index 4722107a314f9..063ed6944946f 100644 --- a/packages/contracts-bedrock/test/BenchmarkTest.t.sol +++ b/packages/contracts-bedrock/test/BenchmarkTest.t.sol @@ -1,14 +1,20 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -// Testing utilities +// Testing import { Test } from "forge-std/Test.sol"; import { Vm } from "forge-std/Vm.sol"; import { CommonTest } from "test/setup/CommonTest.sol"; import { Bridge_Initializer } from "test/setup/Bridge_Initializer.sol"; -import { CrossDomainMessenger } from "src/universal/CrossDomainMessenger.sol"; -import { ResourceMetering } from "src/L1/ResourceMetering.sol"; + +// Libraries import { Types } from "src/libraries/Types.sol"; +import { SafeCall } from "src/libraries/SafeCall.sol"; +import { L1BlockIsthmus } from "src/L2/L1BlockIsthmus.sol"; +import { Encoding } from "src/libraries/Encoding.sol"; + +// Interfaces +import { ICrossDomainMessenger } from "src/universal/interfaces/ICrossDomainMessenger.sol"; // Free function for setting the prevBaseFee param in the OptimismPortal. function setPrevBaseFee(Vm _vm, address _op, uint128 _prevBaseFee) { @@ -179,7 +185,7 @@ contract GasBenchMark_L1StandardBridge_Finalize is Bridge_Initializer { deal(address(L1Token), address(l1StandardBridge), 100, true); vm.mockCall( address(l1StandardBridge.messenger()), - abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector), + abi.encodeWithSelector(ICrossDomainMessenger.xDomainMessageSender.selector), abi.encode(address(l1StandardBridge.OTHER_BRIDGE())) ); vm.startPrank(address(l1StandardBridge.messenger())); @@ -209,3 +215,101 @@ contract GasBenchMark_L2OutputOracle is CommonTest { l2OutputOracle.proposeL2Output(nonZeroHash, nextBlockNumber, 0, 0); } } + +contract GasBenchMark_L1Block is CommonTest { + address depositor; + bytes setValuesCalldata; + + function setUp() public virtual override { + super.setUp(); + depositor = l1Block.DEPOSITOR_ACCOUNT(); + setValuesCalldata = Encoding.encodeSetL1BlockValuesEcotone( + type(uint32).max, + type(uint32).max, + type(uint64).max, + type(uint64).max, + type(uint64).max, + type(uint256).max, + type(uint256).max, + keccak256(abi.encode(1)), + bytes32(type(uint256).max) + ); + vm.startPrank(depositor); + } +} + +contract GasBenchMark_L1Block_SetValuesEcotone is GasBenchMark_L1Block { + function test_setL1BlockValuesEcotone_benchmark() external { + SafeCall.call({ _target: address(l1Block), _calldata: setValuesCalldata }); + } +} + +contract GasBenchMark_L1Block_SetValuesEcotone_Warm is GasBenchMark_L1Block { + function setUp() public virtual override { + SafeCall.call({ _target: address(l1Block), _calldata: setValuesCalldata }); + } + + function test_setL1BlockValuesEcotone_benchmark() external { + SafeCall.call({ _target: address(l1Block), _calldata: setValuesCalldata }); + } +} + +contract GasBenchMark_L1BlockIsthmus is GasBenchMark_L1Block { + L1BlockIsthmus l1BlockIsthmus; + + function setUp() public virtual override { + super.setUp(); + l1BlockIsthmus = new L1BlockIsthmus(); + setValuesCalldata = Encoding.encodeSetL1BlockValuesIsthmus( + type(uint32).max, + type(uint32).max, + type(uint64).max, + type(uint64).max, + type(uint64).max, + type(uint256).max, + type(uint256).max, + keccak256(abi.encode(1)), + bytes32(type(uint256).max) + ); + } +} + +contract GasBenchMark_L1BlockIsthmus_SetValuesIsthmus is GasBenchMark_L1BlockIsthmus { + function test_setL1BlockValuesIsthmus_benchmark() external { + SafeCall.call({ _target: address(l1BlockIsthmus), _calldata: setValuesCalldata }); + } +} + +contract GasBenchMark_L1BlockIsthmus_SetValuesIsthmus_Warm is GasBenchMark_L1BlockIsthmus { + function setUp() public virtual override { + SafeCall.call({ _target: address(l1BlockIsthmus), _calldata: setValuesCalldata }); + } + + function test_setL1BlockValuesIsthmus_benchmark() external { + SafeCall.call({ _target: address(l1BlockIsthmus), _calldata: setValuesCalldata }); + } +} + +contract GasBenchMark_L1BlockIsthmus_DepositsComplete is GasBenchMark_L1BlockIsthmus { + function test_depositsComplete_benchmark() external { + SafeCall.call({ + _target: address(l1BlockIsthmus), + _calldata: abi.encodeWithSelector(l1BlockIsthmus.depositsComplete.selector) + }); + } +} + +contract GasBenchMark_L1BlockIsthmus_DepositsComplete_Warm is GasBenchMark_L1BlockIsthmus { + function setUp() public virtual override { + super.setUp(); + // Set the isDeposit flag to true so then we can benchmark when it is reset. + SafeCall.call({ _target: address(l1BlockIsthmus), _calldata: setValuesCalldata }); + } + + function test_depositsComplete_benchmark() external { + SafeCall.call({ + _target: address(l1BlockIsthmus), + _calldata: abi.encodeWithSelector(l1BlockIsthmus.depositsComplete.selector) + }); + } +} diff --git a/packages/contracts-bedrock/test/DeployAuthSystem.t.sol b/packages/contracts-bedrock/test/DeployAuthSystem.t.sol new file mode 100644 index 0000000000000..19985ef490b9d --- /dev/null +++ b/packages/contracts-bedrock/test/DeployAuthSystem.t.sol @@ -0,0 +1,159 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +import { Test, stdStorage, StdStorage } from "forge-std/Test.sol"; +import { stdToml } from "forge-std/StdToml.sol"; +import { Solarray } from "scripts/libraries/Solarray.sol"; + +import { DeployAuthSystemInput, DeployAuthSystem, DeployAuthSystemOutput } from "scripts/DeployAuthSystem.s.sol"; + +contract DeployAuthSystemInput_Test is Test { + DeployAuthSystemInput dasi; + + uint256 threshold = 5; + address[] owners; + + function setUp() public { + dasi = new DeployAuthSystemInput(); + address[] memory _owners = Solarray.addresses( + 0x1111111111111111111111111111111111111111, + 0x2222222222222222222222222222222222222222, + 0x3333333333333333333333333333333333333333, + 0x4444444444444444444444444444444444444444, + 0x5555555555555555555555555555555555555555, + 0x6666666666666666666666666666666666666666, + 0x7777777777777777777777777777777777777777 + ); + + for (uint256 i = 0; i < _owners.length; i++) { + owners.push(_owners[i]); + } + } + + function test_getters_whenNotSet_revert() public { + vm.expectRevert("DeployAuthSystemInput: threshold not set"); + dasi.threshold(); + + vm.expectRevert("DeployAuthSystemInput: owners not set"); + dasi.owners(); + } + + function test_setters_ownerAlreadySet_revert() public { + dasi.set(dasi.owners.selector, owners); + + vm.expectRevert("DeployAuthSystemInput: owners already set"); + dasi.set(dasi.owners.selector, owners); + } +} + +contract DeployAuthSystemOutput_Test is Test { + using stdToml for string; + + DeployAuthSystemOutput daso; + + function setUp() public { + daso = new DeployAuthSystemOutput(); + } + + function test_set_succeeds() public { + address safeAddr = makeAddr("safe"); + + vm.etch(safeAddr, hex"01"); + + daso.set(daso.safe.selector, safeAddr); + + assertEq(safeAddr, address(daso.safe()), "100"); + } + + function test_getter_whenNotSet_reverts() public { + vm.expectRevert("DeployUtils: zero address"); + daso.safe(); + } + + function test_getter_whenAddrHasNoCode_reverts() public { + address emptyAddr = makeAddr("emptyAddr"); + bytes memory expectedErr = bytes(string.concat("DeployUtils: no code at ", vm.toString(emptyAddr))); + + daso.set(daso.safe.selector, emptyAddr); + vm.expectRevert(expectedErr); + daso.safe(); + } +} + +contract DeployAuthSystem_Test is Test { + using stdStorage for StdStorage; + + DeployAuthSystem deployAuthSystem; + DeployAuthSystemInput dasi; + DeployAuthSystemOutput daso; + + // Define default input variables for testing. + uint256 defaultThreshold = 5; + uint256 defaultOwnersLength = 7; + address[] defaultOwners; + + function setUp() public { + deployAuthSystem = new DeployAuthSystem(); + (dasi, daso) = deployAuthSystem.etchIOContracts(); + for (uint256 i = 0; i < defaultOwnersLength; i++) { + defaultOwners.push(makeAddr(string.concat("owner", vm.toString(i)))); + } + } + + function hash(bytes32 _seed, uint256 _i) internal pure returns (bytes32) { + return keccak256(abi.encode(_seed, _i)); + } + + function testFuzz_run_memory_succeeds(bytes32 _seed) public { + address[] memory _owners = Solarray.addresses( + address(uint160(uint256(hash(_seed, 0)))), + address(uint160(uint256(hash(_seed, 1)))), + address(uint160(uint256(hash(_seed, 2)))), + address(uint160(uint256(hash(_seed, 3)))), + address(uint160(uint256(hash(_seed, 4)))), + address(uint160(uint256(hash(_seed, 5)))), + address(uint160(uint256(hash(_seed, 6)))) + ); + + uint256 threshold = bound(uint256(_seed), 1, _owners.length - 1); + + dasi.set(dasi.owners.selector, _owners); + dasi.set(dasi.threshold.selector, threshold); + + deployAuthSystem.run(dasi, daso); + + assertNotEq(address(daso.safe()), address(0), "100"); + assertEq(daso.safe().getThreshold(), threshold, "200"); + // TODO: the getOwners() method requires iterating over the owners linked list. + // Since we're not yet performing a proper deployment of the Safe, this call will revert. + // assertEq(daso.safe().getOwners().length, _owners.length, "300"); + + // Architecture assertions. + // TODO: these will become relevant as we add more contracts to the auth system, and need to test their + // relationships. + + daso.checkOutput(); + } + + function test_run_NullInput_reverts() public { + dasi.set(dasi.owners.selector, defaultOwners); + dasi.set(dasi.threshold.selector, defaultThreshold); + + // Zero out the owners length slot + uint256 slot = 9; + vm.store(address(dasi), bytes32(uint256(9)), bytes32(0)); + vm.expectRevert("DeployAuthSystemInput: owners not set"); + deployAuthSystem.run(dasi, daso); + vm.store(address(dasi), bytes32(uint256(9)), bytes32(defaultOwnersLength)); + + slot = zeroOutSlotForSelector(dasi.threshold.selector); + vm.expectRevert("DeployAuthSystemInput: threshold not set"); + deployAuthSystem.run(dasi, daso); + vm.store(address(dasi), bytes32(slot), bytes32(defaultThreshold)); + } + + function zeroOutSlotForSelector(bytes4 _selector) internal returns (uint256 slot_) { + slot_ = stdstore.enable_packed_slots().target(address(dasi)).sig(_selector).find(); + vm.store(address(dasi), bytes32(slot_), bytes32(0)); + } +} diff --git a/packages/contracts-bedrock/test/DeployImplementations.t.sol b/packages/contracts-bedrock/test/DeployImplementations.t.sol index 4a6adfa6edc9c..1dca71b4ec706 100644 --- a/packages/contracts-bedrock/test/DeployImplementations.t.sol +++ b/packages/contracts-bedrock/test/DeployImplementations.t.sol @@ -1,275 +1,486 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { Test } from "forge-std/Test.sol"; +import { Test, stdStorage, StdStorage } from "forge-std/Test.sol"; -import { DelayedWETH } from "src/dispute/weth/DelayedWETH.sol"; +import { DelayedWETH } from "src/dispute/DelayedWETH.sol"; import { PreimageOracle } from "src/cannon/PreimageOracle.sol"; import { MIPS } from "src/cannon/MIPS.sol"; +import { DisputeGameFactory } from "src/dispute/DisputeGameFactory.sol"; +import { SuperchainConfig } from "src/L1/SuperchainConfig.sol"; +import { ProtocolVersions } from "src/L1/ProtocolVersions.sol"; +import { OPContractsManager } from "src/L1/OPContractsManager.sol"; import { OptimismPortal2 } from "src/L1/OptimismPortal2.sol"; import { SystemConfig } from "src/L1/SystemConfig.sol"; import { L1CrossDomainMessenger } from "src/L1/L1CrossDomainMessenger.sol"; import { L1ERC721Bridge } from "src/L1/L1ERC721Bridge.sol"; import { L1StandardBridge } from "src/L1/L1StandardBridge.sol"; import { OptimismMintableERC20Factory } from "src/universal/OptimismMintableERC20Factory.sol"; +import { ProxyAdmin } from "src/universal/ProxyAdmin.sol"; +import { Proxy } from "src/universal/Proxy.sol"; import { DeployImplementationsInput, DeployImplementations, + DeployImplementationsInterop, DeployImplementationsOutput } from "scripts/DeployImplementations.s.sol"; contract DeployImplementationsInput_Test is Test { - DeployImplementationsInput dsi; + DeployImplementationsInput dii; - DeployImplementationsInput.Input input = DeployImplementationsInput.Input({ - withdrawalDelaySeconds: 100, - minProposalSizeBytes: 200, - challengePeriodSeconds: 300, - proofMaturityDelaySeconds: 400, - disputeGameFinalityDelaySeconds: 500 - }); + uint256 withdrawalDelaySeconds = 100; + uint256 minProposalSizeBytes = 200; + uint256 challengePeriodSeconds = 300; + uint256 proofMaturityDelaySeconds = 400; + uint256 disputeGameFinalityDelaySeconds = 500; + string release = "dev-release"; // this means implementation contracts will be deployed + SuperchainConfig superchainConfigProxy = SuperchainConfig(makeAddr("superchainConfigProxy")); + ProtocolVersions protocolVersionsProxy = ProtocolVersions(makeAddr("protocolVersionsProxy")); function setUp() public { - dsi = new DeployImplementationsInput(); + dii = new DeployImplementationsInput(); } - function test_loadInput_succeeds() public { - dsi.loadInput(input); + function test_getters_whenNotSet_revert() public { + vm.expectRevert("DeployImplementationsInput: not set"); + dii.withdrawalDelaySeconds(); - assertTrue(dsi.inputSet(), "100"); + vm.expectRevert("DeployImplementationsInput: not set"); + dii.minProposalSizeBytes(); - // Compare the test input struct to the getter methods. - assertEq(input.withdrawalDelaySeconds, dsi.withdrawalDelaySeconds(), "200"); - assertEq(input.minProposalSizeBytes, dsi.minProposalSizeBytes(), "300"); - assertEq(input.challengePeriodSeconds, dsi.challengePeriodSeconds(), "400"); - assertEq(input.proofMaturityDelaySeconds, dsi.proofMaturityDelaySeconds(), "500"); - assertEq(input.disputeGameFinalityDelaySeconds, dsi.disputeGameFinalityDelaySeconds(), "600"); + vm.expectRevert("DeployImplementationsInput: not set"); + dii.challengePeriodSeconds(); - // Compare the test input struct to the `input` getter method. - assertEq(keccak256(abi.encode(input)), keccak256(abi.encode(dsi.input())), "800"); - } + vm.expectRevert("DeployImplementationsInput: not set"); + dii.proofMaturityDelaySeconds(); - function test_getters_whenNotSet_revert() public { - bytes memory expectedErr = "DeployImplementationsInput: input not set"; + vm.expectRevert("DeployImplementationsInput: not set"); + dii.disputeGameFinalityDelaySeconds(); - vm.expectRevert(expectedErr); - dsi.withdrawalDelaySeconds(); + vm.expectRevert("DeployImplementationsInput: not set"); + dii.release(); - vm.expectRevert(expectedErr); - dsi.minProposalSizeBytes(); + vm.expectRevert("DeployImplementationsInput: not set"); + dii.superchainConfigProxy(); - vm.expectRevert(expectedErr); - dsi.challengePeriodSeconds(); + vm.expectRevert("DeployImplementationsInput: not set"); + dii.protocolVersionsProxy(); - vm.expectRevert(expectedErr); - dsi.proofMaturityDelaySeconds(); + vm.expectRevert("DeployImplementationsInput: not set"); + dii.superchainProxyAdmin(); - vm.expectRevert(expectedErr); - dsi.disputeGameFinalityDelaySeconds(); + vm.expectRevert("DeployImplementationsInput: not set"); + dii.standardVersionsToml(); + } + + function test_superchainProxyAdmin_whenNotSet_reverts() public { + vm.expectRevert("DeployImplementationsInput: not set"); + dii.superchainProxyAdmin(); + + dii.set(dii.superchainConfigProxy.selector, address(superchainConfigProxy)); + vm.expectRevert(); + dii.superchainProxyAdmin(); + + Proxy noAdminProxy = new Proxy(address(0)); + dii.set(dii.superchainConfigProxy.selector, address(noAdminProxy)); + vm.expectRevert("DeployImplementationsInput: not set"); + dii.superchainProxyAdmin(); + } + + function test_superchainProxyAdmin_succeeds() public { + Proxy proxyWithAdminSet = new Proxy(msg.sender); + dii.set(dii.superchainConfigProxy.selector, address(proxyWithAdminSet)); + ProxyAdmin proxyAdmin = dii.superchainProxyAdmin(); + assertEq(address(msg.sender), address(proxyAdmin), "100"); } } contract DeployImplementationsOutput_Test is Test { - DeployImplementationsOutput dso; + DeployImplementationsOutput dio; function setUp() public { - dso = new DeployImplementationsOutput(); + dio = new DeployImplementationsOutput(); } function test_set_succeeds() public { - DeployImplementationsOutput.Output memory output = DeployImplementationsOutput.Output({ - optimismPortal2Impl: OptimismPortal2(payable(makeAddr("optimismPortal2Impl"))), - delayedWETHImpl: DelayedWETH(payable(makeAddr("delayedWETHImpl"))), - preimageOracleSingleton: PreimageOracle(makeAddr("preimageOracleSingleton")), - mipsSingleton: MIPS(makeAddr("mipsSingleton")), - systemConfigImpl: SystemConfig(makeAddr("systemConfigImpl")), - l1CrossDomainMessengerImpl: L1CrossDomainMessenger(makeAddr("l1CrossDomainMessengerImpl")), - l1ERC721BridgeImpl: L1ERC721Bridge(makeAddr("l1ERC721BridgeImpl")), - l1StandardBridgeImpl: L1StandardBridge(payable(makeAddr("l1StandardBridgeImpl"))), - optimismMintableERC20FactoryImpl: OptimismMintableERC20Factory(makeAddr("optimismMintableERC20FactoryImpl")) - }); - - vm.etch(address(output.optimismPortal2Impl), hex"01"); - vm.etch(address(output.delayedWETHImpl), hex"01"); - vm.etch(address(output.preimageOracleSingleton), hex"01"); - vm.etch(address(output.mipsSingleton), hex"01"); - vm.etch(address(output.systemConfigImpl), hex"01"); - vm.etch(address(output.l1CrossDomainMessengerImpl), hex"01"); - vm.etch(address(output.l1ERC721BridgeImpl), hex"01"); - vm.etch(address(output.l1StandardBridgeImpl), hex"01"); - vm.etch(address(output.optimismMintableERC20FactoryImpl), hex"01"); - - dso.set(dso.optimismPortal2Impl.selector, address(output.optimismPortal2Impl)); - dso.set(dso.delayedWETHImpl.selector, address(output.delayedWETHImpl)); - dso.set(dso.preimageOracleSingleton.selector, address(output.preimageOracleSingleton)); - dso.set(dso.mipsSingleton.selector, address(output.mipsSingleton)); - dso.set(dso.systemConfigImpl.selector, address(output.systemConfigImpl)); - dso.set(dso.l1CrossDomainMessengerImpl.selector, address(output.l1CrossDomainMessengerImpl)); - dso.set(dso.l1ERC721BridgeImpl.selector, address(output.l1ERC721BridgeImpl)); - dso.set(dso.l1StandardBridgeImpl.selector, address(output.l1StandardBridgeImpl)); - dso.set(dso.optimismMintableERC20FactoryImpl.selector, address(output.optimismMintableERC20FactoryImpl)); - - assertEq(address(output.optimismPortal2Impl), address(dso.optimismPortal2Impl()), "100"); - assertEq(address(output.delayedWETHImpl), address(dso.delayedWETHImpl()), "200"); - assertEq(address(output.preimageOracleSingleton), address(dso.preimageOracleSingleton()), "300"); - assertEq(address(output.mipsSingleton), address(dso.mipsSingleton()), "400"); - assertEq(address(output.systemConfigImpl), address(dso.systemConfigImpl()), "500"); - assertEq(address(output.l1CrossDomainMessengerImpl), address(dso.l1CrossDomainMessengerImpl()), "600"); - assertEq(address(output.l1ERC721BridgeImpl), address(dso.l1ERC721BridgeImpl()), "700"); - assertEq(address(output.l1StandardBridgeImpl), address(dso.l1StandardBridgeImpl()), "800"); - assertEq( - address(output.optimismMintableERC20FactoryImpl), address(dso.optimismMintableERC20FactoryImpl()), "900" - ); - - assertEq(keccak256(abi.encode(output)), keccak256(abi.encode(dso.output())), "1000"); + Proxy proxy = new Proxy(address(0)); + address opcmImpl = address(makeAddr("opcmImpl")); + vm.prank(address(0)); + proxy.upgradeTo(opcmImpl); + + OPContractsManager opcmProxy = OPContractsManager(address(proxy)); + OptimismPortal2 optimismPortalImpl = OptimismPortal2(payable(makeAddr("optimismPortalImpl"))); + DelayedWETH delayedWETHImpl = DelayedWETH(payable(makeAddr("delayedWETHImpl"))); + PreimageOracle preimageOracleSingleton = PreimageOracle(makeAddr("preimageOracleSingleton")); + MIPS mipsSingleton = MIPS(makeAddr("mipsSingleton")); + SystemConfig systemConfigImpl = SystemConfig(makeAddr("systemConfigImpl")); + L1CrossDomainMessenger l1CrossDomainMessengerImpl = + L1CrossDomainMessenger(makeAddr("l1CrossDomainMessengerImpl")); + L1ERC721Bridge l1ERC721BridgeImpl = L1ERC721Bridge(makeAddr("l1ERC721BridgeImpl")); + L1StandardBridge l1StandardBridgeImpl = L1StandardBridge(payable(makeAddr("l1StandardBridgeImpl"))); + OptimismMintableERC20Factory optimismMintableERC20FactoryImpl = + OptimismMintableERC20Factory(makeAddr("optimismMintableERC20FactoryImpl")); + DisputeGameFactory disputeGameFactoryImpl = DisputeGameFactory(makeAddr("disputeGameFactoryImpl")); + + vm.etch(address(opcmProxy), address(opcmProxy).code); + vm.etch(address(opcmImpl), hex"01"); + vm.etch(address(optimismPortalImpl), hex"01"); + vm.etch(address(delayedWETHImpl), hex"01"); + vm.etch(address(preimageOracleSingleton), hex"01"); + vm.etch(address(mipsSingleton), hex"01"); + vm.etch(address(systemConfigImpl), hex"01"); + vm.etch(address(l1CrossDomainMessengerImpl), hex"01"); + vm.etch(address(l1ERC721BridgeImpl), hex"01"); + vm.etch(address(l1StandardBridgeImpl), hex"01"); + vm.etch(address(optimismMintableERC20FactoryImpl), hex"01"); + vm.etch(address(disputeGameFactoryImpl), hex"01"); + dio.set(dio.opcmProxy.selector, address(opcmProxy)); + dio.set(dio.optimismPortalImpl.selector, address(optimismPortalImpl)); + dio.set(dio.delayedWETHImpl.selector, address(delayedWETHImpl)); + dio.set(dio.preimageOracleSingleton.selector, address(preimageOracleSingleton)); + dio.set(dio.mipsSingleton.selector, address(mipsSingleton)); + dio.set(dio.systemConfigImpl.selector, address(systemConfigImpl)); + dio.set(dio.l1CrossDomainMessengerImpl.selector, address(l1CrossDomainMessengerImpl)); + dio.set(dio.l1ERC721BridgeImpl.selector, address(l1ERC721BridgeImpl)); + dio.set(dio.l1StandardBridgeImpl.selector, address(l1StandardBridgeImpl)); + dio.set(dio.optimismMintableERC20FactoryImpl.selector, address(optimismMintableERC20FactoryImpl)); + dio.set(dio.disputeGameFactoryImpl.selector, address(disputeGameFactoryImpl)); + + assertEq(address(opcmProxy), address(dio.opcmProxy()), "50"); + assertEq(address(optimismPortalImpl), address(dio.optimismPortalImpl()), "100"); + assertEq(address(delayedWETHImpl), address(dio.delayedWETHImpl()), "200"); + assertEq(address(preimageOracleSingleton), address(dio.preimageOracleSingleton()), "300"); + assertEq(address(mipsSingleton), address(dio.mipsSingleton()), "400"); + assertEq(address(systemConfigImpl), address(dio.systemConfigImpl()), "500"); + assertEq(address(l1CrossDomainMessengerImpl), address(dio.l1CrossDomainMessengerImpl()), "600"); + assertEq(address(l1ERC721BridgeImpl), address(dio.l1ERC721BridgeImpl()), "700"); + assertEq(address(l1StandardBridgeImpl), address(dio.l1StandardBridgeImpl()), "800"); + assertEq(address(optimismMintableERC20FactoryImpl), address(dio.optimismMintableERC20FactoryImpl()), "900"); + assertEq(address(disputeGameFactoryImpl), address(dio.disputeGameFactoryImpl()), "950"); } function test_getters_whenNotSet_revert() public { bytes memory expectedErr = "DeployUtils: zero address"; vm.expectRevert(expectedErr); - dso.optimismPortal2Impl(); + dio.optimismPortalImpl(); vm.expectRevert(expectedErr); - dso.delayedWETHImpl(); + dio.delayedWETHImpl(); vm.expectRevert(expectedErr); - dso.preimageOracleSingleton(); + dio.preimageOracleSingleton(); vm.expectRevert(expectedErr); - dso.mipsSingleton(); + dio.mipsSingleton(); vm.expectRevert(expectedErr); - dso.systemConfigImpl(); + dio.systemConfigImpl(); vm.expectRevert(expectedErr); - dso.l1CrossDomainMessengerImpl(); + dio.l1CrossDomainMessengerImpl(); vm.expectRevert(expectedErr); - dso.l1ERC721BridgeImpl(); + dio.l1ERC721BridgeImpl(); vm.expectRevert(expectedErr); - dso.l1StandardBridgeImpl(); + dio.l1StandardBridgeImpl(); vm.expectRevert(expectedErr); - dso.optimismMintableERC20FactoryImpl(); + dio.optimismMintableERC20FactoryImpl(); + + vm.expectRevert(expectedErr); + dio.disputeGameFactoryImpl(); } function test_getters_whenAddrHasNoCode_reverts() public { address emptyAddr = makeAddr("emptyAddr"); bytes memory expectedErr = bytes(string.concat("DeployUtils: no code at ", vm.toString(emptyAddr))); - dso.set(dso.optimismPortal2Impl.selector, emptyAddr); + dio.set(dio.optimismPortalImpl.selector, emptyAddr); vm.expectRevert(expectedErr); - dso.optimismPortal2Impl(); + dio.optimismPortalImpl(); - dso.set(dso.delayedWETHImpl.selector, emptyAddr); + dio.set(dio.delayedWETHImpl.selector, emptyAddr); vm.expectRevert(expectedErr); - dso.delayedWETHImpl(); + dio.delayedWETHImpl(); - dso.set(dso.preimageOracleSingleton.selector, emptyAddr); + dio.set(dio.preimageOracleSingleton.selector, emptyAddr); vm.expectRevert(expectedErr); - dso.preimageOracleSingleton(); + dio.preimageOracleSingleton(); - dso.set(dso.mipsSingleton.selector, emptyAddr); + dio.set(dio.mipsSingleton.selector, emptyAddr); vm.expectRevert(expectedErr); - dso.mipsSingleton(); + dio.mipsSingleton(); - dso.set(dso.systemConfigImpl.selector, emptyAddr); + dio.set(dio.systemConfigImpl.selector, emptyAddr); vm.expectRevert(expectedErr); - dso.systemConfigImpl(); + dio.systemConfigImpl(); - dso.set(dso.l1CrossDomainMessengerImpl.selector, emptyAddr); + dio.set(dio.l1CrossDomainMessengerImpl.selector, emptyAddr); vm.expectRevert(expectedErr); - dso.l1CrossDomainMessengerImpl(); + dio.l1CrossDomainMessengerImpl(); - dso.set(dso.l1ERC721BridgeImpl.selector, emptyAddr); + dio.set(dio.l1ERC721BridgeImpl.selector, emptyAddr); vm.expectRevert(expectedErr); - dso.l1ERC721BridgeImpl(); + dio.l1ERC721BridgeImpl(); - dso.set(dso.l1StandardBridgeImpl.selector, emptyAddr); + dio.set(dio.l1StandardBridgeImpl.selector, emptyAddr); vm.expectRevert(expectedErr); - dso.l1StandardBridgeImpl(); + dio.l1StandardBridgeImpl(); - dso.set(dso.optimismMintableERC20FactoryImpl.selector, emptyAddr); + dio.set(dio.optimismMintableERC20FactoryImpl.selector, emptyAddr); vm.expectRevert(expectedErr); - dso.optimismMintableERC20FactoryImpl(); + dio.optimismMintableERC20FactoryImpl(); } } contract DeployImplementations_Test is Test { - DeployImplementations deployImplementations; - DeployImplementationsInput dsi; - DeployImplementationsOutput dso; - - // Define a default input struct for testing. - DeployImplementationsInput.Input input = DeployImplementationsInput.Input({ - withdrawalDelaySeconds: 100, - minProposalSizeBytes: 200, - challengePeriodSeconds: 300, - proofMaturityDelaySeconds: 400, - disputeGameFinalityDelaySeconds: 500 - }); + using stdStorage for StdStorage; - function setUp() public { + DeployImplementations deployImplementations; + DeployImplementationsInput dii; + DeployImplementationsOutput dio; + + // Define default inputs for testing. + uint256 withdrawalDelaySeconds = 100; + uint256 minProposalSizeBytes = 200; + uint256 challengePeriodSeconds = 300; + uint256 proofMaturityDelaySeconds = 400; + uint256 disputeGameFinalityDelaySeconds = 500; + SuperchainConfig superchainConfigProxy = SuperchainConfig(makeAddr("superchainConfigProxy")); + ProtocolVersions protocolVersionsProxy = ProtocolVersions(makeAddr("protocolVersionsProxy")); + + function setUp() public virtual { deployImplementations = new DeployImplementations(); - (dsi, dso) = deployImplementations.getIOContracts(); + (dii, dio) = deployImplementations.etchIOContracts(); + + // End users of the DeployImplementations contract will need to set the `standardVersionsToml`. + string memory standardVersionsTomlPath = + string.concat(vm.projectRoot(), "/test/fixtures/standard-versions.toml"); + string memory standardVersionsToml = vm.readFile(standardVersionsTomlPath); + dii.set(dii.standardVersionsToml.selector, standardVersionsToml); + } + + // By deploying the `DeployImplementations` contract with this virtual function, we provide a + // hook that child contracts can override to return a different implementation of the contract. + // This lets us test e.g. the `DeployImplementationsInterop` contract without duplicating test code. + function createDeployImplementationsContract() internal virtual returns (DeployImplementations) { + return new DeployImplementations(); + } + + function hash(bytes32 _seed, uint256 _i) internal pure returns (bytes32) { + return keccak256(abi.encode(_seed, _i)); + } + + function test_deployImplementation_succeeds() public { + string memory deployContractsRelease = "dev-release"; + dii.set(dii.release.selector, deployContractsRelease); + deployImplementations.deploySystemConfigImpl(dii, dio); + assertTrue(address(0) != address(dio.systemConfigImpl())); + } + + function test_reuseImplementation_succeeds() public { + // All hardcoded addresses below are taken from the superchain-registry config: + // https://github.com/ethereum-optimism/superchain-registry/blob/be65d22f8128cf0c4e5b4e1f677daf86843426bf/validation/standard/standard-versions.toml#L11 + string memory testRelease = "op-contracts/v1.6.0"; + dii.set(dii.release.selector, testRelease); + + deployImplementations.deploySystemConfigImpl(dii, dio); + address srSystemConfigImpl = address(0xF56D96B2535B932656d3c04Ebf51baBff241D886); + vm.etch(address(srSystemConfigImpl), hex"01"); + assertEq(srSystemConfigImpl, address(dio.systemConfigImpl())); + + address srL1CrossDomainMessengerImpl = address(0xD3494713A5cfaD3F5359379DfA074E2Ac8C6Fd65); + vm.etch(address(srL1CrossDomainMessengerImpl), hex"01"); + deployImplementations.deployL1CrossDomainMessengerImpl(dii, dio); + assertEq(srL1CrossDomainMessengerImpl, address(dio.l1CrossDomainMessengerImpl())); + + address srL1ERC721BridgeImpl = address(0xAE2AF01232a6c4a4d3012C5eC5b1b35059caF10d); + vm.etch(address(srL1ERC721BridgeImpl), hex"01"); + deployImplementations.deployL1ERC721BridgeImpl(dii, dio); + assertEq(srL1ERC721BridgeImpl, address(dio.l1ERC721BridgeImpl())); + + address srL1StandardBridgeImpl = address(0x64B5a5Ed26DCb17370Ff4d33a8D503f0fbD06CfF); + vm.etch(address(srL1StandardBridgeImpl), hex"01"); + deployImplementations.deployL1StandardBridgeImpl(dii, dio); + assertEq(srL1StandardBridgeImpl, address(dio.l1StandardBridgeImpl())); + + address srOptimismMintableERC20FactoryImpl = address(0xE01efbeb1089D1d1dB9c6c8b135C934C0734c846); + vm.etch(address(srOptimismMintableERC20FactoryImpl), hex"01"); + deployImplementations.deployOptimismMintableERC20FactoryImpl(dii, dio); + assertEq(srOptimismMintableERC20FactoryImpl, address(dio.optimismMintableERC20FactoryImpl())); + + address srOptimismPortalImpl = address(0xe2F826324b2faf99E513D16D266c3F80aE87832B); + vm.etch(address(srOptimismPortalImpl), hex"01"); + deployImplementations.deployOptimismPortalImpl(dii, dio); + assertEq(srOptimismPortalImpl, address(dio.optimismPortalImpl())); + + address srDelayedWETHImpl = address(0x71e966Ae981d1ce531a7b6d23DC0f27B38409087); + vm.etch(address(srDelayedWETHImpl), hex"01"); + deployImplementations.deployDelayedWETHImpl(dii, dio); + assertEq(srDelayedWETHImpl, address(dio.delayedWETHImpl())); + + address srPreimageOracleSingleton = address(0x9c065e11870B891D214Bc2Da7EF1f9DDFA1BE277); + vm.etch(address(srPreimageOracleSingleton), hex"01"); + deployImplementations.deployPreimageOracleSingleton(dii, dio); + assertEq(srPreimageOracleSingleton, address(dio.preimageOracleSingleton())); + + address srMipsSingleton = address(0x16e83cE5Ce29BF90AD9Da06D2fE6a15d5f344ce4); + vm.etch(address(srMipsSingleton), hex"01"); + deployImplementations.deployMipsSingleton(dii, dio); + assertEq(srMipsSingleton, address(dio.mipsSingleton())); + + address srDisputeGameFactoryImpl = address(0xc641A33cab81C559F2bd4b21EA34C290E2440C2B); + vm.etch(address(srDisputeGameFactoryImpl), hex"01"); + deployImplementations.deployDisputeGameFactoryImpl(dii, dio); + assertEq(srDisputeGameFactoryImpl, address(dio.disputeGameFactoryImpl())); } - function test_run_succeeds(DeployImplementationsInput.Input memory _input) public { - // This is a requirement in the PreimageOracle contract. - _input.challengePeriodSeconds = bound(_input.challengePeriodSeconds, 0, type(uint64).max); - - DeployImplementationsOutput.Output memory output = deployImplementations.run(_input); - - // Assert that individual input fields were properly set based on the input struct. - assertEq(_input.withdrawalDelaySeconds, dsi.withdrawalDelaySeconds(), "100"); - assertEq(_input.minProposalSizeBytes, dsi.minProposalSizeBytes(), "200"); - assertEq(_input.challengePeriodSeconds, dsi.challengePeriodSeconds(), "300"); - assertEq(_input.proofMaturityDelaySeconds, dsi.proofMaturityDelaySeconds(), "400"); - assertEq(_input.disputeGameFinalityDelaySeconds, dsi.disputeGameFinalityDelaySeconds(), "500"); - - // Assert that individual output fields were properly set based on the output struct. - assertEq(address(output.optimismPortal2Impl), address(dso.optimismPortal2Impl()), "600"); - assertEq(address(output.delayedWETHImpl), address(dso.delayedWETHImpl()), "700"); - assertEq(address(output.preimageOracleSingleton), address(dso.preimageOracleSingleton()), "800"); - assertEq(address(output.mipsSingleton), address(dso.mipsSingleton()), "900"); - assertEq(address(output.systemConfigImpl), address(dso.systemConfigImpl()), "1000"); - assertEq(address(output.l1CrossDomainMessengerImpl), address(dso.l1CrossDomainMessengerImpl()), "1100"); - assertEq(address(output.l1ERC721BridgeImpl), address(dso.l1ERC721BridgeImpl()), "1200"); - assertEq(address(output.l1StandardBridgeImpl), address(dso.l1StandardBridgeImpl()), "1300"); - assertEq( - address(output.optimismMintableERC20FactoryImpl), address(dso.optimismMintableERC20FactoryImpl()), "1400" - ); - - // Assert that the full input and output structs were properly set. - assertEq(keccak256(abi.encode(_input)), keccak256(abi.encode(DeployImplementationsInput(dsi).input())), "1500"); - assertEq( - keccak256(abi.encode(output)), keccak256(abi.encode(DeployImplementationsOutput(dso).output())), "1600" - ); - - // Assert inputs were properly passed through to the contract initializers. - assertEq(output.delayedWETHImpl.delay(), _input.withdrawalDelaySeconds, "1700"); - assertEq(output.preimageOracleSingleton.challengePeriod(), _input.challengePeriodSeconds, "1800"); - assertEq(output.preimageOracleSingleton.minProposalSize(), _input.minProposalSizeBytes, "1900"); - assertEq(output.optimismPortal2Impl.proofMaturityDelaySeconds(), _input.proofMaturityDelaySeconds, "2000"); - assertEq( - output.optimismPortal2Impl.disputeGameFinalityDelaySeconds(), _input.disputeGameFinalityDelaySeconds, "2100" - ); + function test_deployAtNonExistentRelease_reverts() public { + string memory unknownRelease = "op-contracts/v0.0.0"; + dii.set(dii.release.selector, unknownRelease); + + bytes memory expectedErr = + bytes(string.concat("DeployImplementations: failed to deploy release ", unknownRelease)); + + vm.expectRevert(expectedErr); + deployImplementations.deploySystemConfigImpl(dii, dio); + + vm.expectRevert(expectedErr); + deployImplementations.deployL1CrossDomainMessengerImpl(dii, dio); + + vm.expectRevert(expectedErr); + deployImplementations.deployL1ERC721BridgeImpl(dii, dio); + + vm.expectRevert(expectedErr); + deployImplementations.deployL1StandardBridgeImpl(dii, dio); + + vm.expectRevert(expectedErr); + deployImplementations.deployOptimismMintableERC20FactoryImpl(dii, dio); + + // TODO: Uncomment the code below when OPContractsManager is deployed based on release. Superchain-registry + // doesn't contain OPContractsManager yet. + // dii.set(dii.superchainConfigProxy.selector, address(superchainConfigProxy)); + // dii.set(dii.protocolVersionsProxy.selector, address(protocolVersionsProxy)); + // vm.etch(address(superchainConfigProxy), hex"01"); + // vm.etch(address(protocolVersionsProxy), hex"01"); + // vm.expectRevert(expectedErr); + // deployImplementations.deployOPContractsManagerImpl(dii, dio); + + dii.set(dii.proofMaturityDelaySeconds.selector, 1); + dii.set(dii.disputeGameFinalityDelaySeconds.selector, 2); + vm.expectRevert(expectedErr); + deployImplementations.deployOptimismPortalImpl(dii, dio); + + dii.set(dii.withdrawalDelaySeconds.selector, 1); + vm.expectRevert(expectedErr); + deployImplementations.deployDelayedWETHImpl(dii, dio); + + dii.set(dii.minProposalSizeBytes.selector, 1); + dii.set(dii.challengePeriodSeconds.selector, 2); + vm.expectRevert(expectedErr); + deployImplementations.deployPreimageOracleSingleton(dii, dio); + + address preImageOracleSingleton = makeAddr("preImageOracleSingleton"); + vm.etch(address(preImageOracleSingleton), hex"01"); + dio.set(dio.preimageOracleSingleton.selector, preImageOracleSingleton); + vm.expectRevert(expectedErr); + deployImplementations.deployMipsSingleton(dii, dio); + + vm.expectRevert(expectedErr); // fault proof contracts don't exist at this release + deployImplementations.deployDisputeGameFactoryImpl(dii, dio); + } + + function test_noContractExistsAtRelease_reverts() public { + string memory unknownRelease = "op-contracts/v1.3.0"; + dii.set(dii.release.selector, unknownRelease); + bytes memory expectedErr = + bytes(string.concat("DeployImplementations: failed to deploy release ", unknownRelease)); + + vm.expectRevert(expectedErr); // fault proof contracts don't exist at this release + deployImplementations.deployDisputeGameFactoryImpl(dii, dio); + } + + function testFuzz_run_memory_succeeds(bytes32 _seed) public { + withdrawalDelaySeconds = uint256(hash(_seed, 0)); + minProposalSizeBytes = uint256(hash(_seed, 1)); + challengePeriodSeconds = bound(uint256(hash(_seed, 2)), 0, type(uint64).max); + proofMaturityDelaySeconds = uint256(hash(_seed, 3)); + disputeGameFinalityDelaySeconds = uint256(hash(_seed, 4)); + string memory release = string(bytes.concat(hash(_seed, 5))); + protocolVersionsProxy = ProtocolVersions(address(uint160(uint256(hash(_seed, 7))))); + + // Must configure the ProxyAdmin contract which is used to upgrade the OPCM's proxy contract. + ProxyAdmin superchainProxyAdmin = new ProxyAdmin(msg.sender); + superchainConfigProxy = SuperchainConfig(address(new Proxy(payable(address(superchainProxyAdmin))))); + + SuperchainConfig superchainConfigImpl = SuperchainConfig(address(uint160(uint256(hash(_seed, 6))))); + vm.prank(address(superchainProxyAdmin)); + Proxy(payable(address(superchainConfigProxy))).upgradeTo(address(superchainConfigImpl)); + + vm.etch(address(superchainProxyAdmin), address(superchainProxyAdmin).code); + vm.etch(address(superchainConfigProxy), address(superchainConfigProxy).code); + vm.etch(address(protocolVersionsProxy), hex"01"); + + dii.set(dii.withdrawalDelaySeconds.selector, withdrawalDelaySeconds); + dii.set(dii.minProposalSizeBytes.selector, minProposalSizeBytes); + dii.set(dii.challengePeriodSeconds.selector, challengePeriodSeconds); + dii.set(dii.proofMaturityDelaySeconds.selector, proofMaturityDelaySeconds); + dii.set(dii.disputeGameFinalityDelaySeconds.selector, disputeGameFinalityDelaySeconds); + dii.set(dii.release.selector, release); + dii.set(dii.superchainConfigProxy.selector, address(superchainConfigProxy)); + dii.set(dii.protocolVersionsProxy.selector, address(protocolVersionsProxy)); + + deployImplementations.run(dii, dio); + + // Assert that individual input fields were properly set based on the inputs. + assertEq(withdrawalDelaySeconds, dii.withdrawalDelaySeconds(), "100"); + assertEq(minProposalSizeBytes, dii.minProposalSizeBytes(), "200"); + assertEq(challengePeriodSeconds, dii.challengePeriodSeconds(), "300"); + assertEq(proofMaturityDelaySeconds, dii.proofMaturityDelaySeconds(), "400"); + assertEq(disputeGameFinalityDelaySeconds, dii.disputeGameFinalityDelaySeconds(), "500"); + assertEq(release, dii.release(), "525"); + assertEq(address(superchainConfigProxy), address(dii.superchainConfigProxy()), "550"); + assertEq(address(protocolVersionsProxy), address(dii.protocolVersionsProxy()), "575"); + assertEq(address(superchainProxyAdmin), address(dii.superchainProxyAdmin()), "580"); // Architecture assertions. - assertEq(address(output.mipsSingleton.oracle()), address(output.preimageOracleSingleton), "2200"); + assertEq(address(dio.mipsSingleton().oracle()), address(dio.preimageOracleSingleton()), "600"); // Ensure that `checkOutput` passes. This is called by the `run` function during execution, // so this just acts as a sanity check. It reverts on failure. - dso.checkOutput(); + dio.checkOutput(dii); } - function test_run_largeChallengePeriodSeconds_reverts(uint256 _challengePeriodSeconds) public { - input.challengePeriodSeconds = bound(_challengePeriodSeconds, uint256(type(uint64).max) + 1, type(uint256).max); - vm.expectRevert("DeployImplementationsInput: challenge period too large"); - deployImplementations.run(input); + function testFuzz_run_largeChallengePeriodSeconds_reverts(uint256 _challengePeriodSeconds) public { + // Set the defaults. + dii.set(dii.withdrawalDelaySeconds.selector, withdrawalDelaySeconds); + dii.set(dii.minProposalSizeBytes.selector, minProposalSizeBytes); + dii.set(dii.challengePeriodSeconds.selector, challengePeriodSeconds); + dii.set(dii.proofMaturityDelaySeconds.selector, proofMaturityDelaySeconds); + dii.set(dii.disputeGameFinalityDelaySeconds.selector, disputeGameFinalityDelaySeconds); + string memory release = "dev-release"; + dii.set(dii.release.selector, release); + dii.set(dii.superchainConfigProxy.selector, address(superchainConfigProxy)); + dii.set(dii.protocolVersionsProxy.selector, address(protocolVersionsProxy)); + + // Set the challenge period to a value that is too large, using vm.store because the setter + // method won't allow it. + challengePeriodSeconds = bound(_challengePeriodSeconds, uint256(type(uint64).max) + 1, type(uint256).max); + uint256 slot = + stdstore.enable_packed_slots().target(address(dii)).sig(dii.challengePeriodSeconds.selector).find(); + vm.store(address(dii), bytes32(slot), bytes32(challengePeriodSeconds)); + + vm.expectRevert("DeployImplementationsInput: challengePeriodSeconds too large"); + deployImplementations.run(dii, dio); + } +} + +contract DeployImplementationsInterop_Test is DeployImplementations_Test { + function createDeployImplementationsContract() internal override returns (DeployImplementations) { + return new DeployImplementationsInterop(); } } diff --git a/packages/contracts-bedrock/test/DeployOPChain.t.sol b/packages/contracts-bedrock/test/DeployOPChain.t.sol index 5b4b60d175c43..9537f6339575e 100644 --- a/packages/contracts-bedrock/test/DeployOPChain.t.sol +++ b/packages/contracts-bedrock/test/DeployOPChain.t.sol @@ -3,304 +3,510 @@ pragma solidity 0.8.15; import { Test } from "forge-std/Test.sol"; +import { DeploySuperchainInput, DeploySuperchain, DeploySuperchainOutput } from "scripts/DeploySuperchain.s.sol"; +import { + DeployImplementationsInput, + DeployImplementations, + DeployImplementationsInterop, + DeployImplementationsOutput +} from "scripts/DeployImplementations.s.sol"; +import { DeployOPChainInput, DeployOPChain, DeployOPChainOutput } from "scripts/DeployOPChain.s.sol"; + import { ProxyAdmin } from "src/universal/ProxyAdmin.sol"; import { AddressManager } from "src/legacy/AddressManager.sol"; -import { DelayedWETH } from "src/dispute/weth/DelayedWETH.sol"; +import { DelayedWETH } from "src/dispute/DelayedWETH.sol"; import { DisputeGameFactory } from "src/dispute/DisputeGameFactory.sol"; import { AnchorStateRegistry } from "src/dispute/AnchorStateRegistry.sol"; import { FaultDisputeGame } from "src/dispute/FaultDisputeGame.sol"; import { PermissionedDisputeGame } from "src/dispute/PermissionedDisputeGame.sol"; +import { SuperchainConfig } from "src/L1/SuperchainConfig.sol"; +import { ProtocolVersions, ProtocolVersion } from "src/L1/ProtocolVersions.sol"; +import { OPContractsManager } from "src/L1/OPContractsManager.sol"; import { OptimismPortal2 } from "src/L1/OptimismPortal2.sol"; import { SystemConfig } from "src/L1/SystemConfig.sol"; import { L1CrossDomainMessenger } from "src/L1/L1CrossDomainMessenger.sol"; import { L1ERC721Bridge } from "src/L1/L1ERC721Bridge.sol"; import { L1StandardBridge } from "src/L1/L1StandardBridge.sol"; import { OptimismMintableERC20Factory } from "src/universal/OptimismMintableERC20Factory.sol"; +import { Proxy } from "src/universal/Proxy.sol"; -import { DeployOPChainInput, DeployOPChain, DeployOPChainOutput } from "scripts/DeployOPChain.s.sol"; +import { GameType, GameTypes, Hash, OutputRoot } from "src/dispute/lib/Types.sol"; contract DeployOPChainInput_Test is Test { - DeployOPChainInput dsi; - - DeployOPChainInput.Input input = DeployOPChainInput.Input({ - roles: DeployOPChainInput.Roles({ - opChainProxyAdminOwner: makeAddr("opChainProxyAdminOwner"), - systemConfigOwner: makeAddr("systemConfigOwner"), - batcher: makeAddr("batcher"), - unsafeBlockSigner: makeAddr("unsafeBlockSigner"), - proposer: makeAddr("proposer"), - challenger: makeAddr("challenger") - }), - basefeeScalar: 100, - blobBaseFeeScalar: 200, - l2ChainId: 300 - }); + DeployOPChainInput doi; + + // Define defaults. + address opChainProxyAdminOwner = makeAddr("opChainProxyAdminOwner"); + address systemConfigOwner = makeAddr("systemConfigOwner"); + address batcher = makeAddr("batcher"); + address unsafeBlockSigner = makeAddr("unsafeBlockSigner"); + address proposer = makeAddr("proposer"); + address challenger = makeAddr("challenger"); + uint32 basefeeScalar = 100; + uint32 blobBaseFeeScalar = 200; + uint256 l2ChainId = 300; + OPContractsManager opcm = OPContractsManager(makeAddr("opcm")); function setUp() public { - dsi = new DeployOPChainInput(); + doi = new DeployOPChainInput(); } - function test_loadInput_succeeds() public { - dsi.loadInput(input); - - assertTrue(dsi.inputSet(), "100"); - - // Compare the test input struct to the getter methods. - assertEq(input.roles.opChainProxyAdminOwner, dsi.opChainProxyAdminOwner(), "200"); - assertEq(input.roles.systemConfigOwner, dsi.systemConfigOwner(), "300"); - assertEq(input.roles.batcher, dsi.batcher(), "400"); - assertEq(input.roles.unsafeBlockSigner, dsi.unsafeBlockSigner(), "500"); - assertEq(input.roles.proposer, dsi.proposer(), "600"); - assertEq(input.roles.challenger, dsi.challenger(), "700"); - assertEq(input.basefeeScalar, dsi.basefeeScalar(), "800"); - assertEq(input.blobBaseFeeScalar, dsi.blobBaseFeeScalar(), "900"); - assertEq(input.l2ChainId, dsi.l2ChainId(), "1000"); + function buildOpcmProxy() public returns (Proxy opcmProxy) { + opcmProxy = new Proxy(address(0)); + OPContractsManager opcmImpl = OPContractsManager(address(makeAddr("opcmImpl"))); + vm.prank(address(0)); + opcmProxy.upgradeTo(address(opcmImpl)); + vm.etch(address(opcmProxy), address(opcmProxy).code); + vm.etch(address(opcmImpl), hex"01"); + } - // Compare the test input struct to the `input` getter method. - assertEq(keccak256(abi.encode(input)), keccak256(abi.encode(dsi.input())), "1100"); + function test_set_succeeds() public { + doi.set(doi.opChainProxyAdminOwner.selector, opChainProxyAdminOwner); + doi.set(doi.systemConfigOwner.selector, systemConfigOwner); + doi.set(doi.batcher.selector, batcher); + doi.set(doi.unsafeBlockSigner.selector, unsafeBlockSigner); + doi.set(doi.proposer.selector, proposer); + doi.set(doi.challenger.selector, challenger); + doi.set(doi.basefeeScalar.selector, basefeeScalar); + doi.set(doi.blobBaseFeeScalar.selector, blobBaseFeeScalar); + doi.set(doi.l2ChainId.selector, l2ChainId); + + (Proxy opcmProxy) = buildOpcmProxy(); + doi.set(doi.opcmProxy.selector, address(opcmProxy)); + + // Compare the default inputs to the getter methods. + assertEq(opChainProxyAdminOwner, doi.opChainProxyAdminOwner(), "200"); + assertEq(systemConfigOwner, doi.systemConfigOwner(), "300"); + assertEq(batcher, doi.batcher(), "400"); + assertEq(unsafeBlockSigner, doi.unsafeBlockSigner(), "500"); + assertEq(proposer, doi.proposer(), "600"); + assertEq(challenger, doi.challenger(), "700"); + assertEq(basefeeScalar, doi.basefeeScalar(), "800"); + assertEq(blobBaseFeeScalar, doi.blobBaseFeeScalar(), "900"); + assertEq(l2ChainId, doi.l2ChainId(), "1000"); + assertEq(address(opcmProxy), address(doi.opcmProxy()), "1100"); } function test_getters_whenNotSet_revert() public { - bytes memory expectedErr = "DeployOPChainInput: input not set"; + bytes memory expectedErr = "DeployOPChainInput: not set"; vm.expectRevert(expectedErr); - dsi.opChainProxyAdminOwner(); + doi.opChainProxyAdminOwner(); vm.expectRevert(expectedErr); - dsi.systemConfigOwner(); + doi.systemConfigOwner(); vm.expectRevert(expectedErr); - dsi.batcher(); + doi.batcher(); vm.expectRevert(expectedErr); - dsi.unsafeBlockSigner(); + doi.unsafeBlockSigner(); vm.expectRevert(expectedErr); - dsi.proposer(); + doi.proposer(); vm.expectRevert(expectedErr); - dsi.challenger(); + doi.challenger(); vm.expectRevert(expectedErr); - dsi.basefeeScalar(); + doi.basefeeScalar(); vm.expectRevert(expectedErr); - dsi.blobBaseFeeScalar(); + doi.blobBaseFeeScalar(); vm.expectRevert(expectedErr); - dsi.l2ChainId(); + doi.l2ChainId(); } } contract DeployOPChainOutput_Test is Test { - DeployOPChainOutput dso; + DeployOPChainOutput doo; + + // Define default outputs to set. + // We set these in storage because doing it locally in test_set_succeeds results in stack too deep. + ProxyAdmin opChainProxyAdmin = ProxyAdmin(makeAddr("optimismPortal2Impl")); + AddressManager addressManager = AddressManager(makeAddr("delayedWETHImpl")); + L1ERC721Bridge l1ERC721BridgeProxy = L1ERC721Bridge(makeAddr("l1ERC721BridgeProxy")); + SystemConfig systemConfigProxy = SystemConfig(makeAddr("systemConfigProxy")); + OptimismMintableERC20Factory optimismMintableERC20FactoryProxy = + OptimismMintableERC20Factory(makeAddr("optimismMintableERC20FactoryProxy")); + L1StandardBridge l1StandardBridgeProxy = L1StandardBridge(payable(makeAddr("l1StandardBridgeProxy"))); + L1CrossDomainMessenger l1CrossDomainMessengerProxy = L1CrossDomainMessenger(makeAddr("l1CrossDomainMessengerProxy")); + OptimismPortal2 optimismPortalProxy = OptimismPortal2(payable(makeAddr("optimismPortalProxy"))); + DisputeGameFactory disputeGameFactoryProxy = DisputeGameFactory(makeAddr("disputeGameFactoryProxy")); + AnchorStateRegistry anchorStateRegistryProxy = AnchorStateRegistry(makeAddr("anchorStateRegistryProxy")); + AnchorStateRegistry anchorStateRegistryImpl = AnchorStateRegistry(makeAddr("anchorStateRegistryImpl")); + FaultDisputeGame faultDisputeGame = FaultDisputeGame(makeAddr("faultDisputeGame")); + PermissionedDisputeGame permissionedDisputeGame = PermissionedDisputeGame(makeAddr("permissionedDisputeGame")); + DelayedWETH delayedWETHPermissionedGameProxy = DelayedWETH(payable(makeAddr("delayedWETHPermissionedGameProxy"))); + DelayedWETH delayedWETHPermissionlessGameProxy = + DelayedWETH(payable(makeAddr("delayedWETHPermissionlessGameProxy"))); function setUp() public { - dso = new DeployOPChainOutput(); + doo = new DeployOPChainOutput(); } function test_set_succeeds() public { - DeployOPChainOutput.Output memory output = DeployOPChainOutput.Output({ - opChainProxyAdmin: ProxyAdmin(makeAddr("optimismPortal2Impl")), - addressManager: AddressManager(makeAddr("delayedWETHImpl")), - l1ERC721BridgeProxy: L1ERC721Bridge(makeAddr("l1ERC721BridgeProxy")), - systemConfigProxy: SystemConfig(makeAddr("systemConfigProxy")), - optimismMintableERC20FactoryProxy: OptimismMintableERC20Factory(makeAddr("optimismMintableERC20FactoryProxy")), - l1StandardBridgeProxy: L1StandardBridge(payable(makeAddr("l1StandardBridgeProxy"))), - l1CrossDomainMessengerProxy: L1CrossDomainMessenger(makeAddr("l1CrossDomainMessengerProxy")), - optimismPortalProxy: OptimismPortal2(payable(makeAddr("optimismPortalProxy"))), - disputeGameFactoryProxy: DisputeGameFactory(makeAddr("disputeGameFactoryProxy")), - disputeGameFactoryImpl: DisputeGameFactory(makeAddr("disputeGameFactoryImpl")), - anchorStateRegistryProxy: AnchorStateRegistry(makeAddr("anchorStateRegistryProxy")), - anchorStateRegistryImpl: AnchorStateRegistry(makeAddr("anchorStateRegistryImpl")), - faultDisputeGame: FaultDisputeGame(makeAddr("faultDisputeGame")), - permissionedDisputeGame: PermissionedDisputeGame(makeAddr("permissionedDisputeGame")), - delayedWETHPermissionedGameProxy: DelayedWETH(payable(makeAddr("delayedWETHPermissionedGameProxy"))), - delayedWETHPermissionlessGameProxy: DelayedWETH(payable(makeAddr("delayedWETHPermissionlessGameProxy"))) - }); - - vm.etch(address(output.opChainProxyAdmin), hex"01"); - vm.etch(address(output.addressManager), hex"01"); - vm.etch(address(output.l1ERC721BridgeProxy), hex"01"); - vm.etch(address(output.systemConfigProxy), hex"01"); - vm.etch(address(output.optimismMintableERC20FactoryProxy), hex"01"); - vm.etch(address(output.l1StandardBridgeProxy), hex"01"); - vm.etch(address(output.l1CrossDomainMessengerProxy), hex"01"); - vm.etch(address(output.optimismPortalProxy), hex"01"); - vm.etch(address(output.disputeGameFactoryProxy), hex"01"); - vm.etch(address(output.disputeGameFactoryImpl), hex"01"); - vm.etch(address(output.anchorStateRegistryProxy), hex"01"); - vm.etch(address(output.anchorStateRegistryImpl), hex"01"); - vm.etch(address(output.faultDisputeGame), hex"01"); - vm.etch(address(output.permissionedDisputeGame), hex"01"); - vm.etch(address(output.delayedWETHPermissionedGameProxy), hex"01"); - vm.etch(address(output.delayedWETHPermissionlessGameProxy), hex"01"); - - dso.set(dso.opChainProxyAdmin.selector, address(output.opChainProxyAdmin)); - dso.set(dso.addressManager.selector, address(output.addressManager)); - dso.set(dso.l1ERC721BridgeProxy.selector, address(output.l1ERC721BridgeProxy)); - dso.set(dso.systemConfigProxy.selector, address(output.systemConfigProxy)); - dso.set(dso.optimismMintableERC20FactoryProxy.selector, address(output.optimismMintableERC20FactoryProxy)); - dso.set(dso.l1StandardBridgeProxy.selector, address(output.l1StandardBridgeProxy)); - dso.set(dso.l1CrossDomainMessengerProxy.selector, address(output.l1CrossDomainMessengerProxy)); - dso.set(dso.optimismPortalProxy.selector, address(output.optimismPortalProxy)); - dso.set(dso.disputeGameFactoryProxy.selector, address(output.disputeGameFactoryProxy)); - dso.set(dso.disputeGameFactoryImpl.selector, address(output.disputeGameFactoryImpl)); - dso.set(dso.anchorStateRegistryProxy.selector, address(output.anchorStateRegistryProxy)); - dso.set(dso.anchorStateRegistryImpl.selector, address(output.anchorStateRegistryImpl)); - dso.set(dso.faultDisputeGame.selector, address(output.faultDisputeGame)); - dso.set(dso.permissionedDisputeGame.selector, address(output.permissionedDisputeGame)); - dso.set(dso.delayedWETHPermissionedGameProxy.selector, address(output.delayedWETHPermissionedGameProxy)); - dso.set(dso.delayedWETHPermissionlessGameProxy.selector, address(output.delayedWETHPermissionlessGameProxy)); - - assertEq(address(output.opChainProxyAdmin), address(dso.opChainProxyAdmin()), "100"); - assertEq(address(output.addressManager), address(dso.addressManager()), "200"); - assertEq(address(output.l1ERC721BridgeProxy), address(dso.l1ERC721BridgeProxy()), "300"); - assertEq(address(output.systemConfigProxy), address(dso.systemConfigProxy()), "400"); - assertEq( - address(output.optimismMintableERC20FactoryProxy), address(dso.optimismMintableERC20FactoryProxy()), "500" - ); - assertEq(address(output.l1StandardBridgeProxy), address(dso.l1StandardBridgeProxy()), "600"); - assertEq(address(output.l1CrossDomainMessengerProxy), address(dso.l1CrossDomainMessengerProxy()), "700"); - assertEq(address(output.optimismPortalProxy), address(dso.optimismPortalProxy()), "800"); - assertEq(address(output.disputeGameFactoryProxy), address(dso.disputeGameFactoryProxy()), "900"); - assertEq(address(output.disputeGameFactoryImpl), address(dso.disputeGameFactoryImpl()), "1000"); - assertEq(address(output.anchorStateRegistryProxy), address(dso.anchorStateRegistryProxy()), "1100"); - assertEq(address(output.anchorStateRegistryImpl), address(dso.anchorStateRegistryImpl()), "1200"); - assertEq(address(output.faultDisputeGame), address(dso.faultDisputeGame()), "1300"); - assertEq(address(output.permissionedDisputeGame), address(dso.permissionedDisputeGame()), "1400"); - assertEq( - address(output.delayedWETHPermissionedGameProxy), address(dso.delayedWETHPermissionedGameProxy()), "1500" - ); - assertEq( - address(output.delayedWETHPermissionlessGameProxy), - address(dso.delayedWETHPermissionlessGameProxy()), - "1600" - ); - - assertEq(keccak256(abi.encode(output)), keccak256(abi.encode(dso.output())), "1700"); + vm.etch(address(opChainProxyAdmin), hex"01"); + vm.etch(address(addressManager), hex"01"); + vm.etch(address(l1ERC721BridgeProxy), hex"01"); + vm.etch(address(systemConfigProxy), hex"01"); + vm.etch(address(optimismMintableERC20FactoryProxy), hex"01"); + vm.etch(address(l1StandardBridgeProxy), hex"01"); + vm.etch(address(l1CrossDomainMessengerProxy), hex"01"); + vm.etch(address(optimismPortalProxy), hex"01"); + vm.etch(address(disputeGameFactoryProxy), hex"01"); + vm.etch(address(anchorStateRegistryProxy), hex"01"); + vm.etch(address(anchorStateRegistryImpl), hex"01"); + vm.etch(address(faultDisputeGame), hex"01"); + vm.etch(address(permissionedDisputeGame), hex"01"); + vm.etch(address(delayedWETHPermissionedGameProxy), hex"01"); + vm.etch(address(delayedWETHPermissionlessGameProxy), hex"01"); + + doo.set(doo.opChainProxyAdmin.selector, address(opChainProxyAdmin)); + doo.set(doo.addressManager.selector, address(addressManager)); + doo.set(doo.l1ERC721BridgeProxy.selector, address(l1ERC721BridgeProxy)); + doo.set(doo.systemConfigProxy.selector, address(systemConfigProxy)); + doo.set(doo.optimismMintableERC20FactoryProxy.selector, address(optimismMintableERC20FactoryProxy)); + doo.set(doo.l1StandardBridgeProxy.selector, address(l1StandardBridgeProxy)); + doo.set(doo.l1CrossDomainMessengerProxy.selector, address(l1CrossDomainMessengerProxy)); + doo.set(doo.optimismPortalProxy.selector, address(optimismPortalProxy)); + doo.set(doo.disputeGameFactoryProxy.selector, address(disputeGameFactoryProxy)); + doo.set(doo.anchorStateRegistryProxy.selector, address(anchorStateRegistryProxy)); + doo.set(doo.anchorStateRegistryImpl.selector, address(anchorStateRegistryImpl)); + doo.set(doo.faultDisputeGame.selector, address(faultDisputeGame)); + doo.set(doo.permissionedDisputeGame.selector, address(permissionedDisputeGame)); + doo.set(doo.delayedWETHPermissionedGameProxy.selector, address(delayedWETHPermissionedGameProxy)); + doo.set(doo.delayedWETHPermissionlessGameProxy.selector, address(delayedWETHPermissionlessGameProxy)); + + assertEq(address(opChainProxyAdmin), address(doo.opChainProxyAdmin()), "100"); + assertEq(address(addressManager), address(doo.addressManager()), "200"); + assertEq(address(l1ERC721BridgeProxy), address(doo.l1ERC721BridgeProxy()), "300"); + assertEq(address(systemConfigProxy), address(doo.systemConfigProxy()), "400"); + assertEq(address(optimismMintableERC20FactoryProxy), address(doo.optimismMintableERC20FactoryProxy()), "500"); + assertEq(address(l1StandardBridgeProxy), address(doo.l1StandardBridgeProxy()), "600"); + assertEq(address(l1CrossDomainMessengerProxy), address(doo.l1CrossDomainMessengerProxy()), "700"); + assertEq(address(optimismPortalProxy), address(doo.optimismPortalProxy()), "800"); + assertEq(address(disputeGameFactoryProxy), address(doo.disputeGameFactoryProxy()), "900"); + assertEq(address(anchorStateRegistryProxy), address(doo.anchorStateRegistryProxy()), "1100"); + assertEq(address(anchorStateRegistryImpl), address(doo.anchorStateRegistryImpl()), "1200"); + assertEq(address(faultDisputeGame), address(doo.faultDisputeGame()), "1300"); + assertEq(address(permissionedDisputeGame), address(doo.permissionedDisputeGame()), "1400"); + assertEq(address(delayedWETHPermissionedGameProxy), address(doo.delayedWETHPermissionedGameProxy()), "1500"); + assertEq(address(delayedWETHPermissionlessGameProxy), address(doo.delayedWETHPermissionlessGameProxy()), "1600"); } function test_getters_whenNotSet_revert() public { bytes memory expectedErr = "DeployUtils: zero address"; vm.expectRevert(expectedErr); - dso.opChainProxyAdmin(); - - vm.expectRevert(expectedErr); - dso.addressManager(); + doo.opChainProxyAdmin(); vm.expectRevert(expectedErr); - dso.l1ERC721BridgeProxy(); + doo.addressManager(); vm.expectRevert(expectedErr); - dso.systemConfigProxy(); + doo.l1ERC721BridgeProxy(); vm.expectRevert(expectedErr); - dso.optimismMintableERC20FactoryProxy(); + doo.systemConfigProxy(); vm.expectRevert(expectedErr); - dso.l1StandardBridgeProxy(); + doo.optimismMintableERC20FactoryProxy(); vm.expectRevert(expectedErr); - dso.l1CrossDomainMessengerProxy(); + doo.l1StandardBridgeProxy(); vm.expectRevert(expectedErr); - dso.optimismPortalProxy(); + doo.l1CrossDomainMessengerProxy(); vm.expectRevert(expectedErr); - dso.disputeGameFactoryProxy(); + doo.optimismPortalProxy(); vm.expectRevert(expectedErr); - dso.disputeGameFactoryImpl(); + doo.disputeGameFactoryProxy(); vm.expectRevert(expectedErr); - dso.anchorStateRegistryProxy(); + doo.anchorStateRegistryProxy(); vm.expectRevert(expectedErr); - dso.anchorStateRegistryImpl(); + doo.anchorStateRegistryImpl(); vm.expectRevert(expectedErr); - dso.faultDisputeGame(); + doo.faultDisputeGame(); vm.expectRevert(expectedErr); - dso.permissionedDisputeGame(); + doo.permissionedDisputeGame(); vm.expectRevert(expectedErr); - dso.delayedWETHPermissionedGameProxy(); + doo.delayedWETHPermissionedGameProxy(); vm.expectRevert(expectedErr); - dso.delayedWETHPermissionlessGameProxy(); + doo.delayedWETHPermissionlessGameProxy(); } function test_getters_whenAddrHasNoCode_reverts() public { address emptyAddr = makeAddr("emptyAddr"); bytes memory expectedErr = bytes(string.concat("DeployUtils: no code at ", vm.toString(emptyAddr))); - dso.set(dso.opChainProxyAdmin.selector, emptyAddr); + doo.set(doo.opChainProxyAdmin.selector, emptyAddr); vm.expectRevert(expectedErr); - dso.opChainProxyAdmin(); + doo.opChainProxyAdmin(); - dso.set(dso.addressManager.selector, emptyAddr); + doo.set(doo.addressManager.selector, emptyAddr); vm.expectRevert(expectedErr); - dso.addressManager(); + doo.addressManager(); - dso.set(dso.l1ERC721BridgeProxy.selector, emptyAddr); + doo.set(doo.l1ERC721BridgeProxy.selector, emptyAddr); vm.expectRevert(expectedErr); - dso.l1ERC721BridgeProxy(); + doo.l1ERC721BridgeProxy(); - dso.set(dso.systemConfigProxy.selector, emptyAddr); + doo.set(doo.systemConfigProxy.selector, emptyAddr); vm.expectRevert(expectedErr); - dso.systemConfigProxy(); + doo.systemConfigProxy(); - dso.set(dso.optimismMintableERC20FactoryProxy.selector, emptyAddr); + doo.set(doo.optimismMintableERC20FactoryProxy.selector, emptyAddr); vm.expectRevert(expectedErr); - dso.optimismMintableERC20FactoryProxy(); + doo.optimismMintableERC20FactoryProxy(); - dso.set(dso.l1StandardBridgeProxy.selector, emptyAddr); + doo.set(doo.l1StandardBridgeProxy.selector, emptyAddr); vm.expectRevert(expectedErr); - dso.l1StandardBridgeProxy(); + doo.l1StandardBridgeProxy(); - dso.set(dso.l1CrossDomainMessengerProxy.selector, emptyAddr); + doo.set(doo.l1CrossDomainMessengerProxy.selector, emptyAddr); vm.expectRevert(expectedErr); - dso.l1CrossDomainMessengerProxy(); + doo.l1CrossDomainMessengerProxy(); - dso.set(dso.optimismPortalProxy.selector, emptyAddr); + doo.set(doo.optimismPortalProxy.selector, emptyAddr); vm.expectRevert(expectedErr); - dso.optimismPortalProxy(); + doo.optimismPortalProxy(); - dso.set(dso.disputeGameFactoryProxy.selector, emptyAddr); + doo.set(doo.disputeGameFactoryProxy.selector, emptyAddr); vm.expectRevert(expectedErr); - dso.disputeGameFactoryProxy(); + doo.disputeGameFactoryProxy(); - dso.set(dso.disputeGameFactoryImpl.selector, emptyAddr); + doo.set(doo.anchorStateRegistryProxy.selector, emptyAddr); vm.expectRevert(expectedErr); - dso.disputeGameFactoryImpl(); + doo.anchorStateRegistryProxy(); - dso.set(dso.anchorStateRegistryProxy.selector, emptyAddr); + doo.set(doo.anchorStateRegistryImpl.selector, emptyAddr); vm.expectRevert(expectedErr); - dso.anchorStateRegistryProxy(); + doo.anchorStateRegistryImpl(); - dso.set(dso.anchorStateRegistryImpl.selector, emptyAddr); + doo.set(doo.faultDisputeGame.selector, emptyAddr); vm.expectRevert(expectedErr); - dso.anchorStateRegistryImpl(); + doo.faultDisputeGame(); - dso.set(dso.faultDisputeGame.selector, emptyAddr); + doo.set(doo.permissionedDisputeGame.selector, emptyAddr); vm.expectRevert(expectedErr); - dso.faultDisputeGame(); + doo.permissionedDisputeGame(); - dso.set(dso.permissionedDisputeGame.selector, emptyAddr); + doo.set(doo.delayedWETHPermissionedGameProxy.selector, emptyAddr); vm.expectRevert(expectedErr); - dso.permissionedDisputeGame(); + doo.delayedWETHPermissionedGameProxy(); - dso.set(dso.delayedWETHPermissionedGameProxy.selector, emptyAddr); + doo.set(doo.delayedWETHPermissionlessGameProxy.selector, emptyAddr); vm.expectRevert(expectedErr); - dso.delayedWETHPermissionedGameProxy(); + doo.delayedWETHPermissionlessGameProxy(); + } +} - dso.set(dso.delayedWETHPermissionlessGameProxy.selector, emptyAddr); - vm.expectRevert(expectedErr); - dso.delayedWETHPermissionlessGameProxy(); +// To mimic a production environment, we default to integration tests here that actually run the +// DeploySuperchain and DeployImplementations scripts. +contract DeployOPChain_TestBase is Test { + DeployOPChain deployOPChain; + DeployOPChainInput doi; + DeployOPChainOutput doo; + + // Define default inputs for DeploySuperchain. + address superchainProxyAdminOwner = makeAddr("defaultSuperchainProxyAdminOwner"); + address protocolVersionsOwner = makeAddr("defaultProtocolVersionsOwner"); + address guardian = makeAddr("defaultGuardian"); + bool paused = false; + ProtocolVersion requiredProtocolVersion = ProtocolVersion.wrap(1); + ProtocolVersion recommendedProtocolVersion = ProtocolVersion.wrap(2); + + // Define default inputs for DeployImplementations. + // `superchainConfigProxy` and `protocolVersionsProxy` are set during `setUp` since they are + // outputs of the previous step. + uint256 withdrawalDelaySeconds = 100; + uint256 minProposalSizeBytes = 200; + uint256 challengePeriodSeconds = 300; + uint256 proofMaturityDelaySeconds = 400; + uint256 disputeGameFinalityDelaySeconds = 500; + string release = "dev-release"; // this means implementation contracts will be deployed + SuperchainConfig superchainConfigProxy; + ProtocolVersions protocolVersionsProxy; + + // Define default inputs for DeployOPChain. + // `opcm` is set during `setUp` since it is an output of the previous step. + address opChainProxyAdminOwner = makeAddr("defaultOPChainProxyAdminOwner"); + address systemConfigOwner = makeAddr("defaultSystemConfigOwner"); + address batcher = makeAddr("defaultBatcher"); + address unsafeBlockSigner = makeAddr("defaultUnsafeBlockSigner"); + address proposer = makeAddr("defaultProposer"); + address challenger = makeAddr("defaultChallenger"); + uint32 basefeeScalar = 100; + uint32 blobBaseFeeScalar = 200; + uint256 l2ChainId = 300; + AnchorStateRegistry.StartingAnchorRoot[] startingAnchorRoots; + OPContractsManager opcm = OPContractsManager(address(0)); + + function setUp() public virtual { + // Set defaults for reference types + uint256 cannonBlock = 400; + uint256 permissionedBlock = 500; + startingAnchorRoots.push( + AnchorStateRegistry.StartingAnchorRoot({ + gameType: GameTypes.CANNON, + outputRoot: OutputRoot({ root: Hash.wrap(keccak256("defaultOutputRootCannon")), l2BlockNumber: cannonBlock }) + }) + ); + startingAnchorRoots.push( + AnchorStateRegistry.StartingAnchorRoot({ + gameType: GameTypes.PERMISSIONED_CANNON, + outputRoot: OutputRoot({ + root: Hash.wrap(keccak256("defaultOutputRootPermissioned")), + l2BlockNumber: permissionedBlock + }) + }) + ); + + // Configure and deploy Superchain contracts + DeploySuperchain deploySuperchain = new DeploySuperchain(); + (DeploySuperchainInput dsi, DeploySuperchainOutput dso) = deploySuperchain.etchIOContracts(); + + dsi.set(dsi.superchainProxyAdminOwner.selector, superchainProxyAdminOwner); + dsi.set(dsi.protocolVersionsOwner.selector, protocolVersionsOwner); + dsi.set(dsi.guardian.selector, guardian); + dsi.set(dsi.paused.selector, paused); + dsi.set(dsi.requiredProtocolVersion.selector, requiredProtocolVersion); + dsi.set(dsi.recommendedProtocolVersion.selector, recommendedProtocolVersion); + + deploySuperchain.run(dsi, dso); + + // Populate the inputs for DeployImplementations based on the output of DeploySuperchain. + superchainConfigProxy = dso.superchainConfigProxy(); + protocolVersionsProxy = dso.protocolVersionsProxy(); + + // Configure and deploy Implementation contracts + DeployImplementations deployImplementations = createDeployImplementationsContract(); + (DeployImplementationsInput dii, DeployImplementationsOutput dio) = deployImplementations.etchIOContracts(); + + dii.set(dii.withdrawalDelaySeconds.selector, withdrawalDelaySeconds); + dii.set(dii.minProposalSizeBytes.selector, minProposalSizeBytes); + dii.set(dii.challengePeriodSeconds.selector, challengePeriodSeconds); + dii.set(dii.proofMaturityDelaySeconds.selector, proofMaturityDelaySeconds); + dii.set(dii.disputeGameFinalityDelaySeconds.selector, disputeGameFinalityDelaySeconds); + dii.set(dii.release.selector, release); + dii.set(dii.superchainConfigProxy.selector, address(superchainConfigProxy)); + dii.set(dii.protocolVersionsProxy.selector, address(protocolVersionsProxy)); + // End users of the DeployImplementations contract will need to set the `standardVersionsToml`. + string memory standardVersionsTomlPath = + string.concat(vm.projectRoot(), "/test/fixtures/standard-versions.toml"); + string memory standardVersionsToml = vm.readFile(standardVersionsTomlPath); + dii.set(dii.standardVersionsToml.selector, standardVersionsToml); + deployImplementations.run(dii, dio); + + // Deploy DeployOpChain, but defer populating the input values to the test suites inheriting this contract. + deployOPChain = new DeployOPChain(); + (doi, doo) = deployOPChain.etchIOContracts(); + + // Set the OPContractsManager input for DeployOPChain. + opcm = dio.opcmProxy(); + } + + // See the function of the same name in the `DeployImplementations_Test` contract of + // `DeployImplementations.t.sol` for more details on why we use this method. + function createDeployImplementationsContract() internal virtual returns (DeployImplementations) { + return new DeployImplementations(); + } +} + +contract DeployOPChain_Test is DeployOPChain_TestBase { + function hash(bytes32 _seed, uint256 _i) internal pure returns (bytes32) { + return keccak256(abi.encode(_seed, _i)); + } + + function testFuzz_run_memory_succeed(bytes32 _seed) public { + opChainProxyAdminOwner = address(uint160(uint256(hash(_seed, 0)))); + systemConfigOwner = address(uint160(uint256(hash(_seed, 1)))); + batcher = address(uint160(uint256(hash(_seed, 2)))); + unsafeBlockSigner = address(uint160(uint256(hash(_seed, 3)))); + proposer = address(uint160(uint256(hash(_seed, 4)))); + challenger = address(uint160(uint256(hash(_seed, 5)))); + basefeeScalar = uint32(uint256(hash(_seed, 6))); + blobBaseFeeScalar = uint32(uint256(hash(_seed, 7))); + l2ChainId = uint256(hash(_seed, 8)); + + // Set the initial anchor states. The typical usage we expect is to pass in one root per game type. + uint256 cannonBlock = uint256(hash(_seed, 9)); + uint256 permissionedBlock = uint256(hash(_seed, 10)); + startingAnchorRoots.push( + AnchorStateRegistry.StartingAnchorRoot({ + gameType: GameTypes.CANNON, + outputRoot: OutputRoot({ root: Hash.wrap(keccak256(abi.encode(_seed, 11))), l2BlockNumber: cannonBlock }) + }) + ); + startingAnchorRoots.push( + AnchorStateRegistry.StartingAnchorRoot({ + gameType: GameTypes.PERMISSIONED_CANNON, + outputRoot: OutputRoot({ + root: Hash.wrap(keccak256(abi.encode(_seed, 12))), + l2BlockNumber: permissionedBlock + }) + }) + ); + + doi.set(doi.opChainProxyAdminOwner.selector, opChainProxyAdminOwner); + doi.set(doi.systemConfigOwner.selector, systemConfigOwner); + doi.set(doi.batcher.selector, batcher); + doi.set(doi.unsafeBlockSigner.selector, unsafeBlockSigner); + doi.set(doi.proposer.selector, proposer); + doi.set(doi.challenger.selector, challenger); + doi.set(doi.basefeeScalar.selector, basefeeScalar); + doi.set(doi.blobBaseFeeScalar.selector, blobBaseFeeScalar); + doi.set(doi.l2ChainId.selector, l2ChainId); + doi.set(doi.opcmProxy.selector, address(opcm)); // Not fuzzed since it must be an actual instance. + + deployOPChain.run(doi, doo); + + // TODO Add fault proof contract assertions below once OPCM fully supports them. + + // Assert that individual input fields were properly set based on the inputs. + assertEq(opChainProxyAdminOwner, doi.opChainProxyAdminOwner(), "100"); + assertEq(systemConfigOwner, doi.systemConfigOwner(), "200"); + assertEq(batcher, doi.batcher(), "300"); + assertEq(unsafeBlockSigner, doi.unsafeBlockSigner(), "400"); + assertEq(proposer, doi.proposer(), "500"); + assertEq(challenger, doi.challenger(), "600"); + assertEq(basefeeScalar, doi.basefeeScalar(), "700"); + assertEq(blobBaseFeeScalar, doi.blobBaseFeeScalar(), "800"); + assertEq(l2ChainId, doi.l2ChainId(), "900"); + + // Assert inputs were properly passed through to the contract initializers. + assertEq(address(doo.opChainProxyAdmin().owner()), opChainProxyAdminOwner, "2100"); + assertEq(address(doo.systemConfigProxy().owner()), systemConfigOwner, "2200"); + address batcherActual = address(uint160(uint256(doo.systemConfigProxy().batcherHash()))); + assertEq(batcherActual, batcher, "2300"); + assertEq(address(doo.systemConfigProxy().unsafeBlockSigner()), unsafeBlockSigner, "2400"); + assertEq(address(doo.permissionedDisputeGame().proposer()), proposer, "2500"); + assertEq(address(doo.permissionedDisputeGame().challenger()), challenger, "2600"); + + // TODO once we deploy the Permissionless Dispute Game + // assertEq(address(doo.faultDisputeGame().proposer()), proposer, "2700"); + // assertEq(address(doo.faultDisputeGame().challenger()), challenger, "2800"); + + // Most architecture assertions are handled within the OP Contracts Manager itself and therefore + // we only assert on the things that are not visible onchain. + // TODO add these assertions: AddressManager, Proxy, ProxyAdmin, etc. + } +} + +contract DeployOPChain_Test_Interop is DeployOPChain_Test { + function createDeployImplementationsContract() internal override returns (DeployImplementations) { + return new DeployImplementationsInterop(); } } diff --git a/packages/contracts-bedrock/test/DeploySuperchain.t.sol b/packages/contracts-bedrock/test/DeploySuperchain.t.sol index 2eeffb68e48a9..a6bcf2aa2f50a 100644 --- a/packages/contracts-bedrock/test/DeploySuperchain.t.sol +++ b/packages/contracts-bedrock/test/DeploySuperchain.t.sol @@ -1,7 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -import { Test } from "forge-std/Test.sol"; +import { Test, stdStorage, StdStorage } from "forge-std/Test.sol"; +import { stdToml } from "forge-std/StdToml.sol"; import { ProxyAdmin } from "src/universal/ProxyAdmin.sol"; import { Proxy } from "src/universal/Proxy.sol"; @@ -12,73 +13,38 @@ import { DeploySuperchainInput, DeploySuperchain, DeploySuperchainOutput } from contract DeploySuperchainInput_Test is Test { DeploySuperchainInput dsi; - DeploySuperchainInput.Input input = DeploySuperchainInput.Input({ - roles: DeploySuperchainInput.Roles({ - proxyAdminOwner: makeAddr("defaultProxyAdminOwner"), - protocolVersionsOwner: makeAddr("defaultProtocolVersionsOwner"), - guardian: makeAddr("defaultGuardian") - }), - paused: false, - requiredProtocolVersion: ProtocolVersion.wrap(1), - recommendedProtocolVersion: ProtocolVersion.wrap(2) - }); + address superchainProxyAdminOwner = makeAddr("superchainProxyAdminOwner"); + address protocolVersionsOwner = makeAddr("defaultProtocolVersionsOwner"); + address guardian = makeAddr("defaultGuardian"); + bool paused = false; + ProtocolVersion requiredProtocolVersion = ProtocolVersion.wrap(1); + ProtocolVersion recommendedProtocolVersion = ProtocolVersion.wrap(2); function setUp() public { dsi = new DeploySuperchainInput(); } - function test_loadInput_succeeds() public { - // We avoid using a fuzz test here because we'd need to modify the inputs of multiple - // parameters to e.g. avoid the zero address. Therefore we hardcode a concrete test case - // which is simpler and still sufficient. - dsi.loadInput(input); - - assertTrue(dsi.inputSet(), "100"); - - // Compare the test input struct to the getter methods. - assertEq(input.roles.proxyAdminOwner, dsi.proxyAdminOwner(), "200"); - assertEq(input.roles.protocolVersionsOwner, dsi.protocolVersionsOwner(), "300"); - assertEq(input.roles.guardian, dsi.guardian(), "400"); - assertEq(input.paused, dsi.paused(), "500"); - assertEq( - ProtocolVersion.unwrap(input.requiredProtocolVersion), - ProtocolVersion.unwrap(dsi.requiredProtocolVersion()), - "600" - ); - assertEq( - ProtocolVersion.unwrap(input.recommendedProtocolVersion), - ProtocolVersion.unwrap(dsi.recommendedProtocolVersion()), - "700" - ); - - // Compare the test input struct to the `input` getter method. - assertEq(keccak256(abi.encode(input)), keccak256(abi.encode(dsi.input())), "800"); - } - function test_getters_whenNotSet_revert() public { - bytes memory expectedErr = "DeploySuperchainInput: input not set"; - - vm.expectRevert(expectedErr); - dsi.proxyAdminOwner(); + vm.expectRevert("DeploySuperchainInput: superchainProxyAdminOwner not set"); + dsi.superchainProxyAdminOwner(); - vm.expectRevert(expectedErr); + vm.expectRevert("DeploySuperchainInput: protocolVersionsOwner not set"); dsi.protocolVersionsOwner(); - vm.expectRevert(expectedErr); + vm.expectRevert("DeploySuperchainInput: guardian not set"); dsi.guardian(); - vm.expectRevert(expectedErr); - dsi.paused(); - - vm.expectRevert(expectedErr); + vm.expectRevert("DeploySuperchainInput: requiredProtocolVersion not set"); dsi.requiredProtocolVersion(); - vm.expectRevert(expectedErr); + vm.expectRevert("DeploySuperchainInput: recommendedProtocolVersion not set"); dsi.recommendedProtocolVersion(); } } contract DeploySuperchainOutput_Test is Test { + using stdToml for string; + DeploySuperchainOutput dso; function setUp() public { @@ -89,55 +55,45 @@ contract DeploySuperchainOutput_Test is Test { // We don't fuzz, because we need code at the address, and we can't etch code if the fuzzer // provides precompiles, so we end up with a lot of boilerplate logic to get valid inputs. // Hardcoding a concrete set of valid addresses is simpler and still sufficient. - DeploySuperchainOutput.Output memory output = DeploySuperchainOutput.Output({ - superchainProxyAdmin: ProxyAdmin(makeAddr("superchainProxyAdmin")), - superchainConfigImpl: SuperchainConfig(makeAddr("superchainConfigImpl")), - superchainConfigProxy: SuperchainConfig(makeAddr("superchainConfigProxy")), - protocolVersionsImpl: ProtocolVersions(makeAddr("protocolVersionsImpl")), - protocolVersionsProxy: ProtocolVersions(makeAddr("protocolVersionsProxy")) - }); + ProxyAdmin superchainProxyAdmin = ProxyAdmin(makeAddr("superchainProxyAdmin")); + SuperchainConfig superchainConfigImpl = SuperchainConfig(makeAddr("superchainConfigImpl")); + SuperchainConfig superchainConfigProxy = SuperchainConfig(makeAddr("superchainConfigProxy")); + ProtocolVersions protocolVersionsImpl = ProtocolVersions(makeAddr("protocolVersionsImpl")); + ProtocolVersions protocolVersionsProxy = ProtocolVersions(makeAddr("protocolVersionsProxy")); // Ensure each address has code, since these are expected to be contracts. - vm.etch(address(output.superchainProxyAdmin), hex"01"); - vm.etch(address(output.superchainConfigImpl), hex"01"); - vm.etch(address(output.superchainConfigProxy), hex"01"); - vm.etch(address(output.protocolVersionsImpl), hex"01"); - vm.etch(address(output.protocolVersionsProxy), hex"01"); + vm.etch(address(superchainProxyAdmin), hex"01"); + vm.etch(address(superchainConfigImpl), hex"01"); + vm.etch(address(superchainConfigProxy), hex"01"); + vm.etch(address(protocolVersionsImpl), hex"01"); + vm.etch(address(protocolVersionsProxy), hex"01"); // Set the output data. - dso.set(dso.superchainProxyAdmin.selector, address(output.superchainProxyAdmin)); - dso.set(dso.superchainConfigImpl.selector, address(output.superchainConfigImpl)); - dso.set(dso.superchainConfigProxy.selector, address(output.superchainConfigProxy)); - dso.set(dso.protocolVersionsImpl.selector, address(output.protocolVersionsImpl)); - dso.set(dso.protocolVersionsProxy.selector, address(output.protocolVersionsProxy)); - - // Compare the test output struct to the getter methods. - assertEq(address(output.superchainProxyAdmin), address(dso.superchainProxyAdmin()), "100"); - assertEq(address(output.superchainConfigImpl), address(dso.superchainConfigImpl()), "200"); - assertEq(address(output.superchainConfigProxy), address(dso.superchainConfigProxy()), "300"); - assertEq(address(output.protocolVersionsImpl), address(dso.protocolVersionsImpl()), "400"); - assertEq(address(output.protocolVersionsProxy), address(dso.protocolVersionsProxy()), "500"); - - // Compare the test output struct to the `output` getter method. - assertEq(keccak256(abi.encode(output)), keccak256(abi.encode(dso.output())), "600"); + dso.set(dso.superchainProxyAdmin.selector, address(superchainProxyAdmin)); + dso.set(dso.superchainConfigImpl.selector, address(superchainConfigImpl)); + dso.set(dso.superchainConfigProxy.selector, address(superchainConfigProxy)); + dso.set(dso.protocolVersionsImpl.selector, address(protocolVersionsImpl)); + dso.set(dso.protocolVersionsProxy.selector, address(protocolVersionsProxy)); + + // Compare the test data to the getter methods. + assertEq(address(superchainProxyAdmin), address(dso.superchainProxyAdmin()), "100"); + assertEq(address(superchainConfigImpl), address(dso.superchainConfigImpl()), "200"); + assertEq(address(superchainConfigProxy), address(dso.superchainConfigProxy()), "300"); + assertEq(address(protocolVersionsImpl), address(dso.protocolVersionsImpl()), "400"); + assertEq(address(protocolVersionsProxy), address(dso.protocolVersionsProxy()), "500"); } function test_getters_whenNotSet_revert() public { - bytes memory expectedErr = "DeployUtils: zero address"; - - vm.expectRevert(expectedErr); - dso.superchainProxyAdmin(); - - vm.expectRevert(expectedErr); + vm.expectRevert("DeployUtils: zero address"); dso.superchainConfigImpl(); - vm.expectRevert(expectedErr); + vm.expectRevert("DeployUtils: zero address"); dso.superchainConfigProxy(); - vm.expectRevert(expectedErr); + vm.expectRevert("DeployUtils: zero address"); dso.protocolVersionsImpl(); - vm.expectRevert(expectedErr); + vm.expectRevert("DeployUtils: zero address"); dso.protocolVersionsProxy(); } @@ -145,10 +101,6 @@ contract DeploySuperchainOutput_Test is Test { address emptyAddr = makeAddr("emptyAddr"); bytes memory expectedErr = bytes(string.concat("DeployUtils: no code at ", vm.toString(emptyAddr))); - dso.set(dso.superchainProxyAdmin.selector, emptyAddr); - vm.expectRevert(expectedErr); - dso.superchainProxyAdmin(); - dso.set(dso.superchainConfigImpl.selector, emptyAddr); vm.expectRevert(expectedErr); dso.superchainConfigImpl(); @@ -168,99 +120,122 @@ contract DeploySuperchainOutput_Test is Test { } contract DeploySuperchain_Test is Test { + using stdStorage for StdStorage; + DeploySuperchain deploySuperchain; DeploySuperchainInput dsi; DeploySuperchainOutput dso; - // Define a default input struct for testing. - DeploySuperchainInput.Input input = DeploySuperchainInput.Input({ - roles: DeploySuperchainInput.Roles({ - proxyAdminOwner: makeAddr("defaultProxyAdminOwner"), - protocolVersionsOwner: makeAddr("defaultProtocolVersionsOwner"), - guardian: makeAddr("defaultGuardian") - }), - paused: false, - requiredProtocolVersion: ProtocolVersion.wrap(1), - recommendedProtocolVersion: ProtocolVersion.wrap(2) - }); + // Define default input variables for testing. + address defaultProxyAdminOwner = makeAddr("defaultProxyAdminOwner"); + address defaultProtocolVersionsOwner = makeAddr("defaultProtocolVersionsOwner"); + address defaultGuardian = makeAddr("defaultGuardian"); + bool defaultPaused = false; + ProtocolVersion defaultRequiredProtocolVersion = ProtocolVersion.wrap(1); + ProtocolVersion defaultRecommendedProtocolVersion = ProtocolVersion.wrap(2); function setUp() public { deploySuperchain = new DeploySuperchain(); - (dsi, dso) = deploySuperchain.getIOContracts(); + (dsi, dso) = deploySuperchain.etchIOContracts(); } function unwrap(ProtocolVersion _pv) internal pure returns (uint256) { return ProtocolVersion.unwrap(_pv); } - function test_run_succeeds(DeploySuperchainInput.Input memory _input) public { - vm.assume(_input.roles.proxyAdminOwner != address(0)); - vm.assume(_input.roles.protocolVersionsOwner != address(0)); - vm.assume(_input.roles.guardian != address(0)); - - DeploySuperchainOutput.Output memory output = deploySuperchain.run(_input); - - // Assert that individual input fields were properly set based on the input struct. - assertEq(_input.roles.proxyAdminOwner, dsi.proxyAdminOwner(), "100"); - assertEq(_input.roles.protocolVersionsOwner, dsi.protocolVersionsOwner(), "200"); - assertEq(_input.roles.guardian, dsi.guardian(), "300"); - assertEq(_input.paused, dsi.paused(), "400"); - assertEq(unwrap(_input.requiredProtocolVersion), unwrap(dsi.requiredProtocolVersion()), "500"); - assertEq(unwrap(_input.recommendedProtocolVersion), unwrap(dsi.recommendedProtocolVersion()), "600"); - - // Assert that individual output fields were properly set based on the output struct. - assertEq(address(output.superchainProxyAdmin), address(dso.superchainProxyAdmin()), "700"); - assertEq(address(output.superchainConfigImpl), address(dso.superchainConfigImpl()), "800"); - assertEq(address(output.superchainConfigProxy), address(dso.superchainConfigProxy()), "900"); - assertEq(address(output.protocolVersionsImpl), address(dso.protocolVersionsImpl()), "1000"); - assertEq(address(output.protocolVersionsProxy), address(dso.protocolVersionsProxy()), "1100"); + function hash(bytes32 _seed, uint256 _i) internal pure returns (bytes32) { + return keccak256(abi.encode(_seed, _i)); + } - // Assert that the full input and output structs were properly set. - assertEq(keccak256(abi.encode(_input)), keccak256(abi.encode(DeploySuperchainInput(dsi).input())), "1200"); - assertEq(keccak256(abi.encode(output)), keccak256(abi.encode(DeploySuperchainOutput(dso).output())), "1300"); + function testFuzz_run_memory_succeeds(bytes32 _seed) public { + // Generate random input values from the seed. This doesn't give us the benefit of the forge + // fuzzer's dictionary, but that's ok because we are just testing that values are set and + // passed correctly. + address superchainProxyAdminOwner = address(uint160(uint256(hash(_seed, 0)))); + address protocolVersionsOwner = address(uint160(uint256(hash(_seed, 1)))); + address guardian = address(uint160(uint256(hash(_seed, 2)))); + bool paused = bool(uint8(uint256(hash(_seed, 3))) % 2 == 0); + ProtocolVersion requiredProtocolVersion = ProtocolVersion.wrap(uint256(hash(_seed, 4))); + ProtocolVersion recommendedProtocolVersion = ProtocolVersion.wrap(uint256(hash(_seed, 5))); + + // Set the input values on the input contract. + dsi.set(dsi.superchainProxyAdminOwner.selector, superchainProxyAdminOwner); + dsi.set(dsi.protocolVersionsOwner.selector, protocolVersionsOwner); + dsi.set(dsi.guardian.selector, guardian); + dsi.set(dsi.paused.selector, paused); + dsi.set(dsi.requiredProtocolVersion.selector, requiredProtocolVersion); + dsi.set(dsi.recommendedProtocolVersion.selector, recommendedProtocolVersion); + + // Run the deployment script. + deploySuperchain.run(dsi, dso); // Assert inputs were properly passed through to the contract initializers. - assertEq(address(output.superchainProxyAdmin.owner()), _input.roles.proxyAdminOwner, "1400"); - assertEq(address(output.protocolVersionsProxy.owner()), _input.roles.protocolVersionsOwner, "1500"); - assertEq(address(output.superchainConfigProxy.guardian()), _input.roles.guardian, "1600"); - assertEq(output.superchainConfigProxy.paused(), _input.paused, "1700"); - assertEq(unwrap(output.protocolVersionsProxy.required()), unwrap(_input.requiredProtocolVersion), "1800"); - assertEq(unwrap(output.protocolVersionsProxy.recommended()), unwrap(_input.recommendedProtocolVersion), "1900"); + assertEq(address(dso.superchainProxyAdmin().owner()), superchainProxyAdminOwner, "100"); + assertEq(address(dso.protocolVersionsProxy().owner()), protocolVersionsOwner, "200"); + assertEq(address(dso.superchainConfigProxy().guardian()), guardian, "300"); + assertEq(dso.superchainConfigProxy().paused(), paused, "400"); + assertEq(unwrap(dso.protocolVersionsProxy().required()), unwrap(requiredProtocolVersion), "500"); + assertEq(unwrap(dso.protocolVersionsProxy().recommended()), unwrap(recommendedProtocolVersion), "600"); // Architecture assertions. // We prank as the zero address due to the Proxy's `proxyCallIfNotAdmin` modifier. - Proxy superchainConfigProxy = Proxy(payable(address(output.superchainConfigProxy))); - Proxy protocolVersionsProxy = Proxy(payable(address(output.protocolVersionsProxy))); + Proxy superchainConfigProxy = Proxy(payable(address(dso.superchainConfigProxy()))); + Proxy protocolVersionsProxy = Proxy(payable(address(dso.protocolVersionsProxy()))); vm.startPrank(address(0)); - assertEq(superchainConfigProxy.implementation(), address(output.superchainConfigImpl), "900"); - assertEq(protocolVersionsProxy.implementation(), address(output.protocolVersionsImpl), "1000"); - assertEq(superchainConfigProxy.admin(), protocolVersionsProxy.admin(), "1100"); - assertEq(superchainConfigProxy.admin(), address(output.superchainProxyAdmin), "1200"); + assertEq(superchainConfigProxy.implementation(), address(dso.superchainConfigImpl()), "700"); + assertEq(protocolVersionsProxy.implementation(), address(dso.protocolVersionsImpl()), "800"); + assertEq(superchainConfigProxy.admin(), protocolVersionsProxy.admin(), "900"); + assertEq(superchainConfigProxy.admin(), address(dso.superchainProxyAdmin()), "1000"); vm.stopPrank(); // Ensure that `checkOutput` passes. This is called by the `run` function during execution, // so this just acts as a sanity check. It reverts on failure. - dso.checkOutput(); + dso.checkOutput(dsi); } - function test_run_ZeroAddressRoleInput_reverts() public { - // Snapshot the state so we can revert to the default `input` struct between assertions. - uint256 snapshotId = vm.snapshot(); - - // Assert over each role being set to the zero address. - input.roles.proxyAdminOwner = address(0); - vm.expectRevert("DeploySuperchainInput: null proxyAdminOwner"); - deploySuperchain.run(input); - - vm.revertTo(snapshotId); - input.roles.protocolVersionsOwner = address(0); - vm.expectRevert("DeploySuperchainInput: null protocolVersionsOwner"); - deploySuperchain.run(input); + function test_run_NullInput_reverts() public { + // Set default values for all inputs. + dsi.set(dsi.superchainProxyAdminOwner.selector, defaultProxyAdminOwner); + dsi.set(dsi.protocolVersionsOwner.selector, defaultProtocolVersionsOwner); + dsi.set(dsi.guardian.selector, defaultGuardian); + dsi.set(dsi.paused.selector, defaultPaused); + dsi.set(dsi.requiredProtocolVersion.selector, defaultRequiredProtocolVersion); + dsi.set(dsi.recommendedProtocolVersion.selector, defaultRecommendedProtocolVersion); + + // Assert over each role being set to the zero address. We aren't allowed to use the setter + // methods to set the zero address, so we use StdStorage. We can't use the `checked_write` + // method, because it does a final call to test that the value was set correctly, but for us + // that would revert. Therefore we use StdStorage to find the slot, then we write to it. + uint256 slot = zeroOutSlotForSelector(dsi.superchainProxyAdminOwner.selector); + vm.expectRevert("DeploySuperchainInput: superchainProxyAdminOwner not set"); + deploySuperchain.run(dsi, dso); + // Restore the value we just tested. + vm.store(address(dsi), bytes32(slot), bytes32(uint256(uint160(defaultProxyAdminOwner)))); + + slot = zeroOutSlotForSelector(dsi.protocolVersionsOwner.selector); + vm.expectRevert("DeploySuperchainInput: protocolVersionsOwner not set"); + deploySuperchain.run(dsi, dso); + vm.store(address(dsi), bytes32(slot), bytes32(uint256(uint160(defaultProtocolVersionsOwner)))); + + slot = zeroOutSlotForSelector(dsi.guardian.selector); + vm.expectRevert("DeploySuperchainInput: guardian not set"); + deploySuperchain.run(dsi, dso); + vm.store(address(dsi), bytes32(slot), bytes32(uint256(uint160(defaultGuardian)))); + + slot = zeroOutSlotForSelector(dsi.requiredProtocolVersion.selector); + vm.expectRevert("DeploySuperchainInput: requiredProtocolVersion not set"); + deploySuperchain.run(dsi, dso); + vm.store(address(dsi), bytes32(slot), bytes32(unwrap(defaultRequiredProtocolVersion))); + + slot = zeroOutSlotForSelector(dsi.recommendedProtocolVersion.selector); + vm.expectRevert("DeploySuperchainInput: recommendedProtocolVersion not set"); + deploySuperchain.run(dsi, dso); + vm.store(address(dsi), bytes32(slot), bytes32(unwrap(defaultRecommendedProtocolVersion))); + } - vm.revertTo(snapshotId); - input.roles.guardian = address(0); - vm.expectRevert("DeploySuperchainInput: null guardian"); - deploySuperchain.run(input); + function zeroOutSlotForSelector(bytes4 _selector) internal returns (uint256 slot_) { + slot_ = stdstore.enable_packed_slots().target(address(dsi)).sig(_selector).find(); + vm.store(address(dsi), bytes32(slot_), bytes32(0)); } } diff --git a/packages/contracts-bedrock/test/ExtendedPause.t.sol b/packages/contracts-bedrock/test/ExtendedPause.t.sol index 93e207ac6e9db..df6e9d39132b2 100644 --- a/packages/contracts-bedrock/test/ExtendedPause.t.sol +++ b/packages/contracts-bedrock/test/ExtendedPause.t.sol @@ -2,7 +2,6 @@ pragma solidity 0.8.15; import { CommonTest } from "test/setup/CommonTest.sol"; -import { SuperchainConfig } from "src/L1/SuperchainConfig.sol"; /// @dev These tests are somewhat redundant with tests in the SuperchainConfig and other pausable contracts, however /// it is worthwhile to pull them into one location to ensure that the behavior is consistent. diff --git a/packages/contracts-bedrock/test/L1/DataAvailabilityChallenge.t.sol b/packages/contracts-bedrock/test/L1/DataAvailabilityChallenge.t.sol index fd8e82c9320f1..5304cf797449d 100644 --- a/packages/contracts-bedrock/test/L1/DataAvailabilityChallenge.t.sol +++ b/packages/contracts-bedrock/test/L1/DataAvailabilityChallenge.t.sol @@ -2,14 +2,15 @@ pragma solidity 0.8.15; import { - DataAvailabilityChallenge, + IDataAvailabilityChallenge, ChallengeStatus, Challenge, - CommitmentType, - computeCommitmentKeccak256 -} from "src/L1/DataAvailabilityChallenge.sol"; + CommitmentType +} from "src/L1/interfaces/IDataAvailabilityChallenge.sol"; +import { computeCommitmentKeccak256 } from "src/L1/DataAvailabilityChallenge.sol"; import { Proxy } from "src/universal/Proxy.sol"; import { CommonTest } from "test/setup/CommonTest.sol"; +import { Preinstalls } from "src/libraries/Preinstalls.sol"; contract DataAvailabilityChallengeTest is CommonTest { function setUp() public virtual override { @@ -33,6 +34,8 @@ contract DataAvailabilityChallengeTest is CommonTest { function testWithdraw(address sender, uint256 amount) public { assumePayable(sender); assumeNotPrecompile(sender); + // EntryPoint will revert if using amount > type(uint112).max. + vm.assume(sender != Preinstalls.EntryPoint_v060); vm.assume(sender != address(dataAvailabilityChallenge)); vm.assume(sender.balance == 0); vm.deal(sender, amount); @@ -145,7 +148,9 @@ contract DataAvailabilityChallengeTest is CommonTest { uint256 actualBond = requiredBond - 1; dataAvailabilityChallenge.deposit{ value: actualBond }(); - vm.expectRevert(abi.encodeWithSelector(DataAvailabilityChallenge.BondTooLow.selector, actualBond, requiredBond)); + vm.expectRevert( + abi.encodeWithSelector(IDataAvailabilityChallenge.BondTooLow.selector, actualBond, requiredBond) + ); dataAvailabilityChallenge.challenge(0, computeCommitmentKeccak256("some hash")); } @@ -160,7 +165,7 @@ contract DataAvailabilityChallengeTest is CommonTest { // Second challenge of the same hash/blockNumber fails dataAvailabilityChallenge.deposit{ value: dataAvailabilityChallenge.bondSize() }(); - vm.expectRevert(abi.encodeWithSelector(DataAvailabilityChallenge.ChallengeExists.selector)); + vm.expectRevert(abi.encodeWithSelector(IDataAvailabilityChallenge.ChallengeExists.selector)); dataAvailabilityChallenge.challenge(0, challengedCommitment); // Challenge succeed if the challenged block number is different @@ -181,7 +186,7 @@ contract DataAvailabilityChallengeTest is CommonTest { // 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)); + vm.expectRevert(abi.encodeWithSelector(IDataAvailabilityChallenge.ChallengeWindowNotOpen.selector)); dataAvailabilityChallenge.challenge(challengedBlockNumber, challengedCommitment); } @@ -194,7 +199,7 @@ contract DataAvailabilityChallengeTest is CommonTest { // Challenge fails because the block number is after the challenge window dataAvailabilityChallenge.deposit{ value: dataAvailabilityChallenge.bondSize() }(); - vm.expectRevert(abi.encodeWithSelector(DataAvailabilityChallenge.ChallengeWindowNotOpen.selector)); + vm.expectRevert(abi.encodeWithSelector(IDataAvailabilityChallenge.ChallengeWindowNotOpen.selector)); dataAvailabilityChallenge.challenge(challengedBlockNumber, challengedCommitment); } @@ -287,7 +292,7 @@ contract DataAvailabilityChallengeTest is CommonTest { vm.roll(challengedBlockNumber + 1); // Resolving a non-existent challenge fails - vm.expectRevert(abi.encodeWithSelector(DataAvailabilityChallenge.ChallengeNotActive.selector)); + vm.expectRevert(abi.encodeWithSelector(IDataAvailabilityChallenge.ChallengeNotActive.selector)); dataAvailabilityChallenge.resolve(challengedBlockNumber, computeCommitmentKeccak256(preImage), preImage); } @@ -307,7 +312,7 @@ contract DataAvailabilityChallengeTest is CommonTest { dataAvailabilityChallenge.resolve(challengedBlockNumber, challengedCommitment, preImage); // Resolving an already resolved challenge fails - vm.expectRevert(abi.encodeWithSelector(DataAvailabilityChallenge.ChallengeNotActive.selector)); + vm.expectRevert(abi.encodeWithSelector(IDataAvailabilityChallenge.ChallengeNotActive.selector)); dataAvailabilityChallenge.resolve(challengedBlockNumber, challengedCommitment, preImage); } @@ -327,7 +332,7 @@ contract DataAvailabilityChallengeTest is CommonTest { vm.roll(block.number + dataAvailabilityChallenge.resolveWindow() + 1); // Resolving an expired challenge fails - vm.expectRevert(abi.encodeWithSelector(DataAvailabilityChallenge.ChallengeNotActive.selector)); + vm.expectRevert(abi.encodeWithSelector(IDataAvailabilityChallenge.ChallengeNotActive.selector)); dataAvailabilityChallenge.resolve(challengedBlockNumber, challengedCommitment, preImage); } @@ -347,7 +352,7 @@ contract DataAvailabilityChallengeTest is CommonTest { vm.roll(block.number + dataAvailabilityChallenge.resolveWindow() + 1); // Resolve the challenge - vm.expectRevert(abi.encodeWithSelector(DataAvailabilityChallenge.ChallengeNotActive.selector)); + vm.expectRevert(abi.encodeWithSelector(IDataAvailabilityChallenge.ChallengeNotActive.selector)); dataAvailabilityChallenge.resolve(challengedBlockNumber, challengedCommitment, preImage); } @@ -405,7 +410,7 @@ contract DataAvailabilityChallengeTest is CommonTest { vm.roll(challengedBlockNumber + 1); // Unlock a bond of a non-existent challenge fails - vm.expectRevert(abi.encodeWithSelector(DataAvailabilityChallenge.ChallengeNotExpired.selector)); + vm.expectRevert(abi.encodeWithSelector(IDataAvailabilityChallenge.ChallengeNotExpired.selector)); dataAvailabilityChallenge.unlockBond(challengedBlockNumber, challengedCommitment); } @@ -425,7 +430,7 @@ contract DataAvailabilityChallengeTest is CommonTest { dataAvailabilityChallenge.resolve(challengedBlockNumber, challengedCommitment, preImage); // Attempting to unlock a bond of a resolved challenge fails - vm.expectRevert(abi.encodeWithSelector(DataAvailabilityChallenge.ChallengeNotExpired.selector)); + vm.expectRevert(abi.encodeWithSelector(IDataAvailabilityChallenge.ChallengeNotExpired.selector)); dataAvailabilityChallenge.unlockBond(challengedBlockNumber, challengedCommitment); } @@ -469,7 +474,7 @@ contract DataAvailabilityChallengeTest is CommonTest { vm.roll(block.number + dataAvailabilityChallenge.resolveWindow() - 1); // Expiring the challenge before the resolve window closes fails - vm.expectRevert(abi.encodeWithSelector(DataAvailabilityChallenge.ChallengeNotExpired.selector)); + vm.expectRevert(abi.encodeWithSelector(IDataAvailabilityChallenge.ChallengeNotExpired.selector)); dataAvailabilityChallenge.unlockBond(challengedBlockNumber, challengedCommitment); } @@ -480,7 +485,9 @@ contract DataAvailabilityChallengeTest is CommonTest { // 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)); + vm.expectRevert( + abi.encodeWithSelector(IDataAvailabilityChallenge.BondTooLow.selector, actualBond, requiredBond) + ); dataAvailabilityChallenge.challenge(0, challengedCommitment); // Reduce the required bond @@ -500,7 +507,9 @@ contract DataAvailabilityChallengeTest is CommonTest { function testSetResolverRefundPercentageFail() public { address owner = dataAvailabilityChallenge.owner(); - vm.expectRevert(abi.encodeWithSelector(DataAvailabilityChallenge.InvalidResolverRefundPercentage.selector, 101)); + vm.expectRevert( + abi.encodeWithSelector(IDataAvailabilityChallenge.InvalidResolverRefundPercentage.selector, 101) + ); vm.prank(owner); dataAvailabilityChallenge.setResolverRefundPercentage(101); } @@ -520,13 +529,13 @@ contract DataAvailabilityChallengeTest is CommonTest { dataAvailabilityChallenge.validateCommitment(validCommitment); // Should revert if the commitment type is unknown - vm.expectRevert(abi.encodeWithSelector(DataAvailabilityChallenge.UnknownCommitmentType.selector, uint8(1))); + vm.expectRevert(abi.encodeWithSelector(IDataAvailabilityChallenge.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) + abi.encodeWithSelector(IDataAvailabilityChallenge.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 5e67a7ba5cf9c..8c35ced064d5f 100644 --- a/packages/contracts-bedrock/test/L1/DelayedVetoable.t.sol +++ b/packages/contracts-bedrock/test/L1/DelayedVetoable.t.sol @@ -3,6 +3,7 @@ pragma solidity 0.8.15; import { Test } from "forge-std/Test.sol"; import { DelayedVetoable } from "src/L1/DelayedVetoable.sol"; +import { IDelayedVetoable } from "src/L1/interfaces/IDelayedVetoable.sol"; contract DelayedVetoable_Init is Test { error Unauthorized(address expected, address actual); @@ -16,7 +17,7 @@ contract DelayedVetoable_Init is Test { address initiator; address vetoer; uint256 operatingDelay = 14 days; - DelayedVetoable delayedVetoable; + IDelayedVetoable delayedVetoable; function setUp() public { initiator = makeAddr("initiator"); @@ -25,12 +26,16 @@ contract DelayedVetoable_Init is Test { vm.deal(initiator, 10000 ether); vm.deal(vetoer, 10000 ether); - delayedVetoable = new DelayedVetoable({ - initiator_: initiator, - vetoer_: vetoer, - target_: address(target), - operatingDelay_: operatingDelay - }); + delayedVetoable = IDelayedVetoable( + address( + new DelayedVetoable({ + initiator_: initiator, + vetoer_: vetoer, + target_: address(target), + operatingDelay_: operatingDelay + }) + ) + ); // Most tests will use the operating delay, so we call as the initiator with null data // to set the delay. For tests that need to use the initial zero delay, we'll modify the diff --git a/packages/contracts-bedrock/test/L1/L1CrossDomainMessenger.t.sol b/packages/contracts-bedrock/test/L1/L1CrossDomainMessenger.t.sol index 3f585f7957629..8740c09d38cae 100644 --- a/packages/contracts-bedrock/test/L1/L1CrossDomainMessenger.t.sol +++ b/packages/contracts-bedrock/test/L1/L1CrossDomainMessenger.t.sol @@ -13,10 +13,10 @@ import { Encoding } from "src/libraries/Encoding.sol"; import { Constants } from "src/libraries/Constants.sol"; // Target contract dependencies -import { L1CrossDomainMessenger } from "src/L1/L1CrossDomainMessenger.sol"; -import { OptimismPortal } from "src/L1/OptimismPortal.sol"; -import { SuperchainConfig } from "src/L1/SuperchainConfig.sol"; -import { SystemConfig } from "src/L1/SystemConfig.sol"; +import { IL1CrossDomainMessenger } from "src/L1/interfaces/IL1CrossDomainMessenger.sol"; +import { IOptimismPortal } from "src/L1/interfaces/IOptimismPortal.sol"; +import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol"; +import { ISystemConfig } from "src/L1/interfaces/ISystemConfig.sol"; contract L1CrossDomainMessenger_Test is Bridge_Initializer { /// @dev The receiver address @@ -29,7 +29,7 @@ contract L1CrossDomainMessenger_Test is Bridge_Initializer { /// @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")); + IL1CrossDomainMessenger impl = IL1CrossDomainMessenger(deploy.mustGetAddress("L1CrossDomainMessenger")); assertEq(address(impl.superchainConfig()), address(0)); assertEq(address(impl.PORTAL()), address(0)); assertEq(address(impl.portal()), address(0)); @@ -60,7 +60,7 @@ contract L1CrossDomainMessenger_Test is Bridge_Initializer { vm.expectCall( address(optimismPortal), abi.encodeWithSelector( - OptimismPortal.depositTransaction.selector, + IOptimismPortal.depositTransaction.selector, Predeploys.L2_CROSS_DOMAIN_MESSENGER, 0, l1CrossDomainMessenger.baseGas(hex"ff", 100), @@ -605,7 +605,7 @@ contract L1CrossDomainMessenger_Test is Bridge_Initializer { /// @dev Tests that the superchain config is called by the messengers paused function function test_pause_callsSuperchainConfig_succeeds() external { - vm.expectCall(address(superchainConfig), abi.encodeWithSelector(SuperchainConfig.paused.selector)); + vm.expectCall(address(superchainConfig), abi.encodeWithSelector(ISuperchainConfig.paused.selector)); l1CrossDomainMessenger.paused(); } @@ -632,7 +632,7 @@ contract L1CrossDomainMessenger_Test is Bridge_Initializer { vm.expectCall( address(optimismPortal), abi.encodeWithSelector( - OptimismPortal.depositTransaction.selector, + IOptimismPortal.depositTransaction.selector, Predeploys.L2_CROSS_DOMAIN_MESSENGER, 0, l1CrossDomainMessenger.baseGas(hex"ff", 100), @@ -770,7 +770,7 @@ contract L1CrossDomainMessenger_ReinitReentryTest is Bridge_Initializer { // call the initializer function l1CrossDomainMessenger.initialize( - SuperchainConfig(superchainConfig), OptimismPortal(optimismPortal), SystemConfig(systemConfig) + ISuperchainConfig(superchainConfig), IOptimismPortal(optimismPortal), ISystemConfig(systemConfig) ); // attempt to re-replay the withdrawal diff --git a/packages/contracts-bedrock/test/L1/L1ERC721Bridge.t.sol b/packages/contracts-bedrock/test/L1/L1ERC721Bridge.t.sol index 3c8abcb4843d6..44feddc5031d4 100644 --- a/packages/contracts-bedrock/test/L1/L1ERC721Bridge.t.sol +++ b/packages/contracts-bedrock/test/L1/L1ERC721Bridge.t.sol @@ -1,18 +1,20 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -// Testing utilities +// Testing import { Bridge_Initializer } from "test/setup/Bridge_Initializer.sol"; + +// Contracts import { ERC721 } from "@openzeppelin/contracts/token/ERC721/ERC721.sol"; -// Target contract dependencies -import { L2ERC721Bridge } from "src/L2/L2ERC721Bridge.sol"; +// Libraries import { Predeploys } from "src/libraries/Predeploys.sol"; -import { SuperchainConfig } from "src/L1/SuperchainConfig.sol"; -import { CrossDomainMessenger } from "src/universal/CrossDomainMessenger.sol"; -// Target contract -import { L1ERC721Bridge } from "src/L1/L1ERC721Bridge.sol"; +// Interfaces +import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol"; +import { ICrossDomainMessenger } from "src/universal/interfaces/ICrossDomainMessenger.sol"; +import { IL1ERC721Bridge } from "src/L1/interfaces/IL1ERC721Bridge.sol"; +import { IL2ERC721Bridge } from "src/L2/interfaces/IL2ERC721Bridge.sol"; /// @dev Test ERC721 contract. contract TestERC721 is ERC721 { @@ -67,7 +69,7 @@ contract L1ERC721Bridge_Test is Bridge_Initializer { /// @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")); + IL1ERC721Bridge impl = IL1ERC721Bridge(deploy.mustGetAddress("L1ERC721Bridge")); assertEq(address(impl.MESSENGER()), address(0)); assertEq(address(impl.messenger()), address(0)); assertEq(address(impl.OTHER_BRIDGE()), Predeploys.L2_ERC721_BRIDGE); @@ -94,7 +96,7 @@ contract L1ERC721Bridge_Test is Bridge_Initializer { ( address(l2ERC721Bridge), abi.encodeCall( - L2ERC721Bridge.finalizeBridgeERC721, + IL2ERC721Bridge.finalizeBridgeERC721, (address(remoteToken), address(localToken), alice, alice, tokenId, hex"5678") ), 1234 @@ -175,7 +177,7 @@ contract L1ERC721Bridge_Test is Bridge_Initializer { ( address(Predeploys.L2_ERC721_BRIDGE), abi.encodeCall( - L2ERC721Bridge.finalizeBridgeERC721, + IL2ERC721Bridge.finalizeBridgeERC721, (address(remoteToken), address(localToken), alice, bob, tokenId, hex"5678") ), 1234 @@ -323,7 +325,7 @@ contract L1ERC721Bridge_Pause_Test is Bridge_Initializer { /// @dev Ensures that the `paused` function of the bridge contract actually calls the `paused` function of the /// `superchainConfig`. function test_pause_callsSuperchainConfig_succeeds() external { - vm.expectCall(address(superchainConfig), abi.encodeWithSelector(SuperchainConfig.paused.selector)); + vm.expectCall(address(superchainConfig), abi.encodeWithSelector(ISuperchainConfig.paused.selector)); l1ERC721Bridge.paused(); } @@ -352,7 +354,7 @@ contract L1ERC721Bridge_Pause_TestFail is Bridge_Initializer { vm.mockCall( address(l1ERC721Bridge.messenger()), - abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector), + abi.encodeWithSelector(ICrossDomainMessenger.xDomainMessageSender.selector), abi.encode(address(l1ERC721Bridge.otherBridge())) ); } diff --git a/packages/contracts-bedrock/test/L1/L1StandardBridge.t.sol b/packages/contracts-bedrock/test/L1/L1StandardBridge.t.sol index d01fb1c260488..abe7196070e8c 100644 --- a/packages/contracts-bedrock/test/L1/L1StandardBridge.t.sol +++ b/packages/contracts-bedrock/test/L1/L1StandardBridge.t.sol @@ -1,33 +1,32 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -// Testing utilities +// Testing import { stdStorage, StdStorage } from "forge-std/Test.sol"; -import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import { Bridge_Initializer } from "test/setup/Bridge_Initializer.sol"; +// Contracts +import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import { StandardBridge } from "src/universal/StandardBridge.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"; -import { L1StandardBridge } from "src/L1/L1StandardBridge.sol"; -import { L2StandardBridge } from "src/L2/L2StandardBridge.sol"; -import { CrossDomainMessenger } from "src/universal/CrossDomainMessenger.sol"; -import { SuperchainConfig } from "src/L1/SuperchainConfig.sol"; import { AddressAliasHelper } from "src/vendor/AddressAliasHelper.sol"; -// Target contract -import { OptimismPortal } from "src/L1/OptimismPortal.sol"; +// Interfaces +import { ICrossDomainMessenger } from "src/universal/interfaces/ICrossDomainMessenger.sol"; +import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol"; +import { IOptimismPortal } from "src/L1/interfaces/IOptimismPortal.sol"; +import { IL1StandardBridge } from "src/L1/interfaces/IL1StandardBridge.sol"; contract L1StandardBridge_Getter_Test is Bridge_Initializer { /// @dev Test that the accessors return the correct initialized values. function test_getters_succeeds() external view { assert(l1StandardBridge.l2TokenBridge() == address(l2StandardBridge)); - assert(l1StandardBridge.OTHER_BRIDGE() == l2StandardBridge); - assert(l1StandardBridge.messenger() == l1CrossDomainMessenger); - assert(l1StandardBridge.MESSENGER() == l1CrossDomainMessenger); + assert(address(l1StandardBridge.OTHER_BRIDGE()) == address(l2StandardBridge)); + assert(address(l1StandardBridge.messenger()) == address(l1CrossDomainMessenger)); + assert(address(l1StandardBridge.MESSENGER()) == address(l1CrossDomainMessenger)); assert(l1StandardBridge.superchainConfig() == superchainConfig); assert(l1StandardBridge.systemConfig() == systemConfig); } @@ -38,7 +37,7 @@ contract L1StandardBridge_Initialize_Test is Bridge_Initializer { /// @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")); + IL1StandardBridge impl = IL1StandardBridge(deploy.mustGetAddress("L1StandardBridge")); assertEq(address(impl.superchainConfig()), address(0)); assertEq(address(impl.MESSENGER()), address(0)); assertEq(address(impl.messenger()), address(0)); @@ -70,7 +69,7 @@ contract L1StandardBridge_Pause_Test is Bridge_Initializer { /// @dev Ensures that the `paused` function of the bridge contract actually calls the `paused` function of the /// `superchainConfig`. function test_pause_callsSuperchainConfig_succeeds() external { - vm.expectCall(address(superchainConfig), abi.encodeWithSelector(SuperchainConfig.paused.selector)); + vm.expectCall(address(superchainConfig), abi.encodeWithSelector(ISuperchainConfig.paused.selector)); l1StandardBridge.paused(); } @@ -101,7 +100,7 @@ contract L1StandardBridge_Pause_TestFail is Bridge_Initializer { vm.mockCall( address(l1StandardBridge.messenger()), - abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector), + abi.encodeWithSelector(ICrossDomainMessenger.xDomainMessageSender.selector), abi.encode(address(l1StandardBridge.otherBridge())) ); } @@ -176,7 +175,7 @@ contract L1StandardBridge_Receive_Test is Bridge_Initializer { vm.expectCall( address(l1CrossDomainMessenger), abi.encodeWithSelector( - CrossDomainMessenger.sendMessage.selector, + ICrossDomainMessenger.sendMessage.selector, address(l2StandardBridge), abi.encodeWithSelector(StandardBridge.finalizeBridgeETH.selector, alice, alice, 100, hex""), 200_000 @@ -235,11 +234,13 @@ contract PreBridgeETH is Bridge_Initializer { vm.expectCall( address(l1CrossDomainMessenger), value, - abi.encodeWithSelector(CrossDomainMessenger.sendMessage.selector, address(l2StandardBridge), message, 50000) + abi.encodeWithSelector( + ICrossDomainMessenger.sendMessage.selector, address(l2StandardBridge), message, 50000 + ) ); bytes memory innerMessage = abi.encodeWithSelector( - CrossDomainMessenger.relayMessage.selector, + ICrossDomainMessenger.relayMessage.selector, nonce, address(l1StandardBridge), address(l2StandardBridge), @@ -253,7 +254,7 @@ contract PreBridgeETH is Bridge_Initializer { address(optimismPortal), value, abi.encodeWithSelector( - OptimismPortal.depositTransaction.selector, + IOptimismPortal.depositTransaction.selector, address(l2CrossDomainMessenger), value, baseGas, @@ -375,11 +376,13 @@ contract PreBridgeETHTo is Bridge_Initializer { // L1CrossDomainMessenger.sendMessage vm.expectCall( address(l1CrossDomainMessenger), - abi.encodeWithSelector(CrossDomainMessenger.sendMessage.selector, address(l2StandardBridge), message, 60000) + abi.encodeWithSelector( + ICrossDomainMessenger.sendMessage.selector, address(l2StandardBridge), message, 60000 + ) ); bytes memory innerMessage = abi.encodeWithSelector( - CrossDomainMessenger.relayMessage.selector, + ICrossDomainMessenger.relayMessage.selector, nonce, address(l1StandardBridge), address(l2StandardBridge), @@ -392,7 +395,7 @@ contract PreBridgeETHTo is Bridge_Initializer { vm.expectCall( address(optimismPortal), abi.encodeWithSelector( - OptimismPortal.depositTransaction.selector, + IOptimismPortal.depositTransaction.selector, address(l2CrossDomainMessenger), value, baseGas, @@ -527,11 +530,13 @@ contract L1StandardBridge_DepositERC20_Test is Bridge_Initializer { // the L1 bridge should call L1CrossDomainMessenger.sendMessage vm.expectCall( address(l1CrossDomainMessenger), - abi.encodeWithSelector(CrossDomainMessenger.sendMessage.selector, address(l2StandardBridge), message, 10000) + abi.encodeWithSelector( + ICrossDomainMessenger.sendMessage.selector, address(l2StandardBridge), message, 10000 + ) ); bytes memory innerMessage = abi.encodeWithSelector( - CrossDomainMessenger.relayMessage.selector, + ICrossDomainMessenger.relayMessage.selector, nonce, address(l1StandardBridge), address(l2StandardBridge), @@ -544,7 +549,7 @@ contract L1StandardBridge_DepositERC20_Test is Bridge_Initializer { vm.expectCall( address(optimismPortal), abi.encodeWithSelector( - OptimismPortal.depositTransaction.selector, + IOptimismPortal.depositTransaction.selector, address(l2CrossDomainMessenger), 0, baseGas, @@ -610,7 +615,7 @@ contract L1StandardBridge_DepositERC20To_Test is Bridge_Initializer { ); bytes memory innerMessage = abi.encodeWithSelector( - CrossDomainMessenger.relayMessage.selector, + ICrossDomainMessenger.relayMessage.selector, nonce, address(l1StandardBridge), address(l2StandardBridge), @@ -649,13 +654,15 @@ contract L1StandardBridge_DepositERC20To_Test is Bridge_Initializer { // the L1 bridge should call L1CrossDomainMessenger.sendMessage vm.expectCall( address(l1CrossDomainMessenger), - abi.encodeWithSelector(CrossDomainMessenger.sendMessage.selector, address(l2StandardBridge), message, 10000) + abi.encodeWithSelector( + ICrossDomainMessenger.sendMessage.selector, address(l2StandardBridge), message, 10000 + ) ); // The L1 XDM should call OptimismPortal.depositTransaction vm.expectCall( address(optimismPortal), abi.encodeWithSelector( - OptimismPortal.depositTransaction.selector, + IOptimismPortal.depositTransaction.selector, address(l2CrossDomainMessenger), 0, baseGas, @@ -694,7 +701,7 @@ contract L1StandardBridge_FinalizeETHWithdrawal_Test is Bridge_Initializer { vm.mockCall( address(l1StandardBridge.messenger()), - abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector), + abi.encodeWithSelector(ICrossDomainMessenger.xDomainMessageSender.selector), abi.encode(address(l1StandardBridge.OTHER_BRIDGE())) ); // ensure that the messenger has ETH to call with @@ -720,7 +727,7 @@ contract L1StandardBridge_FinalizeETHWithdrawal_TestFail is Bridge_Initializer { ); vm.mockCall( address(l1StandardBridge.messenger()), - abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector), + abi.encodeWithSelector(ICrossDomainMessenger.xDomainMessageSender.selector), abi.encode(address(l1StandardBridge.OTHER_BRIDGE())) ); vm.deal(address(l1StandardBridge.messenger()), _value); @@ -759,7 +766,7 @@ contract L1StandardBridge_FinalizeERC20Withdrawal_Test is Bridge_Initializer { vm.mockCall( address(l1StandardBridge.messenger()), - abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector), + abi.encodeWithSelector(ICrossDomainMessenger.xDomainMessageSender.selector), abi.encode(address(l1StandardBridge.OTHER_BRIDGE())) ); vm.prank(address(l1StandardBridge.messenger())); @@ -775,7 +782,7 @@ contract L1StandardBridge_FinalizeERC20Withdrawal_TestFail is Bridge_Initializer function test_finalizeERC20Withdrawal_notMessenger_reverts() external { vm.mockCall( address(l1StandardBridge.messenger()), - abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector), + abi.encodeWithSelector(ICrossDomainMessenger.xDomainMessageSender.selector), abi.encode(address(l1StandardBridge.OTHER_BRIDGE())) ); vm.prank(address(28)); @@ -787,7 +794,7 @@ contract L1StandardBridge_FinalizeERC20Withdrawal_TestFail is Bridge_Initializer function test_finalizeERC20Withdrawal_notOtherBridge_reverts() external { vm.mockCall( address(l1StandardBridge.messenger()), - abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector), + abi.encodeWithSelector(ICrossDomainMessenger.xDomainMessageSender.selector), abi.encode(address(address(0))) ); vm.prank(address(l1StandardBridge.messenger())); @@ -802,7 +809,7 @@ contract L1StandardBridge_FinalizeBridgeETH_Test is Bridge_Initializer { address messenger = address(l1StandardBridge.messenger()); vm.mockCall( messenger, - abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector), + abi.encodeWithSelector(ICrossDomainMessenger.xDomainMessageSender.selector), abi.encode(address(l1StandardBridge.OTHER_BRIDGE())) ); vm.deal(messenger, 100); @@ -820,7 +827,7 @@ contract L1StandardBridge_FinalizeBridgeETH_TestFail is Bridge_Initializer { function testFuzz_finalizeBridgeETH_customGasToken_reverts(uint256 _value, bytes calldata _extraData) external { vm.mockCall( address(l1StandardBridge.messenger()), - abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector), + abi.encodeWithSelector(ICrossDomainMessenger.xDomainMessageSender.selector), abi.encode(address(l1StandardBridge.OTHER_BRIDGE())) ); vm.deal(address(l1CrossDomainMessenger), _value); @@ -838,7 +845,7 @@ contract L1StandardBridge_FinalizeBridgeETH_TestFail is Bridge_Initializer { address messenger = address(l1StandardBridge.messenger()); vm.mockCall( messenger, - abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector), + abi.encodeWithSelector(ICrossDomainMessenger.xDomainMessageSender.selector), abi.encode(address(l1StandardBridge.OTHER_BRIDGE())) ); vm.deal(messenger, 100); @@ -852,7 +859,7 @@ contract L1StandardBridge_FinalizeBridgeETH_TestFail is Bridge_Initializer { address messenger = address(l1StandardBridge.messenger()); vm.mockCall( messenger, - abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector), + abi.encodeWithSelector(ICrossDomainMessenger.xDomainMessageSender.selector), abi.encode(address(l1StandardBridge.OTHER_BRIDGE())) ); vm.deal(messenger, 100); @@ -866,7 +873,7 @@ contract L1StandardBridge_FinalizeBridgeETH_TestFail is Bridge_Initializer { address messenger = address(l1StandardBridge.messenger()); vm.mockCall( messenger, - abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector), + abi.encodeWithSelector(ICrossDomainMessenger.xDomainMessageSender.selector), abi.encode(address(l1StandardBridge.OTHER_BRIDGE())) ); vm.deal(messenger, 100); diff --git a/packages/contracts-bedrock/test/L1/L2OutputOracle.t.sol b/packages/contracts-bedrock/test/L1/L2OutputOracle.t.sol index 3d89809e9b304..7acca0fae187d 100644 --- a/packages/contracts-bedrock/test/L1/L2OutputOracle.t.sol +++ b/packages/contracts-bedrock/test/L1/L2OutputOracle.t.sol @@ -16,11 +16,12 @@ import { Proxy } from "src/universal/Proxy.sol"; // Target contract import { L2OutputOracle } from "src/L1/L2OutputOracle.sol"; +import { IL2OutputOracle } from "src/L1/interfaces/IL2OutputOracle.sol"; contract L2OutputOracle_constructor_Test is CommonTest { /// @dev Tests that constructor sets the initial values correctly. function test_constructor_succeeds() external { - L2OutputOracle oracleImpl = new L2OutputOracle(); + IL2OutputOracle oracleImpl = IL2OutputOracle(address(new L2OutputOracle())); assertEq(oracleImpl.SUBMISSION_INTERVAL(), 1); assertEq(oracleImpl.submissionInterval(), 1); diff --git a/packages/contracts-bedrock/test/L1/OPContractsManager.t.sol b/packages/contracts-bedrock/test/L1/OPContractsManager.t.sol new file mode 100644 index 0000000000000..54c87616e1762 --- /dev/null +++ b/packages/contracts-bedrock/test/L1/OPContractsManager.t.sol @@ -0,0 +1,127 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +import { Test, stdStorage, StdStorage } from "forge-std/Test.sol"; + +import { DeployOPChainInput } from "scripts/DeployOPChain.s.sol"; +import { DeployOPChain_TestBase } from "test/DeployOPChain.t.sol"; + +import { OPContractsManager } from "src/L1/OPContractsManager.sol"; +import { SuperchainConfig } from "src/L1/SuperchainConfig.sol"; +import { ProtocolVersions } from "src/L1/ProtocolVersions.sol"; +import { SystemConfig } from "src/L1/SystemConfig.sol"; + +// Exposes internal functions for testing. +contract OPContractsManager_Harness is OPContractsManager { + constructor( + SuperchainConfig _superchainConfig, + ProtocolVersions _protocolVersions + ) + OPContractsManager(_superchainConfig, _protocolVersions) + { } + + function chainIdToBatchInboxAddress_exposed(uint256 l2ChainId) public pure returns (address) { + return super.chainIdToBatchInboxAddress(l2ChainId); + } +} + +// Unlike other test suites, we intentionally do not inherit from CommonTest or Setup. This is +// because OPContractsManager acts as a deploy script, so we start from a clean slate here and +// work OPContractsManager's deployment into the existing test setup, instead of using the existing +// test setup to deploy OPContractsManager. We do however inherit from DeployOPChain_TestBase so +// we can use its setup to deploy the implementations similarly to how a real deployment would +// happen. +contract OPContractsManager_Deploy_Test is DeployOPChain_TestBase { + using stdStorage for StdStorage; + + event Deployed( + uint256 indexed outputVersion, uint256 indexed l2ChainId, address indexed deployer, bytes deployOutput + ); + + function setUp() public override { + DeployOPChain_TestBase.setUp(); + + doi.set(doi.opChainProxyAdminOwner.selector, opChainProxyAdminOwner); + doi.set(doi.systemConfigOwner.selector, systemConfigOwner); + doi.set(doi.batcher.selector, batcher); + doi.set(doi.unsafeBlockSigner.selector, unsafeBlockSigner); + doi.set(doi.proposer.selector, proposer); + doi.set(doi.challenger.selector, challenger); + doi.set(doi.basefeeScalar.selector, basefeeScalar); + doi.set(doi.blobBaseFeeScalar.selector, blobBaseFeeScalar); + doi.set(doi.l2ChainId.selector, l2ChainId); + doi.set(doi.opcmProxy.selector, address(opcm)); + } + + // This helper function is used to convert the input struct type defined in DeployOPChain.s.sol + // to the input struct type defined in OPContractsManager.sol. + function toOPCMDeployInput(DeployOPChainInput _doi) internal view returns (OPContractsManager.DeployInput memory) { + return OPContractsManager.DeployInput({ + roles: OPContractsManager.Roles({ + opChainProxyAdminOwner: _doi.opChainProxyAdminOwner(), + systemConfigOwner: _doi.systemConfigOwner(), + batcher: _doi.batcher(), + unsafeBlockSigner: _doi.unsafeBlockSigner(), + proposer: _doi.proposer(), + challenger: _doi.challenger() + }), + basefeeScalar: _doi.basefeeScalar(), + blobBasefeeScalar: _doi.blobBaseFeeScalar(), + l2ChainId: _doi.l2ChainId(), + startingAnchorRoots: _doi.startingAnchorRoots() + }); + } + + function test_deploy_l2ChainIdEqualsZero_reverts() public { + OPContractsManager.DeployInput memory deployInput = toOPCMDeployInput(doi); + deployInput.l2ChainId = 0; + vm.expectRevert(OPContractsManager.InvalidChainId.selector); + opcm.deploy(deployInput); + } + + function test_deploy_l2ChainIdEqualsCurrentChainId_reverts() public { + OPContractsManager.DeployInput memory deployInput = toOPCMDeployInput(doi); + deployInput.l2ChainId = block.chainid; + + vm.expectRevert(OPContractsManager.InvalidChainId.selector); + opcm.deploy(deployInput); + } + + function test_deploy_succeeds() public { + vm.expectEmit(true, true, true, false); // TODO precompute the expected `deployOutput`. + emit Deployed(0, doi.l2ChainId(), address(this), bytes("")); + opcm.deploy(toOPCMDeployInput(doi)); + } +} + +// These tests use the harness which exposes internal functions for testing. +contract OPContractsManager_InternalMethods_Test is Test { + OPContractsManager_Harness opcmHarness; + + function setUp() public { + SuperchainConfig superchainConfigProxy = SuperchainConfig(makeAddr("superchainConfig")); + ProtocolVersions protocolVersionsProxy = ProtocolVersions(makeAddr("protocolVersions")); + vm.etch(address(superchainConfigProxy), hex"01"); + vm.etch(address(protocolVersionsProxy), hex"01"); + + opcmHarness = new OPContractsManager_Harness({ + _superchainConfig: superchainConfigProxy, + _protocolVersions: protocolVersionsProxy + }); + } + + function test_calculatesBatchInboxAddress_succeeds() public view { + // These test vectors were calculated manually: + // 1. Compute the bytes32 encoding of the chainId: bytes32(uint256(chainId)); + // 2. Hash it and manually take the first 19 bytes, and prefixed it with 0x00. + uint256 chainId = 1234; + address expected = 0x0017FA14b0d73Aa6A26D6b8720c1c84b50984f5C; + address actual = opcmHarness.chainIdToBatchInboxAddress_exposed(chainId); + vm.assertEq(expected, actual); + + chainId = type(uint256).max; + expected = 0x00a9C584056064687E149968cBaB758a3376D22A; + actual = opcmHarness.chainIdToBatchInboxAddress_exposed(chainId); + vm.assertEq(expected, actual); + } +} diff --git a/packages/contracts-bedrock/test/L1/OPStackManager.t.sol b/packages/contracts-bedrock/test/L1/OPStackManager.t.sol deleted file mode 100644 index c97e9632faac8..0000000000000 --- a/packages/contracts-bedrock/test/L1/OPStackManager.t.sol +++ /dev/null @@ -1,65 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.15; - -// Testing utilities -import { Test } from "forge-std/Test.sol"; - -// Target contract -import { OPStackManager } from "src/L1/OPStackManager.sol"; - -// Exposes internal functions for testing. -contract OPStackManager_Harness is OPStackManager { - function chainIdToBatchInboxAddress_exposed(uint256 l2ChainId) public pure returns (address) { - return super.chainIdToBatchInboxAddress(l2ChainId); - } -} - -// Unlike other test suites, we intentionally do not inherit from CommonTest or Setup. This is -// because OPStackManager acts as a deploy script, so we start from a clean slate here and -// work OPStackManager's deployment into the existing test setup, instead of using the existing -// test setup to deploy OPStackManager. -contract OPStackManager_Init is Test { - OPStackManager opsm; - - // Default dummy parameters for the deploy function. - OPStackManager.Roles roles; - uint256 l2ChainId = 1234; - uint32 basefeeScalar = 1; - uint32 blobBasefeeScalar = 1; - - function setUp() public { - opsm = new OPStackManager(); - } -} - -contract OPStackManager_Deploy_Test is OPStackManager_Init { - function test_deploy_l2ChainIdEqualsZero_reverts() public { - vm.expectRevert(OPStackManager.InvalidChainId.selector); - opsm.deploy(0, basefeeScalar, blobBasefeeScalar, roles); - } - - function test_deploy_l2ChainIdEqualsCurrentChainId_reverts() public { - vm.expectRevert(OPStackManager.InvalidChainId.selector); - opsm.deploy(block.chainid, basefeeScalar, blobBasefeeScalar, roles); - } -} - -// These tests use the harness which exposes internal functions for testing. -contract OPStackManager_InternalMethods_Test is Test { - function test_calculatesBatchInboxAddress_succeeds() public { - OPStackManager_Harness opsmHarness = new OPStackManager_Harness(); - - // These test vectors were calculated manually: - // 1. Compute the bytes32 encoding of the chainId: bytes32(uint256(chainId)); - // 2. Hash it and manually take the first 19 bytes, and prefixed it with 0x00. - uint256 chainId = 1234; - address expected = 0x0017FA14b0d73Aa6A26D6b8720c1c84b50984f5C; - address actual = opsmHarness.chainIdToBatchInboxAddress_exposed(chainId); - vm.assertEq(expected, actual); - - chainId = type(uint256).max; - expected = 0x00a9C584056064687E149968cBaB758a3376D22A; - actual = opsmHarness.chainIdToBatchInboxAddress_exposed(chainId); - vm.assertEq(expected, actual); - } -} diff --git a/packages/contracts-bedrock/test/L1/OptimismPortal.t.sol b/packages/contracts-bedrock/test/L1/OptimismPortal.t.sol index 474c052a40163..0472c0781ce86 100644 --- a/packages/contracts-bedrock/test/L1/OptimismPortal.t.sol +++ b/packages/contracts-bedrock/test/L1/OptimismPortal.t.sol @@ -1,34 +1,33 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -// Testing utilities +// Testing import { stdError } from "forge-std/Test.sol"; import { VmSafe } from "forge-std/Vm.sol"; - +import { MockERC20 } from "solmate/test/utils/mocks/MockERC20.sol"; import { CommonTest } from "test/setup/CommonTest.sol"; import { NextImpl } from "test/mocks/NextImpl.sol"; import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; +// Contracts +import { Proxy } from "src/universal/Proxy.sol"; +import { SuperchainConfig } from "src/L1/SuperchainConfig.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 { L2OutputOracle } from "src/L1/L2OutputOracle.sol"; -import { SystemConfig } from "src/L1/SystemConfig.sol"; -import { SuperchainConfig } from "src/L1/SuperchainConfig.sol"; -import { L1Block } from "src/L2/L1Block.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; -import { OptimismPortal } from "src/L1/OptimismPortal.sol"; import { GasPayingToken } from "src/libraries/GasPayingToken.sol"; -import { MockERC20 } from "solmate/test/utils/mocks/MockERC20.sol"; import { AddressAliasHelper } from "src/vendor/AddressAliasHelper.sol"; import "src/libraries/PortalErrors.sol"; +// Interfaces +import { IResourceMetering } from "src/L1/interfaces/IResourceMetering.sol"; +import { IL2OutputOracle } from "src/L1/interfaces/IL2OutputOracle.sol"; +import { IL1Block } from "src/L2/interfaces/IL1Block.sol"; +import { IOptimismPortal } from "src/L1/interfaces/IOptimismPortal.sol"; + contract OptimismPortal_Test is CommonTest { address depositor; @@ -43,7 +42,7 @@ contract OptimismPortal_Test is CommonTest { /// @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"))); + IOptimismPortal opImpl = IOptimismPortal(payable(deploy.mustGetAddress("OptimismPortal"))); assertEq(address(opImpl.l2Oracle()), address(0)); assertEq(address(opImpl.systemConfig()), address(0)); assertEq(address(opImpl.superchainConfig()), address(0)); @@ -170,7 +169,7 @@ contract OptimismPortal_Test is CommonTest { _to = address(0); } vm.assume(_data.length <= 120_000); - ResourceMetering.ResourceConfig memory rcfg = systemConfig.resourceConfig(); + IResourceMetering.ResourceConfig memory rcfg = systemConfig.resourceConfig(); _gasLimit = uint64(bound(_gasLimit, optimismPortal.minimumGasLimit(uint64(_data.length)), rcfg.maxResourceLimit)); @@ -403,7 +402,7 @@ contract OptimismPortal_Test is CommonTest { uint256 ts = block.timestamp; vm.mockCall( address(optimismPortal.l2Oracle()), - abi.encodeWithSelector(L2OutputOracle.getL2Output.selector), + abi.encodeWithSelector(IL2OutputOracle.getL2Output.selector), abi.encode(Types.OutputProposal(bytes32(uint256(1)), uint128(ts), uint128(startingBlockNumber))) ); @@ -463,7 +462,7 @@ contract OptimismPortal_Test is CommonTest { uint256(0), // value uint64(200_000), // gasLimit false, // isCreation, - abi.encodeCall(L1Block.setGasPayingToken, (_token, _decimals, _name, _symbol)) + abi.encodeCall(IL1Block.setGasPayingToken, (_token, _decimals, _name, _symbol)) ) ); @@ -498,7 +497,7 @@ contract OptimismPortal_Test is CommonTest { _value: 0, _gasLimit: 200_000, _isCreation: false, - _data: abi.encodeCall(L1Block.setGasPayingToken, (_token, 18, name, symbol)) + _data: abi.encodeCall(IL1Block.setGasPayingToken, (_token, 18, name, symbol)) }); VmSafe.Log[] memory logs = vm.getRecordedLogs(); @@ -831,7 +830,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is CommonTest { // this case we just use bytes32(uint256(1)). vm.mockCall( address(optimismPortal.l2Oracle()), - abi.encodeWithSelector(L2OutputOracle.getL2Output.selector), + abi.encodeWithSelector(IL2OutputOracle.getL2Output.selector), abi.encode(bytes32(uint256(1)), _proposedBlockNumber) ); @@ -886,7 +885,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is CommonTest { // to finalize the withdrawal. vm.mockCall( address(optimismPortal.l2Oracle()), - abi.encodeWithSelector(L2OutputOracle.getL2Output.selector), + abi.encodeWithSelector(IL2OutputOracle.getL2Output.selector), abi.encode( Types.OutputProposal(bytes32(uint256(0)), uint128(block.timestamp), uint128(_proposedBlockNumber)) ) @@ -917,7 +916,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is CommonTest { // finalization period. vm.mockCall( address(optimismPortal.l2Oracle()), - abi.encodeWithSelector(L2OutputOracle.getL2Output.selector), + abi.encodeWithSelector(IL2OutputOracle.getL2Output.selector), abi.encode(Types.OutputProposal(_outputRoot, uint128(block.timestamp + 1), uint128(_proposedBlockNumber))) ); @@ -953,7 +952,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is CommonTest { uint256 recentTimestamp = block.timestamp - 1; vm.mockCall( address(optimismPortal.l2Oracle()), - abi.encodeWithSelector(L2OutputOracle.getL2Output.selector), + abi.encodeWithSelector(IL2OutputOracle.getL2Output.selector), abi.encode(Types.OutputProposal(_outputRoot, uint128(recentTimestamp), uint128(_proposedBlockNumber))) ); @@ -1005,7 +1004,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is CommonTest { vm.mockCall( address(optimismPortal.l2Oracle()), - abi.encodeWithSelector(L2OutputOracle.getL2Output.selector), + abi.encodeWithSelector(IL2OutputOracle.getL2Output.selector), abi.encode( Types.OutputProposal( Hashing.hashOutputRootProof(outputRootProof), @@ -1054,7 +1053,7 @@ contract OptimismPortal_FinalizeWithdrawal_Test is CommonTest { uint256 finalizedTimestamp = block.timestamp - l2OutputOracle.FINALIZATION_PERIOD_SECONDS() - 1; vm.mockCall( address(optimismPortal.l2Oracle()), - abi.encodeWithSelector(L2OutputOracle.getL2Output.selector), + abi.encodeWithSelector(IL2OutputOracle.getL2Output.selector), abi.encode(Types.OutputProposal(outputRoot, uint128(finalizedTimestamp), uint128(_proposedBlockNumber))) ); @@ -1156,7 +1155,7 @@ contract OptimismPortalUpgradeable_Test is CommonTest { /// @dev Tests that the proxy is initialized correctly. function test_params_initValuesOnProxy_succeeds() external view { (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = optimismPortal.params(); - ResourceMetering.ResourceConfig memory rcfg = systemConfig.resourceConfig(); + IResourceMetering.ResourceConfig memory rcfg = systemConfig.resourceConfig(); assertEq(prevBaseFee, rcfg.minimumBaseFee); assertEq(prevBoughtGas, 0); @@ -1211,24 +1210,36 @@ contract OptimismPortalResourceFuzz_Test is CommonTest { { // 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)); + _prevBoughtGas = uint64(bound(_prevBoughtGas, 0, _maxResourceLimit - _gasLimit)); + _blockDiff = uint8(bound(_blockDiff, 0, 3)); + _baseFeeMaxChangeDenominator = uint8(bound(_baseFeeMaxChangeDenominator, 2, type(uint8).max)); + _elasticityMultiplier = uint8(bound(_elasticityMultiplier, 1, type(uint8).max)); + // 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)); + + // Base fee can increase quickly and mean that we can't buy the amount of gas we want. + // Here we add a VM assumption to bound the potential increase. + // Compute the maximum possible increase in base fee. + uint256 maxPercentIncrease = uint256(_elasticityMultiplier - 1) * 100 / uint256(_baseFeeMaxChangeDenominator); + // Assume that we have enough gas to burn. + // Compute the maximum amount of gas we'd need to burn. + // Assume we need 1/5 of our gas to do other stuff. + vm.assume(_prevBaseFee * maxPercentIncrease * _gasLimit / 100 < MAX_GAS_LIMIT * 4 / 5); + // 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({ + IResourceMetering.ResourceConfig memory rcfg = IResourceMetering.ResourceConfig({ maxResourceLimit: _maxResourceLimit, elasticityMultiplier: _elasticityMultiplier, baseFeeMaxChangeDenominator: _baseFeeMaxChangeDenominator, @@ -1287,7 +1298,7 @@ contract OptimismPortalWithMockERC20_Test is OptimismPortal_FinalizeWithdrawal_T _to = address(0); } vm.assume(_data.length <= 120_000); - ResourceMetering.ResourceConfig memory rcfg = systemConfig.resourceConfig(); + IResourceMetering.ResourceConfig memory rcfg = systemConfig.resourceConfig(); _gasLimit = uint64(bound(_gasLimit, optimismPortal.minimumGasLimit(uint64(_data.length)), rcfg.maxResourceLimit)); @@ -1502,7 +1513,7 @@ contract OptimismPortalWithMockERC20_Test is OptimismPortal_FinalizeWithdrawal_T _to = address(0); } vm.assume(_data.length <= 120_000); - ResourceMetering.ResourceConfig memory rcfg = systemConfig.resourceConfig(); + IResourceMetering.ResourceConfig memory rcfg = systemConfig.resourceConfig(); _gasLimit = uint64(bound(_gasLimit, optimismPortal.minimumGasLimit(uint64(_data.length)), rcfg.maxResourceLimit)); diff --git a/packages/contracts-bedrock/test/L1/OptimismPortal2.t.sol b/packages/contracts-bedrock/test/L1/OptimismPortal2.t.sol index 5c8ba27f6335e..c131995c1a6b2 100644 --- a/packages/contracts-bedrock/test/L1/OptimismPortal2.t.sol +++ b/packages/contracts-bedrock/test/L1/OptimismPortal2.t.sol @@ -1,35 +1,35 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -// Testing utilities +// Testing import { stdError } from "forge-std/Test.sol"; import { VmSafe } from "forge-std/Vm.sol"; - +import { MockERC20 } from "solmate/test/utils/mocks/MockERC20.sol"; import { CommonTest } from "test/setup/CommonTest.sol"; import { NextImpl } from "test/mocks/NextImpl.sol"; import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; +// Contracts +import { Proxy } from "src/universal/Proxy.sol"; +import { SuperchainConfig } from "src/L1/SuperchainConfig.sol"; + // Libraries import { Types } from "src/libraries/Types.sol"; import { Hashing } from "src/libraries/Hashing.sol"; import { Constants } from "src/libraries/Constants.sol"; import { Predeploys } from "src/libraries/Predeploys.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 { L1Block } from "src/L2/L1Block.sol"; -import { SuperchainConfig } from "src/L1/SuperchainConfig.sol"; -import { OptimismPortal2 } from "src/L1/OptimismPortal2.sol"; import { GasPayingToken } from "src/libraries/GasPayingToken.sol"; -import { MockERC20 } from "solmate/test/utils/mocks/MockERC20.sol"; - -import { FaultDisputeGame, IDisputeGame } from "src/dispute/FaultDisputeGame.sol"; +import { AddressAliasHelper } from "src/vendor/AddressAliasHelper.sol"; import "src/dispute/lib/Types.sol"; import "src/libraries/PortalErrors.sol"; +// Interfaces +import { IResourceMetering } from "src/L1/interfaces/IResourceMetering.sol"; +import { IL1Block } from "src/L2/interfaces/IL1Block.sol"; +import { IOptimismPortal2 } from "src/L1/interfaces/IOptimismPortal2.sol"; +import { IDisputeGame } from "src/dispute/interfaces/IDisputeGame.sol"; +import { IFaultDisputeGame } from "src/dispute/interfaces/IFaultDisputeGame.sol"; + contract OptimismPortal2_Test is CommonTest { address depositor; @@ -50,7 +50,7 @@ contract OptimismPortal2_Test is CommonTest { /// @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"))); + IOptimismPortal2 opImpl = IOptimismPortal2(payable(deploy.mustGetAddress("OptimismPortal2"))); assertEq(address(opImpl.disputeGameFactory()), address(0)); assertEq(address(opImpl.systemConfig()), address(0)); assertEq(address(opImpl.superchainConfig()), address(0)); @@ -317,7 +317,7 @@ contract OptimismPortal2_Test is CommonTest { uint256(0), // value uint64(200_000), // gasLimit false, // isCreation, - abi.encodeCall(L1Block.setGasPayingToken, (_token, _decimals, _name, _symbol)) + abi.encodeCall(IL1Block.setGasPayingToken, (_token, _decimals, _name, _symbol)) ) ); @@ -352,7 +352,7 @@ contract OptimismPortal2_Test is CommonTest { _value: 0, _gasLimit: 200_000, _isCreation: false, - _data: abi.encodeCall(L1Block.setGasPayingToken, (_token, 18, name, symbol)) + _data: abi.encodeCall(IL1Block.setGasPayingToken, (_token, 18, name, symbol)) }); VmSafe.Log[] memory logs = vm.getRecordedLogs(); @@ -424,7 +424,7 @@ contract OptimismPortal2_FinalizeWithdrawal_Test is CommonTest { // Reusable default values for a test withdrawal Types.WithdrawalTransaction _defaultTx; - FaultDisputeGame game; + IFaultDisputeGame game; uint256 _proposedGameIndex; uint256 _proposedBlockNumber; bytes32 _stateRoot; @@ -463,7 +463,7 @@ contract OptimismPortal2_FinalizeWithdrawal_Test is CommonTest { /// @dev Setup the system for a ready-to-use state. function setUp() public virtual override { _proposedBlockNumber = 0xFF; - game = FaultDisputeGame( + game = IFaultDisputeGame( payable( address( disputeGameFactory.create( @@ -1404,7 +1404,7 @@ contract OptimismPortal2_Upgradeable_Test is CommonTest { /// @dev Tests that the proxy is initialized correctly. function test_params_initValuesOnProxy_succeeds() external view { (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = optimismPortal2.params(); - ResourceMetering.ResourceConfig memory rcfg = systemConfig.resourceConfig(); + IResourceMetering.ResourceConfig memory rcfg = systemConfig.resourceConfig(); assertEq(prevBaseFee, rcfg.minimumBaseFee); assertEq(prevBoughtGas, 0); @@ -1464,24 +1464,37 @@ contract OptimismPortal2_ResourceFuzz_Test is CommonTest { { // 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)); + _prevBoughtGas = uint64(bound(_prevBoughtGas, 0, _maxResourceLimit - _gasLimit)); + _blockDiff = uint8(bound(_blockDiff, 0, 3)); + _baseFeeMaxChangeDenominator = uint8(bound(_baseFeeMaxChangeDenominator, 2, type(uint8).max)); + _elasticityMultiplier = uint8(bound(_elasticityMultiplier, 1, type(uint8).max)); + // 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)); + + // Base fee can increase quickly and mean that we can't buy the amount of gas we want. + // Here we add a VM assumption to bound the potential increase. + // Compute the maximum possible increase in base fee. + uint256 maxPercentIncrease = uint256(_elasticityMultiplier - 1) * 100 / uint256(_baseFeeMaxChangeDenominator); + // Assume that we have enough gas to burn. + // Compute the maximum amount of gas we'd need to burn. + // Assume we need 1/5 of our gas to do other stuff. + vm.assume(_prevBaseFee * maxPercentIncrease * _gasLimit / 100 < MAX_GAS_LIMIT * 4 / 5); + // 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({ + IResourceMetering.ResourceConfig memory rcfg = IResourceMetering.ResourceConfig({ maxResourceLimit: _maxResourceLimit, elasticityMultiplier: _elasticityMultiplier, baseFeeMaxChangeDenominator: _baseFeeMaxChangeDenominator, @@ -1540,7 +1553,7 @@ contract OptimismPortal2WithMockERC20_Test is OptimismPortal2_FinalizeWithdrawal _to = address(0); } vm.assume(_data.length <= 120_000); - ResourceMetering.ResourceConfig memory rcfg = systemConfig.resourceConfig(); + IResourceMetering.ResourceConfig memory rcfg = systemConfig.resourceConfig(); _gasLimit = uint64(bound(_gasLimit, optimismPortal2.minimumGasLimit(uint64(_data.length)), rcfg.maxResourceLimit)); @@ -1764,7 +1777,7 @@ contract OptimismPortal2WithMockERC20_Test is OptimismPortal2_FinalizeWithdrawal _to = address(0); } vm.assume(_data.length <= 120_000); - ResourceMetering.ResourceConfig memory rcfg = systemConfig.resourceConfig(); + IResourceMetering.ResourceConfig memory rcfg = systemConfig.resourceConfig(); _gasLimit = uint64(bound(_gasLimit, optimismPortal2.minimumGasLimit(uint64(_data.length)), rcfg.maxResourceLimit)); diff --git a/packages/contracts-bedrock/test/L1/OptimismPortalInterop.t.sol b/packages/contracts-bedrock/test/L1/OptimismPortalInterop.t.sol index 1d9c2b01a2487..6e0235774df6b 100644 --- a/packages/contracts-bedrock/test/L1/OptimismPortalInterop.t.sol +++ b/packages/contracts-bedrock/test/L1/OptimismPortalInterop.t.sol @@ -7,11 +7,15 @@ import { CommonTest } from "test/setup/CommonTest.sol"; // Libraries import { Constants } from "src/libraries/Constants.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; +import "src/libraries/PortalErrors.sol"; // Target contract dependencies import "src/libraries/PortalErrors.sol"; import { OptimismPortalInterop } from "src/L1/OptimismPortalInterop.sol"; -import { L1BlockInterop, ConfigType } from "src/L2/L1BlockInterop.sol"; +import { L1BlockIsthmus, ConfigType } from "src/L2/L1BlockIsthmus.sol"; + +// Interfaces +import { IOptimismPortalInterop } from "src/L1/interfaces/IOptimismPortalInterop.sol"; contract OptimismPortalInterop_Test is CommonTest { /// @notice Marked virtual to be overridden in @@ -31,7 +35,7 @@ contract OptimismPortalInterop_Test is CommonTest { _mint: 0, _gasLimit: 200_000, _isCreation: false, - _data: abi.encodeCall(L1BlockInterop.setConfig, (ConfigType.SET_GAS_PAYING_TOKEN, _value)) + _data: abi.encodeCall(L1BlockIsthmus.setConfig, (ConfigType.SET_GAS_PAYING_TOKEN, _value)) }); vm.prank(address(_optimismPortalInterop().systemConfig())); @@ -54,7 +58,7 @@ contract OptimismPortalInterop_Test is CommonTest { _mint: 0, _gasLimit: 200_000, _isCreation: false, - _data: abi.encodeCall(L1BlockInterop.setConfig, (ConfigType.ADD_DEPENDENCY, _value)) + _data: abi.encodeCall(L1BlockIsthmus.setConfig, (ConfigType.ADD_DEPENDENCY, _value)) }); vm.prank(address(_optimismPortalInterop().systemConfig())); @@ -77,7 +81,7 @@ contract OptimismPortalInterop_Test is CommonTest { _mint: 0, _gasLimit: 200_000, _isCreation: false, - _data: abi.encodeCall(L1BlockInterop.setConfig, (ConfigType.REMOVE_DEPENDENCY, _value)) + _data: abi.encodeCall(L1BlockIsthmus.setConfig, (ConfigType.REMOVE_DEPENDENCY, _value)) }); vm.prank(address(_optimismPortalInterop().systemConfig())); @@ -91,7 +95,7 @@ contract OptimismPortalInterop_Test is CommonTest { } /// @dev Returns the OptimismPortalInterop instance. - function _optimismPortalInterop() internal view returns (OptimismPortalInterop) { - return OptimismPortalInterop(payable(address(optimismPortal))); + function _optimismPortalInterop() internal view returns (IOptimismPortalInterop) { + return IOptimismPortalInterop(payable(address(optimismPortal))); } } diff --git a/packages/contracts-bedrock/test/L1/ProtocolVersions.t.sol b/packages/contracts-bedrock/test/L1/ProtocolVersions.t.sol index 235654d38af60..957d2b914f382 100644 --- a/packages/contracts-bedrock/test/L1/ProtocolVersions.t.sol +++ b/packages/contracts-bedrock/test/L1/ProtocolVersions.t.sol @@ -12,10 +12,10 @@ import { Constants } from "src/libraries/Constants.sol"; import { Proxy } from "src/universal/Proxy.sol"; // Target contract -import { ProtocolVersions, ProtocolVersion } from "src/L1/ProtocolVersions.sol"; +import { IProtocolVersions, ProtocolVersion } from "src/L1/interfaces/IProtocolVersions.sol"; contract ProtocolVersions_Init is CommonTest { - event ConfigUpdate(uint256 indexed version, ProtocolVersions.UpdateType indexed updateType, bytes data); + event ConfigUpdate(uint256 indexed version, IProtocolVersions.UpdateType indexed updateType, bytes data); ProtocolVersion required; ProtocolVersion recommended; @@ -30,7 +30,7 @@ contract ProtocolVersions_Init is CommonTest { contract ProtocolVersions_Initialize_Test is ProtocolVersions_Init { /// @dev Tests that initialization sets the correct values. function test_initialize_values_succeeds() external view { - ProtocolVersions protocolVersionsImpl = ProtocolVersions(deploy.mustGetAddress("ProtocolVersions")); + IProtocolVersions protocolVersionsImpl = IProtocolVersions(deploy.mustGetAddress("ProtocolVersions")); address owner = deploy.cfg().finalSystemOwner(); assertEq(ProtocolVersion.unwrap(protocolVersions.required()), ProtocolVersion.unwrap(required)); @@ -44,7 +44,7 @@ contract ProtocolVersions_Initialize_Test is ProtocolVersions_Init { /// @dev Ensures that the events are emitted during initialization. function test_initialize_events_succeeds() external { - ProtocolVersions protocolVersionsImpl = ProtocolVersions(deploy.mustGetAddress("ProtocolVersions")); + IProtocolVersions protocolVersionsImpl = IProtocolVersions(deploy.mustGetAddress("ProtocolVersions")); assertEq(protocolVersionsImpl.owner(), address(0xdEad)); // Wipe out the initialized slot so the proxy can be initialized again @@ -52,15 +52,15 @@ contract ProtocolVersions_Initialize_Test is ProtocolVersions_Init { // The order depends here vm.expectEmit(true, true, true, true, address(protocolVersions)); - emit ConfigUpdate(0, ProtocolVersions.UpdateType.REQUIRED_PROTOCOL_VERSION, abi.encode(required)); + emit ConfigUpdate(0, IProtocolVersions.UpdateType.REQUIRED_PROTOCOL_VERSION, abi.encode(required)); vm.expectEmit(true, true, true, true, address(protocolVersions)); - emit ConfigUpdate(0, ProtocolVersions.UpdateType.RECOMMENDED_PROTOCOL_VERSION, abi.encode(recommended)); + emit ConfigUpdate(0, IProtocolVersions.UpdateType.RECOMMENDED_PROTOCOL_VERSION, abi.encode(recommended)); vm.prank(EIP1967Helper.getAdmin(address(protocolVersions))); Proxy(payable(address(protocolVersions))).upgradeToAndCall( address(protocolVersionsImpl), abi.encodeCall( - ProtocolVersions.initialize, + IProtocolVersions.initialize, ( alice, // _owner required, // _required @@ -89,7 +89,7 @@ contract ProtocolVersions_Setters_Test is ProtocolVersions_Init { /// @dev Tests that `setRequired` updates the required protocol version successfully. function testFuzz_setRequired_succeeds(uint256 _version) external { vm.expectEmit(true, true, true, true); - emit ConfigUpdate(0, ProtocolVersions.UpdateType.REQUIRED_PROTOCOL_VERSION, abi.encode(_version)); + emit ConfigUpdate(0, IProtocolVersions.UpdateType.REQUIRED_PROTOCOL_VERSION, abi.encode(_version)); vm.prank(protocolVersions.owner()); protocolVersions.setRequired(ProtocolVersion.wrap(_version)); @@ -99,7 +99,7 @@ contract ProtocolVersions_Setters_Test is ProtocolVersions_Init { /// @dev Tests that `setRecommended` updates the recommended protocol version successfully. function testFuzz_setRecommended_succeeds(uint256 _version) external { vm.expectEmit(true, true, true, true); - emit ConfigUpdate(0, ProtocolVersions.UpdateType.RECOMMENDED_PROTOCOL_VERSION, abi.encode(_version)); + emit ConfigUpdate(0, IProtocolVersions.UpdateType.RECOMMENDED_PROTOCOL_VERSION, abi.encode(_version)); vm.prank(protocolVersions.owner()); protocolVersions.setRecommended(ProtocolVersion.wrap(_version)); diff --git a/packages/contracts-bedrock/test/L1/ResourceMetering.t.sol b/packages/contracts-bedrock/test/L1/ResourceMetering.t.sol index f4bca39ea4180..f315b5212fd64 100644 --- a/packages/contracts-bedrock/test/L1/ResourceMetering.t.sol +++ b/packages/contracts-bedrock/test/L1/ResourceMetering.t.sol @@ -12,13 +12,22 @@ import { Proxy } from "src/universal/Proxy.sol"; // Target contract import { ResourceMetering } from "src/L1/ResourceMetering.sol"; +import { IResourceMetering } from "src/L1/interfaces/IResourceMetering.sol"; contract MeterUser is ResourceMetering { ResourceMetering.ResourceConfig public innerConfig; constructor() { initialize(); - innerConfig = Constants.DEFAULT_RESOURCE_CONFIG(); + IResourceMetering.ResourceConfig memory rcfg = Constants.DEFAULT_RESOURCE_CONFIG(); + innerConfig = ResourceMetering.ResourceConfig({ + maxResourceLimit: rcfg.maxResourceLimit, + elasticityMultiplier: rcfg.elasticityMultiplier, + baseFeeMaxChangeDenominator: rcfg.baseFeeMaxChangeDenominator, + minimumBaseFee: rcfg.minimumBaseFee, + systemTxMaxGas: rcfg.systemTxMaxGas, + maximumBaseFee: rcfg.maximumBaseFee + }); } function initialize() public initializer { @@ -231,7 +240,15 @@ contract CustomMeterUser is ResourceMetering { } function _resourceConfig() internal pure override returns (ResourceMetering.ResourceConfig memory) { - return Constants.DEFAULT_RESOURCE_CONFIG(); + IResourceMetering.ResourceConfig memory rcfg = Constants.DEFAULT_RESOURCE_CONFIG(); + return ResourceMetering.ResourceConfig({ + maxResourceLimit: rcfg.maxResourceLimit, + elasticityMultiplier: rcfg.elasticityMultiplier, + baseFeeMaxChangeDenominator: rcfg.baseFeeMaxChangeDenominator, + minimumBaseFee: rcfg.minimumBaseFee, + systemTxMaxGas: rcfg.systemTxMaxGas, + maximumBaseFee: rcfg.maximumBaseFee + }); } function use(uint64 _amount) public returns (uint256) { diff --git a/packages/contracts-bedrock/test/L1/SuperchainConfig.t.sol b/packages/contracts-bedrock/test/L1/SuperchainConfig.t.sol index 97b25f3f611ab..409bb0003941d 100644 --- a/packages/contracts-bedrock/test/L1/SuperchainConfig.t.sol +++ b/packages/contracts-bedrock/test/L1/SuperchainConfig.t.sol @@ -12,6 +12,7 @@ import { Proxy } from "src/universal/Proxy.sol"; // Target contract import { SuperchainConfig } from "src/L1/SuperchainConfig.sol"; +import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol"; contract SuperchainConfig_Init_Test is CommonTest { /// @dev Tests that initialization sets the correct values. These are defined in CommonTest.sol. @@ -23,16 +24,16 @@ contract SuperchainConfig_Init_Test is CommonTest { /// @dev Tests that it can be intialized as paused. function test_initialize_paused_succeeds() external { Proxy newProxy = new Proxy(alice); - SuperchainConfig newImpl = new SuperchainConfig(); + ISuperchainConfig newImpl = ISuperchainConfig(address(new SuperchainConfig())); vm.startPrank(alice); newProxy.upgradeToAndCall( address(newImpl), - abi.encodeWithSelector(SuperchainConfig.initialize.selector, deploy.cfg().superchainConfigGuardian(), true) + abi.encodeWithSelector(ISuperchainConfig.initialize.selector, deploy.cfg().superchainConfigGuardian(), true) ); - assertTrue(SuperchainConfig(address(newProxy)).paused()); - assertEq(SuperchainConfig(address(newProxy)).guardian(), deploy.cfg().superchainConfigGuardian()); + assertTrue(ISuperchainConfig(address(newProxy)).paused()); + assertEq(ISuperchainConfig(address(newProxy)).guardian(), deploy.cfg().superchainConfigGuardian()); } } diff --git a/packages/contracts-bedrock/test/L1/SystemConfig.t.sol b/packages/contracts-bedrock/test/L1/SystemConfig.t.sol index 9b48f354d2487..ddfafc0edb2f1 100644 --- a/packages/contracts-bedrock/test/L1/SystemConfig.t.sol +++ b/packages/contracts-bedrock/test/L1/SystemConfig.t.sol @@ -1,26 +1,26 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -// Testing utilities +// Testing import { CommonTest } from "test/setup/CommonTest.sol"; +import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; + +// Contracts import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import { Proxy } from "src/universal/Proxy.sol"; // Libraries import { Constants } from "src/libraries/Constants.sol"; -import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; - -// Target contract dependencies -import { ResourceMetering } from "src/L1/ResourceMetering.sol"; -import { Proxy } from "src/universal/Proxy.sol"; -import { L1Block } from "src/L2/L1Block.sol"; import { GasPayingToken } from "src/libraries/GasPayingToken.sol"; -// Target contract -import { SystemConfig } from "src/L1/SystemConfig.sol"; +// Interfaces +import { IResourceMetering } from "src/L1/interfaces/IResourceMetering.sol"; +import { ISystemConfig } from "src/L1/interfaces/ISystemConfig.sol"; +import { IL1Block } from "src/L2/interfaces/IL1Block.sol"; contract SystemConfig_Init is CommonTest { - event ConfigUpdate(uint256 indexed version, SystemConfig.UpdateType indexed updateType, bytes data); + event ConfigUpdate(uint256 indexed version, ISystemConfig.UpdateType indexed updateType, bytes data); } contract SystemConfig_Initialize_Test is SystemConfig_Init { @@ -49,7 +49,7 @@ contract SystemConfig_Initialize_Test is SystemConfig_Init { /// @dev Tests that constructor sets the correct values. function test_constructor_succeeds() external view { - SystemConfig impl = SystemConfig(systemConfigImpl); + ISystemConfig impl = ISystemConfig(systemConfigImpl); assertEq(impl.owner(), address(0xdEaD)); assertEq(impl.overhead(), 0); assertEq(impl.scalar(), uint256(0x01) << 248); @@ -58,7 +58,7 @@ contract SystemConfig_Initialize_Test is SystemConfig_Init { assertEq(impl.unsafeBlockSigner(), address(0)); assertEq(impl.basefeeScalar(), 0); assertEq(impl.blobbasefeeScalar(), 0); - ResourceMetering.ResourceConfig memory actual = impl.resourceConfig(); + IResourceMetering.ResourceConfig memory actual = impl.resourceConfig(); assertEq(actual.maxResourceLimit, 1); assertEq(actual.elasticityMultiplier, 1); assertEq(actual.baseFeeMaxChangeDenominator, 2); @@ -91,8 +91,8 @@ contract SystemConfig_Initialize_Test is SystemConfig_Init { assertEq(systemConfig.basefeeScalar(), basefeeScalar); assertEq(systemConfig.blobbasefeeScalar(), blobbasefeeScalar); // Depends on `initialize` being called with defaults - ResourceMetering.ResourceConfig memory rcfg = Constants.DEFAULT_RESOURCE_CONFIG(); - ResourceMetering.ResourceConfig memory actual = systemConfig.resourceConfig(); + IResourceMetering.ResourceConfig memory rcfg = Constants.DEFAULT_RESOURCE_CONFIG(); + IResourceMetering.ResourceConfig memory actual = systemConfig.resourceConfig(); assertEq(actual.maxResourceLimit, rcfg.maxResourceLimit); assertEq(actual.elasticityMultiplier, rcfg.elasticityMultiplier); assertEq(actual.baseFeeMaxChangeDenominator, rcfg.baseFeeMaxChangeDenominator); @@ -138,7 +138,7 @@ contract SystemConfig_Initialize_TestFail is SystemConfig_Initialize_Test { _unsafeBlockSigner: address(1), _config: Constants.DEFAULT_RESOURCE_CONFIG(), _batchInbox: address(0), - _addresses: SystemConfig.Addresses({ + _addresses: ISystemConfig.Addresses({ l1CrossDomainMessenger: address(0), l1ERC721Bridge: address(0), l1StandardBridge: address(0), @@ -168,7 +168,7 @@ contract SystemConfig_Initialize_TestFail is SystemConfig_Initialize_Test { _unsafeBlockSigner: address(1), _config: Constants.DEFAULT_RESOURCE_CONFIG(), _batchInbox: address(0), - _addresses: SystemConfig.Addresses({ + _addresses: ISystemConfig.Addresses({ l1CrossDomainMessenger: address(0), l1ERC721Bridge: address(0), l1StandardBridge: address(0), @@ -199,7 +199,7 @@ contract SystemConfig_Initialize_TestFail is SystemConfig_Initialize_Test { _unsafeBlockSigner: address(1), _config: Constants.DEFAULT_RESOURCE_CONFIG(), _batchInbox: address(0), - _addresses: SystemConfig.Addresses({ + _addresses: ISystemConfig.Addresses({ l1CrossDomainMessenger: address(0), l1ERC721Bridge: address(0), l1StandardBridge: address(0), @@ -217,7 +217,7 @@ contract SystemConfig_Init_ResourceConfig is SystemConfig_Init { /// @dev Tests that `setResourceConfig` reverts if the min base fee /// is greater than the maximum allowed base fee. function test_setResourceConfig_badMinMax_reverts() external { - ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({ + IResourceMetering.ResourceConfig memory config = IResourceMetering.ResourceConfig({ maxResourceLimit: 20_000_000, elasticityMultiplier: 10, baseFeeMaxChangeDenominator: 8, @@ -231,7 +231,7 @@ contract SystemConfig_Init_ResourceConfig is SystemConfig_Init { /// @dev Tests that `setResourceConfig` reverts if the baseFeeMaxChangeDenominator /// is zero. function test_setResourceConfig_zeroDenominator_reverts() external { - ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({ + IResourceMetering.ResourceConfig memory config = IResourceMetering.ResourceConfig({ maxResourceLimit: 20_000_000, elasticityMultiplier: 10, baseFeeMaxChangeDenominator: 0, @@ -246,7 +246,7 @@ contract SystemConfig_Init_ResourceConfig is SystemConfig_Init { function test_setResourceConfig_lowGasLimit_reverts() external { uint64 gasLimit = systemConfig.gasLimit(); - ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({ + IResourceMetering.ResourceConfig memory config = IResourceMetering.ResourceConfig({ maxResourceLimit: uint32(gasLimit), elasticityMultiplier: 10, baseFeeMaxChangeDenominator: 8, @@ -260,7 +260,7 @@ contract SystemConfig_Init_ResourceConfig is SystemConfig_Init { /// @dev Tests that `setResourceConfig` reverts if the elasticity multiplier /// and max resource limit are configured such that there is a loss of precision. function test_setResourceConfig_badPrecision_reverts() external { - ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({ + IResourceMetering.ResourceConfig memory config = IResourceMetering.ResourceConfig({ maxResourceLimit: 20_000_000, elasticityMultiplier: 11, baseFeeMaxChangeDenominator: 8, @@ -274,7 +274,7 @@ contract SystemConfig_Init_ResourceConfig is SystemConfig_Init { /// @dev Helper to initialize the system config with a resource config and default values, and expect a revert /// with the given message. function _initializeWithResourceConfig( - ResourceMetering.ResourceConfig memory config, + IResourceMetering.ResourceConfig memory config, string memory revertMessage ) internal @@ -294,7 +294,7 @@ contract SystemConfig_Init_ResourceConfig is SystemConfig_Init { _unsafeBlockSigner: address(0), _config: config, _batchInbox: address(0), - _addresses: SystemConfig.Addresses({ + _addresses: ISystemConfig.Addresses({ l1CrossDomainMessenger: address(0), l1ERC721Bridge: address(0), l1StandardBridge: address(0), @@ -332,7 +332,7 @@ contract SystemConfig_Init_CustomGasToken is SystemConfig_Init { _unsafeBlockSigner: address(1), _config: Constants.DEFAULT_RESOURCE_CONFIG(), _batchInbox: address(0), - _addresses: SystemConfig.Addresses({ + _addresses: ISystemConfig.Addresses({ l1CrossDomainMessenger: address(0), l1ERC721Bridge: address(0), disputeGameFactory: address(0), @@ -467,7 +467,7 @@ contract SystemConfig_Init_CustomGasToken is SystemConfig_Init { uint256(0), // value uint64(200_000), // gasLimit false, // isCreation, - abi.encodeCall(L1Block.setGasPayingToken, (address(token), 18, bytes32("Silly"), bytes32("SIL"))) + abi.encodeCall(IL1Block.setGasPayingToken, (address(token), 18, bytes32("Silly"), bytes32("SIL"))) ) ); @@ -533,7 +533,7 @@ contract SystemConfig_Setters_Test is SystemConfig_Init { /// @dev Tests that `setBatcherHash` updates the batcher hash successfully. function testFuzz_setBatcherHash_succeeds(bytes32 newBatcherHash) external { vm.expectEmit(address(systemConfig)); - emit ConfigUpdate(0, SystemConfig.UpdateType.BATCHER, abi.encode(newBatcherHash)); + emit ConfigUpdate(0, ISystemConfig.UpdateType.BATCHER, abi.encode(newBatcherHash)); vm.prank(systemConfig.owner()); systemConfig.setBatcherHash(newBatcherHash); @@ -545,7 +545,7 @@ contract SystemConfig_Setters_Test is SystemConfig_Init { // always zero out most significant byte newScalar = (newScalar << 16) >> 16; vm.expectEmit(address(systemConfig)); - emit ConfigUpdate(0, SystemConfig.UpdateType.GAS_CONFIG, abi.encode(newOverhead, newScalar)); + emit ConfigUpdate(0, ISystemConfig.UpdateType.GAS_CONFIG, abi.encode(newOverhead, newScalar)); vm.prank(systemConfig.owner()); systemConfig.setGasConfig(newOverhead, newScalar); @@ -558,7 +558,7 @@ contract SystemConfig_Setters_Test is SystemConfig_Init { ffi.encodeScalarEcotone({ _basefeeScalar: _basefeeScalar, _blobbasefeeScalar: _blobbasefeeScalar }); vm.expectEmit(address(systemConfig)); - emit ConfigUpdate(0, SystemConfig.UpdateType.GAS_CONFIG, abi.encode(systemConfig.overhead(), encoded)); + emit ConfigUpdate(0, ISystemConfig.UpdateType.GAS_CONFIG, abi.encode(systemConfig.overhead(), encoded)); vm.prank(systemConfig.owner()); systemConfig.setGasConfigEcotone({ _basefeeScalar: _basefeeScalar, _blobbasefeeScalar: _blobbasefeeScalar }); @@ -578,7 +578,7 @@ contract SystemConfig_Setters_Test is SystemConfig_Init { newGasLimit = uint64(bound(uint256(newGasLimit), uint256(minimumGasLimit), uint256(maximumGasLimit))); vm.expectEmit(address(systemConfig)); - emit ConfigUpdate(0, SystemConfig.UpdateType.GAS_LIMIT, abi.encode(newGasLimit)); + emit ConfigUpdate(0, ISystemConfig.UpdateType.GAS_LIMIT, abi.encode(newGasLimit)); vm.prank(systemConfig.owner()); systemConfig.setGasLimit(newGasLimit); @@ -588,7 +588,7 @@ contract SystemConfig_Setters_Test is SystemConfig_Init { /// @dev Tests that `setUnsafeBlockSigner` updates the block signer successfully. function testFuzz_setUnsafeBlockSigner_succeeds(address newUnsafeSigner) external { vm.expectEmit(address(systemConfig)); - emit ConfigUpdate(0, SystemConfig.UpdateType.UNSAFE_BLOCK_SIGNER, abi.encode(newUnsafeSigner)); + emit ConfigUpdate(0, ISystemConfig.UpdateType.UNSAFE_BLOCK_SIGNER, abi.encode(newUnsafeSigner)); vm.prank(systemConfig.owner()); systemConfig.setUnsafeBlockSigner(newUnsafeSigner); diff --git a/packages/contracts-bedrock/test/L1/SystemConfigInterop.t.sol b/packages/contracts-bedrock/test/L1/SystemConfigInterop.t.sol index 36887fa336844..6cd3c8b3145c2 100644 --- a/packages/contracts-bedrock/test/L1/SystemConfigInterop.t.sol +++ b/packages/contracts-bedrock/test/L1/SystemConfigInterop.t.sol @@ -1,20 +1,22 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -// Testing utilities +// Testing import { CommonTest } from "test/setup/CommonTest.sol"; +// Contracts +import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import { ConfigType } from "src/L2/L1BlockIsthmus.sol"; + // Libraries import { Constants } from "src/libraries/Constants.sol"; import { StaticConfig } from "src/libraries/StaticConfig.sol"; import { GasPayingToken } from "src/libraries/GasPayingToken.sol"; -// Target contract dependencies -import { SystemConfig } from "src/L1/SystemConfig.sol"; -import { SystemConfigInterop } from "src/L1/SystemConfigInterop.sol"; -import { OptimismPortalInterop } from "src/L1/OptimismPortalInterop.sol"; -import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; -import { ConfigType } from "src/L2/L1BlockInterop.sol"; +// Interfaces +import { ISystemConfig } from "src/L1/interfaces/ISystemConfig.sol"; +import { ISystemConfigInterop } from "src/L1/interfaces/ISystemConfigInterop.sol"; +import { IOptimismPortalInterop } from "src/L1/interfaces/IOptimismPortalInterop.sol"; contract SystemConfigInterop_Test is CommonTest { /// @notice Marked virtual to be overridden in @@ -46,7 +48,7 @@ contract SystemConfigInterop_Test is CommonTest { vm.expectCall( address(optimismPortal), abi.encodeCall( - OptimismPortalInterop.setConfig, + IOptimismPortalInterop.setConfig, ( ConfigType.SET_GAS_PAYING_TOKEN, StaticConfig.encodeSetGasPayingToken({ @@ -67,7 +69,8 @@ contract SystemConfigInterop_Test is CommonTest { vm.expectCall( address(optimismPortal), abi.encodeCall( - OptimismPortalInterop.setConfig, (ConfigType.ADD_DEPENDENCY, StaticConfig.encodeAddDependency(_chainId)) + IOptimismPortalInterop.setConfig, + (ConfigType.ADD_DEPENDENCY, StaticConfig.encodeAddDependency(_chainId)) ) ); @@ -86,7 +89,7 @@ contract SystemConfigInterop_Test is CommonTest { vm.expectCall( address(optimismPortal), abi.encodeCall( - OptimismPortalInterop.setConfig, + IOptimismPortalInterop.setConfig, (ConfigType.REMOVE_DEPENDENCY, StaticConfig.encodeRemoveDependency(_chainId)) ) ); @@ -118,7 +121,7 @@ contract SystemConfigInterop_Test is CommonTest { _unsafeBlockSigner: address(1), _config: Constants.DEFAULT_RESOURCE_CONFIG(), _batchInbox: address(0), - _addresses: SystemConfig.Addresses({ + _addresses: ISystemConfig.Addresses({ l1CrossDomainMessenger: address(0), l1ERC721Bridge: address(0), disputeGameFactory: address(0), @@ -131,7 +134,7 @@ contract SystemConfigInterop_Test is CommonTest { } /// @dev Returns the SystemConfigInterop instance. - function _systemConfigInterop() internal view returns (SystemConfigInterop) { - return SystemConfigInterop(address(systemConfig)); + function _systemConfigInterop() internal view returns (ISystemConfigInterop) { + return ISystemConfigInterop(address(systemConfig)); } } diff --git a/packages/contracts-bedrock/test/L2/CrossL2Inbox.t.sol b/packages/contracts-bedrock/test/L2/CrossL2Inbox.t.sol index 12b24ae1d479b..0d3175d41ed1f 100644 --- a/packages/contracts-bedrock/test/L2/CrossL2Inbox.t.sol +++ b/packages/contracts-bedrock/test/L2/CrossL2Inbox.t.sol @@ -12,13 +12,15 @@ import { TransientContext } from "src/libraries/TransientContext.sol"; import { CrossL2Inbox, NotEntered, + NoExecutingDeposits, InvalidTimestamp, InvalidChainId, TargetCallFailed, NotDepositor, InteropStartAlreadySet } from "src/L2/CrossL2Inbox.sol"; -import { ICrossL2Inbox } from "src/L2/ICrossL2Inbox.sol"; +import { IL1BlockIsthmus } from "src/L2/interfaces/IL1BlockIsthmus.sol"; +import { ICrossL2Inbox } from "src/L2/interfaces/ICrossL2Inbox.sol"; /// @title CrossL2InboxWithModifiableTransientStorage /// @dev CrossL2Inbox contract with methods to modify the transient storage. @@ -155,6 +157,13 @@ contract CrossL2InboxTest is Test { // Ensure that the target call is payable if value is sent if (_value > 0) assumePayable(_target); + // Ensure is not a deposit transaction + vm.mockCall({ + callee: Predeploys.L1_BLOCK_ATTRIBUTES, + data: abi.encodeWithSelector(IL1BlockIsthmus.isDeposit.selector), + returnData: abi.encode(false) + }); + // Ensure that the target call does not revert vm.mockCall({ callee: _target, msgValue: _value, data: _message, returnData: abi.encode(true) }); @@ -210,6 +219,13 @@ contract CrossL2InboxTest is Test { _id1.timestamp = bound(_id1.timestamp, interopStartTime + 1, block.timestamp); _id2.timestamp = bound(_id2.timestamp, interopStartTime + 1, block.timestamp); + // Ensure is not a deposit transaction + vm.mockCall({ + callee: Predeploys.L1_BLOCK_ATTRIBUTES, + data: abi.encodeWithSelector(IL1BlockIsthmus.isDeposit.selector), + returnData: abi.encode(false) + }); + // Ensure that id1's chain ID is in the dependency set vm.mockCall({ callee: Predeploys.L1_BLOCK_ATTRIBUTES, @@ -254,6 +270,32 @@ contract CrossL2InboxTest is Test { assertEq(crossL2Inbox.chainId(), _id2.chainId); } + /// @dev Tests that the `executeMessage` function reverts if the transaction comes from a deposit. + function testFuzz_executeMessage_isDeposit_reverts( + ICrossL2Inbox.Identifier calldata _id, + address _target, + bytes calldata _message, + uint256 _value + ) + external + { + // Ensure it is a deposit transaction + vm.mockCall({ + callee: Predeploys.L1_BLOCK_ATTRIBUTES, + data: abi.encodeWithSelector(IL1BlockIsthmus.isDeposit.selector), + returnData: abi.encode(true) + }); + + // Ensure that the contract has enough balance to send with value + vm.deal(address(this), _value); + + // Expect a revert with the NoExecutingDeposits selector + vm.expectRevert(NoExecutingDeposits.selector); + + // Call the executeMessage function + crossL2Inbox.executeMessage{ value: _value }({ _id: _id, _target: _target, _message: _message }); + } + /// @dev Tests that the `executeMessage` function reverts when called with an identifier with an invalid timestamp. function testFuzz_executeMessage_invalidTimestamp_reverts( ICrossL2Inbox.Identifier calldata _id, @@ -267,6 +309,13 @@ contract CrossL2InboxTest is Test { // Ensure that the id's timestamp is invalid (greater than the current block timestamp) vm.assume(_id.timestamp > block.timestamp); + // Ensure is not a deposit transaction + vm.mockCall({ + callee: Predeploys.L1_BLOCK_ATTRIBUTES, + data: abi.encodeWithSelector(IL1BlockIsthmus.isDeposit.selector), + returnData: abi.encode(false) + }); + // Ensure that the contract has enough balance to send with value vm.deal(address(this), _value); @@ -294,6 +343,13 @@ contract CrossL2InboxTest is Test { // Ensure that the contract has enough balance to send with value vm.deal(address(this), _value); + // Ensure is not a deposit transaction + vm.mockCall({ + callee: Predeploys.L1_BLOCK_ATTRIBUTES, + data: abi.encodeWithSelector(IL1BlockIsthmus.isDeposit.selector), + returnData: abi.encode(false) + }); + // Expect a revert with the InvalidTimestamp selector vm.expectRevert(InvalidTimestamp.selector); @@ -316,6 +372,13 @@ contract CrossL2InboxTest is Test { // interop start time) _id.timestamp = bound(_id.timestamp, interopStartTime + 1, block.timestamp); + // Ensure is not a deposit transaction + vm.mockCall({ + callee: Predeploys.L1_BLOCK_ATTRIBUTES, + data: abi.encodeWithSelector(IL1BlockIsthmus.isDeposit.selector), + returnData: abi.encode(false) + }); + // Ensure that the chain ID is NOT in the dependency set vm.mockCall({ callee: Predeploys.L1_BLOCK_ATTRIBUTES, @@ -353,6 +416,13 @@ contract CrossL2InboxTest is Test { // Ensure that the target call reverts vm.mockCallRevert({ callee: _target, msgValue: _value, data: _message, revertData: abi.encode(false) }); + // Ensure is not a deposit transaction + vm.mockCall({ + callee: Predeploys.L1_BLOCK_ATTRIBUTES, + data: abi.encodeWithSelector(IL1BlockIsthmus.isDeposit.selector), + returnData: abi.encode(false) + }); + // Ensure that the chain ID is in the dependency set vm.mockCall({ callee: Predeploys.L1_BLOCK_ATTRIBUTES, @@ -391,6 +461,13 @@ contract CrossL2InboxTest is Test { returnData: abi.encode(true) }); + // Ensure is not a deposit transaction + vm.mockCall({ + callee: Predeploys.L1_BLOCK_ATTRIBUTES, + data: abi.encodeWithSelector(IL1BlockIsthmus.isDeposit.selector), + returnData: abi.encode(false) + }); + // Look for the emit ExecutingMessage event vm.expectEmit(Predeploys.CROSS_L2_INBOX); emit CrossL2Inbox.ExecutingMessage(_messageHash, _id); @@ -399,6 +476,26 @@ contract CrossL2InboxTest is Test { crossL2Inbox.validateMessage(_id, _messageHash); } + function testFuzz_validateMessage_isDeposit_reverts( + ICrossL2Inbox.Identifier calldata _id, + bytes32 _messageHash + ) + external + { + // Ensure it is a deposit transaction + vm.mockCall({ + callee: Predeploys.L1_BLOCK_ATTRIBUTES, + data: abi.encodeWithSelector(IL1BlockIsthmus.isDeposit.selector), + returnData: abi.encode(true) + }); + + // Expect a revert with the NoExecutingDeposits selector + vm.expectRevert(NoExecutingDeposits.selector); + + // Call the executeMessage function + crossL2Inbox.validateMessage(_id, _messageHash); + } + /// @dev Tests that the `validateMessage` function reverts when called with an identifier with a timestamp later /// than current block.timestamp. function testFuzz_validateMessage_invalidTimestamp_reverts( @@ -408,6 +505,13 @@ contract CrossL2InboxTest is Test { external setInteropStart { + // Ensure is not a deposit transaction + vm.mockCall({ + callee: Predeploys.L1_BLOCK_ATTRIBUTES, + data: abi.encodeWithSelector(IL1BlockIsthmus.isDeposit.selector), + returnData: abi.encode(false) + }); + // Ensure that the id's timestamp is invalid (greater than the current block timestamp) vm.assume(_id.timestamp > block.timestamp); @@ -430,6 +534,13 @@ contract CrossL2InboxTest is Test { // Ensure that the id's timestamp is invalid (less than or equal to interopStartTime) _id.timestamp = bound(_id.timestamp, 0, crossL2Inbox.interopStart()); + // Ensure is not a deposit transaction + vm.mockCall({ + callee: Predeploys.L1_BLOCK_ATTRIBUTES, + data: abi.encodeWithSelector(IL1BlockIsthmus.isDeposit.selector), + returnData: abi.encode(false) + }); + // Expect a revert with the InvalidTimestamp selector vm.expectRevert(InvalidTimestamp.selector); @@ -457,6 +568,13 @@ contract CrossL2InboxTest is Test { returnData: abi.encode(false) }); + // Ensure is not a deposit transaction + vm.mockCall({ + callee: Predeploys.L1_BLOCK_ATTRIBUTES, + data: abi.encodeWithSelector(IL1BlockIsthmus.isDeposit.selector), + returnData: abi.encode(false) + }); + // Expect a revert with the InvalidChainId selector vm.expectRevert(InvalidChainId.selector); diff --git a/packages/contracts-bedrock/test/L2/L1Block.t.sol b/packages/contracts-bedrock/test/L2/L1Block.t.sol index ce67a66922234..762553a2ff2f3 100644 --- a/packages/contracts-bedrock/test/L2/L1Block.t.sol +++ b/packages/contracts-bedrock/test/L2/L1Block.t.sol @@ -1,15 +1,12 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -// Testing utilities +// Testing import { CommonTest } from "test/setup/CommonTest.sol"; // Libraries import { Encoding } from "src/libraries/Encoding.sol"; import { Constants } from "src/libraries/Constants.sol"; - -// Target contract -import { L1Block } from "src/L2/L1Block.sol"; import "src/libraries/L1BlockErrors.sol"; contract L1BlockTest is CommonTest { diff --git a/packages/contracts-bedrock/test/L2/L1BlockInterop.t.sol b/packages/contracts-bedrock/test/L2/L1BlockIsthmus.t.sol similarity index 50% rename from packages/contracts-bedrock/test/L2/L1BlockInterop.t.sol rename to packages/contracts-bedrock/test/L2/L1BlockIsthmus.t.sol index 159021e77dcc5..1c2407dd73abe 100644 --- a/packages/contracts-bedrock/test/L2/L1BlockInterop.t.sol +++ b/packages/contracts-bedrock/test/L2/L1BlockIsthmus.t.sol @@ -8,16 +8,17 @@ import { CommonTest } from "test/setup/CommonTest.sol"; import { StaticConfig } from "src/libraries/StaticConfig.sol"; // Target contract dependencies -import { L1BlockInterop, ConfigType } from "src/L2/L1BlockInterop.sol"; +import { L1BlockIsthmus, ConfigType } from "src/L2/L1BlockIsthmus.sol"; +import { Predeploys } from "src/libraries/Predeploys.sol"; import "src/libraries/L1BlockErrors.sol"; -contract L1BlockInteropTest is CommonTest { +contract L1BlockIsthmusTest is CommonTest { event GasPayingTokenSet(address indexed token, uint8 indexed decimals, bytes32 name, bytes32 symbol); event DependencyAdded(uint256 indexed chainId); event DependencyRemoved(uint256 indexed chainId); modifier prankDepositor() { - vm.startPrank(l1Block.DEPOSITOR_ACCOUNT()); + vm.startPrank(_l1BlockIsthmus().DEPOSITOR_ACCOUNT()); _; vm.stopPrank(); } @@ -33,14 +34,14 @@ contract L1BlockInteropTest is CommonTest { function testFuzz_isInDependencySet_succeeds(uint256 _chainId) public prankDepositor { vm.assume(_chainId != block.chainid); - _l1BlockInterop().setConfig(ConfigType.ADD_DEPENDENCY, StaticConfig.encodeAddDependency(_chainId)); + _l1BlockIsthmus().setConfig(ConfigType.ADD_DEPENDENCY, StaticConfig.encodeAddDependency(_chainId)); - assertTrue(_l1BlockInterop().isInDependencySet(_chainId)); + assertTrue(_l1BlockIsthmus().isInDependencySet(_chainId)); } /// @dev Tests that `isInDependencySet` returns true when the chain's chain ID is passed as the input. function test_isInDependencySet_chainChainId_succeeds() public view { - assertTrue(_l1BlockInterop().isInDependencySet(block.chainid)); + assertTrue(_l1BlockIsthmus().isInDependencySet(block.chainid)); } /// @dev Tests that `isInDependencySet` reverts when the input chain ID is not in the dependency set @@ -49,16 +50,16 @@ contract L1BlockInteropTest is CommonTest { vm.assume(_chainId != block.chainid); // Check that the chain ID is not in the dependency set - assertFalse(_l1BlockInterop().isInDependencySet(_chainId)); + assertFalse(_l1BlockIsthmus().isInDependencySet(_chainId)); } /// @dev Tests that `isInDependencySet` returns false when the dependency set is empty. function testFuzz_isInDependencySet_dependencySetEmpty_succeeds(uint256 _chainId) public view { vm.assume(_chainId != block.chainid); - assertEq(_l1BlockInterop().dependencySetSize(), 0); + assertEq(_l1BlockIsthmus().dependencySetSize(), 0); - assertFalse(_l1BlockInterop().isInDependencySet(_chainId)); + assertFalse(_l1BlockIsthmus().isInDependencySet(_chainId)); } /// @dev Tests that the dependency set size is correct when adding an arbitrary number of chain IDs. @@ -69,16 +70,16 @@ contract L1BlockInteropTest is CommonTest { for (uint256 i = 0; i < _dependencySetSize; i++) { if (i == block.chainid) continue; - _l1BlockInterop().setConfig(ConfigType.ADD_DEPENDENCY, StaticConfig.encodeAddDependency(i)); + _l1BlockIsthmus().setConfig(ConfigType.ADD_DEPENDENCY, StaticConfig.encodeAddDependency(i)); uniqueCount++; } - assertEq(_l1BlockInterop().dependencySetSize(), uniqueCount); + assertEq(_l1BlockIsthmus().dependencySetSize(), uniqueCount); } /// @dev Tests that the dependency set size is correct when the dependency set is empty. function test_dependencySetSize_dependencySetEmpty_succeeds() public view { - assertEq(_l1BlockInterop().dependencySetSize(), 0); + assertEq(_l1BlockIsthmus().dependencySetSize(), 0); } /// @dev Tests that the config for setting the gas paying token succeeds. @@ -96,7 +97,7 @@ contract L1BlockInteropTest is CommonTest { vm.expectEmit(address(l1Block)); emit GasPayingTokenSet({ token: _token, decimals: _decimals, name: _name, symbol: _symbol }); - _l1BlockInterop().setConfig( + _l1BlockIsthmus().setConfig( ConfigType.SET_GAS_PAYING_TOKEN, StaticConfig.encodeSetGasPayingToken({ _token: _token, _decimals: _decimals, _name: _name, _symbol: _symbol }) ); @@ -114,7 +115,7 @@ contract L1BlockInteropTest is CommonTest { vm.assume(_token != address(vm)); vm.expectRevert(NotDepositor.selector); - _l1BlockInterop().setConfig( + _l1BlockIsthmus().setConfig( ConfigType.SET_GAS_PAYING_TOKEN, StaticConfig.encodeSetGasPayingToken({ _token: _token, _decimals: _decimals, _name: _name, _symbol: _symbol }) ); @@ -127,41 +128,41 @@ contract L1BlockInteropTest is CommonTest { vm.expectEmit(address(l1Block)); emit DependencyAdded(_chainId); - _l1BlockInterop().setConfig(ConfigType.ADD_DEPENDENCY, StaticConfig.encodeAddDependency(_chainId)); + _l1BlockIsthmus().setConfig(ConfigType.ADD_DEPENDENCY, StaticConfig.encodeAddDependency(_chainId)); } /// @dev Tests that adding a dependency reverts if it's the chain's chain id function test_setConfig_addDependency_chainChainId_reverts() public prankDepositor { vm.expectRevert(AlreadyDependency.selector); - _l1BlockInterop().setConfig(ConfigType.ADD_DEPENDENCY, StaticConfig.encodeAddDependency(block.chainid)); + _l1BlockIsthmus().setConfig(ConfigType.ADD_DEPENDENCY, StaticConfig.encodeAddDependency(block.chainid)); } /// @dev Tests that adding a dependency already in the set reverts function test_setConfig_addDependency_alreadyDependency_reverts(uint256 _chainId) public prankDepositor { vm.assume(_chainId != block.chainid); - _l1BlockInterop().setConfig(ConfigType.ADD_DEPENDENCY, StaticConfig.encodeAddDependency(_chainId)); + _l1BlockIsthmus().setConfig(ConfigType.ADD_DEPENDENCY, StaticConfig.encodeAddDependency(_chainId)); vm.expectRevert(AlreadyDependency.selector); - _l1BlockInterop().setConfig(ConfigType.ADD_DEPENDENCY, StaticConfig.encodeAddDependency(_chainId)); + _l1BlockIsthmus().setConfig(ConfigType.ADD_DEPENDENCY, StaticConfig.encodeAddDependency(_chainId)); } /// @dev Tests that setting the add dependency config as not the depositor reverts. function testFuzz_setConfig_addDependency_notDepositor_reverts(uint256 _chainId) public { vm.expectRevert(NotDepositor.selector); - _l1BlockInterop().setConfig(ConfigType.ADD_DEPENDENCY, StaticConfig.encodeAddDependency(_chainId)); + _l1BlockIsthmus().setConfig(ConfigType.ADD_DEPENDENCY, StaticConfig.encodeAddDependency(_chainId)); } /// @dev Tests that setting the add dependency config when the dependency set size is too large reverts. function test_setConfig_addDependency_dependencySetSizeTooLarge_reverts() public prankDepositor { for (uint256 i = 0; i < type(uint8).max; i++) { - _l1BlockInterop().setConfig(ConfigType.ADD_DEPENDENCY, StaticConfig.encodeAddDependency(i)); + _l1BlockIsthmus().setConfig(ConfigType.ADD_DEPENDENCY, StaticConfig.encodeAddDependency(i)); } - assertEq(_l1BlockInterop().dependencySetSize(), type(uint8).max); + assertEq(_l1BlockIsthmus().dependencySetSize(), type(uint8).max); vm.expectRevert(DependencySetSizeTooLarge.selector); - _l1BlockInterop().setConfig(ConfigType.ADD_DEPENDENCY, StaticConfig.encodeAddDependency(1)); + _l1BlockIsthmus().setConfig(ConfigType.ADD_DEPENDENCY, StaticConfig.encodeAddDependency(1)); } /// @dev Tests that the config for removing a dependency can be set. @@ -169,24 +170,24 @@ contract L1BlockInteropTest is CommonTest { vm.assume(_chainId != block.chainid); // Add the chain ID to the dependency set before removing it - _l1BlockInterop().setConfig(ConfigType.ADD_DEPENDENCY, StaticConfig.encodeAddDependency(_chainId)); + _l1BlockIsthmus().setConfig(ConfigType.ADD_DEPENDENCY, StaticConfig.encodeAddDependency(_chainId)); vm.expectEmit(address(l1Block)); emit DependencyRemoved(_chainId); - _l1BlockInterop().setConfig(ConfigType.REMOVE_DEPENDENCY, StaticConfig.encodeRemoveDependency(_chainId)); + _l1BlockIsthmus().setConfig(ConfigType.REMOVE_DEPENDENCY, StaticConfig.encodeRemoveDependency(_chainId)); } /// @dev Tests that setting the remove dependency config as not the depositor reverts. function testFuzz_setConfig_removeDependency_notDepositor_reverts(uint256 _chainId) public { vm.expectRevert(NotDepositor.selector); - _l1BlockInterop().setConfig(ConfigType.REMOVE_DEPENDENCY, StaticConfig.encodeRemoveDependency(_chainId)); + _l1BlockIsthmus().setConfig(ConfigType.REMOVE_DEPENDENCY, StaticConfig.encodeRemoveDependency(_chainId)); } /// @dev Tests that setting the remove dependency config for the chain's chain ID reverts. function test_setConfig_removeDependency_chainChainId_reverts() public prankDepositor { vm.expectRevert(CantRemovedDependency.selector); - _l1BlockInterop().setConfig(ConfigType.REMOVE_DEPENDENCY, StaticConfig.encodeRemoveDependency(block.chainid)); + _l1BlockIsthmus().setConfig(ConfigType.REMOVE_DEPENDENCY, StaticConfig.encodeRemoveDependency(block.chainid)); } /// @dev Tests that setting the remove dependency config for a chain ID that is not in the dependency set reverts. @@ -194,11 +195,118 @@ contract L1BlockInteropTest is CommonTest { vm.assume(_chainId != block.chainid); vm.expectRevert(NotDependency.selector); - _l1BlockInterop().setConfig(ConfigType.REMOVE_DEPENDENCY, StaticConfig.encodeRemoveDependency(_chainId)); + _l1BlockIsthmus().setConfig(ConfigType.REMOVE_DEPENDENCY, StaticConfig.encodeRemoveDependency(_chainId)); } - /// @dev Returns the L1BlockInterop instance. - function _l1BlockInterop() internal view returns (L1BlockInterop) { - return L1BlockInterop(address(l1Block)); + /// @dev Returns the L1BlockIsthmus instance. + function _l1BlockIsthmus() internal view returns (L1BlockIsthmus) { + return L1BlockIsthmus(address(l1Block)); + } +} + +contract L1BlockIsthmusIsDeposit_Test is L1BlockIsthmusTest { + /// @dev Tests that `isDeposit` reverts if the caller is not the cross L2 inbox. + function test_isDeposit_notCrossL2Inbox_reverts(address _caller) external { + vm.assume(_caller != Predeploys.CROSS_L2_INBOX); + vm.expectRevert(NotCrossL2Inbox.selector); + _l1BlockIsthmus().isDeposit(); + } + + /// @dev Tests that `isDeposit` always returns the correct value. + function test_isDeposit_succeeds() external { + // Assert is false if the value is not updated + vm.prank(Predeploys.CROSS_L2_INBOX); + assertEq(_l1BlockIsthmus().isDeposit(), false); + + /// @dev Assuming that `setL1BlockValuesIsthmus` will set the proper value. That function is tested as well + vm.prank(_l1BlockIsthmus().DEPOSITOR_ACCOUNT()); + _l1BlockIsthmus().setL1BlockValuesIsthmus(); + + // Assert is true if the value is updated + vm.prank(Predeploys.CROSS_L2_INBOX); + assertEq(_l1BlockIsthmus().isDeposit(), true); + } +} + +contract L1BlockIsthmusSetL1BlockValuesIsthmus_Test is L1BlockIsthmusTest { + /// @dev Tests that `setL1BlockValuesIsthmus` reverts if sender address is not the depositor + function test_setL1BlockValuesIsthmus_notDepositor_reverts(address _caller) external { + vm.assume(_caller != _l1BlockIsthmus().DEPOSITOR_ACCOUNT()); + vm.prank(_caller); + vm.expectRevert(NotDepositor.selector); + _l1BlockIsthmus().setL1BlockValuesIsthmus(); + } + + /// @dev Tests that `setL1BlockValuesIsthmus` succeeds if sender address is the depositor + function test_setL1BlockValuesIsthmus_succeeds( + uint32 baseFeeScalar, + uint32 blobBaseFeeScalar, + uint64 sequenceNumber, + uint64 timestamp, + uint64 number, + uint256 baseFee, + uint256 blobBaseFee, + bytes32 hash, + bytes32 batcherHash + ) + external + { + // Ensure the `isDepositTransaction` flag is false before calling `setL1BlockValuesIsthmus` + vm.prank(Predeploys.CROSS_L2_INBOX); + assertEq(_l1BlockIsthmus().isDeposit(), false); + + bytes memory setValuesEcotoneCalldata = abi.encodePacked( + baseFeeScalar, blobBaseFeeScalar, sequenceNumber, timestamp, number, baseFee, blobBaseFee, hash, batcherHash + ); + + vm.prank(_l1BlockIsthmus().DEPOSITOR_ACCOUNT()); + (bool success,) = address(l1Block).call( + abi.encodePacked(L1BlockIsthmus.setL1BlockValuesIsthmus.selector, setValuesEcotoneCalldata) + ); + assertTrue(success, "function call failed"); + + // Assert that the `isDepositTransaction` flag was properly set to true + vm.prank(Predeploys.CROSS_L2_INBOX); + assertEq(_l1BlockIsthmus().isDeposit(), true); + + // Assert `setL1BlockValuesEcotone` was properly called, forwarding the calldata to it + assertEq(_l1BlockIsthmus().baseFeeScalar(), baseFeeScalar, "base fee scalar not properly set"); + assertEq(_l1BlockIsthmus().blobBaseFeeScalar(), blobBaseFeeScalar, "blob base fee scalar not properly set"); + assertEq(_l1BlockIsthmus().sequenceNumber(), sequenceNumber, "sequence number not properly set"); + assertEq(_l1BlockIsthmus().timestamp(), timestamp, "timestamp not properly set"); + assertEq(_l1BlockIsthmus().number(), number, "number not properly set"); + assertEq(_l1BlockIsthmus().basefee(), baseFee, "base fee not properly set"); + assertEq(_l1BlockIsthmus().blobBaseFee(), blobBaseFee, "blob base fee not properly set"); + assertEq(_l1BlockIsthmus().hash(), hash, "hash not properly set"); + assertEq(_l1BlockIsthmus().batcherHash(), batcherHash, "batcher hash not properly set"); + } +} + +contract L1BlockDepositsComplete_Test is L1BlockIsthmusTest { + // @dev Tests that `depositsComplete` reverts if the caller is not the depositor. + function test_deposits_is_depositor_reverts(address _caller) external { + vm.assume(_caller != _l1BlockIsthmus().DEPOSITOR_ACCOUNT()); + vm.expectRevert(NotDepositor.selector); + _l1BlockIsthmus().depositsComplete(); + } + + // @dev Tests that `depositsComplete` succeeds if the caller is the depositor. + function test_depositsComplete_succeeds() external { + // Set the `isDeposit` flag to true + vm.prank(_l1BlockIsthmus().DEPOSITOR_ACCOUNT()); + _l1BlockIsthmus().setL1BlockValuesIsthmus(); + + // Assert that the `isDeposit` flag was properly set to true + vm.prank(Predeploys.CROSS_L2_INBOX); + assertTrue(_l1BlockIsthmus().isDeposit()); + + // Call `depositsComplete` + vm.prank(_l1BlockIsthmus().DEPOSITOR_ACCOUNT()); + _l1BlockIsthmus().depositsComplete(); + + // Assert that the `isDeposit` flag was properly set to false + /// @dev Assuming that `isDeposit()` wil return the proper value. That function is tested as well + vm.prank(Predeploys.CROSS_L2_INBOX); + assertEq(_l1BlockIsthmus().isDeposit(), false); } } diff --git a/packages/contracts-bedrock/test/L2/L2CrossDomainMessenger.t.sol b/packages/contracts-bedrock/test/L2/L2CrossDomainMessenger.t.sol index c3805b9912612..1c13ece264fc1 100644 --- a/packages/contracts-bedrock/test/L2/L2CrossDomainMessenger.t.sol +++ b/packages/contracts-bedrock/test/L2/L2CrossDomainMessenger.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -// Testing utilities +// Testing import { Bridge_Initializer } from "test/setup/Bridge_Initializer.sol"; import { Reverter, ConfigurableCaller } from "test/mocks/Callers.sol"; import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; @@ -11,12 +11,11 @@ import { Hashing } from "src/libraries/Hashing.sol"; import { Encoding } from "src/libraries/Encoding.sol"; import { Types } from "src/libraries/Types.sol"; import { Constants } from "src/libraries/Constants.sol"; - -// Target contract dependencies -import { L2CrossDomainMessenger } from "src/L2/L2CrossDomainMessenger.sol"; -import { L2ToL1MessagePasser } from "src/L2/L2ToL1MessagePasser.sol"; import { AddressAliasHelper } from "src/vendor/AddressAliasHelper.sol"; -import { OptimismPortal } from "src/L1/OptimismPortal.sol"; + +// Interfaces +import { IL2CrossDomainMessenger } from "src/L2/interfaces/IL2CrossDomainMessenger.sol"; +import { IL2ToL1MessagePasser } from "src/L2/interfaces/IL2ToL1MessagePasser.sol"; contract L2CrossDomainMessenger_Test is Bridge_Initializer { /// @dev Receiver address for testing @@ -24,8 +23,8 @@ contract L2CrossDomainMessenger_Test is Bridge_Initializer { /// @dev Tests that the implementation is initialized correctly. function test_constructor_succeeds() external view { - L2CrossDomainMessenger impl = - L2CrossDomainMessenger(EIP1967Helper.getImplementation(deploy.mustGetAddress("L2CrossDomainMessenger"))); + IL2CrossDomainMessenger impl = + IL2CrossDomainMessenger(EIP1967Helper.getImplementation(deploy.mustGetAddress("L2CrossDomainMessenger"))); assertEq(address(impl.OTHER_MESSENGER()), address(0)); assertEq(address(impl.otherMessenger()), address(0)); assertEq(address(impl.l1CrossDomainMessenger()), address(0)); @@ -51,7 +50,7 @@ contract L2CrossDomainMessenger_Test is Bridge_Initializer { vm.expectCall( address(l2ToL1MessagePasser), abi.encodeWithSelector( - L2ToL1MessagePasser.initiateWithdrawal.selector, + IL2ToL1MessagePasser.initiateWithdrawal.selector, address(l1CrossDomainMessenger), l2CrossDomainMessenger.baseGas(hex"ff", 100), xDomainCallData @@ -239,7 +238,7 @@ contract L2CrossDomainMessenger_Test is Bridge_Initializer { vm.expectCall( address(l2ToL1MessagePasser), abi.encodeWithSelector( - L2ToL1MessagePasser.initiateWithdrawal.selector, + IL2ToL1MessagePasser.initiateWithdrawal.selector, address(l1CrossDomainMessenger), l2CrossDomainMessenger.baseGas(hex"ff", 100), xDomainCallData diff --git a/packages/contracts-bedrock/test/L2/L2ERC721Bridge.t.sol b/packages/contracts-bedrock/test/L2/L2ERC721Bridge.t.sol index b7a3e96bc44b1..664655f38a3b0 100644 --- a/packages/contracts-bedrock/test/L2/L2ERC721Bridge.t.sol +++ b/packages/contracts-bedrock/test/L2/L2ERC721Bridge.t.sol @@ -1,18 +1,17 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Testing import { console } from "forge-std/console.sol"; - -// Testing utilities import { Bridge_Initializer } from "test/setup/Bridge_Initializer.sol"; -// Target contract dependencies +// Contracts import { ERC721 } from "@openzeppelin/contracts/token/ERC721/ERC721.sol"; -import { L1ERC721Bridge } from "src/L1/L1ERC721Bridge.sol"; import { OptimismMintableERC721 } from "src/universal/OptimismMintableERC721.sol"; -// Target contract -import { L2ERC721Bridge } from "src/L2/L2ERC721Bridge.sol"; +// Interfaces +import { IL1ERC721Bridge } from "src/L1/interfaces/IL1ERC721Bridge.sol"; +import { IL2ERC721Bridge } from "src/L2/interfaces/IL2ERC721Bridge.sol"; contract TestERC721 is ERC721 { constructor() ERC721("Test", "TST") { } @@ -98,7 +97,7 @@ contract L2ERC721Bridge_Test is Bridge_Initializer { ( address(l1ERC721Bridge), abi.encodeCall( - L2ERC721Bridge.finalizeBridgeERC721, + IL2ERC721Bridge.finalizeBridgeERC721, (address(remoteToken), address(localToken), alice, alice, tokenId, hex"5678") ), 1234 @@ -175,7 +174,7 @@ contract L2ERC721Bridge_Test is Bridge_Initializer { ( address(l1ERC721Bridge), abi.encodeCall( - L1ERC721Bridge.finalizeBridgeERC721, + IL1ERC721Bridge.finalizeBridgeERC721, (address(remoteToken), address(localToken), alice, bob, tokenId, hex"5678") ), 1234 diff --git a/packages/contracts-bedrock/test/L2/L2StandardBridge.t.sol b/packages/contracts-bedrock/test/L2/L2StandardBridge.t.sol index e07fc0086bd8d..3a173e9743b45 100644 --- a/packages/contracts-bedrock/test/L2/L2StandardBridge.t.sol +++ b/packages/contracts-bedrock/test/L2/L2StandardBridge.t.sol @@ -1,33 +1,33 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -// Testing utilities +// Testing +import { stdStorage, StdStorage } from "forge-std/Test.sol"; 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"; -import { CrossDomainMessenger } from "src/universal/CrossDomainMessenger.sol"; -import { L2ToL1MessagePasser } from "src/L2/L2ToL1MessagePasser.sol"; + +// Contracts import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import { OptimismMintableERC20 } from "src/universal/OptimismMintableERC20.sol"; // Libraries +import { Predeploys } from "src/libraries/Predeploys.sol"; import { Hashing } from "src/libraries/Hashing.sol"; import { Types } from "src/libraries/Types.sol"; -// Target contract dependencies -import { L2StandardBridge } from "src/L2/L2StandardBridge.sol"; -import { Predeploys } from "src/libraries/Predeploys.sol"; -import { StandardBridge } from "src/universal/StandardBridge.sol"; -import { OptimismMintableERC20 } from "src/universal/OptimismMintableERC20.sol"; +// Interfaces +import { ICrossDomainMessenger } from "src/universal/interfaces/ICrossDomainMessenger.sol"; +import { IStandardBridge } from "src/universal/interfaces/IStandardBridge.sol"; +import { IL2ToL1MessagePasser } from "src/L2/interfaces/IL2ToL1MessagePasser.sol"; +import { IL2StandardBridge } from "src/L2/interfaces/IL2StandardBridge.sol"; contract L2StandardBridge_Test is Bridge_Initializer { using stdStorage for StdStorage; /// @dev Test that the bridge's constructor sets the correct values. function test_constructor_succeeds() external view { - L2StandardBridge impl = - L2StandardBridge(payable(EIP1967Helper.getImplementation(deploy.mustGetAddress("L2StandardBridge")))); + IL2StandardBridge impl = + IL2StandardBridge(payable(EIP1967Helper.getImplementation(deploy.mustGetAddress("L2StandardBridge")))); // The implementation contract is initialized with a 0 L1 bridge address, // but the L2 cross-domain-messenger is always set to the predeploy address for both proxy and implementation. assertEq(address(impl.MESSENGER()), Predeploys.L2_CROSS_DOMAIN_MESSENGER, "constructor zero check MESSENGER"); @@ -57,10 +57,10 @@ contract L2StandardBridge_Test is Bridge_Initializer { uint256 nonce = l2CrossDomainMessenger.messageNonce(); bytes memory message = - abi.encodeWithSelector(StandardBridge.finalizeBridgeETH.selector, alice, alice, 100, hex""); + abi.encodeWithSelector(IStandardBridge.finalizeBridgeETH.selector, alice, alice, 100, hex""); uint64 baseGas = l2CrossDomainMessenger.baseGas(message, 200_000); bytes memory withdrawalData = abi.encodeWithSelector( - CrossDomainMessenger.relayMessage.selector, + ICrossDomainMessenger.relayMessage.selector, nonce, address(l2StandardBridge), address(l1StandardBridge), @@ -108,7 +108,7 @@ contract L2StandardBridge_Test is Bridge_Initializer { vm.expectCall( address(l2CrossDomainMessenger), abi.encodeWithSelector( - CrossDomainMessenger.sendMessage.selector, + ICrossDomainMessenger.sendMessage.selector, address(l1StandardBridge), message, 200_000 // StandardBridge's RECEIVE_DEFAULT_GAS_LIMIT @@ -118,7 +118,7 @@ contract L2StandardBridge_Test is Bridge_Initializer { vm.expectCall( Predeploys.L2_TO_L1_MESSAGE_PASSER, abi.encodeWithSelector( - L2ToL1MessagePasser.initiateWithdrawal.selector, + IL2ToL1MessagePasser.initiateWithdrawal.selector, address(l1CrossDomainMessenger), baseGas, withdrawalData @@ -278,11 +278,11 @@ contract PreBridgeERC20 is Bridge_Initializer { assertEq(ERC20(_l2Token).balanceOf(alice), 100); uint256 nonce = l2CrossDomainMessenger.messageNonce(); bytes memory message = abi.encodeWithSelector( - StandardBridge.finalizeBridgeERC20.selector, address(L1Token), _l2Token, alice, alice, 100, hex"" + IStandardBridge.finalizeBridgeERC20.selector, address(L1Token), _l2Token, alice, alice, 100, hex"" ); uint64 baseGas = l2CrossDomainMessenger.baseGas(message, 1000); bytes memory withdrawalData = abi.encodeWithSelector( - CrossDomainMessenger.relayMessage.selector, + ICrossDomainMessenger.relayMessage.selector, nonce, address(l2StandardBridge), address(l1StandardBridge), @@ -317,13 +317,13 @@ contract PreBridgeERC20 is Bridge_Initializer { vm.expectCall( address(l2CrossDomainMessenger), - abi.encodeWithSelector(CrossDomainMessenger.sendMessage.selector, address(l1StandardBridge), message, 1000) + abi.encodeWithSelector(ICrossDomainMessenger.sendMessage.selector, address(l1StandardBridge), message, 1000) ); vm.expectCall( Predeploys.L2_TO_L1_MESSAGE_PASSER, abi.encodeWithSelector( - L2ToL1MessagePasser.initiateWithdrawal.selector, + IL2ToL1MessagePasser.initiateWithdrawal.selector, address(l1CrossDomainMessenger), baseGas, withdrawalData @@ -416,11 +416,11 @@ contract PreBridgeERC20To is Bridge_Initializer { assertEq(ERC20(L2Token).balanceOf(alice), 100); uint256 nonce = l2CrossDomainMessenger.messageNonce(); bytes memory message = abi.encodeWithSelector( - StandardBridge.finalizeBridgeERC20.selector, address(L1Token), _l2Token, alice, bob, 100, hex"" + IStandardBridge.finalizeBridgeERC20.selector, address(L1Token), _l2Token, alice, bob, 100, hex"" ); uint64 baseGas = l2CrossDomainMessenger.baseGas(message, 1000); bytes memory withdrawalData = abi.encodeWithSelector( - CrossDomainMessenger.relayMessage.selector, + ICrossDomainMessenger.relayMessage.selector, nonce, address(l2StandardBridge), address(l1StandardBridge), @@ -480,13 +480,13 @@ contract PreBridgeERC20To is Bridge_Initializer { vm.expectCall( address(l2CrossDomainMessenger), - abi.encodeWithSelector(CrossDomainMessenger.sendMessage.selector, address(l1StandardBridge), message, 1000) + abi.encodeWithSelector(ICrossDomainMessenger.sendMessage.selector, address(l1StandardBridge), message, 1000) ); vm.expectCall( Predeploys.L2_TO_L1_MESSAGE_PASSER, abi.encodeWithSelector( - L2ToL1MessagePasser.initiateWithdrawal.selector, + IL2ToL1MessagePasser.initiateWithdrawal.selector, address(l1CrossDomainMessenger), baseGas, withdrawalData @@ -524,7 +524,7 @@ contract L2StandardBridge_Bridge_Test is Bridge_Initializer { function test_finalizeBridgeETH_sendToSelf_reverts() external { vm.mockCall( address(l2StandardBridge.messenger()), - abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector), + abi.encodeWithSelector(ICrossDomainMessenger.xDomainMessageSender.selector), abi.encode(address(l2StandardBridge.OTHER_BRIDGE())) ); vm.deal(address(l2CrossDomainMessenger), 100); @@ -537,7 +537,7 @@ contract L2StandardBridge_Bridge_Test is Bridge_Initializer { function test_finalizeBridgeETH_sendToMessenger_reverts() external { vm.mockCall( address(l2StandardBridge.messenger()), - abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector), + abi.encodeWithSelector(ICrossDomainMessenger.xDomainMessageSender.selector), abi.encode(address(l2StandardBridge.OTHER_BRIDGE())) ); vm.deal(address(l2CrossDomainMessenger), 100); @@ -551,7 +551,7 @@ contract L2StandardBridge_Bridge_Test is Bridge_Initializer { uint256 nonce = l2CrossDomainMessenger.messageNonce(); bytes memory message = - abi.encodeWithSelector(StandardBridge.finalizeBridgeETH.selector, alice, alice, _value, _extraData); + abi.encodeWithSelector(IStandardBridge.finalizeBridgeETH.selector, alice, alice, _value, _extraData); vm.expectCall( address(l2StandardBridge), @@ -563,7 +563,7 @@ contract L2StandardBridge_Bridge_Test is Bridge_Initializer { address(l2CrossDomainMessenger), _value, abi.encodeWithSelector( - CrossDomainMessenger.sendMessage.selector, address(l1StandardBridge), message, _minGasLimit + ICrossDomainMessenger.sendMessage.selector, address(l1StandardBridge), message, _minGasLimit ) ); @@ -604,14 +604,14 @@ contract L2StandardBridge_Bridge_Test is Bridge_Initializer { ); bytes memory message = - abi.encodeWithSelector(StandardBridge.finalizeBridgeETH.selector, alice, bob, _value, _extraData); + abi.encodeWithSelector(IStandardBridge.finalizeBridgeETH.selector, alice, bob, _value, _extraData); // the L2 bridge should call // L2CrossDomainMessenger.sendMessage vm.expectCall( address(l2CrossDomainMessenger), abi.encodeWithSelector( - CrossDomainMessenger.sendMessage.selector, address(l1StandardBridge), message, _minGasLimit + ICrossDomainMessenger.sendMessage.selector, address(l1StandardBridge), message, _minGasLimit ) ); @@ -654,7 +654,7 @@ contract L2StandardBridge_FinalizeBridgeETH_Test is Bridge_Initializer { address messenger = address(l2StandardBridge.messenger()); vm.mockCall( messenger, - abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector), + abi.encodeWithSelector(ICrossDomainMessenger.xDomainMessageSender.selector), abi.encode(address(l2StandardBridge.OTHER_BRIDGE())) ); vm.deal(messenger, 100); @@ -674,7 +674,7 @@ contract L2StandardBridge_FinalizeBridgeETH_Test is Bridge_Initializer { address messenger = address(l2StandardBridge.messenger()); vm.mockCall( messenger, - abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector), + abi.encodeWithSelector(ICrossDomainMessenger.xDomainMessageSender.selector), abi.encode(address(l2StandardBridge.OTHER_BRIDGE())) ); vm.deal(address(l2CrossDomainMessenger), 1); diff --git a/packages/contracts-bedrock/test/L2/L2StandardBridgeInterop.t.sol b/packages/contracts-bedrock/test/L2/L2StandardBridgeInterop.t.sol index 812ab36deed0f..db8ca94e37c89 100644 --- a/packages/contracts-bedrock/test/L2/L2StandardBridgeInterop.t.sol +++ b/packages/contracts-bedrock/test/L2/L2StandardBridgeInterop.t.sol @@ -1,26 +1,21 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -// Target contract is imported by the `Bridge_Initializer` +// Testing import { Bridge_Initializer } from "test/setup/Bridge_Initializer.sol"; -// Target contract dependencies -import { - L2StandardBridgeInterop, - InvalidDecimals, - InvalidLegacyERC20Address, - InvalidSuperchainERC20Address, - InvalidTokenPair, - IOptimismERC20Factory, - MintableAndBurnable -} from "src/L2/L2StandardBridgeInterop.sol"; -import { IERC20Metadata } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; -import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; -import { IOptimismMintableERC20 } from "src/universal/IOptimismMintableERC20.sol"; - +// Libraries // TODO: Replace Predeploys.OPTIMISM_SUPERCHAIN_ERC20_FACTORY with optimismSuperchainERC20Factory import { Predeploys } from "src/libraries/Predeploys.sol"; +// Interfaces +import { IL2StandardBridgeInterop, IMintableAndBurnable } from "src/L2/interfaces/IL2StandardBridgeInterop.sol"; +import { IERC20Metadata } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; +import { IOptimismMintableERC20 } from "src/universal/interfaces/IOptimismMintableERC20.sol"; +import { ILegacyMintableERC20 } from "src/universal/OptimismMintableERC20.sol"; +import { IOptimismERC20Factory } from "src/L2/interfaces/IOptimismERC20Factory.sol"; + contract L2StandardBridgeInterop_Test is Bridge_Initializer { /// @notice Emitted when a conversion is made. event Converted(address indexed from, address indexed to, address indexed caller, uint256 amount); @@ -76,7 +71,7 @@ contract L2StandardBridgeInterop_LegacyToSuper_Test is L2StandardBridgeInterop_T // Mock `_from` to be a legacy address _mockInterface(_from, type(IERC165).interfaceId, true); - _mockInterface(_from, type(IOptimismMintableERC20).interfaceId, true); + _mockInterface(_from, type(ILegacyMintableERC20).interfaceId, true); } /// @notice Test that the `convert` function with different decimals reverts @@ -101,7 +96,7 @@ contract L2StandardBridgeInterop_LegacyToSuper_Test is L2StandardBridgeInterop_T _mockDecimals(_to, _decimalsTo); // Expect the revert with `InvalidDecimals` selector - vm.expectRevert(InvalidDecimals.selector); + vm.expectRevert(IL2StandardBridgeInterop.InvalidDecimals.selector); // Act l2StandardBridge.convert(_from, _to, _amount); @@ -116,7 +111,7 @@ contract L2StandardBridgeInterop_LegacyToSuper_Test is L2StandardBridgeInterop_T _mockDeployments(address(l2OptimismMintableERC20Factory), _from, address(0)); // Expect the revert with `InvalidLegacyERC20Address` selector - vm.expectRevert(InvalidLegacyERC20Address.selector); + vm.expectRevert(IL2StandardBridgeInterop.InvalidLegacyERC20Address.selector); // Act l2StandardBridge.convert(_from, _to, _amount); @@ -141,10 +136,10 @@ contract L2StandardBridgeInterop_LegacyToSuper_Test is L2StandardBridgeInterop_T _mockDeployments(address(l2OptimismMintableERC20Factory), _from, _remoteToken); // Mock the superchain factory to return address(0) - _mockDeployments(Predeploys.OPTIMISM_SUPERCHAIN_ERC20_FACTORY, _to, address(0)); + _mockDeployments(address(l2OptimismSuperchainERC20Factory), _to, address(0)); // Expect the revert with `InvalidSuperchainERC20Address` selector - vm.expectRevert(InvalidSuperchainERC20Address.selector); + vm.expectRevert(IL2StandardBridgeInterop.InvalidSuperchainERC20Address.selector); // Act l2StandardBridge.convert(_from, _to, _amount); @@ -172,10 +167,10 @@ contract L2StandardBridgeInterop_LegacyToSuper_Test is L2StandardBridgeInterop_T _mockDeployments(address(l2OptimismMintableERC20Factory), _from, _fromRemoteToken); // Mock the superchain factory to return `_toRemoteToken` - _mockDeployments(Predeploys.OPTIMISM_SUPERCHAIN_ERC20_FACTORY, _to, _toRemoteToken); + _mockDeployments(address(l2OptimismSuperchainERC20Factory), _to, _toRemoteToken); // Expect the revert with `InvalidTokenPair` selector - vm.expectRevert(InvalidTokenPair.selector); + vm.expectRevert(IL2StandardBridgeInterop.InvalidTokenPair.selector); // Act l2StandardBridge.convert(_from, _to, _amount); @@ -199,15 +194,17 @@ contract L2StandardBridgeInterop_LegacyToSuper_Test is L2StandardBridgeInterop_T // Mock the legacy and superchain factory to return `_remoteToken` _mockDeployments(address(l2OptimismMintableERC20Factory), _from, _remoteToken); - _mockDeployments(Predeploys.OPTIMISM_SUPERCHAIN_ERC20_FACTORY, _to, _remoteToken); + _mockDeployments(address(l2OptimismSuperchainERC20Factory), _to, _remoteToken); // Expect the `Converted` event to be emitted vm.expectEmit(address(l2StandardBridge)); emit Converted(_from, _to, _caller, _amount); // Mock and expect the `burn` and `mint` functions - _mockAndExpect(_from, abi.encodeWithSelector(MintableAndBurnable.burn.selector, _caller, _amount), abi.encode()); - _mockAndExpect(_to, abi.encodeWithSelector(MintableAndBurnable.mint.selector, _caller, _amount), abi.encode()); + _mockAndExpect( + _from, abi.encodeWithSelector(IMintableAndBurnable.burn.selector, _caller, _amount), abi.encode() + ); + _mockAndExpect(_to, abi.encodeWithSelector(IMintableAndBurnable.mint.selector, _caller, _amount), abi.encode()); // Act vm.prank(_caller); @@ -226,6 +223,11 @@ contract L2StandardBridgeInterop_SuperToLegacy_Test is L2StandardBridgeInterop_T // Mock same decimals _mockDecimals(_from, 18); _mockDecimals(_to, 18); + + // Mock `_from` so it is not a LegacyMintableERC20 address + _mockInterface(_from, type(IERC165).interfaceId, true); + _mockInterface(_from, type(ILegacyMintableERC20).interfaceId, false); + _mockInterface(_from, type(IOptimismMintableERC20).interfaceId, false); } /// @notice Test that the `convert` function with different decimals reverts @@ -250,7 +252,7 @@ contract L2StandardBridgeInterop_SuperToLegacy_Test is L2StandardBridgeInterop_T _mockDecimals(_to, _decimalsTo); // Expect the revert with `InvalidDecimals` selector - vm.expectRevert(InvalidDecimals.selector); + vm.expectRevert(IL2StandardBridgeInterop.InvalidDecimals.selector); // Act l2StandardBridge.convert(_from, _to, _amount); @@ -265,7 +267,7 @@ contract L2StandardBridgeInterop_SuperToLegacy_Test is L2StandardBridgeInterop_T _mockDeployments(address(l2OptimismMintableERC20Factory), _to, address(0)); // Expect the revert with `InvalidLegacyERC20Address` selector - vm.expectRevert(InvalidLegacyERC20Address.selector); + vm.expectRevert(IL2StandardBridgeInterop.InvalidLegacyERC20Address.selector); // Act l2StandardBridge.convert(_from, _to, _amount); @@ -290,10 +292,10 @@ contract L2StandardBridgeInterop_SuperToLegacy_Test is L2StandardBridgeInterop_T _mockDeployments(address(l2OptimismMintableERC20Factory), _to, _remoteToken); // Mock the superchain factory to return address(0) - _mockDeployments(Predeploys.OPTIMISM_SUPERCHAIN_ERC20_FACTORY, _from, address(0)); + _mockDeployments(address(l2OptimismSuperchainERC20Factory), _from, address(0)); // Expect the revert with `InvalidSuperchainERC20Address` selector - vm.expectRevert(InvalidSuperchainERC20Address.selector); + vm.expectRevert(IL2StandardBridgeInterop.InvalidSuperchainERC20Address.selector); // Act l2StandardBridge.convert(_from, _to, _amount); @@ -321,10 +323,10 @@ contract L2StandardBridgeInterop_SuperToLegacy_Test is L2StandardBridgeInterop_T _mockDeployments(address(l2OptimismMintableERC20Factory), _to, _fromRemoteToken); // Mock the superchain factory to return `_toRemoteToken` - _mockDeployments(Predeploys.OPTIMISM_SUPERCHAIN_ERC20_FACTORY, _from, _toRemoteToken); + _mockDeployments(address(l2OptimismSuperchainERC20Factory), _from, _toRemoteToken); // Expect the revert with `InvalidTokenPair` selector - vm.expectRevert(InvalidTokenPair.selector); + vm.expectRevert(IL2StandardBridgeInterop.InvalidTokenPair.selector); // Act l2StandardBridge.convert(_from, _to, _amount); @@ -348,15 +350,17 @@ contract L2StandardBridgeInterop_SuperToLegacy_Test is L2StandardBridgeInterop_T // Mock the legacy and superchain factory to return `_remoteToken` _mockDeployments(address(l2OptimismMintableERC20Factory), _to, _remoteToken); - _mockDeployments(Predeploys.OPTIMISM_SUPERCHAIN_ERC20_FACTORY, _from, _remoteToken); + _mockDeployments(address(l2OptimismSuperchainERC20Factory), _from, _remoteToken); // Expect the `Converted` event to be emitted vm.expectEmit(address(l2StandardBridge)); emit Converted(_from, _to, _caller, _amount); // Mock and expect the `burn` and `mint` functions - _mockAndExpect(_from, abi.encodeWithSelector(MintableAndBurnable.burn.selector, _caller, _amount), abi.encode()); - _mockAndExpect(_to, abi.encodeWithSelector(MintableAndBurnable.mint.selector, _caller, _amount), abi.encode()); + _mockAndExpect( + _from, abi.encodeWithSelector(IMintableAndBurnable.burn.selector, _caller, _amount), abi.encode() + ); + _mockAndExpect(_to, abi.encodeWithSelector(IMintableAndBurnable.mint.selector, _caller, _amount), abi.encode()); // Act vm.prank(_caller); diff --git a/packages/contracts-bedrock/test/L2/L2ToL2CrossDomainMessenger.t.sol b/packages/contracts-bedrock/test/L2/L2ToL2CrossDomainMessenger.t.sol index 1bf394d1a0d5b..66b0b7e83209d 100644 --- a/packages/contracts-bedrock/test/L2/L2ToL2CrossDomainMessenger.t.sol +++ b/packages/contracts-bedrock/test/L2/L2ToL2CrossDomainMessenger.t.sol @@ -194,8 +194,12 @@ contract L2ToL2CrossDomainMessengerTest is Test { ) external { + // Ensure that the target contract is not a Forge contract. + assumeNotForgeAddress(_target); + // Ensure that the target contract is not CrossL2Inbox or L2ToL2CrossDomainMessenger - vm.assume(_target != Predeploys.CROSS_L2_INBOX && _target != Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER); + vm.assume(_target != Predeploys.CROSS_L2_INBOX); + vm.assume(_target != Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER); // Ensure that the target call is payable if value is sent if (_value > 0) assumePayable(_target); diff --git a/packages/contracts-bedrock/test/L2/OptimismSuperchainERC20.t.sol b/packages/contracts-bedrock/test/L2/OptimismSuperchainERC20.t.sol index 84580fdd8687b..b8de1468421ba 100644 --- a/packages/contracts-bedrock/test/L2/OptimismSuperchainERC20.t.sol +++ b/packages/contracts-bedrock/test/L2/OptimismSuperchainERC20.t.sol @@ -3,25 +3,25 @@ pragma solidity 0.8.25; // Testing utilities import { Test } from "forge-std/Test.sol"; +import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; // Libraries import { Predeploys } from "src/libraries/Predeploys.sol"; import { IERC20 } from "@openzeppelin/contracts-v5/token/ERC20/IERC20.sol"; -import { IL2ToL2CrossDomainMessenger } from "src/L2/IL2ToL2CrossDomainMessenger.sol"; +import { IL2ToL2CrossDomainMessenger } from "src/L2/interfaces/IL2ToL2CrossDomainMessenger.sol"; import { ERC1967Proxy } from "@openzeppelin/contracts-v5/proxy/ERC1967/ERC1967Proxy.sol"; import { Initializable } from "@openzeppelin/contracts-v5/proxy/utils/Initializable.sol"; import { IERC165 } from "@openzeppelin/contracts-v5/utils/introspection/IERC165.sol"; +import { IBeacon } from "@openzeppelin/contracts-v5/proxy/beacon/IBeacon.sol"; +import { BeaconProxy } from "@openzeppelin/contracts-v5/proxy/beacon/BeaconProxy.sol"; // Target contract import { - OptimismSuperchainERC20, - IOptimismSuperchainERC20Extension, - CallerNotL2ToL2CrossDomainMessenger, - InvalidCrossDomainSender, - OnlyBridge, - ZeroAddress + OptimismSuperchainERC20, IOptimismSuperchainERC20Extension, OnlyBridge } from "src/L2/OptimismSuperchainERC20.sol"; -import { ISuperchainERC20Extensions } from "src/L2/ISuperchainERC20.sol"; + +// SuperchainERC20 Interfaces +import { ISuperchainERC20Extensions, ISuperchainERC20Errors } from "src/L2/interfaces/ISuperchainERC20.sol"; /// @title OptimismSuperchainERC20Test /// @notice Contract for testing the OptimismSuperchainERC20 contract. @@ -40,9 +40,32 @@ contract OptimismSuperchainERC20Test is Test { /// @notice Sets up the test suite. function setUp() public { superchainERC20Impl = new OptimismSuperchainERC20(); + + // Deploy the OptimismSuperchainERC20Beacon contract + _deployBeacon(); + superchainERC20 = _deploySuperchainERC20Proxy(REMOTE_TOKEN, NAME, SYMBOL, DECIMALS); } + /// @notice Deploy the OptimismSuperchainERC20Beacon predeploy contract + function _deployBeacon() internal { + // Deploy the OptimismSuperchainERC20Beacon implementation + address _addr = Predeploys.OPTIMISM_SUPERCHAIN_ERC20_BEACON; + address _impl = Predeploys.predeployToCodeNamespace(_addr); + vm.etch(_impl, vm.getDeployedCode("OptimismSuperchainERC20Beacon.sol:OptimismSuperchainERC20Beacon")); + + // Deploy the ERC1967Proxy contract at the Predeploy + bytes memory code = vm.getDeployedCode("universal/Proxy.sol:Proxy"); + vm.etch(_addr, code); + EIP1967Helper.setAdmin(_addr, Predeploys.PROXY_ADMIN); + EIP1967Helper.setImplementation(_addr, _impl); + + // Mock implementation address + vm.mockCall( + _impl, abi.encodeWithSelector(IBeacon.implementation.selector), abi.encode(address(superchainERC20Impl)) + ); + } + /// @notice Helper function to deploy a proxy of the OptimismSuperchainERC20 contract. function _deploySuperchainERC20Proxy( address _remoteToken, @@ -55,9 +78,8 @@ contract OptimismSuperchainERC20Test is Test { { return OptimismSuperchainERC20( address( - // TODO: Use the SuperchainERC20 Beacon Proxy - new ERC1967Proxy( - address(superchainERC20Impl), + new BeaconProxy( + Predeploys.OPTIMISM_SUPERCHAIN_ERC20_BEACON, abi.encodeCall(OptimismSuperchainERC20.initialize, (_remoteToken, _name, _symbol, _decimals)) ) ) @@ -110,7 +132,7 @@ contract OptimismSuperchainERC20Test is Test { /// @notice Tests the `mint` function reverts when the amount is zero. function testFuzz_mint_zeroAddressTo_reverts(uint256 _amount) public { // Expect the revert with `ZeroAddress` selector - vm.expectRevert(ZeroAddress.selector); + vm.expectRevert(ISuperchainERC20Errors.ZeroAddress.selector); // Call the `mint` function with the zero address vm.prank(BRIDGE); @@ -127,11 +149,11 @@ contract OptimismSuperchainERC20Test is Test { uint256 _toBalanceBefore = superchainERC20.balanceOf(_to); // Look for the emit of the `Transfer` event - vm.expectEmit(true, true, true, true, address(superchainERC20)); + vm.expectEmit(address(superchainERC20)); emit IERC20.Transfer(ZERO_ADDRESS, _to, _amount); // Look for the emit of the `Mint` event - vm.expectEmit(true, true, true, true, address(superchainERC20)); + vm.expectEmit(address(superchainERC20)); emit IOptimismSuperchainERC20Extension.Mint(_to, _amount); // Call the `mint` function with the bridge caller @@ -159,7 +181,7 @@ contract OptimismSuperchainERC20Test is Test { /// @notice Tests the `burn` function reverts when the amount is zero. function testFuzz_burn_zeroAddressFrom_reverts(uint256 _amount) public { // Expect the revert with `ZeroAddress` selector - vm.expectRevert(ZeroAddress.selector); + vm.expectRevert(ISuperchainERC20Errors.ZeroAddress.selector); // Call the `burn` function with the zero address vm.prank(BRIDGE); @@ -180,11 +202,11 @@ contract OptimismSuperchainERC20Test is Test { uint256 _fromBalanceBefore = superchainERC20.balanceOf(_from); // Look for the emit of the `Transfer` event - vm.expectEmit(true, true, true, true, address(superchainERC20)); + vm.expectEmit(address(superchainERC20)); emit IERC20.Transfer(_from, ZERO_ADDRESS, _amount); // Look for the emit of the `Burn` event - vm.expectEmit(true, true, true, true, address(superchainERC20)); + vm.expectEmit(address(superchainERC20)); emit IOptimismSuperchainERC20Extension.Burn(_from, _amount); // Call the `burn` function with the bridge caller @@ -199,7 +221,7 @@ contract OptimismSuperchainERC20Test is Test { /// @notice Tests the `sendERC20` function reverts when the `_to` address is the zero address. function testFuzz_sendERC20_zeroAddressTo_reverts(uint256 _amount, uint256 _chainId) public { // Expect the revert with `ZeroAddress` selector - vm.expectRevert(ZeroAddress.selector); + vm.expectRevert(ISuperchainERC20Errors.ZeroAddress.selector); // Call the `sendERC20` function with the zero address vm.prank(BRIDGE); @@ -222,11 +244,11 @@ contract OptimismSuperchainERC20Test is Test { uint256 _senderBalanceBefore = superchainERC20.balanceOf(_sender); // Look for the emit of the `Transfer` event - vm.expectEmit(true, true, true, true, address(superchainERC20)); + vm.expectEmit(address(superchainERC20)); emit IERC20.Transfer(_sender, ZERO_ADDRESS, _amount); // Look for the emit of the `SendERC20` event - vm.expectEmit(true, true, true, true, address(superchainERC20)); + vm.expectEmit(address(superchainERC20)); emit ISuperchainERC20Extensions.SendERC20(_sender, _to, _amount, _chainId); // Mock the call over the `sendMessage` function and expect it to be called properly @@ -255,7 +277,7 @@ contract OptimismSuperchainERC20Test is Test { vm.assume(_to != ZERO_ADDRESS); // Expect the revert with `CallerNotL2ToL2CrossDomainMessenger` selector - vm.expectRevert(CallerNotL2ToL2CrossDomainMessenger.selector); + vm.expectRevert(ISuperchainERC20Errors.CallerNotL2ToL2CrossDomainMessenger.selector); // Call the `relayERC20` function with the non-messenger caller vm.prank(_caller); @@ -282,30 +304,13 @@ contract OptimismSuperchainERC20Test is Test { ); // Expect the revert with `InvalidCrossDomainSender` selector - vm.expectRevert(InvalidCrossDomainSender.selector); + vm.expectRevert(ISuperchainERC20Errors.InvalidCrossDomainSender.selector); // Call the `relayERC20` function with the sender caller vm.prank(MESSENGER); superchainERC20.relayERC20(_crossDomainMessageSender, _to, _amount); } - /// @notice Tests the `relayERC20` function reverts when the `_to` address is the zero address. - function testFuzz_relayERC20_zeroAddressTo_reverts(uint256 _amount) public { - // Expect the revert with `ZeroAddress` selector - vm.expectRevert(ZeroAddress.selector); - - // Mock the call over the `crossDomainMessageSender` function setting the same address as value - vm.mockCall( - MESSENGER, - abi.encodeWithSelector(IL2ToL2CrossDomainMessenger.crossDomainMessageSender.selector), - abi.encode(address(superchainERC20)) - ); - - // Call the `relayERC20` function with the zero address - vm.prank(MESSENGER); - superchainERC20.relayERC20({ _from: ZERO_ADDRESS, _to: ZERO_ADDRESS, _amount: _amount }); - } - /// @notice Tests the `relayERC20` mints the proper amount and emits the `RelayERC20` event. function testFuzz_relayERC20_succeeds(address _from, address _to, uint256 _amount, uint256 _source) public { vm.assume(_from != ZERO_ADDRESS); @@ -330,11 +335,11 @@ contract OptimismSuperchainERC20Test is Test { uint256 _toBalanceBefore = superchainERC20.balanceOf(_to); // Look for the emit of the `Transfer` event - vm.expectEmit(true, true, true, true, address(superchainERC20)); + vm.expectEmit(address(superchainERC20)); emit IERC20.Transfer(ZERO_ADDRESS, _to, _amount); // Look for the emit of the `RelayERC20` event - vm.expectEmit(true, true, true, true, address(superchainERC20)); + vm.expectEmit(address(superchainERC20)); emit ISuperchainERC20Extensions.RelayERC20(_from, _to, _amount, _source); // Call the `relayERC20` function with the messenger caller diff --git a/packages/contracts-bedrock/test/L2/OptimismSuperchainERC20Factory.t.sol b/packages/contracts-bedrock/test/L2/OptimismSuperchainERC20Factory.t.sol new file mode 100644 index 0000000000000..3951ebf7452e4 --- /dev/null +++ b/packages/contracts-bedrock/test/L2/OptimismSuperchainERC20Factory.t.sol @@ -0,0 +1,111 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.25; + +// Testing utilities +import { Test } from "forge-std/Test.sol"; +import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; + +// Libraries +import { Predeploys } from "src/libraries/Predeploys.sol"; +import { CREATE3, Bytes32AddressLib } from "@rari-capital/solmate/src/utils/CREATE3.sol"; +import { IBeacon } from "@openzeppelin/contracts-v5/proxy/beacon/IBeacon.sol"; + +// Target contract +import { OptimismSuperchainERC20Factory, OptimismSuperchainERC20 } from "src/L2/OptimismSuperchainERC20Factory.sol"; + +/// @title OptimismSuperchainERC20FactoryTest +/// @notice Contract for testing the OptimismSuperchainERC20Factory contract. +contract OptimismSuperchainERC20FactoryTest is Test { + using Bytes32AddressLib for bytes32; + + OptimismSuperchainERC20 public superchainERC20Impl; + OptimismSuperchainERC20Factory public superchainERC20Factory; + + /// @notice Sets up the test suite. + function setUp() public { + superchainERC20Impl = new OptimismSuperchainERC20(); + + // Deploy the OptimismSuperchainERC20Beacon contract + _deployBeacon(); + + superchainERC20Factory = new OptimismSuperchainERC20Factory(); + } + + /// @notice Deploy the OptimismSuperchainERC20Beacon predeploy contract + function _deployBeacon() internal { + // Deploy the OptimismSuperchainERC20Beacon implementation + address _addr = Predeploys.OPTIMISM_SUPERCHAIN_ERC20_BEACON; + address _impl = Predeploys.predeployToCodeNamespace(_addr); + vm.etch(_impl, vm.getDeployedCode("OptimismSuperchainERC20Beacon.sol:OptimismSuperchainERC20Beacon")); + + // Deploy the ERC1967Proxy contract at the Predeploy + bytes memory code = vm.getDeployedCode("universal/Proxy.sol:Proxy"); + vm.etch(_addr, code); + EIP1967Helper.setAdmin(_addr, Predeploys.PROXY_ADMIN); + EIP1967Helper.setImplementation(_addr, _impl); + + // Mock implementation address + vm.mockCall( + _impl, abi.encodeWithSelector(IBeacon.implementation.selector), abi.encode(address(superchainERC20Impl)) + ); + } + + /// @notice Test that calling `deploy` with valid parameters succeeds. + function test_deploy_succeeds( + address _caller, + address _remoteToken, + string memory _name, + string memory _symbol, + uint8 _decimals + ) + public + { + // Arrange + bytes32 salt = keccak256(abi.encode(_remoteToken, _name, _symbol, _decimals)); + address deployment = _calculateTokenAddress(salt, address(superchainERC20Factory)); + + vm.expectEmit(address(superchainERC20Factory)); + emit OptimismSuperchainERC20Factory.OptimismSuperchainERC20Created(deployment, _remoteToken, _caller); + + // Act + vm.prank(_caller); + address addr = superchainERC20Factory.deploy(_remoteToken, _name, _symbol, _decimals); + + // Assert + assertTrue(addr == deployment); + assertTrue(OptimismSuperchainERC20(deployment).decimals() == _decimals); + assertTrue(OptimismSuperchainERC20(deployment).remoteToken() == _remoteToken); + assertEq(OptimismSuperchainERC20(deployment).name(), _name); + assertEq(OptimismSuperchainERC20(deployment).symbol(), _symbol); + assertEq(superchainERC20Factory.deployments(deployment), _remoteToken); + } + + /// @notice Test that calling `deploy` with the same parameters twice reverts. + function test_deploy_sameTwice_reverts( + address _caller, + address _remoteToken, + string memory _name, + string memory _symbol, + uint8 _decimals + ) + external + { + // Arrange + vm.prank(_caller); + superchainERC20Factory.deploy(_remoteToken, _name, _symbol, _decimals); + + vm.expectRevert(bytes("DEPLOYMENT_FAILED")); + + // Act + vm.prank(_caller); + superchainERC20Factory.deploy(_remoteToken, _name, _symbol, _decimals); + } + + /// @notice Precalculates the address of the token contract using CREATE3. + function _calculateTokenAddress(bytes32 _salt, address _deployer) internal pure returns (address) { + address proxy = + keccak256(abi.encodePacked(bytes1(0xFF), _deployer, _salt, CREATE3.PROXY_BYTECODE_HASH)).fromLast20Bytes(); + + return keccak256(abi.encodePacked(hex"d694", proxy, hex"01")).fromLast20Bytes(); + } +} diff --git a/packages/contracts-bedrock/test/L2/SequencerFeeVault.t.sol b/packages/contracts-bedrock/test/L2/SequencerFeeVault.t.sol index da01248c585ec..1367e00bbc9cf 100644 --- a/packages/contracts-bedrock/test/L2/SequencerFeeVault.t.sol +++ b/packages/contracts-bedrock/test/L2/SequencerFeeVault.t.sol @@ -1,24 +1,20 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -// Testing utilities +// Testing import { CommonTest } from "test/setup/CommonTest.sol"; import { Reverter } from "test/mocks/Callers.sol"; -import { StandardBridge } from "src/universal/StandardBridge.sol"; import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; -import { L2ToL1MessagePasser } from "src/L2/L2ToL1MessagePasser.sol"; -import { Hashing } from "src/libraries/Hashing.sol"; -import { Types } from "src/libraries/Types.sol"; - -// Libraries -import { Predeploys } from "src/libraries/Predeploys.sol"; -// Target contract dependencies +// Contracts import { FeeVault } from "src/universal/FeeVault.sol"; - -// Target contract import { SequencerFeeVault } from "src/L2/SequencerFeeVault.sol"; +// Libraries +import { Hashing } from "src/libraries/Hashing.sol"; +import { Types } from "src/libraries/Types.sol"; +import { Predeploys } from "src/libraries/Predeploys.sol"; + contract SequencerFeeVault_Test is CommonTest { address recipient; diff --git a/packages/contracts-bedrock/test/L2/SuperchainERC20.t.sol b/packages/contracts-bedrock/test/L2/SuperchainERC20.t.sol new file mode 100644 index 0000000000000..66b20c1b911af --- /dev/null +++ b/packages/contracts-bedrock/test/L2/SuperchainERC20.t.sol @@ -0,0 +1,223 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.25; + +// Testing utilities +import { Test } from "forge-std/Test.sol"; + +// Libraries +import { Predeploys } from "src/libraries/Predeploys.sol"; +import { IERC20 } from "@openzeppelin/contracts-v5/token/ERC20/IERC20.sol"; +import { IL2ToL2CrossDomainMessenger } from "src/L2/interfaces/IL2ToL2CrossDomainMessenger.sol"; + +// Target contract +import { SuperchainERC20 } from "src/L2/SuperchainERC20.sol"; +import { ISuperchainERC20Extensions, ISuperchainERC20Errors } from "src/L2/interfaces/ISuperchainERC20.sol"; + +/// @notice Mock contract for the SuperchainERC20 contract so tests can mint tokens. +contract SuperchainERC20Mock is SuperchainERC20 { + string private _name; + string private _symbol; + uint8 private _decimals; + + constructor(string memory __name, string memory __symbol, uint8 __decimals) { + _name = __name; + _symbol = __symbol; + _decimals = __decimals; + } + + function mint(address _account, uint256 _amount) public { + _mint(_account, _amount); + } + + function name() public view virtual override returns (string memory) { + return _name; + } + + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + function decimals() public view virtual override returns (uint8) { + return _decimals; + } +} +/// @title SuperchainERC20Test +/// @notice Contract for testing the SuperchainERC20 contract. + +contract SuperchainERC20Test is Test { + address internal constant ZERO_ADDRESS = address(0); + string internal constant NAME = "SuperchainERC20"; + string internal constant SYMBOL = "SCE"; + uint8 internal constant DECIMALS = 18; + address internal constant MESSENGER = Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER; + + SuperchainERC20 public superchainERC20Impl; + SuperchainERC20Mock public superchainERC20; + + /// @notice Sets up the test suite. + function setUp() public { + superchainERC20 = new SuperchainERC20Mock(NAME, SYMBOL, DECIMALS); + } + + /// @notice Helper function to setup a mock and expect a call to it. + function _mockAndExpect(address _receiver, bytes memory _calldata, bytes memory _returned) internal { + vm.mockCall(_receiver, _calldata, _returned); + vm.expectCall(_receiver, _calldata); + } + + /// @notice Test that the contract's `constructor` sets the correct values. + function test_constructor_succeeds() public view { + assertEq(superchainERC20.name(), NAME); + assertEq(superchainERC20.symbol(), SYMBOL); + assertEq(superchainERC20.decimals(), DECIMALS); + } + + /// @notice Tests the `sendERC20` function reverts when the `_to` address is the zero address. + function testFuzz_sendERC20_zeroAddressTo_reverts(uint256 _amount, uint256 _chainId) public { + // Expect the revert with `ZeroAddress` selector + vm.expectRevert(ISuperchainERC20Errors.ZeroAddress.selector); + + // Call the `sendERC20` function with the zero address + superchainERC20.sendERC20({ _to: ZERO_ADDRESS, _amount: _amount, _chainId: _chainId }); + } + + /// @notice Tests the `sendERC20` function burns the sender tokens, sends the message, and emits the `SendERC20` + /// event. + function testFuzz_sendERC20_succeeds(address _sender, address _to, uint256 _amount, uint256 _chainId) external { + // Ensure `_sender` is not the zero address + vm.assume(_sender != ZERO_ADDRESS); + vm.assume(_to != ZERO_ADDRESS); + + // Mint some tokens to the sender so then they can be sent + superchainERC20.mint(_sender, _amount); + + // Get the total supply and balance of `_sender` before the send to compare later on the assertions + uint256 _totalSupplyBefore = superchainERC20.totalSupply(); + uint256 _senderBalanceBefore = superchainERC20.balanceOf(_sender); + + // Look for the emit of the `Transfer` event + vm.expectEmit(address(superchainERC20)); + emit IERC20.Transfer(_sender, ZERO_ADDRESS, _amount); + + // Look for the emit of the `SendERC20` event + vm.expectEmit(address(superchainERC20)); + emit ISuperchainERC20Extensions.SendERC20(_sender, _to, _amount, _chainId); + + // Mock the call over the `sendMessage` function and expect it to be called properly + bytes memory _message = abi.encodeCall(superchainERC20.relayERC20, (_sender, _to, _amount)); + _mockAndExpect( + MESSENGER, + abi.encodeWithSelector( + IL2ToL2CrossDomainMessenger.sendMessage.selector, _chainId, address(superchainERC20), _message + ), + abi.encode("") + ); + + // Call the `sendERC20` function + vm.prank(_sender); + superchainERC20.sendERC20(_to, _amount, _chainId); + + // Check the total supply and balance of `_sender` after the send were updated correctly + assertEq(superchainERC20.totalSupply(), _totalSupplyBefore - _amount); + assertEq(superchainERC20.balanceOf(_sender), _senderBalanceBefore - _amount); + } + + /// @notice Tests the `relayERC20` function reverts when the caller is not the L2ToL2CrossDomainMessenger. + function testFuzz_relayERC20_notMessenger_reverts(address _caller, address _to, uint256 _amount) public { + // Ensure the caller is not the messenger + vm.assume(_caller != MESSENGER); + vm.assume(_to != ZERO_ADDRESS); + + // Expect the revert with `CallerNotL2ToL2CrossDomainMessenger` selector + vm.expectRevert(ISuperchainERC20Errors.CallerNotL2ToL2CrossDomainMessenger.selector); + + // Call the `relayERC20` function with the non-messenger caller + vm.prank(_caller); + superchainERC20.relayERC20(_caller, _to, _amount); + } + + /// @notice Tests the `relayERC20` function reverts when the `crossDomainMessageSender` that sent the message is not + /// the same SuperchainERC20 address. + function testFuzz_relayERC20_notCrossDomainSender_reverts( + address _crossDomainMessageSender, + address _to, + uint256 _amount + ) + public + { + vm.assume(_to != ZERO_ADDRESS); + vm.assume(_crossDomainMessageSender != address(superchainERC20)); + + // Mock the call over the `crossDomainMessageSender` function setting a wrong sender + vm.mockCall( + MESSENGER, + abi.encodeWithSelector(IL2ToL2CrossDomainMessenger.crossDomainMessageSender.selector), + abi.encode(_crossDomainMessageSender) + ); + + // Expect the revert with `InvalidCrossDomainSender` selector + vm.expectRevert(ISuperchainERC20Errors.InvalidCrossDomainSender.selector); + + // Call the `relayERC20` function with the sender caller + vm.prank(MESSENGER); + superchainERC20.relayERC20(_crossDomainMessageSender, _to, _amount); + } + + /// @notice Tests the `relayERC20` mints the proper amount and emits the `RelayERC20` event. + function testFuzz_relayERC20_succeeds(address _from, address _to, uint256 _amount, uint256 _source) public { + vm.assume(_from != ZERO_ADDRESS); + vm.assume(_to != ZERO_ADDRESS); + + // Mock the call over the `crossDomainMessageSender` function setting the same address as value + _mockAndExpect( + MESSENGER, + abi.encodeWithSelector(IL2ToL2CrossDomainMessenger.crossDomainMessageSender.selector), + abi.encode(address(superchainERC20)) + ); + + // Mock the call over the `crossDomainMessageSource` function setting the source chain ID as value + _mockAndExpect( + MESSENGER, + abi.encodeWithSelector(IL2ToL2CrossDomainMessenger.crossDomainMessageSource.selector), + abi.encode(_source) + ); + + // Get the total supply and balance of `_to` before the relay to compare later on the assertions + uint256 _totalSupplyBefore = superchainERC20.totalSupply(); + uint256 _toBalanceBefore = superchainERC20.balanceOf(_to); + + // Look for the emit of the `Transfer` event + vm.expectEmit(address(superchainERC20)); + emit IERC20.Transfer(ZERO_ADDRESS, _to, _amount); + + // Look for the emit of the `RelayERC20` event + vm.expectEmit(address(superchainERC20)); + emit ISuperchainERC20Extensions.RelayERC20(_from, _to, _amount, _source); + + // Call the `relayERC20` function with the messenger caller + vm.prank(MESSENGER); + superchainERC20.relayERC20(_from, _to, _amount); + + // Check the total supply and balance of `_to` after the relay were updated correctly + assertEq(superchainERC20.totalSupply(), _totalSupplyBefore + _amount); + assertEq(superchainERC20.balanceOf(_to), _toBalanceBefore + _amount); + } + + /// @notice Tests the `name` function always returns the correct value. + function testFuzz_name_succeeds(string memory _name) public { + SuperchainERC20 _newSuperchainERC20 = new SuperchainERC20Mock(_name, SYMBOL, DECIMALS); + assertEq(_newSuperchainERC20.name(), _name); + } + + /// @notice Tests the `symbol` function always returns the correct value. + function testFuzz_symbol_succeeds(string memory _symbol) public { + SuperchainERC20 _newSuperchainERC20 = new SuperchainERC20Mock(NAME, _symbol, DECIMALS); + assertEq(_newSuperchainERC20.symbol(), _symbol); + } + + /// @notice Tests the `decimals` function always returns the correct value. + function testFuzz_decimals_succeeds(uint8 _decimals) public { + SuperchainERC20 _newSuperchainERC20 = new SuperchainERC20Mock(NAME, SYMBOL, _decimals); + assertEq(_newSuperchainERC20.decimals(), _decimals); + } +} diff --git a/packages/contracts-bedrock/test/L2/SuperchainWETH.t.sol b/packages/contracts-bedrock/test/L2/SuperchainWETH.t.sol index 3bee1fc74b7d8..361e982d73249 100644 --- a/packages/contracts-bedrock/test/L2/SuperchainWETH.t.sol +++ b/packages/contracts-bedrock/test/L2/SuperchainWETH.t.sol @@ -1,14 +1,16 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -// Testing utilities +// Testing import { CommonTest } from "test/setup/CommonTest.sol"; -// Contract imports -import { Unauthorized, NotCustomGasToken } from "src/libraries/errors/CommonErrors.sol"; +// Libraries import { Predeploys } from "src/libraries/Predeploys.sol"; -import { IL2ToL2CrossDomainMessenger } from "src/L2/IL2ToL2CrossDomainMessenger.sol"; -import { ETHLiquidity } from "src/L2/ETHLiquidity.sol"; +import { Unauthorized, NotCustomGasToken } from "src/libraries/errors/CommonErrors.sol"; + +// Interfaces +import { IL2ToL2CrossDomainMessenger } from "src/L2/interfaces/IL2ToL2CrossDomainMessenger.sol"; +import { IETHLiquidity } from "src/L2/interfaces/IETHLiquidity.sol"; /// @title SuperchainWETH_Test /// @notice Contract for testing the SuperchainWETH contract. @@ -134,6 +136,8 @@ contract SuperchainWETH_Test is CommonTest { { // Assume vm.assume(_chainId != block.chainid); + vm.assume(_caller != address(ethLiquidity)); + vm.assume(_caller != address(superchainWeth)); _amount = bound(_amount, 0, type(uint248).max - 1); // Arrange @@ -146,7 +150,7 @@ contract SuperchainWETH_Test is CommonTest { emit Transfer(_caller, address(0), _amount); vm.expectEmit(address(superchainWeth)); emit SendERC20(_caller, _recipient, _amount, _chainId); - vm.expectCall(Predeploys.ETH_LIQUIDITY, abi.encodeCall(ETHLiquidity.burn, ()), 1); + vm.expectCall(Predeploys.ETH_LIQUIDITY, abi.encodeCall(IETHLiquidity.burn, ()), 1); vm.expectCall( Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER, abi.encodeCall( @@ -188,7 +192,7 @@ contract SuperchainWETH_Test is CommonTest { emit Transfer(alice, address(0), _amount); vm.expectEmit(address(superchainWeth)); emit SendERC20(alice, bob, _amount, _chainId); - vm.expectCall(Predeploys.ETH_LIQUIDITY, abi.encodeCall(ETHLiquidity.burn, ()), 0); + vm.expectCall(Predeploys.ETH_LIQUIDITY, abi.encodeCall(IETHLiquidity.burn, ()), 0); vm.expectCall( Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER, abi.encodeCall( @@ -233,6 +237,9 @@ contract SuperchainWETH_Test is CommonTest { /// @param _amount The amount of WETH to send. function testFuzz_relayERC20_fromMessenger_succeeds(address _sender, uint256 _amount, uint256 _chainId) public { // Assume + vm.assume(_chainId != block.chainid); + vm.assume(_sender != address(ethLiquidity)); + vm.assume(_sender != address(superchainWeth)); _amount = bound(_amount, 0, type(uint248).max - 1); // Arrange @@ -250,7 +257,7 @@ contract SuperchainWETH_Test is CommonTest { // Act vm.expectEmit(address(superchainWeth)); emit RelayERC20(_sender, bob, _amount, _chainId); - vm.expectCall(Predeploys.ETH_LIQUIDITY, abi.encodeCall(ETHLiquidity.mint, (_amount)), 1); + vm.expectCall(Predeploys.ETH_LIQUIDITY, abi.encodeCall(IETHLiquidity.mint, (_amount)), 1); vm.prank(Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER); superchainWeth.relayERC20(_sender, bob, _amount); @@ -272,6 +279,9 @@ contract SuperchainWETH_Test is CommonTest { public { // Assume + vm.assume(_chainId != block.chainid); + vm.assume(_sender != address(ethLiquidity)); + vm.assume(_sender != address(superchainWeth)); _amount = bound(_amount, 0, type(uint248).max - 1); // Arrange @@ -290,7 +300,7 @@ contract SuperchainWETH_Test is CommonTest { // Act vm.expectEmit(address(superchainWeth)); emit RelayERC20(_sender, bob, _amount, _chainId); - vm.expectCall(Predeploys.ETH_LIQUIDITY, abi.encodeCall(ETHLiquidity.mint, (_amount)), 0); + vm.expectCall(Predeploys.ETH_LIQUIDITY, abi.encodeCall(IETHLiquidity.mint, (_amount)), 0); vm.prank(Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER); superchainWeth.relayERC20(_sender, bob, _amount); diff --git a/packages/contracts-bedrock/test/L2Genesis.t.sol b/packages/contracts-bedrock/test/L2Genesis.t.sol index 23c457da6a2f0..ee993fe1110ce 100644 --- a/packages/contracts-bedrock/test/L2Genesis.t.sol +++ b/packages/contracts-bedrock/test/L2Genesis.t.sol @@ -150,8 +150,8 @@ contract L2GenesisTest is Test { // 2 predeploys do not have proxies assertEq(getCodeCount(_path, "Proxy.sol:Proxy"), Predeploys.PREDEPLOY_COUNT - 2); - // 22 proxies have the implementation set if useInterop is true and 17 if useInterop is false - assertEq(getPredeployCountWithSlotSet(_path, Constants.PROXY_IMPLEMENTATION_ADDRESS), _useInterop ? 22 : 17); + // 23 proxies have the implementation set if useInterop is true and 17 if useInterop is false + assertEq(getPredeployCountWithSlotSet(_path, Constants.PROXY_IMPLEMENTATION_ADDRESS), _useInterop ? 23 : 17); // All proxies except 2 have the proxy 1967 admin slot set to the proxy admin assertEq( @@ -188,7 +188,7 @@ contract L2GenesisTest is Test { expected += 2048 - 2; // predeploy proxies expected += 21; // predeploy implementations (excl. legacy erc20-style eth and legacy message sender) expected += 256; // precompiles - expected += 12; // preinstalls + expected += 13; // preinstalls expected += 1; // 4788 deployer account // 16 prefunded dev accounts are excluded assertEq(expected, getJSONKeyCount(_path), "key count check"); diff --git a/packages/contracts-bedrock/test/Predeploys.t.sol b/packages/contracts-bedrock/test/Predeploys.t.sol index d39eb8b0ff61d..6c9ac3750a036 100644 --- a/packages/contracts-bedrock/test/Predeploys.t.sol +++ b/packages/contracts-bedrock/test/Predeploys.t.sol @@ -7,26 +7,14 @@ import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; /// @title PredeploysTest -contract PredeploysTest is CommonTest { +contract PredeploysBaseTest is CommonTest { ////////////////////////////////////////////////////// /// Internal helpers ////////////////////////////////////////////////////// - /// @dev Returns true if the address is a predeploy that is active (i.e. embedded in L2 genesis). - function _isPredeploy(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.WETH - || _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 Returns true if the address is not proxied. - function _notProxied(address _addr) internal pure returns (bool) { - return _addr == Predeploys.GOVERNANCE_TOKEN || _addr == Predeploys.WETH; + /// @dev Returns true if the address is a predeploy that has a different code in the interop mode. + function _interopCodeDiffer(address _addr) internal pure returns (bool) { + return _addr == Predeploys.L1_BLOCK_ATTRIBUTES || _addr == Predeploys.L2_STANDARD_BRIDGE; } /// @dev Returns true if the account is not meant to be in the L2 genesis anymore. @@ -34,22 +22,17 @@ contract PredeploysTest is CommonTest { return _addr == Predeploys.L1_MESSAGE_SENDER; } + /// @dev Returns true if the predeploy is initializable. function _isInitializable(address _addr) internal pure returns (bool) { - return !( - _addr == Predeploys.LEGACY_MESSAGE_PASSER || _addr == Predeploys.DEPLOYER_WHITELIST - || _addr == Predeploys.GAS_PRICE_ORACLE || _addr == Predeploys.SEQUENCER_FEE_WALLET - || _addr == Predeploys.BASE_FEE_VAULT || _addr == Predeploys.L1_FEE_VAULT - || _addr == Predeploys.L1_BLOCK_NUMBER || _addr == Predeploys.L1_BLOCK_ATTRIBUTES - || _addr == Predeploys.L2_TO_L1_MESSAGE_PASSER || _addr == Predeploys.OPTIMISM_MINTABLE_ERC721_FACTORY - || _addr == Predeploys.PROXY_ADMIN || _addr == Predeploys.SCHEMA_REGISTRY || _addr == Predeploys.EAS - || _addr == Predeploys.GOVERNANCE_TOKEN - ); + return _addr == Predeploys.L2_CROSS_DOMAIN_MESSENGER || _addr == Predeploys.L2_STANDARD_BRIDGE + || _addr == Predeploys.L2_ERC721_BRIDGE || _addr == Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY; } + /// @dev Returns true if the predeploy uses immutables. function _usesImmutables(address _addr) internal pure returns (bool) { return _addr == Predeploys.OPTIMISM_MINTABLE_ERC721_FACTORY || _addr == Predeploys.SEQUENCER_FEE_WALLET || _addr == Predeploys.BASE_FEE_VAULT || _addr == Predeploys.L1_FEE_VAULT || _addr == Predeploys.EAS - || _addr == Predeploys.GOVERNANCE_TOKEN; + || _addr == Predeploys.GOVERNANCE_TOKEN || _addr == Predeploys.OPTIMISM_SUPERCHAIN_ERC20_BEACON; } function test_predeployToCodeNamespace() external pure { @@ -67,9 +50,7 @@ contract PredeploysTest is CommonTest { ); } - /// @dev Tests that the predeploy addresses are set correctly. They have code - /// and the proxied accounts have the correct admin. - function test_predeploys_succeeds() external { + function _test_predeploys(bool _useInterop) internal { uint256 count = 2048; uint160 prefix = uint160(0x420) << 148; @@ -77,23 +58,25 @@ contract PredeploysTest is CommonTest { for (uint256 i = 0; i < count; i++) { address addr = address(prefix | uint160(i)); - bytes memory code = addr.code; - assertTrue(code.length > 0); - address implAddr = Predeploys.predeployToCodeNamespace(addr); if (_isOmitted(addr)) { assertEq(implAddr.code.length, 0, "must have no code"); continue; } - bool isPredeploy = _isPredeploy(addr); + + bool isPredeploy = Predeploys.isSupportedPredeploy(addr, _useInterop); + + bytes memory code = addr.code; + if (isPredeploy) assertTrue(code.length > 0); + + bool proxied = Predeploys.notProxied(addr) == false; if (!isPredeploy) { // All of the predeploys, even if inactive, have their admin set to the proxy admin - assertEq(EIP1967Helper.getAdmin(addr), Predeploys.PROXY_ADMIN, "Admin mismatch"); + if (proxied) assertEq(EIP1967Helper.getAdmin(addr), Predeploys.PROXY_ADMIN, "Admin mismatch"); continue; } - bool proxied = _notProxied(addr) == false; string memory cname = Predeploys.getName(addr); assertNotEq(cname, "", "must have a name"); @@ -118,7 +101,7 @@ contract PredeploysTest is CommonTest { string.concat("Implementation mismatch for ", vm.toString(addr)) ); assertNotEq(implAddr.code.length, 0, "predeploy implementation account must have code"); - if (!_usesImmutables(addr)) { + if (!_usesImmutables(addr) && !_interopCodeDiffer(addr)) { // can't check bytecode if it's modified with immutables in genesis. assertEq(implAddr.code, supposedCode, "proxy implementation contract should match contract source"); } @@ -129,3 +112,25 @@ contract PredeploysTest is CommonTest { } } } + +contract PredeploysTest is PredeploysBaseTest { + /// @dev Tests that the predeploy addresses are set correctly. They have code + /// and the proxied accounts have the correct admin. + function test_predeploys_succeeds() external { + _test_predeploys(false); + } +} + +contract PredeploysInteropTest is PredeploysBaseTest { + /// @notice Test setup. Enabling interop to get all predeploys. + function setUp() public virtual override { + super.enableInterop(); + super.setUp(); + } + + /// @dev Tests that the predeploy addresses are set correctly. They have code + /// and the proxied accounts have the correct admin. Using interop. + function test_predeploys_succeeds() external { + _test_predeploys(true); + } +} diff --git a/packages/contracts-bedrock/test/Preinstalls.t.sol b/packages/contracts-bedrock/test/Preinstalls.t.sol index eca9a063b21c7..9154dfc064c6b 100644 --- a/packages/contracts-bedrock/test/Preinstalls.t.sol +++ b/packages/contracts-bedrock/test/Preinstalls.t.sol @@ -5,10 +5,7 @@ import { CommonTest } from "test/setup/CommonTest.sol"; import { Preinstalls } from "src/libraries/Preinstalls.sol"; import { Bytes } from "src/libraries/Bytes.sol"; import { console2 as console } from "forge-std/console2.sol"; - -interface IEIP712 { - function DOMAIN_SEPARATOR() external view returns (bytes32); -} +import { IEIP712 } from "src/universal/interfaces/IEIP712.sol"; /// @title PreinstallsTest contract PreinstallsTest is CommonTest { @@ -118,4 +115,8 @@ contract PreinstallsTest is CommonTest { assertPreinstall(Preinstalls.BeaconBlockRoots, Preinstalls.BeaconBlockRootsCode); assertEq(vm.getNonce(Preinstalls.BeaconBlockRootsSender), 1, "4788 sender must have nonce=1"); } + + function test_preinstall_createX_succeeds() external view { + assertPreinstall(Preinstalls.CreateX, Preinstalls.CreateXCode); + } } diff --git a/packages/contracts-bedrock/test/Specs.t.sol b/packages/contracts-bedrock/test/Specs.t.sol index ecba915d9cf20..b95604135eb01 100644 --- a/packages/contracts-bedrock/test/Specs.t.sol +++ b/packages/contracts-bedrock/test/Specs.t.sol @@ -1,18 +1,25 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.15; +// Testing import { CommonTest } from "test/setup/CommonTest.sol"; -import { Executables } from "scripts/libraries/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 { OptimismPortalInterop } from "src/L1/OptimismPortalInterop.sol"; -import { OptimismPortal2 } from "src/L1/OptimismPortal2.sol"; -import { SystemConfig } from "src/L1/SystemConfig.sol"; -import { DataAvailabilityChallenge } from "src/L1/DataAvailabilityChallenge.sol"; -import { OPStackManager } from "src/L1/OPStackManager.sol"; + +// Scripts +import { Executables } from "scripts/libraries/Executables.sol"; import { ForgeArtifacts, Abi, AbiEntry } from "scripts/libraries/ForgeArtifacts.sol"; +// Contracts +import { OPContractsManager } from "src/L1/OPContractsManager.sol"; + +// Interfaces +import { IOptimismPortal } from "src/L1/interfaces/IOptimismPortal.sol"; +import { IOptimismPortal2 } from "src/L1/interfaces/IOptimismPortal2.sol"; +import { IOptimismPortalInterop } from "src/L1/interfaces/IOptimismPortalInterop.sol"; +import { ISystemConfig } from "src/L1/interfaces/ISystemConfig.sol"; +import { IDataAvailabilityChallenge } from "src/L1/interfaces/IDataAvailabilityChallenge.sol"; +import { IProtocolVersions } from "src/L1/interfaces/IProtocolVersions.sol"; + /// @title Specification_Test /// @dev Specifies common security properties of entrypoints to L1 contracts, including authorization and /// pausability. @@ -80,25 +87,25 @@ contract Specification_Test is CommonTest { _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: IDataAvailabilityChallenge.initialize.selector }); _addSpec({ _name: "DataAvailabilityChallenge", - _sel: DataAvailabilityChallenge.setBondSize.selector, + _sel: IDataAvailabilityChallenge.setBondSize.selector, _auth: Role.DATAAVAILABILITYCHALLENGEOWNER }); _addSpec({ _name: "DataAvailabilityChallenge", - _sel: DataAvailabilityChallenge.setResolverRefundPercentage.selector, + _sel: IDataAvailabilityChallenge.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 }); + _addSpec({ _name: "DataAvailabilityChallenge", _sel: IDataAvailabilityChallenge.deposit.selector }); + _addSpec({ _name: "DataAvailabilityChallenge", _sel: IDataAvailabilityChallenge.withdraw.selector }); + _addSpec({ _name: "DataAvailabilityChallenge", _sel: IDataAvailabilityChallenge.getChallenge.selector }); + _addSpec({ _name: "DataAvailabilityChallenge", _sel: IDataAvailabilityChallenge.getChallengeStatus.selector }); + _addSpec({ _name: "DataAvailabilityChallenge", _sel: IDataAvailabilityChallenge.validateCommitment.selector }); + _addSpec({ _name: "DataAvailabilityChallenge", _sel: IDataAvailabilityChallenge.challenge.selector }); + _addSpec({ _name: "DataAvailabilityChallenge", _sel: IDataAvailabilityChallenge.resolve.selector }); + _addSpec({ _name: "DataAvailabilityChallenge", _sel: IDataAvailabilityChallenge.unlockBond.selector }); // DelayedVetoable _addSpec({ _name: "DelayedVetoable", _sel: _getSel("delay()") }); @@ -248,7 +255,7 @@ contract Specification_Test is CommonTest { _addSpec({ _name: "OptimismPortal", _sel: _getSel("donateETH()") }); _addSpec({ _name: "OptimismPortal", - _sel: OptimismPortal.finalizeWithdrawalTransaction.selector, + _sel: IOptimismPortal.finalizeWithdrawalTransaction.selector, _pausable: true }); _addSpec({ _name: "OptimismPortal", _sel: _getSel("finalizedWithdrawals(bytes32)") }); @@ -260,7 +267,7 @@ contract Specification_Test is CommonTest { _addSpec({ _name: "OptimismPortal", _sel: _getSel("minimumGasLimit(uint64)") }); _addSpec({ _name: "OptimismPortal", _sel: _getSel("params()") }); _addSpec({ _name: "OptimismPortal", _sel: _getSel("paused()") }); - _addSpec({ _name: "OptimismPortal", _sel: OptimismPortal.proveWithdrawalTransaction.selector, _pausable: true }); + _addSpec({ _name: "OptimismPortal", _sel: IOptimismPortal.proveWithdrawalTransaction.selector, _pausable: true }); _addSpec({ _name: "OptimismPortal", _sel: _getSel("provenWithdrawals(bytes32)") }); _addSpec({ _name: "OptimismPortal", _sel: _getSel("superchainConfig()") }); _addSpec({ _name: "OptimismPortal", _sel: _getSel("systemConfig()") }); @@ -280,12 +287,12 @@ contract Specification_Test is CommonTest { _addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("donateETH()") }); _addSpec({ _name: "OptimismPortalInterop", - _sel: OptimismPortal2.finalizeWithdrawalTransaction.selector, + _sel: IOptimismPortal2.finalizeWithdrawalTransaction.selector, _pausable: true }); _addSpec({ _name: "OptimismPortalInterop", - _sel: OptimismPortal2.finalizeWithdrawalTransactionExternalProof.selector, + _sel: IOptimismPortal2.finalizeWithdrawalTransactionExternalProof.selector, _pausable: true }); _addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("finalizedWithdrawals(bytes32)") }); @@ -297,7 +304,7 @@ contract Specification_Test is CommonTest { _addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("paused()") }); _addSpec({ _name: "OptimismPortalInterop", - _sel: OptimismPortal2.proveWithdrawalTransaction.selector, + _sel: IOptimismPortal2.proveWithdrawalTransaction.selector, _pausable: true }); _addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("provenWithdrawals(bytes32,address)") }); @@ -332,7 +339,7 @@ contract Specification_Test is CommonTest { _addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("setGasPayingToken(address,uint8,bytes32,bytes32)") }); _addSpec({ _name: "OptimismPortalInterop", - _sel: OptimismPortalInterop.setConfig.selector, + _sel: IOptimismPortalInterop.setConfig.selector, _auth: Role.SYSTEMCONFIGOWNER }); @@ -341,12 +348,12 @@ contract Specification_Test is CommonTest { _addSpec({ _name: "OptimismPortal2", _sel: _getSel("donateETH()") }); _addSpec({ _name: "OptimismPortal2", - _sel: OptimismPortal2.finalizeWithdrawalTransaction.selector, + _sel: IOptimismPortal2.finalizeWithdrawalTransaction.selector, _pausable: true }); _addSpec({ _name: "OptimismPortal2", - _sel: OptimismPortal2.finalizeWithdrawalTransactionExternalProof.selector, + _sel: IOptimismPortal2.finalizeWithdrawalTransactionExternalProof.selector, _pausable: true }); _addSpec({ _name: "OptimismPortal2", _sel: _getSel("finalizedWithdrawals(bytes32)") }); @@ -356,7 +363,11 @@ contract Specification_Test is CommonTest { _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: IOptimismPortal2.proveWithdrawalTransaction.selector, + _pausable: true + }); _addSpec({ _name: "OptimismPortal2", _sel: _getSel("provenWithdrawals(bytes32,address)") }); _addSpec({ _name: "OptimismPortal2", _sel: _getSel("superchainConfig()") }); _addSpec({ _name: "OptimismPortal2", _sel: _getSel("systemConfig()") }); @@ -383,19 +394,19 @@ contract Specification_Test is CommonTest { _addSpec({ _name: "ProtocolVersions", _sel: _getSel("RECOMMENDED_SLOT()") }); _addSpec({ _name: "ProtocolVersions", _sel: _getSel("REQUIRED_SLOT()") }); _addSpec({ _name: "ProtocolVersions", _sel: _getSel("VERSION()") }); - _addSpec({ _name: "ProtocolVersions", _sel: ProtocolVersions.initialize.selector }); + _addSpec({ _name: "ProtocolVersions", _sel: IProtocolVersions.initialize.selector }); _addSpec({ _name: "ProtocolVersions", _sel: _getSel("owner()") }); - _addSpec({ _name: "ProtocolVersions", _sel: ProtocolVersions.recommended.selector }); + _addSpec({ _name: "ProtocolVersions", _sel: IProtocolVersions.recommended.selector }); _addSpec({ _name: "ProtocolVersions", _sel: _getSel("renounceOwnership()"), _auth: Role.SYSTEMCONFIGOWNER }); - _addSpec({ _name: "ProtocolVersions", _sel: ProtocolVersions.required.selector }); + _addSpec({ _name: "ProtocolVersions", _sel: IProtocolVersions.required.selector }); _addSpec({ _name: "ProtocolVersions", - _sel: ProtocolVersions.setRequired.selector, + _sel: IProtocolVersions.setRequired.selector, _auth: Role.SYSTEMCONFIGOWNER }); _addSpec({ _name: "ProtocolVersions", - _sel: ProtocolVersions.setRecommended.selector, + _sel: IProtocolVersions.setRecommended.selector, _auth: Role.SYSTEMCONFIGOWNER }); _addSpec({ _name: "ProtocolVersions", _sel: _getSel("transferOwnership(address)") }); @@ -420,23 +431,23 @@ contract Specification_Test is CommonTest { _addSpec({ _name: "SystemConfig", _sel: _getSel("VERSION()") }); _addSpec({ _name: "SystemConfig", _sel: _getSel("batcherHash()") }); _addSpec({ _name: "SystemConfig", _sel: _getSel("gasLimit()") }); - _addSpec({ _name: "SystemConfig", _sel: SystemConfig.initialize.selector }); - _addSpec({ _name: "SystemConfig", _sel: SystemConfig.minimumGasLimit.selector }); + _addSpec({ _name: "SystemConfig", _sel: ISystemConfig.initialize.selector }); + _addSpec({ _name: "SystemConfig", _sel: ISystemConfig.minimumGasLimit.selector }); _addSpec({ _name: "SystemConfig", _sel: _getSel("overhead()") }); _addSpec({ _name: "SystemConfig", _sel: _getSel("owner()") }); _addSpec({ _name: "SystemConfig", _sel: _getSel("renounceOwnership()"), _auth: Role.SYSTEMCONFIGOWNER }); - _addSpec({ _name: "SystemConfig", _sel: SystemConfig.resourceConfig.selector }); + _addSpec({ _name: "SystemConfig", _sel: ISystemConfig.resourceConfig.selector }); _addSpec({ _name: "SystemConfig", _sel: _getSel("scalar()") }); - _addSpec({ _name: "SystemConfig", _sel: SystemConfig.setBatcherHash.selector, _auth: Role.SYSTEMCONFIGOWNER }); - _addSpec({ _name: "SystemConfig", _sel: SystemConfig.setGasConfig.selector, _auth: Role.SYSTEMCONFIGOWNER }); - _addSpec({ _name: "SystemConfig", _sel: SystemConfig.setGasLimit.selector, _auth: Role.SYSTEMCONFIGOWNER }); + _addSpec({ _name: "SystemConfig", _sel: ISystemConfig.setBatcherHash.selector, _auth: Role.SYSTEMCONFIGOWNER }); + _addSpec({ _name: "SystemConfig", _sel: ISystemConfig.setGasConfig.selector, _auth: Role.SYSTEMCONFIGOWNER }); + _addSpec({ _name: "SystemConfig", _sel: ISystemConfig.setGasLimit.selector, _auth: Role.SYSTEMCONFIGOWNER }); _addSpec({ _name: "SystemConfig", - _sel: SystemConfig.setUnsafeBlockSigner.selector, + _sel: ISystemConfig.setUnsafeBlockSigner.selector, _auth: Role.SYSTEMCONFIGOWNER }); _addSpec({ _name: "SystemConfig", _sel: _getSel("transferOwnership(address)"), _auth: Role.SYSTEMCONFIGOWNER }); - _addSpec({ _name: "SystemConfig", _sel: SystemConfig.unsafeBlockSigner.selector }); + _addSpec({ _name: "SystemConfig", _sel: ISystemConfig.unsafeBlockSigner.selector }); _addSpec({ _name: "SystemConfig", _sel: _getSel("version()") }); _addSpec({ _name: "SystemConfig", _sel: _getSel("l1CrossDomainMessenger()") }); _addSpec({ _name: "SystemConfig", _sel: _getSel("l1ERC721Bridge()") }); @@ -472,27 +483,31 @@ contract Specification_Test is CommonTest { _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("VERSION()") }); _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("batcherHash()") }); _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("gasLimit()") }); - _addSpec({ _name: "SystemConfigInterop", _sel: SystemConfig.initialize.selector }); - _addSpec({ _name: "SystemConfigInterop", _sel: SystemConfig.minimumGasLimit.selector }); + _addSpec({ _name: "SystemConfigInterop", _sel: ISystemConfig.initialize.selector }); + _addSpec({ _name: "SystemConfigInterop", _sel: ISystemConfig.minimumGasLimit.selector }); _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("overhead()") }); _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("owner()") }); _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("renounceOwnership()"), _auth: Role.SYSTEMCONFIGOWNER }); - _addSpec({ _name: "SystemConfigInterop", _sel: SystemConfig.resourceConfig.selector }); + _addSpec({ _name: "SystemConfigInterop", _sel: ISystemConfig.resourceConfig.selector }); _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("scalar()") }); _addSpec({ _name: "SystemConfigInterop", - _sel: SystemConfig.setBatcherHash.selector, + _sel: ISystemConfig.setBatcherHash.selector, + _auth: Role.SYSTEMCONFIGOWNER + }); + _addSpec({ + _name: "SystemConfigInterop", + _sel: ISystemConfig.setGasConfig.selector, _auth: Role.SYSTEMCONFIGOWNER }); _addSpec({ _name: "SystemConfigInterop", - _sel: SystemConfig.setGasConfig.selector, + _sel: ISystemConfig.setGasLimit.selector, _auth: Role.SYSTEMCONFIGOWNER }); - _addSpec({ _name: "SystemConfigInterop", _sel: SystemConfig.setGasLimit.selector, _auth: Role.SYSTEMCONFIGOWNER }); _addSpec({ _name: "SystemConfigInterop", - _sel: SystemConfig.setUnsafeBlockSigner.selector, + _sel: ISystemConfig.setUnsafeBlockSigner.selector, _auth: Role.SYSTEMCONFIGOWNER }); _addSpec({ @@ -500,7 +515,7 @@ contract Specification_Test is CommonTest { _sel: _getSel("transferOwnership(address)"), _auth: Role.SYSTEMCONFIGOWNER }); - _addSpec({ _name: "SystemConfigInterop", _sel: SystemConfig.unsafeBlockSigner.selector }); + _addSpec({ _name: "SystemConfigInterop", _sel: ISystemConfig.unsafeBlockSigner.selector }); _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("version()") }); _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("l1CrossDomainMessenger()") }); _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("l1ERC721Bridge()") }); @@ -821,9 +836,31 @@ contract Specification_Test is CommonTest { _addSpec({ _name: "WETH98", _sel: _getSel("transferFrom(address,address,uint256)") }); _addSpec({ _name: "WETH98", _sel: _getSel("withdraw(uint256)") }); - // OPStackManager - _addSpec({ _name: "OPStackManager", _sel: _getSel("version()") }); - _addSpec({ _name: "OPStackManager", _sel: OPStackManager.deploy.selector }); + // OPContractsManager + _addSpec({ _name: "OPContractsManager", _sel: _getSel("version()") }); + _addSpec({ _name: "OPContractsManager", _sel: _getSel("superchainConfig()") }); + _addSpec({ _name: "OPContractsManager", _sel: _getSel("protocolVersions()") }); + _addSpec({ _name: "OPContractsManager", _sel: _getSel("latestRelease()") }); + _addSpec({ _name: "OPContractsManager", _sel: _getSel("implementations(string,string)") }); + _addSpec({ _name: "OPContractsManager", _sel: _getSel("systemConfigs(uint256)") }); + _addSpec({ _name: "OPContractsManager", _sel: _getSel("OUTPUT_VERSION()") }); + _addSpec({ _name: "OPContractsManager", _sel: OPContractsManager.initialize.selector }); + _addSpec({ _name: "OPContractsManager", _sel: OPContractsManager.deploy.selector }); + _addSpec({ _name: "OPContractsManager", _sel: OPContractsManager.blueprints.selector }); + _addSpec({ _name: "OPContractsManager", _sel: OPContractsManager.chainIdToBatchInboxAddress.selector }); + + // OPContractsManagerInterop + _addSpec({ _name: "OPContractsManagerInterop", _sel: _getSel("version()") }); + _addSpec({ _name: "OPContractsManagerInterop", _sel: _getSel("superchainConfig()") }); + _addSpec({ _name: "OPContractsManagerInterop", _sel: _getSel("protocolVersions()") }); + _addSpec({ _name: "OPContractsManagerInterop", _sel: _getSel("latestRelease()") }); + _addSpec({ _name: "OPContractsManagerInterop", _sel: _getSel("implementations(string,string)") }); + _addSpec({ _name: "OPContractsManagerInterop", _sel: _getSel("systemConfigs(uint256)") }); + _addSpec({ _name: "OPContractsManagerInterop", _sel: _getSel("OUTPUT_VERSION()") }); + _addSpec({ _name: "OPContractsManagerInterop", _sel: OPContractsManager.initialize.selector }); + _addSpec({ _name: "OPContractsManagerInterop", _sel: OPContractsManager.deploy.selector }); + _addSpec({ _name: "OPContractsManagerInterop", _sel: OPContractsManager.blueprints.selector }); + _addSpec({ _name: "OPContractsManagerInterop", _sel: OPContractsManager.chainIdToBatchInboxAddress.selector }); // DeputyGuardianModule _addSpec({ @@ -907,12 +944,14 @@ contract Specification_Test is CommonTest { /// @notice Ensures that there's an auth spec for every L1 contract function. function testContractAuth() public { - string[] memory pathExcludes = new string[](3); + string[] memory pathExcludes = new string[](5); pathExcludes[0] = "src/dispute/interfaces/*"; pathExcludes[1] = "src/dispute/lib/*"; - pathExcludes[2] = "src/Safe/SafeSigners.sol"; + pathExcludes[2] = "src/safe/SafeSigners.sol"; + pathExcludes[3] = "src/L1/interfaces/*"; + pathExcludes[4] = "src/governance/interfaces/*"; Abi[] memory abis = ForgeArtifacts.getContractFunctionAbis( - "src/{L1,dispute,governance,Safe,universal/ProxyAdmin.sol}", pathExcludes + "src/{L1,dispute,governance,safe,universal/ProxyAdmin.sol,universal/WETH98.sol}", pathExcludes ); uint256 numCheckedEntries = 0; diff --git a/packages/contracts-bedrock/test/actors/FaultDisputeActors.sol b/packages/contracts-bedrock/test/actors/FaultDisputeActors.sol index 181fc87266acf..20f18eddc3c00 100644 --- a/packages/contracts-bedrock/test/actors/FaultDisputeActors.sol +++ b/packages/contracts-bedrock/test/actors/FaultDisputeActors.sol @@ -1,13 +1,15 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.15; +// Testing import { CommonBase } from "forge-std/Base.sol"; -import { FaultDisputeGame } from "src/dispute/FaultDisputeGame.sol"; -import { IFaultDisputeGame } from "src/dispute/interfaces/IFaultDisputeGame.sol"; - +// Libraries import "src/dispute/lib/Types.sol"; +// Interfaces +import { IFaultDisputeGame } from "src/dispute/interfaces/IFaultDisputeGame.sol"; + /// @title GameSolver /// @notice The `GameSolver` contract is a contract that can produce an array of available /// moves for a given `FaultDisputeGame` contract, from the eyes of an honest @@ -15,7 +17,7 @@ import "src/dispute/lib/Types.sol"; /// it suggests. abstract contract GameSolver is CommonBase { /// @notice The `FaultDisputeGame` proxy that the `GameSolver` will be solving. - FaultDisputeGame public immutable GAME; + IFaultDisputeGame public immutable GAME; /// @notice The split depth of the game uint256 internal immutable SPLIT_DEPTH; /// @notice The max depth of the game @@ -55,7 +57,7 @@ abstract contract GameSolver is CommonBase { } constructor( - FaultDisputeGame _gameProxy, + IFaultDisputeGame _gameProxy, uint256[] memory _l2Outputs, bytes memory _trace, bytes memory _preStateData @@ -89,7 +91,7 @@ contract HonestGameSolver is GameSolver { } constructor( - FaultDisputeGame _gameProxy, + IFaultDisputeGame _gameProxy, uint256[] memory _l2Outputs, bytes memory _trace, bytes memory _preStateData @@ -223,7 +225,7 @@ contract HonestGameSolver is GameSolver { move_ = Move({ kind: isAttack ? MoveKind.Attack : MoveKind.Defend, value: bond, - data: abi.encodeCall(FaultDisputeGame.move, (disputed, _challengeIndex, claimAt(_movePos), isAttack)) + data: abi.encodeCall(IFaultDisputeGame.move, (disputed, _challengeIndex, claimAt(_movePos), isAttack)) }); } @@ -263,7 +265,7 @@ contract HonestGameSolver is GameSolver { move_ = Move({ kind: MoveKind.Step, value: 0, - data: abi.encodeCall(FaultDisputeGame.step, (_challengeIndex, isAttack, preStateTrace, hex"")) + data: abi.encodeCall(IFaultDisputeGame.step, (_challengeIndex, isAttack, preStateTrace, hex"")) }); } @@ -366,10 +368,10 @@ abstract contract DisputeActor { /// that this actor *can* be dishonest if the trace is faulty, but it will always follow /// the rules of the honest actor. contract HonestDisputeActor is DisputeActor { - FaultDisputeGame public immutable GAME; + IFaultDisputeGame public immutable GAME; constructor( - FaultDisputeGame _gameProxy, + IFaultDisputeGame _gameProxy, uint256[] memory _l2Outputs, bytes memory _trace, bytes memory _preStateData diff --git a/packages/contracts-bedrock/test/cannon/MIPS.t.sol b/packages/contracts-bedrock/test/cannon/MIPS.t.sol index 8e4c858b0ce66..9aafbdb5421d6 100644 --- a/packages/contracts-bedrock/test/cannon/MIPS.t.sol +++ b/packages/contracts-bedrock/test/cannon/MIPS.t.sol @@ -6,7 +6,7 @@ import { MIPS } from "src/cannon/MIPS.sol"; import { PreimageOracle } from "src/cannon/PreimageOracle.sol"; import { MIPSInstructions } from "src/cannon/libraries/MIPSInstructions.sol"; import { MIPSSyscalls as sys } from "src/cannon/libraries/MIPSSyscalls.sol"; -import { InvalidExitedValue } from "src/cannon/libraries/CannonErrors.sol"; +import { InvalidExitedValue, InvalidMemoryProof } from "src/cannon/libraries/CannonErrors.sol"; import "src/dispute/lib/Types.sol"; contract MIPS_Test is CommonTest { @@ -27,10 +27,15 @@ contract MIPS_Test is CommonTest { /// For example, in cannon/mipsevm/evm_test.go step input can be pulled here: /// https://github.com/ethereum-optimism/optimism/blob/1f64dd6db5561f3bb76ed1d1ffdaff0cde9b7c4b/cannon/mipsevm/evm_test.go#L80-L80 function test_step_debug_succeeds() external { + bytes memory oracleInput = + hex"e15926110000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000081234567898765432000000000000000000000000000000000000000000000000"; + (bool oracleSuccess,) = address(oracle).call(oracleInput); + assertTrue(oracleSuccess); + bytes memory input = - hex"e14ced3200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e29d9267b33909f55f0cac54cca6427fc17fe0b9efe6c34350ca86605145633fe60000000000000000000000000000000000000000000000000000000000000000000000000008a82c0008a8300000000000000000050000000000000000000000000a000000000008a82c0000000000000000000000007fffd00400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007fffd000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007008fbc00601000ffbd00000000afbffffc27bdfffcafbf000027bdfff4afa400048fb000408fb100448fb200488fb3004c8fb400508fb600548fb800588fb9005caf0ea4ff7928d10f76bc70a73c867e2c9232b35112b060285aedb7b33533e5253d8c8392c902f20c8314d10a807c7bc5de8126736a03c2bdb47667bbfa710375ac2064c969079ba2acbb688f31cd2bdd4cbe18111a8e733c487884d541f1366231e3c23a71546c755f18517db871301ffe7b08676258520720f4cb2fcc23642ddb778fcfd0cfc38a190d5b8bf0bea4e1ce7d2f35d6a068b94cf6d925e0a024d571f505296c77e19f2ea496d88d90cd342189bdedb389ac959bb9b82db9e324d150eb233dbfa0746469950cec5d4f6360fa49f835403946268bf6fa7472bc4a1320e6a7387a6272dcbf4f8280ff680ccedd4b79f02c78eaef3218c1e78f9e266b3b1c7c1c24e7d04470d63c4e1df858f2e7bf9c7cdad07ed51bc383f80a4d3ded70f2c60642ed3c85483b60ea68b5ed606b2f84d90ac876c01c4d01ba58c431390bd20a29a10d408854c7f62a262860ebd3e4af402fa2dcc0662dfa36fd3e85cbab4da3e3d0907392666337a62e5a663c04bc0a3e16d559f825ba2d40a1c81f4d3844b6cfb2e084a80eb9338fad62b25cf83f4738b5c4df1a0ef019e8ebb9d03d8c7e091f91c853d19da08da2245b01b806c73dc0b200672d04e78982eaed71ea20929c6c472715d5c74a31176a5663348a3c02c89ff5edb7cf3041110e8fe44e2733e50f526ec2fa19a22b31e8ed50f23cd1fdf94c9154ed3a7609a2f1ff981fe1d3b5c807b281e4683cc6d6315cf95b9ade8641defcb32372f1c126e398ef7a5a2dce0a8a7f68bb74560f8f71837c2c2ebbcbf7fffb42ae1896f13f7c7479a0b46a28b6f55540f89444f63de0378e3d121be09e06cc9ded1c20e65876d36aa0c65e9645644786b620e2dd2ad648ddfcbf4a7e5b1a3a4ecfe7f64667a3f0b7e2f4418588ed35a2458cffeb39b93d26f18d2ab13bdce6aee58e7b99359ec2dfd95a9c16dc00d6ef18b7933a6f8dc65ccb55667138776f7dea101070dc8796e3774df84f40ae0c8229d0d6069e5c8f39a7c299677a09d367fc7b05e3bc380ee652cdc72595f74c7b1043d0e1ffbab734648c838dfb0527d971b602bc216c9619ef6834d8ef8faaf96b7b45235297538a266eb882b8b5680f621aab3417d43cdc2eb8cd74046ff337f0a7bf2c8e03e10f642c1886798d71806ab1e888d9e5ee87d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5b4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d3021ddb9a356815c3fac1026b6dec5df3124afbadb485c9ba5a3e3398a04b7ba85e58769b32a1beaf1ea27375a44095a0d1fb664ce2dd358e7fcbfb78c26a193440eb01ebfc9ed27500cd4dfc979272d1f0913cc9f66540d7e8005811109e1cf2d887c22bd8750d34016ac3c66b5ff102dacdd73f6b014e710b51e8022af9a1968a60155a81a637d8581c4d275380f7dd05bd2dd27ac3fb7ca905e7aec4e0a1cd99867cc5f7f196b93bae1e27e6320742445d290f2263827498b54fec539f756afcefad4e508c098b9a7e1d8feb19955fb02ba9675585078710969d3440f5054e0f9dc3e7fe016e050eff260334f18a5d4fe391d82092319f5964f2e2eb7c1c3a5f8b13a49e282f609c317a833fb8d976d11517c571d1221a265d25af778ecf8923490c6ceeb450aecdc82e28293031d10c7d73bf85e57bf041a97360aa2c5d99cc1df82d9c4b87413eae2ef048f94b4d3554cea73d92b0f7af96e0271c691e2bb5c67add7c6caf302256adedf7ab114da0acfe870d449a3a489f781d659e8beccda7bce9f4e8618b6bd2f4132ce798cdc7a60e7e1460a7299e3c6342a579626d22733e50f526ec2fa19a22b31e8ed50f23cd1fdf94c9154ed3a7609a2f1ff981fe1d3b5c807b281e4683cc6d6315cf95b9ade8641defcb32372f1c126e398ef7a5a2dce0a8a7f68bb74560f8f71837c2c2ebbcbf7fffb42ae1896f13f7c7479a0b46a28b6f55540f89444f63de0378e3d121be09e06cc9ded1c20e65876d36aa0c65e9645644786b620e2dd2ad648ddfcbf4a7e5b1a3a4ecfe7f64667a3f0b7e2f4418588ed35a2458cffeb39b93d26f18d2ab13bdce6aee58e7b99359ec2dfd95a9c16dc00d6ef18b7933a6f8dc65ccb55667138776f7dea101070dc8796e3774df84f40ae0c8229d0d6069e5c8f39a7c299677a09d367fc7b05e3bc380ee652cdc72595f74c7b1043d0e1ffbab734648c838dfb0527d971b602bc216c9619eff0eb509051ae684fe17ee4373a3c82e88f970dab89cc0915d21b63cb96415cc2b8cd74046ff337f0a7bf2c8e03e10f642c1886798d71806ab1e888d9e5ee87d0"; + hex"e14ced3200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2d0637506e48299469d82d71a947c6771e7d3eaa3db30b44b30b3ac6ba6596c79029df7322a2404a59aebdffb81ab72dd22cc4459131675e63231b2c693676cf100000008f1f85ff4f1f85ff82ad7bda1e5acea1049e0bfd000001f5b0412ffd341c045e665389becadf100000fa3c64fbd7f000000050000ff00000000015b3d97166d1aec28829f3dd43d8cf1f9358e4103b16d09d466e2c7c048ea3ba1aef3141e700270581aa0b75b50e34fc926bb2d83bb3938f8506d442d5e545ba3a5d214515c11955d8ad50cfb04a6a0e484a2a29f1d688138c1883f289a45a6d5d9c37ebe000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000ad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5b4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d3021ddb9a356815c3fac1026b6dec5df3124afbadb485c9ba5a3e3398a04b7ba85e58769b32a1beaf1ea27375a44095a0d1fb664ce2dd358e7fcbfb78c26a193440eb01ebfc9ed27500cd4dfc979272d1f0913cc9f66540d7e8005811109e1cf2d887c22bd8750d34016ac3c66b5ff102dacdd73f6b014e710b51e8022af9a1968ffd70157e48063fc33c97a050f7f640233bf646cc98d9524c6b92bcf3ab56f839867cc5f7f196b93bae1e27e6320742445d290f2263827498b54fec539f756afcefad4e508c098b9a7e1d8feb19955fb02ba9675585078710969d3440f5054e0f9dc3e7fe016e050eff260334f18a5d4fe391d82092319f5964f2e2eb7c1c3a5f8b13a49e282f609c317a833fb8d976d11517c571d1221a265d25af778ecf8923490c6ceeb450aecdc82e28293031d10c7d73bf85e57bf041a97360aa2c5d99cc1df82d9c4b87413eae2ef048f94b4d3554cea73d92b0f7af96e0271c691e2bb5c67add7c6caf302256adedf7ab114da0acfe870d449a3a489f781d659e8beccda7bce9f4e8618b6bd2f4132ce798cdc7a60e7e1460a7299e3c6342a579626d22733e50f526ec2fa19a22b31e8ed50f23cd1fdf94c9154ed3a7609a2f1ff981fe1d3b5c807b281e4683cc6d6315cf95b9ade8641defcb32372f1c126e398ef7a5a2dce0a8a7f68bb74560f8f71837c2c2ebbcbf7fffb42ae1896f13f7c7479a0b46a28b6f55540f89444f63de0378e3d121be09e06cc9ded1c20e65876d36aa0c65e9645644786b620e2dd2ad648ddfcbf4a7e5b1a3a4ecfe7f64667a3f0b7e2f4418588ed35a2458cffeb39b93d26f18d2ab13bdce6aee58e7b99359ec2dfd95a9c16dc00d6ef18b7933a6f8dc65ccb55667138776f7dea101070dc8796e3774df84f40ae0c8229d0d6069e5c8f39a7c299677a09d367fc7b05e3bc380ee652cdc72595f74c7b1043d0e1ffbab734648c838dfb0527d971b602bc216c9619ef0abf5ac974a1ed57f4050aa510dd9c74f508277b39d7973bb2dfccc5eeb0618df7a66599e9dd7409a7d8de62e29bea7821f0f19cfb783952bff507c87eba2365ffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5b4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d3021ddb9a356815c3fac1026b6dec5df3124afbadb485c9ba5a3e3398a04b7ba85e58769b32a1beaf1ea27375a44095a0d1fb664ce2dd358e7fcbfb78c26a193440eb01ebfc9ed27500cd4dfc979272d1f0913cc9f66540d7e8005811109e1cf2d887c22bd8750d34016ac3c66b5ff102dacdd73f6b014e710b51e8022af9a1968ffd70157e48063fc33c97a050f7f640233bf646cc98d9524c6b92bcf3ab56f839867cc5f7f196b93bae1e27e6320742445d290f2263827498b54fec539f756afcefad4e508c098b9a7e1d8feb19955fb02ba9675585078710969d3440f5054e0f9dc3e7fe016e050eff260334f18a5d4fe391d82092319f5964f2e2eb7c1c3a5f8b13a49e282f609c317a833fb8d976d11517c571d1221a265d25af778ecf8923490c6ceeb450aecdc82e28293031d10c7d73bf85e57bf041a97360aa2c5d99cc1df82d9c4b87413eae2ef048f94b4d3554cea73d92b0f7af96e0271c691e2bb5c67add7c6caf302256adedf7ab114da0acfe870d449a3a489f781d659e8beccda7bce9f4e8618b6bd2f4132ce798cdc7a60e7e1460a7299e3c6342a579626d22733e50f526ec2fa19a22b31e8ed50f23cd1fdf94c9154ed3a7609a2f1ff981fe1d3b5c807b281e4683cc6d6315cf95b9ade8641defcb32372f1c126e398ef7a5a2dce0a8a7f68bb74560f8f71837c2c2ebbcbf7fffb42ae1896f13f7c7479a0b46a28b6f55540f89444f63de0378e3d121be09e06cc9ded1c20e65876d36aa0c65e9645644786b620e2dd2ad648ddfcbf4a7e5b1a3a4ecfe7f64667a3f0b7e2f4418588ed35a2458cffeb39b93d26f18d2ab13bdce6aee58e7b99359ec2dfd95a9c16dc00d6ef18b7933a6f8dc65ccb55667138776f7dea101070dc8796e3774df84f40ae0c8229d0d6069e5c8f39a7c299677a09d367fc7b05e3bc380ee652cdc72595f74c7b1043d0e1ffbab734648c838dfb0527d971b602bc216c9619ef0abf5ac974a1ed57f4050aa510dd9c74f508277b39d7973bb2dfccc5eeb0618d53cee4e252442dad999b85c644aa0a6fd8bca90f35f1a5ae696cb8d9eb5a35be"; (bool success, bytes memory retVal) = address(mips).call(input); - bytes memory expectedRetVal = hex"03611b9f88f952fea10b9330e85fbe7b8ddd0d457d3f31e647434a5330789212"; + bytes memory expectedRetVal = hex"03dacdac4e61d89774a305dd0828063706ad878bb6353c0c2cd787d1e5cddd67"; assertTrue(success); assertEq(retVal.length, 32, "Expect a bytes32 hash of the post-state to be returned"); @@ -63,26 +68,28 @@ contract MIPS_Test is CommonTest { /// @notice Tests that the mips step function fails when the value of the exited field is /// invalid (anything greater than 1). - /// @param _exited Value to set the exited field to. - function testFuzz_step_invalidExitedValue_fails(uint8 _exited) external { - // Assume - // Make sure the value of _exited is invalid. - _exited = uint8(bound(uint256(_exited), 2, type(uint8).max)); - - // Rest of this stuff doesn't matter very much, just setting up some state to edit. - // Here just using the parameters for the ADD test below. - uint32 insn = encodespec(17, 18, 8, 0x20); - (MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0); - - // Compute the encoded state and manipulate it. - bytes memory enc = encodeState(state); - assembly { - mstore8(add(add(enc, 0x20), 89), _exited) + function test_step_invalidExitedValue_fails() external { + // Bound to invalid exited values. + for (uint8 exited = 2; exited <= type(uint8).max && exited != 0;) { + // Rest of this stuff doesn't matter very much, just setting up some state to edit. + // Here just using the parameters for the ADD test below. + uint32 insn = encodespec(17, 18, 8, 0x20); + (MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0); + + // Compute the encoded state and manipulate it. + bytes memory enc = encodeState(state); + assembly { + // Push offset by an additional 32 bytes (0x20) to account for length prefix + mstore8(add(add(enc, 0x20), 89), exited) + } + + // Call the step function and expect a revert. + vm.expectRevert(InvalidExitedValue.selector); + mips.step(enc, proof, 0); + unchecked { + exited++; + } } - - // Call the step function and expect a revert. - vm.expectRevert(InvalidExitedValue.selector); - mips.step(enc, proof, 0); } function test_add_succeeds() external { @@ -1658,7 +1665,7 @@ contract MIPS_Test is CommonTest { for (uint256 i = 0; i < proof.length; i++) { proof[i] = 0x0; } - vm.expectRevert(hex"000000000000000000000000000000000000000000000000000000000badf00d"); + vm.expectRevert(InvalidMemoryProof.selector); mips.step(encodeState(state), proof, 0); } @@ -1677,7 +1684,7 @@ contract MIPS_Test is CommonTest { state.registers[2] = 4246; // exit_group syscall state.registers[4] = 0x5; // a0 - vm.expectRevert(hex"000000000000000000000000000000000000000000000000000000000badf00d"); + vm.expectRevert(InvalidMemoryProof.selector); mips.step(encodeState(state), proof, 0); } diff --git a/packages/contracts-bedrock/test/cannon/MIPS2.t.sol b/packages/contracts-bedrock/test/cannon/MIPS2.t.sol index 30d6899caad68..4c02d7a0bdd1f 100644 --- a/packages/contracts-bedrock/test/cannon/MIPS2.t.sol +++ b/packages/contracts-bedrock/test/cannon/MIPS2.t.sol @@ -5,7 +5,9 @@ import { CommonTest } from "test/setup/CommonTest.sol"; import { MIPS2 } from "src/cannon/MIPS2.sol"; import { PreimageOracle } from "src/cannon/PreimageOracle.sol"; import { MIPSSyscalls as sys } from "src/cannon/libraries/MIPSSyscalls.sol"; +import { MIPSInstructions as ins } from "src/cannon/libraries/MIPSInstructions.sol"; import "src/dispute/lib/Types.sol"; +import { InvalidExitedValue, InvalidMemoryProof, InvalidSecondMemoryProof } from "src/cannon/libraries/CannonErrors.sol"; contract ThreadStack { bytes32 internal constant EMPTY_THREAD_ROOT = hex"ad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5"; @@ -139,9 +141,9 @@ contract MIPS2_Test is CommonTest { /// https://github.com/ethereum-optimism/optimism/blob/1f64dd6db5561f3bb76ed1d1ffdaff0cde9b7c4b/cannon/mipsevm/evm_test.go#L80-L80 function test_mips2_step_debug_succeeds() external { bytes memory input = - hex"e14ced3200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a3df82bcbdf27955e04d467b84d94d0b4662c88a70264d7ea31325bc8d826681ef000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000affffffff00cbf05eda4a03d05cc6a14cff1cf2f955bfb253097c296ea96032da307da4f353ad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb500000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007c6000000000000ffffffff000000000000000000000000000000280000002c00000000000000000000000000000000000000010000000000000000000000000000000000000000fffffffd00000003000000000000000000000000000000000000000000000000bffffff00000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a7ef00d0ad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5ae020008ae11000403e0000800000000000000000000000000000000000000003c10bfff3610fff0341100013c08ffff3508fffd34090003010950212d420001ad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5b4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d3021ddb9a356815c3fac1026b6dec5df3124afbadb485c9ba5a3e3398a04b7ba85e58769b32a1beaf1ea27375a44095a0d1fb664ce2dd358e7fcbfb78c26a193440eb01ebfc9ed27500cd4dfc979272d1f0913cc9f66540d7e8005811109e1cf2d887c22bd8750d34016ac3c66b5ff102dacdd73f6b014e710b51e8022af9a1968ffd70157e48063fc33c97a050f7f640233bf646cc98d9524c6b92bcf3ab56f839867cc5f7f196b93bae1e27e6320742445d290f2263827498b54fec539f756afcefad4e508c098b9a7e1d8feb19955fb02ba9675585078710969d3440f5054e0f9dc3e7fe016e050eff260334f18a5d4fe391d82092319f5964f2e2eb7c1c3a5f8b13a49e282f609c317a833fb8d976d11517c571d1221a265d25af778ecf8923490c6ceeb450aecdc82e28293031d10c7d73bf85e57bf041a97360aa2c5d99cc1df82d9c4b87413eae2ef048f94b4d3554cea73d92b0f7af96e0271c691e2bb5c67add7c6caf302256adedf7ab114da0acfe870d449a3a489f781d659e8beccda7bce9f4e8618b6bd2f4132ce798cdc7a60e7e1460a7299e3c6342a579626d22733e50f526ec2fa19a22b31e8ed50f23cd1fdf94c9154ed3a7609a2f1ff981fe1d3b5c807b281e4683cc6d6315cf95b9ade8641defcb32372f1c126e398ef7a5a2dce0a8a7f68bb74560f8f71837c2c2ebbcbf7fffb42ae1896f13f7c7479a0b46a28b6f55540f89444f63de0378e3d121be09e06cc9ded1c20e65876d36aa0c65e9645644786b620e2dd2ad648ddfcbf4a7e5b1a3a4ecfe7f64667a3f0b7e2f4418588ed35a2458cffeb39b93d26f18d2ab13bdce6aee58e7b99359ec2dfd95a9c16dc00d6ef18b7933a6f8dc65ccb55667138776f7dea101070dc8796e3774df84f40ae0c8229d0d6069e5c8f39a7c299677a09d367fc7b05e3bc380ee652cdc72595f74c7b1043d0e1ffbab734648c838dfb0527d971b602bc216c9619ef0abf5ac974a1ed57f4050aa510dd9c74f508277b39d7973bb2dfccc5eeb0618d4e545be579dc7118fc02cd7b19b704e4710a81bce0cb48bb7e289e403e7c969a00000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000ad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5b4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d3021ddb9a356815c3fac1026b6dec5df3124afbadb485c9ba5a3e3398a04b7ba85e58769b32a1beaf1ea27375a44095a0d1fb664ce2dd358e7fcbfb78c26a193440eb01ebfc9ed27500cd4dfc979272d1f0913cc9f66540d7e8005811109e1cf2d887c22bd8750d34016ac3c66b5ff102dacdd73f6b014e710b51e8022af9a1968ffd70157e48063fc33c97a050f7f640233bf646cc98d9524c6b92bcf3ab56f839867cc5f7f196b93bae1e27e6320742445d290f2263827498b54fec539f756afcefad4e508c098b9a7e1d8feb19955fb02ba9675585078710969d3440f5054e0f9dc3e7fe016e050eff260334f18a5d4fe391d82092319f5964f2e2eb7c1c3a5f8b13a49e282f609c317a833fb8d976d11517c571d1221a265d25af778ecf8923490c6ceeb450aecdc82e28293031d10c7d73bf85e57bf041a97360aa2c5d99cc1df82d9c4b87413eae2ef048f94b4d3554cea73d92b0f7af96e0271c691e2bb5c67add7c6caf302256adedf7ab114da0acfe870d449a3a489f781d659e8beccda7bce9f4e8618b6bd2f4132ce798cdc7a60e7e1460a7299e3c6342a579626d22733e50f526ec2fa19a22b31e8ed50f23cd1fdf94c9154ed3a7609a2f1ff981fe1d3b5c807b281e4683cc6d6315cf95b9ade8641defcb32372f1c126e398ef7a5a2dce0a8a7f68bb74560f8f71837c2c2ebbcbf7fffb42ae1896f13f7c7479a0b46a28b6f55540f89444f63de0378e3d121be09e06cc9ded1c20e65876d36aa0c65e9645644786b620e2dd2ad648ddfcbf4a7e5b1a3a4ecfe7f64667a3f0b7e2f4418588ed35a2458cffeb39b93d26f18d2ab13bdce6aee58e7b99359ec2dfd95a9c16dc00d6ef18b7933a6f8dc65ccb55667138776f7dea101070dc8796e3774df84f40ae0c8229d0d6069e5c8f39a7c299677a09d367fc7b05e3bc380ee652cdc72595f74c7b1043d0e1ffbab734648c838dfb0527d971b602bc216c9619ef0abf5ac974a1ed57f4050aa510dd9c74f508277b39d7973bb2dfccc5eeb0618d6a3e23902bafb21ac312e717f7942f8fd8ae795f67c918083442c2ab253cc66e0000000000000000000000000000000000000000000000000000"; + hex"e14ced3200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000acab5a39c6f974b22302e96dcdef1815483eaf580639bb1ee7ac98267afac2bf1ac041d3ff12045b73c86e4ff95ff662a5eee82abdf44a2d0b75fb180daf48a79e3143a81fa7c3d90b000000000000000000000078fc2ffac2fd940100000000000080c8ffffffff006504aeffb6e08baf3f85da5476a9160fa8f9f188a722fdd29268b0cbaf596736ad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb500000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007c6000000000000ffffffff000000000000000000000000f1f85ff4f1f85ff8506d442dbb3938f83eb60825a7ecbff2000010185e1a31f600050f0000000064a7c3d90be5acea102ad7bda149e0bfd0e7111c77d98b335645e665389becadf140ef999cc64fbd7f04799e85c97dadc5cca510bd5b3d97166d1aec28829f3dd43d8cf1f9358e4103b16d09d466e2c7c048ea3ba1aef3141e700270581aa0b75b50e34fc926bb2d83ad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb500000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000ad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5b4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d3021ddb9a356815c3fac1026b6dec5df3124afbadb485c9ba5a3e3398a04b7ba85e58769b32a1beaf1ea27375a44095a0d1fb664ce2dd358e7fcbfb78c26a193440eb01ebfc9ed27500cd4dfc979272d1f0913cc9f66540d7e8005811109e1cf2d887c22bd8750d34016ac3c66b5ff102dacdd73f6b014e710b51e8022af9a1968ffd70157e48063fc33c97a050f7f640233bf646cc98d9524c6b92bcf3ab56f839867cc5f7f196b93bae1e27e6320742445d290f2263827498b54fec539f756afcefad4e508c098b9a7e1d8feb19955fb02ba9675585078710969d3440f5054e0f9dc3e7fe016e050eff260334f18a5d4fe391d82092319f5964f2e2eb7c1c3a5f8b13a49e282f609c317a833fb8d976d11517c571d1221a265d25af778ecf8923490c6ceeb450aecdc82e28293031d10c7d73bf85e57bf041a97360aa2c5d99cc1df82d9c4b87413eae2ef048f94b4d3554cea73d92b0f7af96e0271c691e2bb5c67add7c6caf302256adedf7ab114da0acfe870d449a3a489f781d659e8beccda7bce9f4e8618b6bd2f4132ce798cdc7a60e7e1460a7299e3c6342a579626d22733e50f526ec2fa19a22b31e8ed50f23cd1fdf94c9154ed3a7609a2f1ff981fe1d3b5c807b281e4683cc6d6315cf95b9ade8641defcb32372f1c126e398ef7a5a2dce0a8a7f68bb74560f8f71837c2c2ebbcbf7fffb42ae1896f13f7c7479a0b46a28b6f55540f89444f63de0378e3d121be09e06cc9ded1c20e65876d36aa0c65e9645644786b620e2dd2ad648ddfcbf4a7e5b1a3a4ecfe7f64667a3f0b7e2f4418588ed35a2458cffeb39b93d26f18d2ab13bdce6aee58e7b99359ec2dfd95a9c16dc00d6ef18b7933a6f8dc65ccb55667138776f7dea101070dc8796e3774df84f40ae0c8229d0d6069e5c8f39a7c299677a09d367fc7b05e3bc380ee652cdc72595f74c7b1043d0e1ffbab734648c838dfb0527d971b602bc216c9619ef0abf5ac974a1ed57f4050aa510dd9c74f508277b39d7973bb2dfccc5eeb0618db8cd74046ff337f0a7bf2c8e03e10f642c1886798d71806ab1e888d9e5ee87d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; (bool success, bytes memory retVal) = address(mips).call(input); - bytes memory expectedRetVal = hex"03fc952a0bd8aabc407669b857af995eab91ce55c404d8b32eaf8b941a48188c"; + bytes memory expectedRetVal = hex"0335fe4205f8443eefa7ac4541197874224df35e8536158c2fc2d5c8c2d2adb4"; assertTrue(success); assertEq(retVal.length, 32, "Expect a bytes32 hash of the post-state to be returned"); @@ -175,6 +177,9 @@ contract MIPS2_Test is CommonTest { preimageKey: bytes32(0), preimageOffset: 0, heap: 0, + llReservationActive: false, + llAddress: 0, + llOwnerThread: 0, exitCode: 0, exited: false, step: 1, @@ -191,6 +196,36 @@ contract MIPS2_Test is CommonTest { assertNotEq(post, bytes32(0)); } + /// @notice Tests that the mips step function fails when the value of the exited field is + /// invalid (anything greater than 1). + function test_step_invalidExitedValueInState_fails() external { + // Bound to invalid exited values. + for (uint8 exited = 2; exited <= type(uint8).max && exited != 0;) { + // Setup state + uint32 insn = encodespec(17, 18, 8, 0x20); // Arbitrary instruction: add t0, s1, s2 + (MIPS2.State memory state, MIPS2.ThreadState memory thread, bytes memory memProof) = + constructMIPSState(0, insn, 0x4, 0); + + // Set up step data + bytes memory encodedThread = encodeThread(thread); + bytes memory threadWitness = abi.encodePacked(encodedThread, EMPTY_THREAD_ROOT); + bytes memory proofData = bytes.concat(threadWitness, memProof); + bytes memory stateData = encodeState(state); + assembly { + // Manipulate state data + // Push offset by an additional 32 bytes (0x20) to account for length prefix + mstore8(add(add(stateData, 0x20), 82), exited) + } + + // Call the step function and expect a revert. + vm.expectRevert(InvalidExitedValue.selector); + mips.step(stateData, proofData, 0); + unchecked { + exited++; + } + } + } + function test_invalidThreadWitness_reverts() public { MIPS2.State memory state; MIPS2.ThreadState memory thread; @@ -435,7 +470,7 @@ contract MIPS2_Test is CommonTest { MIPS2.ThreadState memory expectThread = copyThread(thread); expectThread.pc = thread.nextPC; expectThread.nextPC = thread.nextPC + 4; - expectThread.futexAddr = futexAddr; + expectThread.futexAddr = sys.FUTEX_EMPTY_ADDR; expectThread.registers[2] = sys.SYS_ERROR_SIGNAL; expectThread.registers[7] = sys.EAGAIN; // errno threading.replaceCurrent(expectThread); @@ -565,6 +600,211 @@ contract MIPS2_Test is CommonTest { assertEq(postState, outputState(expect), "unexpected post state"); } + function test_syscallGetPid_succeeds() public { + uint32 insn = 0x0000000c; // syscall + (MIPS2.State memory state, MIPS2.ThreadState memory thread, bytes memory memProof) = + constructMIPSState(0, insn, 0x4, 0); + thread.registers[2] = sys.SYS_GETPID; + thread.registers[7] = 0xdead; + bytes memory threadWitness = abi.encodePacked(encodeThread(thread), EMPTY_THREAD_ROOT); + updateThreadStacks(state, thread); + + MIPS2.ThreadState memory expectThread = copyThread(thread); + expectThread.pc = thread.nextPC; + expectThread.nextPC = thread.nextPC + 4; + expectThread.registers[2] = 0x0; + expectThread.registers[7] = 0x0; + MIPS2.State memory expect = copyState(state); + expect.step = state.step + 1; + expect.stepsSinceLastContextSwitch = state.stepsSinceLastContextSwitch + 1; + expect.leftThreadStack = keccak256(abi.encodePacked(EMPTY_THREAD_ROOT, keccak256(encodeThread(expectThread)))); + + bytes32 postState = mips.step(encodeState(state), bytes.concat(threadWitness, memProof), 0); + assertEq(postState, outputState(expect), "unexpected post state"); + } + + /// @dev static unit test asserting that clock_gettime syscall for monotonic time succeeds + function test_syscallClockGettimeMonotonic_succeeds() public { + _test_syscallClockGettime_succeeds(sys.CLOCK_GETTIME_MONOTONIC_FLAG); + } + + /// @dev static unit test asserting that clock_gettime syscall for real time succeeds + function test_syscallClockGettimeRealtime_succeeds() public { + _test_syscallClockGettime_succeeds(sys.CLOCK_GETTIME_REALTIME_FLAG); + } + + function _test_syscallClockGettime_succeeds(uint32 clkid) internal { + uint32 pc = 0; + uint32 insn = 0x0000000c; // syscall + uint32 timespecAddr = 0xb000; + (MIPS2.State memory state, MIPS2.ThreadState memory thread, bytes memory insnAndMemProof) = + constructMIPSState(pc, insn, timespecAddr, 0xbad); + state.step = 100_000_004; + thread.registers[2] = sys.SYS_CLOCKGETTIME; + thread.registers[A0_REG] = clkid; + thread.registers[A1_REG] = timespecAddr; + thread.registers[7] = 0xdead; + + uint32 secs = 0; + uint32 nsecs = 0; + if (clkid == sys.CLOCK_GETTIME_MONOTONIC_FLAG) { + secs = 10; + nsecs = 500; + } + bytes memory threadWitness = abi.encodePacked(encodeThread(thread), EMPTY_THREAD_ROOT); + updateThreadStacks(state, thread); + (, bytes memory memProof2) = ffi.getCannonMemoryProof2(pc, insn, timespecAddr, secs, timespecAddr + 4); + + MIPS2.State memory expect = copyState(state); + (expect.memRoot,) = ffi.getCannonMemoryProof(pc, insn, timespecAddr, secs, timespecAddr + 4, nsecs); + expect.step = state.step + 1; + expect.stepsSinceLastContextSwitch = state.stepsSinceLastContextSwitch + 1; + MIPS2.ThreadState memory expectThread = copyThread(thread); + expectThread.pc = thread.nextPC; + expectThread.nextPC = thread.nextPC + 4; + expectThread.registers[2] = 0x0; + expectThread.registers[7] = 0x0; + expect.leftThreadStack = keccak256(abi.encodePacked(EMPTY_THREAD_ROOT, keccak256(encodeThread(expectThread)))); + + bytes32 postState = mips.step(encodeState(state), bytes.concat(threadWitness, insnAndMemProof, memProof2), 0); + assertEq(postState, outputState(expect), "unexpected post state"); + } + + /// @dev static unit test asserting that clock_gettime syscall for monotonic time succeeds in writing to an + /// unaligned address + function test_syscallClockGettimeMonotonicUnaligned_succeeds() public { + _test_syscallClockGettimeUnaligned_succeeds(sys.CLOCK_GETTIME_MONOTONIC_FLAG); + } + + /// @dev static unit test asserting that clock_gettime syscall for real time succeeds in writing to an + /// unaligned address + function test_syscallClockGettimeRealtimeUnaligned_succeeds() public { + _test_syscallClockGettimeUnaligned_succeeds(sys.CLOCK_GETTIME_REALTIME_FLAG); + } + + function _test_syscallClockGettimeUnaligned_succeeds(uint32 clkid) internal { + uint32 pc = 0; + uint32 insn = 0x0000000c; // syscall + uint32 timespecAddr = 0xb001; + uint32 timespecAddrAligned = 0xb000; + (MIPS2.State memory state, MIPS2.ThreadState memory thread, bytes memory insnAndMemProof) = + constructMIPSState(pc, insn, timespecAddrAligned, 0xbad); + state.step = 100_000_004; + thread.registers[2] = sys.SYS_CLOCKGETTIME; + thread.registers[A0_REG] = clkid; + thread.registers[A1_REG] = timespecAddr; + thread.registers[7] = 0xdead; + + uint32 secs = 0; + uint32 nsecs = 0; + if (clkid == sys.CLOCK_GETTIME_MONOTONIC_FLAG) { + secs = 10; + nsecs = 500; + } + bytes memory threadWitness = abi.encodePacked(encodeThread(thread), EMPTY_THREAD_ROOT); + updateThreadStacks(state, thread); + (, bytes memory memProof2) = + ffi.getCannonMemoryProof2(pc, insn, timespecAddrAligned, secs, timespecAddrAligned + 4); + + MIPS2.State memory expect = copyState(state); + (expect.memRoot,) = + ffi.getCannonMemoryProof(pc, insn, timespecAddrAligned, secs, timespecAddrAligned + 4, nsecs); + expect.step = state.step + 1; + expect.stepsSinceLastContextSwitch = state.stepsSinceLastContextSwitch + 1; + MIPS2.ThreadState memory expectThread = copyThread(thread); + expectThread.pc = thread.nextPC; + expectThread.nextPC = thread.nextPC + 4; + expectThread.registers[2] = 0x0; + expectThread.registers[7] = 0x0; + expect.leftThreadStack = keccak256(abi.encodePacked(EMPTY_THREAD_ROOT, keccak256(encodeThread(expectThread)))); + + bytes32 postState = mips.step(encodeState(state), bytes.concat(threadWitness, insnAndMemProof, memProof2), 0); + assertEq(postState, outputState(expect), "unexpected post state"); + } + + /// @dev Test asserting that an clock_gettime monotonic syscall reverts on an invalid memory proof + function test_syscallClockGettimeMonotonicInvalidProof_reverts() public { + _test_syscallClockGettimeInvalidProof_reverts(sys.CLOCK_GETTIME_MONOTONIC_FLAG); + } + + /// @dev Test asserting that an clock_gettime realtime syscall reverts on an invalid memory proof + function test_syscallClockGettimeRealtimeInvalidProof_reverts() public { + _test_syscallClockGettimeInvalidProof_reverts(sys.CLOCK_GETTIME_REALTIME_FLAG); + } + + function _test_syscallClockGettimeInvalidProof_reverts(uint32 clkid) internal { + // NOTE: too slow to run this test under the forge fuzzer. + for (uint256 proofIndex = 896 + (32 * 2); proofIndex < 896 * 2; proofIndex += 32) { + // proofIndex points to a leaf in the index in the memory proof (in insnAndMemProof) that will be zeroed. + // Note that the second leaf in the memory proof is already zeroed because it's the sibling of the first + // memory write. So start from the third leaf. + + uint32 secs = 0; + if (clkid == sys.CLOCK_GETTIME_MONOTONIC_FLAG) { + secs = 10; + } + uint32 pc = 0; + uint32 insn = 0x0000000c; // syscall + uint32 timespecAddr = 0xb000; + (MIPS2.State memory state, MIPS2.ThreadState memory thread, bytes memory insnAndMemProof) = + constructMIPSState(pc, insn, timespecAddr, 0xbad); + state.step = 100_000_004; + thread.registers[2] = sys.SYS_CLOCKGETTIME; + thread.registers[A0_REG] = sys.CLOCK_GETTIME_MONOTONIC_FLAG; + thread.registers[A1_REG] = timespecAddr; + thread.registers[7] = 0xdead; + bytes memory threadWitness = abi.encodePacked(encodeThread(thread), EMPTY_THREAD_ROOT); + updateThreadStacks(state, thread); + (, bytes memory memProof2) = ffi.getCannonMemoryProof2(pc, insn, timespecAddr, secs, timespecAddr + 4); + + bytes memory invalidInsnAndMemProof = new bytes(insnAndMemProof.length); + for (uint256 i = 0; i < invalidInsnAndMemProof.length; i++) { + // clear the 32-byte insn leaf + if (i >= proofIndex && i < proofIndex + 32) { + invalidInsnAndMemProof[i] = 0x0; + } else { + invalidInsnAndMemProof[i] = insnAndMemProof[i]; + } + } + vm.expectRevert(InvalidMemoryProof.selector); + mips.step(encodeState(state), bytes.concat(threadWitness, invalidInsnAndMemProof, memProof2), 0); + + (, bytes memory invalidMemProof2) = + ffi.getCannonMemoryProof2(pc, insn, timespecAddr, secs + 1, timespecAddr + 4); + vm.expectRevert(InvalidSecondMemoryProof.selector); + mips.step(encodeState(state), bytes.concat(threadWitness, insnAndMemProof, invalidMemProof2), 0); + } + } + + /// @dev static unit test asserting that clock_gettime syscall for non-realtime, non-monotonic time succeeds + function test_syscallClockGettimeOtherFlags_succeeds() public { + uint32 pc = 0; + uint32 insn = 0x0000000c; // syscall + uint32 timespecAddr = 0xb000; + (MIPS2.State memory state, MIPS2.ThreadState memory thread, bytes memory insnAndMemProof) = + constructMIPSState(pc, insn, timespecAddr, 0xbad); + state.step = (sys.HZ * 10 + 5) - 1; + thread.registers[2] = sys.SYS_CLOCKGETTIME; + thread.registers[A0_REG] = sys.CLOCK_GETTIME_MONOTONIC_FLAG + 1; + thread.registers[A1_REG] = timespecAddr; + thread.registers[7] = 0xdead; + bytes memory threadWitness = abi.encodePacked(encodeThread(thread), EMPTY_THREAD_ROOT); + updateThreadStacks(state, thread); + + MIPS2.ThreadState memory expectThread = copyThread(thread); + expectThread.pc = thread.nextPC; + expectThread.nextPC = thread.nextPC + 4; + expectThread.registers[2] = sys.SYS_ERROR_SIGNAL; + expectThread.registers[7] = sys.EINVAL; + MIPS2.State memory expect = copyState(state); + expect.step = state.step + 1; + expect.stepsSinceLastContextSwitch = state.stepsSinceLastContextSwitch + 1; + expect.leftThreadStack = keccak256(abi.encodePacked(EMPTY_THREAD_ROOT, keccak256(encodeThread(expectThread)))); + + bytes32 postState = mips.step(encodeState(state), bytes.concat(threadWitness, insnAndMemProof), 0); + assertEq(postState, outputState(expect), "unexpected post state"); + } + /// @dev Static unit test asserting that VM preempts threads after a certain number of steps function test_threadQuantumSchedule_succeeds() public { MIPS2.ThreadState memory threadA = threading.createThread(); @@ -1076,6 +1316,166 @@ contract MIPS2_Test is CommonTest { assertEq(postState, outputState(expect), "unexpected post state"); } + function test_mmap_succeeds_simple() external { + uint32 insn = 0x0000000c; // syscall + (MIPS2.State memory state, MIPS2.ThreadState memory thread, bytes memory memProof) = + constructMIPSState(0, insn, 0x4, 0); + + state.heap = 4096; + thread.nextPC = 4; + thread.registers[2] = sys.SYS_MMAP; // syscall num + thread.registers[4] = 0x0; // a0 + thread.registers[5] = 4095; // a1 + updateThreadStacks(state, thread); + + // Set up step data + bytes memory threadWitness = abi.encodePacked(encodeThread(thread), EMPTY_THREAD_ROOT); + bytes memory encodedState = encodeState(state); + + MIPS2.State memory expect = copyState(state); + MIPS2.ThreadState memory expectThread = copyThread(thread); + expect.memRoot = state.memRoot; + expect.step = state.step + 1; + expect.stepsSinceLastContextSwitch = state.stepsSinceLastContextSwitch + 1; + expect.heap = state.heap + 4096; + expectThread.pc = thread.nextPC; + expectThread.nextPC = thread.nextPC + 4; + expectThread.registers[2] = state.heap; // return old heap + expectThread.registers[7] = 0; // No error + updateThreadStacks(expect, expectThread); + + bytes32 postState = mips.step(encodedState, bytes.concat(threadWitness, memProof), 0); + assertEq(postState, outputState(expect), "unexpected post state"); + } + + function test_mmap_succeeds_justWithinMemLimit() external { + uint32 insn = 0x0000000c; // syscall + (MIPS2.State memory state, MIPS2.ThreadState memory thread, bytes memory memProof) = + constructMIPSState(0, insn, 0x4, 0); + + state.heap = sys.HEAP_END - 4096; // Set up to increase heap to its limit + thread.nextPC = 4; + thread.registers[2] = sys.SYS_MMAP; // syscall num + thread.registers[4] = 0x0; // a0 + thread.registers[5] = 4095; // a1 + updateThreadStacks(state, thread); + + // Set up step data + bytes memory threadWitness = abi.encodePacked(encodeThread(thread), EMPTY_THREAD_ROOT); + bytes memory encodedState = encodeState(state); + + MIPS2.State memory expect = copyState(state); + MIPS2.ThreadState memory expectThread = copyThread(thread); + expect.memRoot = state.memRoot; + expect.step += 1; + expect.stepsSinceLastContextSwitch += 1; + expect.heap = sys.HEAP_END; + expectThread.pc = thread.nextPC; + expectThread.nextPC = thread.nextPC + 4; + expectThread.registers[2] = state.heap; // Return the old heap value + expectThread.registers[7] = 0; // No error + updateThreadStacks(expect, expectThread); + + bytes32 postState = mips.step(encodedState, bytes.concat(threadWitness, memProof), 0); + assertEq(postState, outputState(expect), "unexpected post state"); + } + + function test_mmap_fails() external { + uint32 insn = 0x0000000c; // syscall + (MIPS2.State memory state, MIPS2.ThreadState memory thread, bytes memory memProof) = + constructMIPSState(0, insn, 0x4, 0); + + state.heap = sys.HEAP_END - 4096; // Set up to increase heap beyond its limit + thread.nextPC = 4; + thread.registers[2] = sys.SYS_MMAP; // syscall num + thread.registers[4] = 0x0; // a0 + thread.registers[5] = 4097; // a1 + updateThreadStacks(state, thread); + + // Set up step data + bytes memory threadWitness = abi.encodePacked(encodeThread(thread), EMPTY_THREAD_ROOT); + bytes memory encodedState = encodeState(state); + + MIPS2.State memory expect = copyState(state); + MIPS2.ThreadState memory expectThread = copyThread(thread); + expect.memRoot = state.memRoot; + expect.step += 1; + expect.stepsSinceLastContextSwitch += 1; + expectThread.pc = thread.nextPC; + expectThread.nextPC = thread.nextPC + 4; + expectThread.registers[2] = sys.SYS_ERROR_SIGNAL; // signal an stdError + expectThread.registers[7] = sys.EINVAL; // Return error value + expectThread.registers[4] = thread.registers[4]; // a0 + expectThread.registers[5] = thread.registers[5]; // a1 + updateThreadStacks(expect, expectThread); + + bytes32 postState = mips.step(encodedState, bytes.concat(threadWitness, memProof), 0); + assertEq(postState, outputState(expect), "unexpected post state"); + } + + function test_srav_succeeds() external { + uint32 insn = encodespec(0xa, 0x9, 0x8, 7); // srav t0, t1, t2 + (MIPS2.State memory state, MIPS2.ThreadState memory thread, bytes memory memProof) = + constructMIPSState(0, insn, 0x4, 0); + thread.registers[9] = 0xdeafbeef; // t1 + thread.registers[10] = 12; // t2 + updateThreadStacks(state, thread); + + // Set up step data + bytes memory threadWitness = abi.encodePacked(encodeThread(thread), EMPTY_THREAD_ROOT); + bytes memory encodedState = encodeState(state); + + MIPS2.State memory expect = copyState(state); + MIPS2.ThreadState memory expectThread = copyThread(thread); + expect.memRoot = state.memRoot; + expect.step += 1; + expect.stepsSinceLastContextSwitch += 1; + expectThread.pc = thread.nextPC; + expectThread.nextPC = thread.nextPC + 4; + expectThread.registers[8] = 0xfffdeafb; // t0 + updateThreadStacks(expect, expectThread); + + bytes32 postState = mips.step(encodedState, bytes.concat(threadWitness, memProof), 0); + assertEq(postState, outputState(expect), "unexpected post state"); + } + + /// @notice Tests that the SRAV instruction succeeds when it includes extra bits in the shift + /// amount beyond the lower 5 bits that are actually used for the shift. Extra bits + /// need to be ignored but the instruction should still succeed. + /// @param _rs Value to set in the shift register $rs. + function testFuzz_srav_withExtraBits_succeeds(uint32 _rs) external { + // Assume + // Force _rs to have more than 5 bits set. + _rs = uint32(bound(uint256(_rs), 0x20, type(uint32).max)); + + uint32 insn = encodespec(0xa, 0x9, 0x8, 7); // srav t0, t1, t2 + (MIPS2.State memory state, MIPS2.ThreadState memory thread, bytes memory memProof) = + constructMIPSState(0, insn, 0x4, 0); + thread.registers[9] = 0xdeadbeef; // t1 + thread.registers[10] = _rs; // t2 + updateThreadStacks(state, thread); + + // Set up step data + bytes memory threadWitness = abi.encodePacked(encodeThread(thread), EMPTY_THREAD_ROOT); + bytes memory encodedState = encodeState(state); + + // Calculate shamt + uint32 shamt = thread.registers[10] & 0x1F; + + MIPS2.State memory expect = copyState(state); + MIPS2.ThreadState memory expectThread = copyThread(thread); + expect.memRoot = state.memRoot; + expect.step += 1; + expect.stepsSinceLastContextSwitch += 1; + expectThread.pc = thread.nextPC; + expectThread.nextPC = thread.nextPC + 4; + expectThread.registers[8] = ins.signExtend(thread.registers[9] >> shamt, 32 - shamt); // t0 + updateThreadStacks(expect, expectThread); + + bytes32 postState = mips.step(encodedState, bytes.concat(threadWitness, memProof), 0); + assertEq(postState, outputState(expect), "unexpected post state"); + } + function test_add_succeeds() public { uint32 insn = encodespec(17, 18, 8, 0x20); // add t0, s1, s2 (MIPS2.State memory state, MIPS2.ThreadState memory thread, bytes memory memProof) = @@ -1595,36 +1995,50 @@ contract MIPS2_Test is CommonTest { } function test_ll_succeeds() public { - uint32 t1 = 0x100; - uint32 val = 0x12_23_45_67; - uint32 insn = encodeitype(0x30, 0x9, 0x8, 0x4); // ll $t0, 4($t1) + uint32 base = 0x100; + uint32 memVal = 0x12_23_45_67; + uint16 offset = 0x4; + uint32 effAddr = base + offset; + uint32 insn = encodeitype(0x30, 0x9, 0x8, offset); // ll baseReg, rtReg, offset + (MIPS2.State memory state, MIPS2.ThreadState memory thread, bytes memory memProof) = - constructMIPSState(0, insn, t1 + 4, val); - thread.registers[8] = 0; // t0 - thread.registers[9] = t1; + constructMIPSState(0, insn, effAddr, memVal); + thread.registers[8] = 0; // rtReg + thread.registers[9] = base; bytes memory threadWitness = abi.encodePacked(encodeThread(thread), EMPTY_THREAD_ROOT); updateThreadStacks(state, thread); - thread.registers[8] = val; // t0 - MIPS2.State memory expect = arithmeticPostState(state, thread, 8, /* t0 */ thread.registers[8]); + MIPS2.State memory expect = arithmeticPostState(state, thread, 8, memVal); + expect.llReservationActive = true; + expect.llAddress = effAddr; + expect.llOwnerThread = thread.threadID; bytes32 postState = mips.step(encodeState(state), bytes.concat(threadWitness, memProof), 0); assertEq(postState, outputState(expect), "unexpected post state"); } function test_sc_succeeds() public { - uint32 t1 = 0x100; - uint32 insn = encodeitype(0x38, 0x9, 0x8, 0x4); // sc $t0, 4($t1) - (MIPS2.State memory state, MIPS2.ThreadState memory thread, bytes memory memProof) = - constructMIPSState(0, insn, t1 + 4, 0); - thread.registers[8] = 0xaa_bb_cc_dd; // t0 - thread.registers[9] = t1; + uint32 base = 0x100; + uint16 offset = 0x4; + uint32 effAddr = base + offset; + uint32 writeMemVal = 0xaa_bb_cc_dd; + uint32 insn = encodeitype(0x38, 0x9, 0x8, offset); // ll baseReg, rtReg, offset + + (MIPS2.State memory state, MIPS2.ThreadState memory thread, bytes memory memProof) = + constructMIPSState(0, insn, effAddr, 0); + state.llReservationActive = true; + state.llAddress = effAddr; + state.llOwnerThread = thread.threadID; + thread.registers[8] = writeMemVal; + thread.registers[9] = base; bytes memory threadWitness = abi.encodePacked(encodeThread(thread), EMPTY_THREAD_ROOT); updateThreadStacks(state, thread); - thread.registers[8] = 0x1; // t0 - MIPS2.State memory expect = arithmeticPostState(state, thread, 8, /* t0 */ thread.registers[8]); - (expect.memRoot,) = ffi.getCannonMemoryProof(0, insn, t1 + 4, 0xaa_bb_cc_dd); + MIPS2.State memory expect = arithmeticPostState(state, thread, 8, 0x1); + (expect.memRoot,) = ffi.getCannonMemoryProof(0, insn, effAddr, writeMemVal); + expect.llReservationActive = false; + expect.llAddress = 0; + expect.llOwnerThread = 0; bytes32 postState = mips.step(encodeState(state), bytes.concat(threadWitness, memProof), 0); assertEq(postState, outputState(expect), "unexpected post state"); @@ -2049,8 +2463,209 @@ contract MIPS2_Test is CommonTest { assertEq(postState, outputState(expect), "unexpected post state"); } - // TODO(client-pod#959): Port over the remaining single-threaded tests from MIPS.t.sol - // TODO(client-pod#959): Assert unimplemented syscalls + function test_sll_succeeds() external { + uint8 shiftamt = 4; + uint32 insn = encodespec(0x0, 0x9, 0x8, uint16(shiftamt) << 6); // sll t0, t1, 3 + (MIPS2.State memory state, MIPS2.ThreadState memory thread, bytes memory memProof) = + constructMIPSState(0, insn, 0x4, 0); + thread.registers[9] = 0x20; // t1 + updateThreadStacks(state, thread); + + uint32 result = thread.registers[9] << shiftamt; + MIPS2.State memory expect = arithmeticPostState(state, thread, 8, /* t0 */ result); + + bytes32 postState = mips.step( + encodeState(state), bytes.concat(abi.encodePacked(encodeThread(thread), EMPTY_THREAD_ROOT), memProof), 0 + ); + assertEq(postState, outputState(expect), "unexpected post state"); + } + + function test_srl_succeeds() external { + uint8 shiftamt = 4; + uint32 insn = encodespec(0x0, 0x9, 0x8, uint16(shiftamt) << 6 | 2); // srl t0, t1, 3 + (MIPS2.State memory state, MIPS2.ThreadState memory thread, bytes memory memProof) = + constructMIPSState(0, insn, 0x4, 0); + thread.registers[9] = 0x20; // t1 + updateThreadStacks(state, thread); + + uint32 result = thread.registers[9] >> shiftamt; + MIPS2.State memory expect = arithmeticPostState(state, thread, 8, /* t0 */ result); + + bytes32 postState = mips.step( + encodeState(state), bytes.concat(abi.encodePacked(encodeThread(thread), EMPTY_THREAD_ROOT), memProof), 0 + ); + assertEq(postState, outputState(expect), "unexpected post state"); + } + + function test_sra_succeeds() external { + uint8 shiftamt = 4; + uint32 insn = encodespec(0x0, 0x9, 0x8, uint16(shiftamt) << 6 | 3); // sra t0, t1, 3 + (MIPS2.State memory state, MIPS2.ThreadState memory thread, bytes memory memProof) = + constructMIPSState(0, insn, 0x4, 0); + thread.registers[9] = 0x80_00_00_20; // t1 + updateThreadStacks(state, thread); + + uint32 result = 0xF8_00_00_02; // 4 shifts while preserving sign bit + MIPS2.State memory expect = arithmeticPostState(state, thread, 8, /* t0 */ result); + + bytes32 postState = mips.step( + encodeState(state), bytes.concat(abi.encodePacked(encodeThread(thread), EMPTY_THREAD_ROOT), memProof), 0 + ); + assertEq(postState, outputState(expect), "unexpected post state"); + } + + function test_sllv_succeeds() external { + uint32 insn = encodespec(0xa, 0x9, 0x8, 4); // sllv t0, t1, t2 + (MIPS2.State memory state, MIPS2.ThreadState memory thread, bytes memory memProof) = + constructMIPSState(0, insn, 0x4, 0); + thread.registers[9] = 0x20; // t1 + thread.registers[10] = 4; // t2 + updateThreadStacks(state, thread); + + uint32 result = thread.registers[9] << thread.registers[10]; + MIPS2.State memory expect = arithmeticPostState(state, thread, 8, /* t0 */ result); + + bytes32 postState = mips.step( + encodeState(state), bytes.concat(abi.encodePacked(encodeThread(thread), EMPTY_THREAD_ROOT), memProof), 0 + ); + assertEq(postState, outputState(expect), "unexpected post state"); + } + + function test_srlv_succeeds() external { + uint32 insn = encodespec(0xa, 0x9, 0x8, 6); // srlv t0, t1, t2 + (MIPS2.State memory state, MIPS2.ThreadState memory thread, bytes memory memProof) = + constructMIPSState(0, insn, 0x4, 0); + thread.registers[9] = 0x20_00; // t1 + thread.registers[10] = 4; // t2 + updateThreadStacks(state, thread); + + uint32 result = thread.registers[9] >> thread.registers[10]; + MIPS2.State memory expect = arithmeticPostState(state, thread, 8, /* t0 */ result); + + bytes32 postState = mips.step( + encodeState(state), bytes.concat(abi.encodePacked(encodeThread(thread), EMPTY_THREAD_ROOT), memProof), 0 + ); + assertEq(postState, outputState(expect), "unexpected post state"); + } + + function test_lui_succeeds() external { + uint32 insn = encodeitype(0xf, 0x0, 0x8, 0x4); // lui $t0, 0x04 + (MIPS2.State memory state, MIPS2.ThreadState memory thread, bytes memory memProof) = + constructMIPSState(0, insn, 0x4, 0); + updateThreadStacks(state, thread); + + MIPS2.State memory expect = arithmeticPostState(state, thread, 8, /* t0 */ 0x00_04_00_00); + bytes32 postState = mips.step( + encodeState(state), bytes.concat(abi.encodePacked(encodeThread(thread), EMPTY_THREAD_ROOT), memProof), 0 + ); + assertEq(postState, outputState(expect), "unexpected post state"); + } + + function test_clo_succeeds() external { + uint32 insn = encodespec2(0x9, 0x0, 0x8, 0x21); // clo t0, t1 + (MIPS2.State memory state, MIPS2.ThreadState memory thread, bytes memory memProof) = + constructMIPSState(0, insn, 0x4, 0); + thread.registers[9] = 0xFF_00_00_00; // t1 + updateThreadStacks(state, thread); + + MIPS2.State memory expect = arithmeticPostState(state, thread, 8, /* t0 */ 8); + bytes32 postState = mips.step( + encodeState(state), bytes.concat(abi.encodePacked(encodeThread(thread), EMPTY_THREAD_ROOT), memProof), 0 + ); + assertEq(postState, outputState(expect), "unexpected post state"); + } + + function test_clz_succeeds() external { + uint32 insn = encodespec2(0x9, 0x0, 0x8, 0x20); // clz t0, t1 + (MIPS2.State memory state, MIPS2.ThreadState memory thread, bytes memory memProof) = + constructMIPSState(0, insn, 0x4, 0); + thread.registers[9] = 0x00_00_F0_00; // t1 + updateThreadStacks(state, thread); + + MIPS2.State memory expect = arithmeticPostState(state, thread, 8, /* t0 */ 16); + bytes32 postState = mips.step( + encodeState(state), bytes.concat(abi.encodePacked(encodeThread(thread), EMPTY_THREAD_ROOT), memProof), 0 + ); + assertEq(postState, outputState(expect), "unexpected post state"); + } + + function test_preimage_read_succeeds() external { + uint32 pc = 0x0; + uint32 insn = 0x0000000c; // syscall + uint32 a1 = 0x4; + uint32 a1_val = 0x0000abba; + (MIPS2.State memory state, MIPS2.ThreadState memory thread, bytes memory memProof) = + constructMIPSState(0, insn, a1, a1_val); + state.preimageKey = bytes32(uint256(1) << 248 | 0x01); + state.preimageOffset = 8; // start reading past the pre-image length prefix + thread.registers[2] = 4003; // read syscall + thread.registers[4] = 5; // fd + thread.registers[5] = a1; // addr + thread.registers[6] = 4; // count + threading.createThread(); + threading.replaceCurrent(thread); + bytes memory threadWitness = threading.witness(); + finalizeThreadingState(threading, state); + + MIPS2.ThreadState memory expectThread = copyThread(thread); + expectThread.pc = thread.nextPC; + expectThread.nextPC = thread.nextPC + 4; + expectThread.registers[2] = 4; // return + expectThread.registers[7] = 0; // errno + threading.replaceCurrent(expectThread); + + // prime the pre-image oracle + bytes32 word = bytes32(uint256(0xdeadbeef) << 224); + uint8 size = 4; + uint8 partOffset = 8; + oracle.loadLocalData(uint256(state.preimageKey), 0, word, size, partOffset); + + MIPS2.State memory expect = copyState(state); + expect.preimageOffset += 4; + expect.step = state.step + 1; + expect.stepsSinceLastContextSwitch = state.stepsSinceLastContextSwitch + 1; + // recompute merkle root of written pre-image + (expect.memRoot,) = ffi.getCannonMemoryProof(pc, insn, a1, 0xdeadbeef); + finalizeThreadingState(threading, expect); + + bytes32 postState = mips.step(encodeState(state), bytes.concat(threadWitness, memProof), 0); + assertEq(postState, outputState(expect), "unexpected post state"); + } + + function test_preimage_write_succeeds() external { + uint32 insn = 0x0000000c; // syscall + uint32 a1 = 0x4; + uint32 a1_val = 0x0000abba; + (MIPS2.State memory state, MIPS2.ThreadState memory thread, bytes memory memProof) = + constructMIPSState(0, insn, a1, a1_val); + state.preimageKey = bytes32(0); + state.preimageOffset = 1; + thread.registers[2] = 4004; // write syscall + thread.registers[4] = 6; // fd + thread.registers[5] = a1; // addr + thread.registers[6] = 4; // count + threading.createThread(); + threading.replaceCurrent(thread); + bytes memory threadWitness = threading.witness(); + finalizeThreadingState(threading, state); + + MIPS2.ThreadState memory expectThread = copyThread(thread); + expectThread.pc = thread.nextPC; + expectThread.nextPC = thread.nextPC + 4; + expectThread.registers[2] = 4; // return + expectThread.registers[7] = 0; // errno + threading.replaceCurrent(expectThread); + + MIPS2.State memory expect = copyState(state); + expect.preimageKey = bytes32(uint256(0xabba)); + expect.preimageOffset = 0; + expect.step = state.step + 1; + expect.stepsSinceLastContextSwitch = state.stepsSinceLastContextSwitch + 1; + finalizeThreadingState(threading, expect); + + bytes32 postState = mips.step(encodeState(state), bytes.concat(threadWitness, memProof), 0); + assertEq(postState, outputState(expect), "unexpected post state"); + } /// @dev Modifies the MIPS2 State based on threading state function finalizeThreadingState(Threading _threading, MIPS2.State memory _state) internal view { @@ -2131,23 +2746,33 @@ contract MIPS2_Test is CommonTest { } function encodeState(MIPS2.State memory _state) internal pure returns (bytes memory) { + // Split up encoding to get around stack-too-deep error + return abi.encodePacked(encodeStateA(_state), encodeStateB(_state)); + } + + function encodeStateA(MIPS2.State memory _state) internal pure returns (bytes memory) { return abi.encodePacked( _state.memRoot, _state.preimageKey, _state.preimageOffset, _state.heap, + _state.llReservationActive, + _state.llAddress, + _state.llOwnerThread, _state.exitCode, _state.exited, _state.step, _state.stepsSinceLastContextSwitch, _state.wakeup, _state.traverseRight, - _state.leftThreadStack, - _state.rightThreadStack, - _state.nextThreadID + _state.leftThreadStack ); } + function encodeStateB(MIPS2.State memory _state) internal pure returns (bytes memory) { + return abi.encodePacked(_state.rightThreadStack, _state.nextThreadID); + } + function copyState(MIPS2.State memory _state) internal pure returns (MIPS2.State memory out_) { bytes memory data = abi.encode(_state); return abi.decode(data, (MIPS2.State)); @@ -2175,8 +2800,11 @@ contract MIPS2_Test is CommonTest { } } - function outputState(MIPS2.State memory state) internal pure returns (bytes32 out_) { + event ExpectedOutputState(bytes encoded, MIPS2.State state); + + function outputState(MIPS2.State memory state) internal returns (bytes32 out_) { bytes memory enc = encodeState(state); + emit ExpectedOutputState(enc, state); VMStatus status = vmStatus(state); out_ = keccak256(enc); assembly { diff --git a/packages/contracts-bedrock/test/dispute/AnchorStateRegistry.t.sol b/packages/contracts-bedrock/test/dispute/AnchorStateRegistry.t.sol index 96729cdb7215e..b5dbac76f6c6a 100644 --- a/packages/contracts-bedrock/test/dispute/AnchorStateRegistry.t.sol +++ b/packages/contracts-bedrock/test/dispute/AnchorStateRegistry.t.sol @@ -1,12 +1,14 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.15; +// Testing +import { Test } from "forge-std/Test.sol"; +import { FaultDisputeGame_Init, _changeClaimStatus } from "test/dispute/FaultDisputeGame.t.sol"; + +// Libraries import "src/dispute/lib/Types.sol"; import "src/dispute/lib/Errors.sol"; -import { Test } from "forge-std/Test.sol"; -import { FaultDisputeGame_Init, IDisputeGame, _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. diff --git a/packages/contracts-bedrock/test/dispute/DelayedWETH.t.sol b/packages/contracts-bedrock/test/dispute/DelayedWETH.t.sol index 7ee45c9b87b3d..bde1e1b9f893e 100644 --- a/packages/contracts-bedrock/test/dispute/DelayedWETH.t.sol +++ b/packages/contracts-bedrock/test/dispute/DelayedWETH.t.sol @@ -1,17 +1,15 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.15; -import "src/dispute/lib/Types.sol"; -import "src/dispute/lib/Errors.sol"; - +// Testing 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 { Burn } from "src/libraries/Burn.sol"; import { CommonTest } from "test/setup/CommonTest.sol"; +// Libraries +import { Burn } from "src/libraries/Burn.sol"; +import "src/dispute/lib/Types.sol"; +import "src/dispute/lib/Errors.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); diff --git a/packages/contracts-bedrock/test/dispute/DisputeGameFactory.t.sol b/packages/contracts-bedrock/test/dispute/DisputeGameFactory.t.sol index 09a087fb5d776..6c3ed2a189441 100644 --- a/packages/contracts-bedrock/test/dispute/DisputeGameFactory.t.sol +++ b/packages/contracts-bedrock/test/dispute/DisputeGameFactory.t.sol @@ -1,14 +1,20 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.15; +// Testing +import { Test } from "forge-std/Test.sol"; +import { CommonTest } from "test/setup/CommonTest.sol"; + +// Contracts +import { Proxy } from "src/universal/Proxy.sol"; + +// Libraries import "src/dispute/lib/Types.sol"; import "src/dispute/lib/Errors.sol"; -import { Test } from "forge-std/Test.sol"; -import { DisputeGameFactory, IDisputeGameFactory } from "src/dispute/DisputeGameFactory.sol"; +// Interfaces +import { IDisputeGameFactory } from "src/dispute/interfaces/IDisputeGameFactory.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 { FakeClone fakeClone; diff --git a/packages/contracts-bedrock/test/dispute/FaultDisputeGame.t.sol b/packages/contracts-bedrock/test/dispute/FaultDisputeGame.t.sol index b01ecec1811c9..bc6537e460e4d 100644 --- a/packages/contracts-bedrock/test/dispute/FaultDisputeGame.t.sol +++ b/packages/contracts-bedrock/test/dispute/FaultDisputeGame.t.sol @@ -1,35 +1,41 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.15; +// Testing 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 { FaultDisputeGame, IDisputeGame } from "src/dispute/FaultDisputeGame.sol"; -import { DelayedWETH } from "src/dispute/weth/DelayedWETH.sol"; +import { AlphabetVM } from "test/mocks/AlphabetVM.sol"; + +// Contracts import { PreimageOracle } from "src/cannon/PreimageOracle.sol"; +import { FaultDisputeGame } from "src/dispute/FaultDisputeGame.sol"; +import { DisputeActor, HonestDisputeActor } from "test/actors/FaultDisputeActors.sol"; -import "src/dispute/lib/Types.sol"; -import "src/dispute/lib/Errors.sol"; +// Libraries import { Types } from "src/libraries/Types.sol"; import { Hashing } from "src/libraries/Hashing.sol"; import { RLPWriter } from "src/libraries/rlp/RLPWriter.sol"; import { LibClock } from "src/dispute/lib/LibUDT.sol"; import { LibPosition } from "src/dispute/lib/LibPosition.sol"; +import "src/dispute/lib/Types.sol"; +import "src/dispute/lib/Errors.sol"; + +// Interfaces +import { IDisputeGame } from "src/dispute/interfaces/IDisputeGame.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"; +import { IFaultDisputeGame } from "src/dispute/interfaces/IFaultDisputeGame.sol"; +import { IDelayedWETH } from "src/dispute/interfaces/IDelayedWETH.sol"; contract FaultDisputeGame_Init is DisputeGameFactory_Init { /// @dev The type of the game being tested. GameType internal constant GAME_TYPE = GameType.wrap(0); /// @dev The implementation of the game. - FaultDisputeGame internal gameImpl; + IFaultDisputeGame internal gameImpl; /// @dev The `Clone` proxy of the game. - FaultDisputeGame internal gameProxy; + IFaultDisputeGame internal gameProxy; /// @dev The extra data passed to the game for initialization. bytes internal extraData; @@ -51,23 +57,27 @@ contract FaultDisputeGame_Init is DisputeGameFactory_Init { AlphabetVM _vm = new AlphabetVM(absolutePrestate, oracle); // Deploy an implementation of the fault game - gameImpl = new FaultDisputeGame({ - _gameType: GAME_TYPE, - _absolutePrestate: absolutePrestate, - _maxGameDepth: 2 ** 3, - _splitDepth: 2 ** 2, - _clockExtension: Duration.wrap(3 hours), - _maxClockDuration: Duration.wrap(3.5 days), - _vm: _vm, - _weth: delayedWeth, - _anchorStateRegistry: anchorStateRegistry, - _l2ChainId: 10 - }); + gameImpl = IFaultDisputeGame( + address( + new FaultDisputeGame({ + _gameType: GAME_TYPE, + _absolutePrestate: absolutePrestate, + _maxGameDepth: 2 ** 3, + _splitDepth: 2 ** 2, + _clockExtension: Duration.wrap(3 hours), + _maxClockDuration: Duration.wrap(3.5 days), + _vm: _vm, + _weth: delayedWeth, + _anchorStateRegistry: anchorStateRegistry, + _l2ChainId: 10 + }) + ) + ); // Register the game implementation with the factory. disputeGameFactory.setImplementation(GAME_TYPE, gameImpl); // Create a new game. - gameProxy = FaultDisputeGame(payable(address(disputeGameFactory.create(GAME_TYPE, rootClaim, extraData)))); + gameProxy = IFaultDisputeGame(payable(address(disputeGameFactory.create(GAME_TYPE, rootClaim, extraData)))); // Check immutables assertEq(gameProxy.gameType().raw(), GAME_TYPE.raw()); @@ -125,7 +135,7 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { _clockExtension: Duration.wrap(3 hours), _maxClockDuration: Duration.wrap(3.5 days), _vm: alphabetVM, - _weth: DelayedWETH(payable(address(0))), + _weth: IDelayedWETH(payable(address(0))), _anchorStateRegistry: IAnchorStateRegistry(address(0)), _l2ChainId: 10 }); @@ -156,7 +166,7 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { _clockExtension: Duration.wrap(3 hours), _maxClockDuration: Duration.wrap(3.5 days), _vm: alphabetVM, - _weth: DelayedWETH(payable(address(0))), + _weth: IDelayedWETH(payable(address(0))), _anchorStateRegistry: IAnchorStateRegistry(address(0)), _l2ChainId: 10 }); @@ -178,7 +188,7 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { _clockExtension: Duration.wrap(3 hours), _maxClockDuration: Duration.wrap(3.5 days), _vm: alphabetVM, - _weth: DelayedWETH(payable(address(0))), + _weth: IDelayedWETH(payable(address(0))), _anchorStateRegistry: IAnchorStateRegistry(address(0)), _l2ChainId: 10 }); @@ -200,7 +210,7 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { _clockExtension: Duration.wrap(3 hours), _maxClockDuration: Duration.wrap(3.5 days), _vm: alphabetVM, - _weth: DelayedWETH(payable(address(0))), + _weth: IDelayedWETH(payable(address(0))), _anchorStateRegistry: IAnchorStateRegistry(address(0)), _l2ChainId: 10 }); @@ -230,7 +240,7 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { _clockExtension: Duration.wrap(_clockExtension), _maxClockDuration: Duration.wrap(_maxClockDuration), _vm: alphabetVM, - _weth: DelayedWETH(payable(address(0))), + _weth: IDelayedWETH(payable(address(0))), _anchorStateRegistry: IAnchorStateRegistry(address(0)), _l2ChainId: 10 }); @@ -278,7 +288,7 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { Claim claim = _dummyClaim(); vm.expectRevert(abi.encodeWithSelector(UnexpectedRootClaim.selector, claim)); gameProxy = - FaultDisputeGame(payable(address(disputeGameFactory.create(GAME_TYPE, claim, abi.encode(_blockNumber))))); + IFaultDisputeGame(payable(address(disputeGameFactory.create(GAME_TYPE, claim, abi.encode(_blockNumber))))); } /// @dev Tests that the proxy receives ETH from the dispute game factory. @@ -287,7 +297,7 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { vm.deal(address(this), _value); assertEq(address(gameProxy).balance, 0); - gameProxy = FaultDisputeGame( + gameProxy = IFaultDisputeGame( payable(address(disputeGameFactory.create{ value: _value }(GAME_TYPE, ROOT_CLAIM, abi.encode(1)))) ); assertEq(address(gameProxy).balance, 0); @@ -315,7 +325,7 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init { Claim claim = _dummyClaim(); vm.expectRevert(abi.encodeWithSelector(BadExtraData.selector)); - gameProxy = FaultDisputeGame(payable(address(disputeGameFactory.create(GAME_TYPE, claim, _extraData)))); + gameProxy = IFaultDisputeGame(payable(address(disputeGameFactory.create(GAME_TYPE, claim, _extraData)))); } /// @dev Tests that the game is initialized with the correct data. @@ -2568,10 +2578,10 @@ contract FaultDispute_1v1_Actors_Test is FaultDisputeGame_Init { contract ClaimCreditReenter { Vm internal immutable vm; - FaultDisputeGame internal immutable GAME; + IFaultDisputeGame internal immutable GAME; uint256 public numCalls; - constructor(FaultDisputeGame _gameProxy, Vm _vm) { + constructor(IFaultDisputeGame _gameProxy, Vm _vm) { GAME = _gameProxy; vm = _vm; } diff --git a/packages/contracts-bedrock/test/dispute/PermissionedDisputeGame.t.sol b/packages/contracts-bedrock/test/dispute/PermissionedDisputeGame.t.sol index 5d3fc6f70f799..8a3639b71cdf8 100644 --- a/packages/contracts-bedrock/test/dispute/PermissionedDisputeGame.t.sol +++ b/packages/contracts-bedrock/test/dispute/PermissionedDisputeGame.t.sol @@ -1,25 +1,26 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.15; +// Testing 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 { AlphabetVM } from "test/mocks/AlphabetVM.sol"; + +// Contracts 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 { DelayedWETH } from "src/dispute/DelayedWETH.sol"; +// Libraries +import { Types } from "src/libraries/Types.sol"; import "src/dispute/lib/Types.sol"; import "src/dispute/lib/Errors.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"; +// Interfaces +import { IBigStepper, IPreimageOracle } from "src/dispute/interfaces/IBigStepper.sol"; +import { IDelayedWETH } from "src/dispute/interfaces/IDelayedWETH.sol"; +import { IPermissionedDisputeGame } from "src/dispute/interfaces/IPermissionedDisputeGame.sol"; contract PermissionedDisputeGame_Init is DisputeGameFactory_Init { /// @dev The type of the game being tested. @@ -30,9 +31,9 @@ contract PermissionedDisputeGame_Init is DisputeGameFactory_Init { address internal constant CHALLENGER = address(0xfacadec); /// @dev The implementation of the game. - PermissionedDisputeGame internal gameImpl; + IPermissionedDisputeGame internal gameImpl; /// @dev The `Clone` proxy of the game. - PermissionedDisputeGame internal gameProxy; + IPermissionedDisputeGame internal gameProxy; /// @dev The extra data passed to the game for initialization. bytes internal extraData; @@ -49,29 +50,33 @@ contract PermissionedDisputeGame_Init is DisputeGameFactory_Init { AlphabetVM _vm = new AlphabetVM(absolutePrestate, new PreimageOracle(0, 0)); // Use a 7 day delayed WETH to simulate withdrawals. - DelayedWETH _weth = new DelayedWETH(7 days); + IDelayedWETH _weth = IDelayedWETH(payable(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, - _clockExtension: Duration.wrap(3 hours), - _maxClockDuration: Duration.wrap(3.5 days), - _vm: _vm, - _weth: _weth, - _anchorStateRegistry: anchorStateRegistry, - _l2ChainId: 10, - _proposer: PROPOSER, - _challenger: CHALLENGER - }); + gameImpl = IPermissionedDisputeGame( + address( + new PermissionedDisputeGame({ + _gameType: GAME_TYPE, + _absolutePrestate: absolutePrestate, + _maxGameDepth: 2 ** 3, + _splitDepth: 2 ** 2, + _clockExtension: Duration.wrap(3 hours), + _maxClockDuration: Duration.wrap(3.5 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)))); + IPermissionedDisputeGame(payable(address(disputeGameFactory.create(GAME_TYPE, rootClaim, extraData)))); // Check immutables assertEq(gameProxy.proposer(), PROPOSER); diff --git a/packages/contracts-bedrock/test/dispute/WETH98.t.sol b/packages/contracts-bedrock/test/dispute/WETH98.t.sol index 6573a9d005c5b..a248e19018854 100644 --- a/packages/contracts-bedrock/test/dispute/WETH98.t.sol +++ b/packages/contracts-bedrock/test/dispute/WETH98.t.sol @@ -1,7 +1,11 @@ +// SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Testing import { Test } from "forge-std/Test.sol"; -import { WETH98 } from "src/dispute/weth/WETH98.sol"; + +// Contracts +import { WETH98 } from "src/universal/WETH98.sol"; contract WETH98_Test is Test { event Approval(address indexed src, address indexed guy, uint256 wad); diff --git a/packages/contracts-bedrock/test/fixtures/standard-versions.toml b/packages/contracts-bedrock/test/fixtures/standard-versions.toml new file mode 100644 index 0000000000000..cb4d336a73364 --- /dev/null +++ b/packages/contracts-bedrock/test/fixtures/standard-versions.toml @@ -0,0 +1,47 @@ +standard_release = "op-contracts/v1.6.0" + +[releases] + +# Contracts which are +# * unproxied singletons: specify a standard "address" +# * proxied : specify a standard "implementation_address" +# * neither : specify neither a standard "address" nor "implementation_address" + +# Fault Proofs https://github.com/ethereum-optimism/optimism/releases/tag/op-contracts%2Fv1.6.0 +[releases."op-contracts/v1.6.0"] +optimism_portal = { version = "3.10.0", implementation_address = "0xe2F826324b2faf99E513D16D266c3F80aE87832B" } +system_config = { version = "2.2.0", implementation_address = "0xF56D96B2535B932656d3c04Ebf51baBff241D886" } +anchor_state_registry = { version = "2.0.0" } +delayed_weth = { version = "1.1.0", implementation_address = "0x71e966Ae981d1ce531a7b6d23DC0f27B38409087" } +dispute_game_factory = { version = "1.0.0", implementation_address = "0xc641A33cab81C559F2bd4b21EA34C290E2440C2B" } +fault_dispute_game = { version = "1.3.0" } +permissioned_dispute_game = { version = "1.3.0" } +mips = { version = "1.1.0", address = "0x16e83cE5Ce29BF90AD9Da06D2fE6a15d5f344ce4" } +preimage_oracle = { version = "1.1.2", address = "0x9c065e11870B891D214Bc2Da7EF1f9DDFA1BE277" } +l1_cross_domain_messenger = { version = "2.3.0", implementation_address = "0xD3494713A5cfaD3F5359379DfA074E2Ac8C6Fd65" } +l1_erc721_bridge = { version = "2.1.0", implementation_address = "0xAE2AF01232a6c4a4d3012C5eC5b1b35059caF10d" } +l1_standard_bridge = { version = "2.1.0", implementation_address = "0x64B5a5Ed26DCb17370Ff4d33a8D503f0fbD06CfF" } +# l2_output_oracle -- This contract not used in fault proofs +optimism_mintable_erc20_factory = { version = "1.9.0", implementation_address = "0xE01efbeb1089D1d1dB9c6c8b135C934C0734c846" } + +# Fault Proofs https://github.com/ethereum-optimism/optimism/releases/tag/op-contracts%2Fv1.4.0 +[releases."op-contracts/v1.4.0"] +optimism_portal = { version = "3.10.0", implementation_address = "0xe2F826324b2faf99E513D16D266c3F80aE87832B" } +system_config = { version = "2.2.0", implementation_address = "0xF56D96B2535B932656d3c04Ebf51baBff241D886" } +anchor_state_registry = { version = "1.0.0" } +delayed_weth = { version = "1.0.0", implementation_address = "0x97988d5624F1ba266E1da305117BCf20713bee08" } +dispute_game_factory = { version = "1.0.0", implementation_address = "0xc641A33cab81C559F2bd4b21EA34C290E2440C2B" } +fault_dispute_game = { version = "1.2.0" } +permissioned_dispute_game = { version = "1.2.0" } +mips = { version = "1.0.1", address = "0x0f8EdFbDdD3c0256A80AD8C0F2560B1807873C9c" } +preimage_oracle = { version = "1.0.0", address = "0xD326E10B8186e90F4E2adc5c13a2d0C137ee8b34" } + +# MCP https://github.com/ethereum-optimism/optimism/releases/tag/op-contracts%2Fv1.3.0 +[releases."op-contracts/v1.3.0"] +l1_cross_domain_messenger = { version = "2.3.0", implementation_address = "0xD3494713A5cfaD3F5359379DfA074E2Ac8C6Fd65" } +l1_erc721_bridge = { version = "2.1.0", implementation_address = "0xAE2AF01232a6c4a4d3012C5eC5b1b35059caF10d" } +l1_standard_bridge = { version = "2.1.0", implementation_address = "0x64B5a5Ed26DCb17370Ff4d33a8D503f0fbD06CfF" } +l2_output_oracle = { version = "1.8.0", implementation_address = "0xF243BEd163251380e78068d317ae10f26042B292" } +optimism_mintable_erc20_factory = { version = "1.9.0", implementation_address = "0xE01efbeb1089D1d1dB9c6c8b135C934C0734c846" } +optimism_portal = { version = "2.5.0", implementation_address = "0x2D778797049FE9259d947D1ED8e5442226dFB589" } +system_config = { version = "1.12.0", implementation_address = "0xba2492e52F45651B60B8B38d4Ea5E2390C64Ffb1" } diff --git a/packages/contracts-bedrock/test/governance/MintManager.t.sol b/packages/contracts-bedrock/test/governance/MintManager.t.sol index 690fa15c0d256..4c008863ed691 100644 --- a/packages/contracts-bedrock/test/governance/MintManager.t.sol +++ b/packages/contracts-bedrock/test/governance/MintManager.t.sol @@ -1,30 +1,32 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -// Testing utilities +// Testing import { CommonTest } from "test/setup/CommonTest.sol"; -// Target contract dependencies +// Contracts import { GovernanceToken } from "src/governance/GovernanceToken.sol"; - -// Target contract import { MintManager } from "src/governance/MintManager.sol"; +// Interfaces +import { IGovernanceToken } from "src/governance/interfaces/IGovernanceToken.sol"; +import { IMintManager } from "src/governance/interfaces/IMintManager.sol"; + contract MintManager_Initializer is CommonTest { address constant owner = address(0x1234); address constant rando = address(0x5678); - GovernanceToken internal gov; - MintManager internal manager; + IGovernanceToken internal gov; + IMintManager internal manager; /// @dev Sets up the test suite. function setUp() public virtual override { super.setUp(); vm.prank(owner); - gov = new GovernanceToken(); + gov = IGovernanceToken(address(new GovernanceToken())); vm.prank(owner); - manager = new MintManager(owner, address(gov)); + manager = IMintManager(address(new MintManager(owner, address(gov)))); vm.prank(owner); gov.transferOwnership(address(manager)); diff --git a/packages/contracts-bedrock/test/invariants/CrossDomainMessenger.t.sol b/packages/contracts-bedrock/test/invariants/CrossDomainMessenger.t.sol index b0b64253493bd..08a0c0027763e 100644 --- a/packages/contracts-bedrock/test/invariants/CrossDomainMessenger.t.sol +++ b/packages/contracts-bedrock/test/invariants/CrossDomainMessenger.t.sol @@ -3,8 +3,8 @@ pragma solidity 0.8.15; import { StdUtils } from "forge-std/StdUtils.sol"; import { Vm } from "forge-std/Vm.sol"; -import { OptimismPortal } from "src/L1/OptimismPortal.sol"; -import { L1CrossDomainMessenger } from "src/L1/L1CrossDomainMessenger.sol"; +import { IOptimismPortal } from "src/L1/interfaces/IOptimismPortal.sol"; +import { IL1CrossDomainMessenger } from "src/L1/interfaces/IL1CrossDomainMessenger.sol"; import { Bridge_Initializer } from "test/setup/Bridge_Initializer.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; import { Constants } from "src/libraries/Constants.sol"; @@ -20,12 +20,12 @@ contract RelayActor is StdUtils { bytes32[] public hashes; bool public reverted = false; - OptimismPortal op; - L1CrossDomainMessenger xdm; + IOptimismPortal op; + IL1CrossDomainMessenger xdm; Vm vm; bool doFail; - constructor(OptimismPortal _op, L1CrossDomainMessenger _xdm, Vm _vm, bool _doFail) { + constructor(IOptimismPortal _op, IL1CrossDomainMessenger _xdm, Vm _vm, bool _doFail) { op = _op; xdm = _xdm; vm = _vm; diff --git a/packages/contracts-bedrock/test/invariants/ETHLiquidity.t.sol b/packages/contracts-bedrock/test/invariants/ETHLiquidity.t.sol index a7da876adb3be..8d1221a792c1b 100644 --- a/packages/contracts-bedrock/test/invariants/ETHLiquidity.t.sol +++ b/packages/contracts-bedrock/test/invariants/ETHLiquidity.t.sol @@ -1,13 +1,16 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Testing import { StdUtils } from "forge-std/Test.sol"; import { Vm } from "forge-std/Vm.sol"; +import { CommonTest } from "test/setup/CommonTest.sol"; +// Libraries import { Predeploys } from "src/libraries/Predeploys.sol"; -import { ETHLiquidity } from "src/L2/ETHLiquidity.sol"; -import { CommonTest } from "test/setup/CommonTest.sol"; +// Interfaces +import { IETHLiquidity } from "src/L2/interfaces/IETHLiquidity.sol"; /// @title ETHLiquidity_User /// @notice Actor contract that interacts with the ETHLiquidity contract. Always pretends to be the @@ -20,12 +23,12 @@ contract ETHLiquidity_User is StdUtils { Vm internal vm; /// @notice The ETHLiquidity contract. - ETHLiquidity internal liquidity; + IETHLiquidity internal liquidity; /// @param _vm The Vm contract. /// @param _liquidity The ETHLiquidity contract. /// @param _balance The initial balance of the contract. - constructor(Vm _vm, ETHLiquidity _liquidity, uint256 _balance) { + constructor(Vm _vm, IETHLiquidity _liquidity, uint256 _balance) { vm = _vm; liquidity = _liquidity; vm.deal(Predeploys.SUPERCHAIN_WETH, _balance); diff --git a/packages/contracts-bedrock/test/invariants/FaultDisputeGame.t.sol b/packages/contracts-bedrock/test/invariants/FaultDisputeGame.t.sol index 295b9f315abf8..49bf2a106bbf4 100644 --- a/packages/contracts-bedrock/test/invariants/FaultDisputeGame.t.sol +++ b/packages/contracts-bedrock/test/invariants/FaultDisputeGame.t.sol @@ -1,14 +1,18 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Testing import { Vm } from "forge-std/Vm.sol"; import { StdUtils } from "forge-std/StdUtils.sol"; -import { FaultDisputeGame } from "src/dispute/FaultDisputeGame.sol"; import { FaultDisputeGame_Init } from "test/dispute/FaultDisputeGame.t.sol"; +// Libraries import "src/dispute/lib/Types.sol"; import "src/dispute/lib/Errors.sol"; +// Interfaces +import { IFaultDisputeGame } from "src/dispute/interfaces/IFaultDisputeGame.sol"; + contract FaultDisputeGame_Solvency_Invariant is FaultDisputeGame_Init { Claim internal constant ROOT_CLAIM = Claim.wrap(bytes32(uint256(10))); Claim internal constant ABSOLUTE_PRESTATE = Claim.wrap(bytes32((uint256(3) << 248) | uint256(0))); @@ -73,12 +77,12 @@ contract FaultDisputeGame_Solvency_Invariant is FaultDisputeGame_Init { } contract RandomClaimActor is StdUtils { - FaultDisputeGame internal immutable GAME; + IFaultDisputeGame internal immutable GAME; Vm internal immutable VM; uint256 public totalBonded; - constructor(FaultDisputeGame _gameProxy, Vm _vm) { + constructor(IFaultDisputeGame _gameProxy, Vm _vm) { GAME = _gameProxy; VM = _vm; } diff --git a/packages/contracts-bedrock/test/invariants/L2OutputOracle.t.sol b/packages/contracts-bedrock/test/invariants/L2OutputOracle.t.sol index 5152d7688be2a..95eac249a5ba4 100644 --- a/packages/contracts-bedrock/test/invariants/L2OutputOracle.t.sol +++ b/packages/contracts-bedrock/test/invariants/L2OutputOracle.t.sol @@ -2,14 +2,14 @@ pragma solidity 0.8.15; import { CommonTest } from "test/setup/CommonTest.sol"; -import { L2OutputOracle } from "src/L1/L2OutputOracle.sol"; +import { IL2OutputOracle } from "src/L1/interfaces/IL2OutputOracle.sol"; import { Vm } from "forge-std/Vm.sol"; contract L2OutputOracle_Proposer { - L2OutputOracle internal oracle; + IL2OutputOracle internal oracle; Vm internal vm; - constructor(L2OutputOracle _oracle, Vm _vm) { + constructor(IL2OutputOracle _oracle, Vm _vm) { oracle = _oracle; vm = _vm; } @@ -36,7 +36,7 @@ contract L2OutputOracle_MonotonicBlockNumIncrease_Invariant is CommonTest { super.setUp(); // Create a proposer actor. - actor = new L2OutputOracle_Proposer(l2OutputOracle, vm); + actor = new L2OutputOracle_Proposer(IL2OutputOracle(address(l2OutputOracle)), vm); // Set the target contract to the proposer actor. targetContract(address(actor)); diff --git a/packages/contracts-bedrock/test/invariants/OptimismPortal.t.sol b/packages/contracts-bedrock/test/invariants/OptimismPortal.t.sol index 804de43202860..8e5319d9aeb68 100644 --- a/packages/contracts-bedrock/test/invariants/OptimismPortal.t.sol +++ b/packages/contracts-bedrock/test/invariants/OptimismPortal.t.sol @@ -4,9 +4,9 @@ pragma solidity 0.8.15; import { StdUtils } from "forge-std/Test.sol"; import { Vm } from "forge-std/Vm.sol"; -import { OptimismPortal } from "src/L1/OptimismPortal.sol"; -import { L2OutputOracle } from "src/L1/L2OutputOracle.sol"; +import { IOptimismPortal } from "src/L1/interfaces/IOptimismPortal.sol"; import { ResourceMetering } from "src/L1/ResourceMetering.sol"; +import { IResourceMetering } from "src/L1/interfaces/IResourceMetering.sol"; import { Constants } from "src/libraries/Constants.sol"; import { CommonTest } from "test/setup/CommonTest.sol"; @@ -15,10 +15,10 @@ import { Types } from "src/libraries/Types.sol"; contract OptimismPortal_Depositor is StdUtils, ResourceMetering { Vm internal vm; - OptimismPortal internal portal; + IOptimismPortal internal portal; bool public failedToComplete; - constructor(Vm _vm, OptimismPortal _portal) { + constructor(Vm _vm, IOptimismPortal _portal) { vm = _vm; portal = _portal; initialize(); @@ -32,9 +32,11 @@ contract OptimismPortal_Depositor is StdUtils, ResourceMetering { return _resourceConfig(); } - function _resourceConfig() internal pure override returns (ResourceMetering.ResourceConfig memory) { - ResourceMetering.ResourceConfig memory rcfg = Constants.DEFAULT_RESOURCE_CONFIG(); - return rcfg; + function _resourceConfig() internal pure override returns (ResourceMetering.ResourceConfig memory config_) { + IResourceMetering.ResourceConfig memory rcfg = Constants.DEFAULT_RESOURCE_CONFIG(); + assembly ("memory-safe") { + config_ := rcfg + } } // A test intended to identify any unexpected halting conditions diff --git a/packages/contracts-bedrock/test/invariants/OptimismPortal2.t.sol b/packages/contracts-bedrock/test/invariants/OptimismPortal2.t.sol index 56c2c1849feb3..dec4525a00945 100644 --- a/packages/contracts-bedrock/test/invariants/OptimismPortal2.t.sol +++ b/packages/contracts-bedrock/test/invariants/OptimismPortal2.t.sol @@ -1,29 +1,32 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Testing import { StdUtils } from "forge-std/Test.sol"; import { Vm } from "forge-std/Vm.sol"; +import { CommonTest } from "test/setup/CommonTest.sol"; +import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; -import { OptimismPortal2 } from "src/L1/OptimismPortal2.sol"; -import { AddressAliasHelper } from "src/vendor/AddressAliasHelper.sol"; -import { SystemConfig } from "src/L1/SystemConfig.sol"; +// Contracts 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"; +// Libraries +import { Constants } from "src/libraries/Constants.sol"; import { Types } from "src/libraries/Types.sol"; - -import { FaultDisputeGame } from "src/dispute/FaultDisputeGame.sol"; import "src/dispute/lib/Types.sol"; import "src/libraries/PortalErrors.sol"; +// Interfaces +import { IOptimismPortal2 } from "src/L1/interfaces/IOptimismPortal2.sol"; +import { IResourceMetering } from "src/L1/interfaces/IResourceMetering.sol"; +import { IFaultDisputeGame } from "src/dispute/interfaces/IFaultDisputeGame.sol"; + contract OptimismPortal2_Depositor is StdUtils, ResourceMetering { Vm internal vm; - OptimismPortal2 internal portal; + IOptimismPortal2 internal portal; bool public failedToComplete; - constructor(Vm _vm, OptimismPortal2 _portal) { + constructor(Vm _vm, IOptimismPortal2 _portal) { vm = _vm; portal = _portal; initialize(); @@ -37,9 +40,11 @@ contract OptimismPortal2_Depositor is StdUtils, ResourceMetering { return _resourceConfig(); } - function _resourceConfig() internal pure override returns (ResourceMetering.ResourceConfig memory) { - ResourceMetering.ResourceConfig memory rcfg = Constants.DEFAULT_RESOURCE_CONFIG(); - return rcfg; + function _resourceConfig() internal pure override returns (ResourceMetering.ResourceConfig memory config_) { + IResourceMetering.ResourceConfig memory rcfg = Constants.DEFAULT_RESOURCE_CONFIG(); + assembly ("memory-safe") { + config_ := rcfg + } } // A test intended to identify any unexpected halting conditions @@ -116,7 +121,7 @@ contract OptimismPortal2_Invariant_Harness is CommonTest { // Create a dispute game with the output root we've proposed. _proposedBlockNumber = 0xFF; - FaultDisputeGame game = FaultDisputeGame( + IFaultDisputeGame game = IFaultDisputeGame( payable( address( disputeGameFactory.create( diff --git a/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20.t.sol b/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20.t.sol deleted file mode 100644 index 028a0124e6ca6..0000000000000 --- a/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20.t.sol +++ /dev/null @@ -1,225 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.25; - -// Testing utilities -import { Test, StdUtils, Vm } from "forge-std/Test.sol"; -import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; - -// Libraries -import { Predeploys } from "src/libraries/Predeploys.sol"; -import { OptimismSuperchainERC20 } from "src/L2/OptimismSuperchainERC20.sol"; -import { IL2ToL2CrossDomainMessenger } from "src/L2/IL2ToL2CrossDomainMessenger.sol"; - -/// @title OptimismSuperchainERC20_User -/// @notice Actor contract that interacts with the OptimismSuperchainERC20 contract. -contract OptimismSuperchainERC20_User is StdUtils { - address public immutable receiver; - - /// @notice Cross domain message data. - struct MessageData { - bytes32 id; - uint256 amount; - } - - uint256 public totalAmountSent; - uint256 public totalAmountRelayed; - - /// @notice Flag to indicate if the test has failed. - bool public failed = false; - - /// @notice The Vm contract. - Vm internal vm; - - /// @notice The OptimismSuperchainERC20 contract. - OptimismSuperchainERC20 internal superchainERC20; - - /// @notice Mapping of sent messages. - mapping(bytes32 => bool) internal sent; - - /// @notice Array of unrelayed messages. - MessageData[] internal unrelayed; - - /// @param _vm The Vm contract. - /// @param _superchainERC20 The OptimismSuperchainERC20 contract. - /// @param _balance The initial balance of the contract. - constructor(Vm _vm, OptimismSuperchainERC20 _superchainERC20, uint256 _balance, address _receiver) { - vm = _vm; - superchainERC20 = _superchainERC20; - - // Mint balance to this actor. - vm.prank(Predeploys.L2_STANDARD_BRIDGE); - superchainERC20.mint(address(this), _balance); - receiver = _receiver; - } - - /// @notice Send ERC20 tokens to another chain. - /// @param _amount The amount of ERC20 tokens to send. - /// @param _chainId The chain ID to send the tokens to. - /// @param _messageId The message ID. - function sendERC20(uint256 _amount, uint256 _chainId, bytes32 _messageId) public { - // Make sure we aren't reusing a message ID. - if (sent[_messageId]) { - return; - } - - // Bound send amount to our ERC20 balance. - _amount = bound(_amount, 0, superchainERC20.balanceOf(address(this))); - - // Send the amount. - try superchainERC20.sendERC20(receiver, _amount, _chainId) { - // Success. - totalAmountSent += _amount; - } catch { - failed = true; - } - - // Mark message as sent. - sent[_messageId] = true; - unrelayed.push(MessageData({ id: _messageId, amount: _amount })); - } - - /// @notice Relay a message from another chain. - function relayMessage(uint256 _source) public { - // Make sure there are unrelayed messages. - if (unrelayed.length == 0) { - return; - } - - // Grab the latest unrelayed message. - MessageData memory message = unrelayed[unrelayed.length - 1]; - - // Simulate the cross-domain message. - // Make sure the cross-domain message sender is set to this contract. - vm.mockCall( - Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER, - abi.encodeCall(IL2ToL2CrossDomainMessenger.crossDomainMessageSender, ()), - abi.encode(address(superchainERC20)) - ); - - // Simulate the cross-domain message source to any chain. - vm.mockCall( - Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER, - abi.encodeCall(IL2ToL2CrossDomainMessenger.crossDomainMessageSource, ()), - abi.encode(_source) - ); - - // Prank the relayERC20 function. - // Balance will just go back to our own account. - vm.prank(Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER); - try superchainERC20.relayERC20(address(this), receiver, message.amount) { - // Success. - totalAmountRelayed += message.amount; - } catch { - failed = true; - } - - // Remove the message from the unrelayed list. - unrelayed.pop(); - } -} - -/// @title OptimismSuperchainERC20_Invariant -/// @notice Invariant test that checks that sending OptimismSuperchainERC20 always succeeds if the actor has a -/// sufficient balance to do so and that the actor's balance does not increase out of nowhere. -contract OptimismSuperchainERC20_Invariant is Test { - /// @notice Starting balance of the contract. - uint256 public constant STARTING_BALANCE = type(uint128).max; - - /// @notice The OptimismSuperchainERC20 contract implementation. - address internal optimismSuperchainERC20Impl; - - /// @notice The OptimismSuperchainERC20_User actor. - OptimismSuperchainERC20_User internal actor; - - /// @notice The OptimismSuperchainERC20 contract. - OptimismSuperchainERC20 internal optimismSuperchainERC20; - - /// @notice The address that will receive the tokens when relaying messages - address internal receiver = makeAddr("receiver"); - - /// @notice Test setup. - function setUp() public { - // Deploy the L2ToL2CrossDomainMessenger contract. - address _impl = _setImplementationCode(Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER); - _setProxyCode(Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER, _impl); - - // Create a new OptimismSuperchainERC20 implementation. - optimismSuperchainERC20Impl = address(new OptimismSuperchainERC20()); - - // Deploy the OptimismSuperchainERC20 contract. - address _proxy = address(0x123456); - _setProxyCode(_proxy, optimismSuperchainERC20Impl); - optimismSuperchainERC20 = OptimismSuperchainERC20(_proxy); - - // Create a new OptimismSuperchainERC20_User actor. - actor = new OptimismSuperchainERC20_User(vm, optimismSuperchainERC20, STARTING_BALANCE, receiver); - - // Set the target contract. - targetContract(address(actor)); - - // Set the target selectors. - bytes4[] memory selectors = new bytes4[](2); - selectors[0] = actor.sendERC20.selector; - selectors[1] = actor.relayMessage.selector; - FuzzSelector memory selector = FuzzSelector({ addr: address(actor), selectors: selectors }); - targetSelector(selector); - - // Setup assertions - assert(optimismSuperchainERC20.balanceOf(address(actor)) == STARTING_BALANCE); - assert(optimismSuperchainERC20.balanceOf(address(receiver)) == 0); - assert(optimismSuperchainERC20.totalSupply() == STARTING_BALANCE); - } - - /// @notice Sets the bytecode in the implementation address. - function _setImplementationCode(address _addr) internal returns (address) { - string memory cname = Predeploys.getName(_addr); - address impl = Predeploys.predeployToCodeNamespace(_addr); - vm.etch(impl, vm.getDeployedCode(string.concat(cname, ".sol:", cname))); - return impl; - } - - /// @notice Sets the bytecode in the proxy address. - function _setProxyCode(address _addr, address _impl) internal { - bytes memory code = vm.getDeployedCode("universal/Proxy.sol:Proxy"); - vm.etch(_addr, code); - EIP1967Helper.setAdmin(_addr, Predeploys.PROXY_ADMIN); - EIP1967Helper.setImplementation(_addr, _impl); - } - - /// @notice Invariant that checks that sending OptimismSuperchainERC20 always succeeds. - /// @custom:invariant Calls to sendERC20 should always succeed as long as the actor has enough balance. - /// Actor's balance should also not increase out of nowhere but instead should decrease by the - /// amount sent. - function invariant_sendERC20_succeeds() public view { - // Assert that the actor has not failed to send OptimismSuperchainERC20. - assertTrue(!actor.failed()); - - // Assert that the actor has sent more than or equal to the amount relayed. - assertTrue(actor.totalAmountSent() >= actor.totalAmountRelayed()); - - // Assert that the actor's balance has decreased by the amount sent. - assertEq(optimismSuperchainERC20.balanceOf(address(actor)), STARTING_BALANCE - actor.totalAmountSent()); - - // Assert that the total supply of the OptimismSuperchainERC20 contract has decreased by the amount unrelayed. - uint256 _unrelayedAmount = actor.totalAmountSent() - actor.totalAmountRelayed(); - assertEq(optimismSuperchainERC20.totalSupply(), STARTING_BALANCE - _unrelayedAmount); - } - - /// @notice Invariant that checks that relaying OptimismSuperchainERC20 always succeeds. - /// @custom:invariant Calls to relayERC20 should always succeeds when a message is received from another chain. - /// Actor's balance should only increase by the amount relayed. - function invariant_relayERC20_succeeds() public view { - // Assert that the actor has not failed to relay OptimismSuperchainERC20. - assertTrue(!actor.failed()); - - // Assert that the actor has sent more than or equal to the amount relayed. - assertTrue(actor.totalAmountSent() >= actor.totalAmountRelayed()); - - // Assert that the actor's balance has increased by the amount relayed. - assertEq(optimismSuperchainERC20.balanceOf(address(receiver)), actor.totalAmountRelayed()); - - // Assert that the total supply of the OptimismSuperchainERC20 contract has decreased by the amount unrelayed. - uint256 _unrelayedAmount = actor.totalAmountSent() - actor.totalAmountRelayed(); - assertEq(optimismSuperchainERC20.totalSupply(), STARTING_BALANCE - _unrelayedAmount); - } -} diff --git a/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/OptimismSuperchainERC20.t.sol b/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/OptimismSuperchainERC20.t.sol new file mode 100644 index 0000000000000..d90e90a2f811c --- /dev/null +++ b/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/OptimismSuperchainERC20.t.sol @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.25; + +// Testing utilities +import { Test, StdUtils, Vm } from "forge-std/Test.sol"; +import { StdInvariant } from "forge-std/StdInvariant.sol"; +import { StdAssertions } from "forge-std/StdAssertions.sol"; +import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; + +// Libraries +import { Predeploys } from "src/libraries/Predeploys.sol"; +import { OptimismSuperchainERC20 } from "src/L2/OptimismSuperchainERC20.sol"; +import { IL2ToL2CrossDomainMessenger } from "src/L2/interfaces/IL2ToL2CrossDomainMessenger.sol"; +import { ProtocolGuided } from "./fuzz/Protocol.guided.t.sol"; +import { ProtocolUnguided } from "./fuzz/Protocol.unguided.t.sol"; +import { HandlerGetters } from "./helpers/HandlerGetters.t.sol"; +import { MockL2ToL2CrossDomainMessenger } from "./helpers/MockL2ToL2CrossDomainMessenger.t.sol"; + +contract OptimismSuperchainERC20Handler is HandlerGetters, ProtocolGuided, ProtocolUnguided { } + +contract OptimismSuperchainERC20Properties is Test { + OptimismSuperchainERC20Handler internal handler; + MockL2ToL2CrossDomainMessenger internal constant MESSENGER = + MockL2ToL2CrossDomainMessenger(Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER); + + function setUp() public { + handler = new OptimismSuperchainERC20Handler(); + targetContract(address(handler)); + } + + // TODO: will need rework after + // - `convert` + /// @custom:invariant sum of supertoken total supply across all chains is always <= to convert(legacy, super)- + /// convert(super, legacy) + function invariant_totalSupplyAcrossChainsEqualsMintsMinusFundsInTransit() external view { + // iterate over unique deploy salts aka supertokens that are supposed to be compatible with each other + for (uint256 deploySaltIndex = 0; deploySaltIndex < handler.deploySaltsLength(); deploySaltIndex++) { + uint256 totalSupply = 0; + (bytes32 currentSalt, uint256 trackedSupply) = handler.totalSupplyAcrossChainsAtIndex(deploySaltIndex); + uint256 fundsInTransit = handler.tokensInTransitForDeploySalt(currentSalt); + // and then over all the (mocked) chain ids where that supertoken could be deployed + for (uint256 validChainId = 0; validChainId < handler.MAX_CHAINS(); validChainId++) { + address supertoken = MESSENGER.superTokenAddresses(validChainId, currentSalt); + if (supertoken != address(0)) { + totalSupply += OptimismSuperchainERC20(supertoken).totalSupply(); + } + } + assertEq(trackedSupply, totalSupply + fundsInTransit); + } + } + + // TODO: will need rework after + // - `convert` + /// @custom:invariant sum of supertoken total supply across all chains is equal to convert(legacy, super)- + /// convert(super, legacy) when all when all cross-chain messages are processed + function invariant_totalSupplyAcrossChainsEqualsMintsWhenQueueIsEmpty() external view { + if (MESSENGER.messageQueueLength() != 0) { + return; + } + // iterate over unique deploy salts aka supertokens that are supposed to be compatible with each other + for (uint256 deploySaltIndex = 0; deploySaltIndex < handler.deploySaltsLength(); deploySaltIndex++) { + uint256 totalSupply = 0; + (bytes32 currentSalt, uint256 trackedSupply) = handler.totalSupplyAcrossChainsAtIndex(deploySaltIndex); + // and then over all the (mocked) chain ids where that supertoken could be deployed + for (uint256 validChainId = 0; validChainId < handler.MAX_CHAINS(); validChainId++) { + address supertoken = MESSENGER.superTokenAddresses(validChainId, currentSalt); + if (supertoken != address(0)) { + totalSupply += OptimismSuperchainERC20(supertoken).totalSupply(); + } + } + assertEq(trackedSupply, totalSupply); + } + } + + /// @custom:invariant many other assertion mode invariants are also defined under + /// `test/invariants/OptimismSuperchainERC20/fuzz/` . + /// + /// since setting`fail_on_revert=false` also ignores StdAssertion failures, this invariant explicitly asks the + /// handler for assertion test failures + function invariant_handlerAssertions() external view { + assertFalse(handler.failed()); + } +} diff --git a/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/PROPERTIES.md b/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/PROPERTIES.md new file mode 100644 index 0000000000000..18970855ca468 --- /dev/null +++ b/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/PROPERTIES.md @@ -0,0 +1,82 @@ +# Supertoken advanced testing + +## Milestones + +The supertoken ecosystem consists of not just the supertoken contract, but the required changes to other contracts for liquidity to reach the former. + +Considering only the supertoken contract is merged into the `develop` branch, and work for the other components is still in progress, we define three milestones for the testing campaign: + +- SupERC20: concerned with only the supertoken contract, the first one to be implemented +- Factories: covers the above + the development of `OptimismSuperchainERC20Factory` and required changes to `OptimismMintableERC20Factory` +- Liquidity Migration: includes the `convert` function on the `L2StandardBridgeInterop` to migrate liquidity from legacy tokens into supertokens + +## Definitions + +- *legacy token:* an OptimismMintableERC20 or L2StandardERC20 token on the suprechain that has either been deployed by the factory after the liquidity migration upgrade to the latter, or has been deployed before it **but** added to factory’s `deployments` mapping as part of the upgrade. This testing campaign is not concerned with tokens on L1 or not listed in the factory’s `deployments` mapping. +- *supertoken:* a SuperchainERC20 contract deployed by the `OptimismSuperchainERC20Factory` + +# Ecosystem properties + +legend: + +- `[ ]`: property not yet tested +- `**[ ]**`: property not yet tested, dev/research team has asked for extra focus on it +- `[X]`: tested/proven property +- `[~]`: partially tested/proven property +- `:(`: property won't be tested due to some limitation + +## Unit test + +| id | milestone | description | tested | +| --- | --- | --- | --- | +| 0 | Factories | supertoken token address does not depend on the executing chain’s chainID | [ ] | +| 1 | Factories | supertoken token address depends on remote token, name, symbol and decimals | [ ] | +| 2 | Liquidity Migration | convert() should only allow converting legacy tokens to supertoken and viceversa | [ ] | +| 3 | Liquidity Migration | convert() only allows migrations between tokens representing the same remote asset | [ ] | +| 4 | Liquidity Migration | convert() only allows migrations from tokens with the same decimals | [ ] | +| 5 | Liquidity Migration | convert() burns the same amount of legacy token that it mints of supertoken, and viceversa | [ ] | +| 25 | SupERC20 | supertokens can't be reinitialized | [x] | + +## Valid state + +| id | milestone | description | tested | +| --- | --- | --- | --- | +| 6 | SupERC20 | calls to sendERC20 succeed as long as caller has enough balance | [x] | +| 7 | SupERC20 | calls to relayERC20 always succeed as long as the cross-domain caller is valid | [~] | + +## Variable transition + +| id | milestone | description | tested | +| --- | --- | --- | --- | +| 8 | SupERC20 | sendERC20 with a value of zero does not modify accounting | [x] | +| 9 | SupERC20 | relayERC20 with a value of zero does not modify accounting | [x] | +| 10 | SupERC20 | sendERC20 decreases the token's totalSupply in the source chain exactly by the input amount | [x] | +| 26 | SupERC20 | sendERC20 decreases the sender's balance in the source chain exactly by the input amount | [x] | +| 27 | SupERC20 | relayERC20 increases sender's balance in the destination chain exactly by the input amount | [x] | +| 11 | SupERC20 | relayERC20 increases the token's totalSupply in the destination chain exactly by the input amount | [ ] | +| 12 | Liquidity Migration | supertoken total supply only increases on calls to mint() by the L2toL2StandardBridge | [~] | +| 13 | Liquidity Migration | supertoken total supply only decreases on calls to burn() by the L2toL2StandardBridge | [ ] | +| 14 | SupERC20 | supertoken total supply starts at zero | [x] | +| 15 | Factories | deploying a supertoken registers its remote token in the factory | [ ] | +| 16 | Factories | deploying an OptimismMintableERC20 registers its remote token in the factory | [ ] | + +## High level + +| id | milestone | description | tested | +| --- | --- | --- | --- | +| 17 | Liquidity Migration | only calls to convert(legacy, super) can increase a supertoken’s total supply across chains | [ ] | +| 18 | Liquidity Migration | only calls to convert(super, legacy) can decrease a supertoken’s total supply across chains | [ ] | +| 19 | Liquidity Migration | sum of supertoken total supply across all chains is always <= to convert(legacy, super)- convert(super, legacy) | [~] | +| 20 | SupERC20 | tokens sendERC20-ed on a source chain to a destination chain can be relayERC20-ed on it as long as the source chain is in the dependency set of the destination chain | [ ] | +| 21 | Liquidity Migration | sum of supertoken total supply across all chains is = to convert(legacy, super)- convert(super, legacy) when all cross-chain messages are processed | [~] | + +## Atomic bridging pseudo-properties + +As another layer of defense, the following properties are defined which assume bridging operations to be atomic (that is, the sequencer and L2Inbox and CrossDomainMessenger contracts are fully abstracted away, `sendERC20` triggering the `relayERC20` call on the same transaction) +It’s worth noting that these properties will not hold for a live system + +| id | milestone | description | tested | +| --- | --- | --- | --- | +| 22 | SupERC20 | sendERC20 decreases sender balance in source chain and increases receiver balance in destination chain exactly by the input amount | [x] | +| 23 | SupERC20 | sendERC20 decreases total supply in source chain and increases it in destination chain exactly by the input amount | [x] | +| 24 | Liquidity Migration | sum of supertoken total supply across all chains is always equal to convert(legacy, super)- convert(super, legacy) | [~] | diff --git a/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/fuzz/Protocol.guided.t.sol b/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/fuzz/Protocol.guided.t.sol new file mode 100644 index 0000000000000..536a4ea7025ae --- /dev/null +++ b/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/fuzz/Protocol.guided.t.sol @@ -0,0 +1,211 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.25; + +import { MockL2ToL2CrossDomainMessenger } from "../helpers/MockL2ToL2CrossDomainMessenger.t.sol"; +import { OptimismSuperchainERC20 } from "src/L2/OptimismSuperchainERC20.sol"; +import { ProtocolHandler } from "../handlers/Protocol.t.sol"; +import { EnumerableMap } from "@openzeppelin/contracts/utils/structs/EnumerableMap.sol"; +import { CompatibleAssert } from "../helpers/CompatibleAssert.t.sol"; + +contract ProtocolGuided is ProtocolHandler, CompatibleAssert { + using EnumerableMap for EnumerableMap.Bytes32ToUintMap; + /// @notice deploy a new supertoken with deploy salt determined by params, to the given (of course mocked) chainId + /// @custom:property-id 14 + /// @custom:property supertoken total supply starts at zero + + function fuzz_deployNewSupertoken( + TokenDeployParams memory params, + uint256 chainId + ) + external + validateTokenDeployParams(params) + { + chainId = bound(chainId, 0, MAX_CHAINS - 1); + OptimismSuperchainERC20 supertoken = _deploySupertoken( + remoteTokens[params.remoteTokenIndex], + WORDS[params.nameIndex], + WORDS[params.symbolIndex], + DECIMALS[params.decimalsIndex], + chainId + ); + // 14 + compatibleAssert(supertoken.totalSupply() == 0); + } + + /// @custom:property-id 6 + /// @custom:property calls to sendERC20 succeed as long as caller has enough balance + /// @custom:property-id 22 + /// @custom:property sendERC20 decreases sender balance in source chain and increases receiver balance in + /// destination chain exactly by the input amount + /// @custom:property-id 23 + /// @custom:property sendERC20 decreases total supply in source chain and increases it in destination chain exactly + /// by the input amount + function fuzz_bridgeSupertokenAtomic( + uint256 fromIndex, + uint256 recipientIndex, + uint256 destinationChainId, + uint256 amount + ) + public + withActor(msg.sender) + { + destinationChainId = bound(destinationChainId, 0, MAX_CHAINS - 1); + fromIndex = bound(fromIndex, 0, allSuperTokens.length - 1); + address recipient = getActorByRawIndex(recipientIndex); + OptimismSuperchainERC20 sourceToken = OptimismSuperchainERC20(allSuperTokens[fromIndex]); + OptimismSuperchainERC20 destinationToken = + MESSENGER.crossChainMessageReceiver(address(sourceToken), destinationChainId); + uint256 sourceBalanceBefore = sourceToken.balanceOf(currentActor()); + uint256 sourceSupplyBefore = sourceToken.totalSupply(); + uint256 destinationBalanceBefore = destinationToken.balanceOf(recipient); + uint256 destinationSupplyBefore = destinationToken.totalSupply(); + + MESSENGER.setAtomic(true); + vm.prank(currentActor()); + try sourceToken.sendERC20(recipient, amount, destinationChainId) { + MESSENGER.setAtomic(false); + uint256 sourceBalanceAfter = sourceToken.balanceOf(currentActor()); + uint256 destinationBalanceAfter = destinationToken.balanceOf(recipient); + // no free mint + compatibleAssert( + sourceBalanceBefore + destinationBalanceBefore == sourceBalanceAfter + destinationBalanceAfter + ); + // 22 + compatibleAssert(sourceBalanceBefore - amount == sourceBalanceAfter); + compatibleAssert(destinationBalanceBefore + amount == destinationBalanceAfter); + uint256 sourceSupplyAfter = sourceToken.totalSupply(); + uint256 destinationSupplyAfter = destinationToken.totalSupply(); + // 23 + compatibleAssert(sourceSupplyBefore - amount == sourceSupplyAfter); + compatibleAssert(destinationSupplyBefore + amount == destinationSupplyAfter); + } catch { + MESSENGER.setAtomic(false); + // 6 + compatibleAssert(address(destinationToken) == address(sourceToken) || sourceBalanceBefore < amount); + } + } + + /// @custom:property-id 6 + /// @custom:property calls to sendERC20 succeed as long as caller has enough balance + /// @custom:property-id 26 + /// @custom:property sendERC20 decreases sender balance in source chain exactly by the input amount + /// @custom:property-id 10 + /// @custom:property sendERC20 decreases total supply in source chain exactly by the input amount + function fuzz_sendERC20( + uint256 fromIndex, + uint256 recipientIndex, + uint256 destinationChainId, + uint256 amount + ) + public + withActor(msg.sender) + { + destinationChainId = bound(destinationChainId, 0, MAX_CHAINS - 1); + fromIndex = bound(fromIndex, 0, allSuperTokens.length - 1); + address recipient = getActorByRawIndex(recipientIndex); + OptimismSuperchainERC20 sourceToken = OptimismSuperchainERC20(allSuperTokens[fromIndex]); + OptimismSuperchainERC20 destinationToken = + MESSENGER.crossChainMessageReceiver(address(sourceToken), destinationChainId); + bytes32 deploySalt = MESSENGER.superTokenInitDeploySalts(address(sourceToken)); + uint256 sourceBalanceBefore = sourceToken.balanceOf(currentActor()); + uint256 sourceSupplyBefore = sourceToken.totalSupply(); + + vm.prank(currentActor()); + try sourceToken.sendERC20(recipient, amount, destinationChainId) { + (, uint256 currentlyInTransit) = ghost_tokensInTransit.tryGet(deploySalt); + ghost_tokensInTransit.set(deploySalt, currentlyInTransit + amount); + // 26 + uint256 sourceBalanceAfter = sourceToken.balanceOf(currentActor()); + compatibleAssert(sourceBalanceBefore - amount == sourceBalanceAfter); + // 10 + uint256 sourceSupplyAfter = sourceToken.totalSupply(); + compatibleAssert(sourceSupplyBefore - amount == sourceSupplyAfter); + } catch { + // 6 + compatibleAssert(address(destinationToken) == address(sourceToken) || sourceBalanceBefore < amount); + } + } + + /// @custom:property-id 11 + /// @custom:property relayERC20 increases the token's totalSupply in the destination chain exactly by the input + /// amount + /// @custom:property-id 27 + /// @custom:property relayERC20 increases sender's balance in the destination chain exactly by the input amount + /// @custom:property-id 7 + /// @custom:property calls to relayERC20 always succeed as long as the cross-domain caller is valid + function fuzz_relayERC20(uint256 messageIndex) external { + MockL2ToL2CrossDomainMessenger.CrossChainMessage memory messageToRelay = MESSENGER.messageQueue(messageIndex); + OptimismSuperchainERC20 destinationToken = OptimismSuperchainERC20(messageToRelay.crossDomainMessageSender); + uint256 destinationSupplyBefore = destinationToken.totalSupply(); + uint256 destinationBalanceBefore = destinationToken.balanceOf(messageToRelay.recipient); + + try MESSENGER.relayMessageFromQueue(messageIndex) { + bytes32 deploySalt = MESSENGER.superTokenInitDeploySalts(address(destinationToken)); + (bool success, uint256 currentlyInTransit) = ghost_tokensInTransit.tryGet(deploySalt); + // if sendERC20 didnt intialize this, then test suite is broken + compatibleAssert(success); + ghost_tokensInTransit.set(deploySalt, currentlyInTransit - messageToRelay.amount); + // 11 + compatibleAssert(destinationSupplyBefore + messageToRelay.amount == destinationToken.totalSupply()); + // 27 + compatibleAssert( + destinationBalanceBefore + messageToRelay.amount == destinationToken.balanceOf(messageToRelay.recipient) + ); + } catch { + // 7 + compatibleAssert(false); + } + } + + /// @custom:property-id 8 + /// @custom:property calls to sendERC20 with a value of zero dont modify accounting + // @notice is a subset of fuzz_sendERC20, so we'll just call it + // instead of re-implementing it. Keeping the function for visibility of the property. + function fuzz_sendZeroDoesNotModifyAccounting( + uint256 fromIndex, + uint256 recipientIndex, + uint256 destinationChainId + ) + external + { + fuzz_sendERC20(fromIndex, recipientIndex, destinationChainId, 0); + } + + /// @custom:property-id 9 + /// @custom:property calls to relayERC20 with a value of zero dont modify accounting + /// @custom:property-id 7 + /// @custom:property calls to relayERC20 always succeed as long as the cross-domain caller is valid + /// @notice cant call fuzz_RelayERC20 internally since that pops a + /// random message, which we cannot guarantee has a value of zero + function fuzz_relayZeroDoesNotModifyAccounting( + uint256 fromIndex, + uint256 recipientIndex + ) + external + withActor(msg.sender) + { + fromIndex = bound(fromIndex, 0, allSuperTokens.length - 1); + address recipient = getActorByRawIndex(recipientIndex); + OptimismSuperchainERC20 token = OptimismSuperchainERC20(allSuperTokens[fromIndex]); + uint256 balanceSenderBefore = token.balanceOf(currentActor()); + uint256 balanceRecipientBefore = token.balanceOf(recipient); + uint256 supplyBefore = token.totalSupply(); + + MESSENGER.setCrossDomainMessageSender(address(token)); + vm.prank(address(MESSENGER)); + try token.relayERC20(currentActor(), recipient, 0) { + MESSENGER.setCrossDomainMessageSender(address(0)); + } catch { + // should not revert because of 7, and if it *does* revert, I want the test suite + // to discard the sequence instead of potentially getting another + // error due to the crossDomainMessageSender being manually set + compatibleAssert(false); + } + uint256 balanceSenderAfter = token.balanceOf(currentActor()); + uint256 balanceRecipeintAfter = token.balanceOf(recipient); + uint256 supplyAfter = token.totalSupply(); + compatibleAssert(balanceSenderBefore == balanceSenderAfter); + compatibleAssert(balanceRecipientBefore == balanceRecipeintAfter); + compatibleAssert(supplyBefore == supplyAfter); + } +} diff --git a/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/fuzz/Protocol.unguided.t.sol b/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/fuzz/Protocol.unguided.t.sol new file mode 100644 index 0000000000000..90cad38baa990 --- /dev/null +++ b/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/fuzz/Protocol.unguided.t.sol @@ -0,0 +1,137 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.25; + +import { ProtocolHandler } from "../handlers/Protocol.t.sol"; +import { EnumerableMap } from "@openzeppelin/contracts/utils/structs/EnumerableMap.sol"; +import { OptimismSuperchainERC20 } from "src/L2/OptimismSuperchainERC20.sol"; +import { CompatibleAssert } from "../helpers/CompatibleAssert.t.sol"; + +// TODO: add fuzz_sendERC20 when we implement non-atomic bridging +contract ProtocolUnguided is ProtocolHandler, CompatibleAssert { + using EnumerableMap for EnumerableMap.Bytes32ToUintMap; + + /// @custom:property-id 7 + /// @custom:property calls to relayERC20 always succeed as long as the cross-domain caller is valid + /// @notice this ensures actors cant simply call relayERC20 and get tokens, no matter the system state + /// but there's still some possible work on how hard we can bork the system state with handlers calling + /// the L2ToL2CrossDomainMessenger or bridge directly (pending on non-atomic bridging) + function fuzz_relayERC20( + uint256 tokenIndex, + address sender, + address crossDomainMessageSender, + address recipient, + uint256 amount + ) + external + { + MESSENGER.setCrossDomainMessageSender(crossDomainMessageSender); + address token = allSuperTokens[bound(tokenIndex, 0, allSuperTokens.length)]; + vm.prank(sender); + try OptimismSuperchainERC20(token).relayERC20(sender, recipient, amount) { + MESSENGER.setCrossDomainMessageSender(address(0)); + compatibleAssert(sender == address(MESSENGER)); + compatibleAssert(crossDomainMessageSender == token); + // this increases the supply across chains without a call to + // `mint` by the MESSENGER, so it kind of breaks an invariant, but + // let's walk around that: + bytes32 salt = MESSENGER.superTokenInitDeploySalts(token); + (, uint256 currentValue) = ghost_totalSupplyAcrossChains.tryGet(salt); + ghost_totalSupplyAcrossChains.set(salt, currentValue + amount); + } catch { + compatibleAssert(sender != address(MESSENGER) || crossDomainMessageSender != token); + MESSENGER.setCrossDomainMessageSender(address(0)); + } + } + + /// @custom:property-id 6 + /// @custom:property calls to sendERC20 succeed as long as caller has enough balance + /// @custom:property-id 26 + /// @custom:property sendERC20 decreases sender balance in source chain exactly by the input amount + /// @custom:property-id 10 + /// @custom:property sendERC20 decreases total supply in source chain exactly by the input amount + function fuzz_sendERC20( + address sender, + address recipient, + uint256 fromIndex, + uint256 destinationChainId, + uint256 amount + ) + public + { + destinationChainId = bound(destinationChainId, 0, MAX_CHAINS - 1); + OptimismSuperchainERC20 sourceToken = OptimismSuperchainERC20(allSuperTokens[fromIndex]); + OptimismSuperchainERC20 destinationToken = + MESSENGER.crossChainMessageReceiver(address(sourceToken), destinationChainId); + bytes32 deploySalt = MESSENGER.superTokenInitDeploySalts(address(sourceToken)); + uint256 sourceBalanceBefore = sourceToken.balanceOf(sender); + uint256 sourceSupplyBefore = sourceToken.totalSupply(); + + vm.prank(sender); + try sourceToken.sendERC20(recipient, amount, destinationChainId) { + (, uint256 currentlyInTransit) = ghost_tokensInTransit.tryGet(deploySalt); + ghost_tokensInTransit.set(deploySalt, currentlyInTransit + amount); + // 26 + uint256 sourceBalanceAfter = sourceToken.balanceOf(sender); + compatibleAssert(sourceBalanceBefore - amount == sourceBalanceAfter); + // 10 + uint256 sourceSupplyAfter = sourceToken.totalSupply(); + compatibleAssert(sourceSupplyBefore - amount == sourceSupplyAfter); + } catch { + // 6 + compatibleAssert(address(destinationToken) == address(sourceToken) || sourceBalanceBefore < amount); + } + } + + /// @custom:property-id 12 + /// @custom:property supertoken total supply only increases on calls to mint() by the L2toL2StandardBridge + function fuzz_mint(uint256 tokenIndex, address to, address sender, uint256 amount) external { + address token = allSuperTokens[bound(tokenIndex, 0, allSuperTokens.length)]; + bytes32 salt = MESSENGER.superTokenInitDeploySalts(token); + amount = bound(amount, 0, type(uint256).max - OptimismSuperchainERC20(token).totalSupply()); + vm.prank(sender); + try OptimismSuperchainERC20(token).mint(to, amount) { + compatibleAssert(sender == BRIDGE); + (, uint256 currentValue) = ghost_totalSupplyAcrossChains.tryGet(salt); + ghost_totalSupplyAcrossChains.set(salt, currentValue + amount); + } catch { + compatibleAssert(sender != BRIDGE || to == address(0)); + } + } + + /// @custom:property-id 13 + /// @custom:property supertoken total supply only increases on calls to mint() by the L2toL2StandardBridge + function fuzz_burn(uint256 tokenIndex, address from, address sender, uint256 amount) external { + address token = allSuperTokens[bound(tokenIndex, 0, allSuperTokens.length)]; + bytes32 salt = MESSENGER.superTokenInitDeploySalts(token); + uint256 senderBalance = OptimismSuperchainERC20(token).balanceOf(sender); + vm.prank(sender); + try OptimismSuperchainERC20(token).burn(from, amount) { + compatibleAssert(sender == BRIDGE); + (, uint256 currentValue) = ghost_totalSupplyAcrossChains.tryGet(salt); + ghost_totalSupplyAcrossChains.set(salt, currentValue - amount); + } catch { + compatibleAssert(sender != BRIDGE || senderBalance < amount); + } + } + + /// @custom:property-id 25 + /// @custom:property supertokens can't be reinitialized + function fuzz_initialize( + address sender, + uint256 tokenIndex, + address remoteToken, + string memory name, + string memory symbol, + uint8 decimals + ) + external + { + vm.prank(sender); + // revert is possible in bound, but is not part of the external call + try OptimismSuperchainERC20(allSuperTokens[bound(tokenIndex, 0, allSuperTokens.length)]).initialize( + remoteToken, name, symbol, decimals + ) { + compatibleAssert(false); + } catch { } + } +} diff --git a/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/handlers/Protocol.t.sol b/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/handlers/Protocol.t.sol new file mode 100644 index 0000000000000..921495b467ab1 --- /dev/null +++ b/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/handlers/Protocol.t.sol @@ -0,0 +1,177 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.25; + +import { TestBase } from "forge-std/Base.sol"; +import { StdUtils } from "forge-std/StdUtils.sol"; + +import { ERC1967Proxy } from "@openzeppelin/contracts-v5/proxy/ERC1967/ERC1967Proxy.sol"; +import { EnumerableMap } from "@openzeppelin/contracts/utils/structs/EnumerableMap.sol"; +import { OptimismSuperchainERC20 } from "src/L2/OptimismSuperchainERC20.sol"; +import { OptimismSuperchainERC20ForToBProperties } from "../helpers/OptimismSuperchainERC20ForToBProperties.t.sol"; +import { Predeploys } from "src/libraries/Predeploys.sol"; +import { MockL2ToL2CrossDomainMessenger } from "../helpers/MockL2ToL2CrossDomainMessenger.t.sol"; +import { Actors } from "../helpers/Actors.t.sol"; + +contract ProtocolHandler is TestBase, StdUtils, Actors { + using EnumerableMap for EnumerableMap.Bytes32ToUintMap; + + uint8 public constant MAX_CHAINS = 4; + uint8 internal constant INITIAL_TOKENS = 1; + uint8 internal constant INITIAL_SUPERTOKENS = 1; + uint8 internal constant SUPERTOKEN_INITIAL_MINT = 100; + address internal constant BRIDGE = Predeploys.L2_STANDARD_BRIDGE; + MockL2ToL2CrossDomainMessenger internal constant MESSENGER = + MockL2ToL2CrossDomainMessenger(Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER); + OptimismSuperchainERC20 internal superchainERC20Impl; + // NOTE: having more options for this enables the fuzzer to configure + // different supertokens for the same remote token + string[] internal WORDS = ["TOKENS"]; + uint8[] internal DECIMALS = [6, 18]; + + struct TokenDeployParams { + uint8 remoteTokenIndex; + uint8 nameIndex; + uint8 symbolIndex; + uint8 decimalsIndex; + } + + address[] internal remoteTokens; + address[] internal allSuperTokens; + + /// @notice 'real' deploy salt => total supply sum across chains + EnumerableMap.Bytes32ToUintMap internal ghost_totalSupplyAcrossChains; + /// @notice 'real' deploy salt => tokens sendERC20'd but not yet relayERC20'd + EnumerableMap.Bytes32ToUintMap internal ghost_tokensInTransit; + + constructor() { + vm.etch(address(MESSENGER), address(new MockL2ToL2CrossDomainMessenger()).code); + superchainERC20Impl = new OptimismSuperchainERC20ForToBProperties(); + for (uint256 remoteTokenIndex; remoteTokenIndex < INITIAL_TOKENS; remoteTokenIndex++) { + _deployRemoteToken(); + for (uint256 supertokenChainId; supertokenChainId < INITIAL_SUPERTOKENS; supertokenChainId++) { + _deploySupertoken(remoteTokens[remoteTokenIndex], WORDS[0], WORDS[0], DECIMALS[0], supertokenChainId); + } + } + // integrate with all ToB properties using address(this) as the sender + addActor(address(this)); + } + + /// @notice the deploy params are _indexes_ to pick from a pre-defined array of options and limit + /// the amount of supertokens for a given remoteAsset that are incompatible between them, as + /// two supertokens have to share decimals, name, symbol and remoteAsset to be considered + /// the same asset, and therefore bridgable. + modifier validateTokenDeployParams(TokenDeployParams memory params) { + params.remoteTokenIndex = uint8(bound(params.remoteTokenIndex, 0, remoteTokens.length - 1)); + params.nameIndex = uint8(bound(params.nameIndex, 0, WORDS.length - 1)); + params.symbolIndex = uint8(bound(params.symbolIndex, 0, WORDS.length - 1)); + params.decimalsIndex = uint8(bound(params.decimalsIndex, 0, DECIMALS.length - 1)); + _; + } + + function handler_mockNewRemoteToken() external { + _deployRemoteToken(); + } + + /// @notice pick one already-deployed supertoken and mint an arbitrary amount of it + /// necessary so there is something to be bridged :D + /// TODO: will be replaced when testing the factories and `convert()` + function handler_mintSupertoken(uint256 index, uint96 amount) external withActor(msg.sender) { + index = bound(index, 0, allSuperTokens.length - 1); + address addr = allSuperTokens[index]; + vm.prank(BRIDGE); + OptimismSuperchainERC20(addr).mint(currentActor(), amount); + // currentValue will be zero if key is not present + (, uint256 currentValue) = ghost_totalSupplyAcrossChains.tryGet(MESSENGER.superTokenInitDeploySalts(addr)); + ghost_totalSupplyAcrossChains.set(MESSENGER.superTokenInitDeploySalts(addr), currentValue + amount); + } + + /// @notice The ToB properties don't preclude the need for this since they + /// always use address(this) as the caller, which won't get any balance + /// until it's transferred to it somehow + function handler_supERC20Transfer( + uint256 tokenIndex, + uint256 toIndex, + uint256 amount + ) + external + withActor(msg.sender) + { + vm.prank(currentActor()); + OptimismSuperchainERC20(allSuperTokens[bound(tokenIndex, 0, allSuperTokens.length)]).transfer( + getActorByRawIndex(toIndex), amount + ); + } + + function handler_supERC20TransferFrom( + uint256 tokenIndex, + uint256 fromIndex, + uint256 toIndex, + uint256 amount + ) + external + withActor(msg.sender) + { + vm.prank(currentActor()); + OptimismSuperchainERC20(allSuperTokens[bound(tokenIndex, 0, allSuperTokens.length)]).transferFrom( + getActorByRawIndex(fromIndex), getActorByRawIndex(toIndex), amount + ); + } + + function handler_supERC20Approve( + uint256 tokenIndex, + uint256 spenderIndex, + uint256 amount + ) + external + withActor(msg.sender) + { + vm.prank(currentActor()); + OptimismSuperchainERC20(allSuperTokens[bound(tokenIndex, 0, allSuperTokens.length)]).approve( + getActorByRawIndex(spenderIndex), amount + ); + } + + /// @notice deploy a remote token, that supertokens will be a representation of. They are never called, so there + /// is no need to actually deploy a contract for them + function _deployRemoteToken() internal { + // make sure they don't conflict with predeploys/preinstalls/precompiles/other tokens + remoteTokens.push(address(uint160(1000 + remoteTokens.length))); + } + + /// @notice deploy a new supertoken representing remoteToken + /// remoteToken, name, symbol and decimals determine the 'real' deploy salt + /// and supertokens sharing it are interoperable between them + /// we however use the chainId as part of the deploy salt to mock the ability of + /// supertokens to exist on different chains on a single EVM. + function _deploySupertoken( + address remoteToken, + string memory name, + string memory symbol, + uint8 decimals, + uint256 chainId + ) + internal + returns (OptimismSuperchainERC20 supertoken) + { + // this salt would be used in production. Tokens sharing it will be bridgable with each other + bytes32 realSalt = keccak256(abi.encode(remoteToken, name, symbol, decimals)); + // Foundry invariant erroneously show other unrelated invariant breaking + // when this deployment fails due to a create2 collision, so we revert eagerly instead + require(MESSENGER.superTokenAddresses(chainId, realSalt) == address(0), "skip duplicate deployment"); + + // what we use in the tests to walk around two contracts needing two different addresses + // tbf we could be using CREATE1, but this feels more verbose + bytes32 hackySalt = keccak256(abi.encode(remoteToken, name, symbol, decimals, chainId)); + supertoken = OptimismSuperchainERC20( + address( + // TODO: Use the SuperchainERC20 Beacon Proxy + new ERC1967Proxy{ salt: hackySalt }( + address(superchainERC20Impl), + abi.encodeCall(OptimismSuperchainERC20.initialize, (remoteToken, name, symbol, decimals)) + ) + ) + ); + MESSENGER.registerSupertoken(realSalt, chainId, address(supertoken)); + allSuperTokens.push(address(supertoken)); + } +} diff --git a/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/helpers/Actors.t.sol b/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/helpers/Actors.t.sol new file mode 100644 index 0000000000000..3a7400667518f --- /dev/null +++ b/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/helpers/Actors.t.sol @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.25; + +import { StdUtils } from "forge-std/StdUtils.sol"; + +/// @notice helper for tracking actors, taking advantage of the fuzzer already using several `msg.sender`s +contract Actors is StdUtils { + mapping(address => bool) private _isActor; + address[] private _actors; + address private _currentActor; + + /// @notice register an actor if it's not already registered + /// usually called with msg.sender as a parameter, to track the actors + /// already provided by the fuzzer + modifier withActor(address who) { + addActor(who); + _currentActor = who; + _; + } + + function addActor(address who) internal { + if (!_isActor[who]) { + _isActor[who] = true; + _actors.push(who); + } + } + + /// @notice get the currently configured actor, should equal msg.sender + function currentActor() internal view returns (address) { + return _currentActor; + } + + /// @notice get one of the actors by index, useful to get another random + /// actor than the one set as currentActor, to perform operations between them + function getActorByRawIndex(uint256 rawIndex) internal view returns (address) { + return _actors[bound(rawIndex, 0, _actors.length - 1)]; + } +} diff --git a/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/helpers/CompatibleAssert.t.sol b/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/helpers/CompatibleAssert.t.sol new file mode 100644 index 0000000000000..4e69c94c85852 --- /dev/null +++ b/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/helpers/CompatibleAssert.t.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-3 +pragma solidity ^0.8.24; + +import { console } from "forge-std/console.sol"; + +/// @title CompatibleAssert +/// @notice meant to add compatibility between medusa assertion tests and +/// foundry invariant test's required architecture +contract CompatibleAssert { + bool public failed; + + function compatibleAssert(bool condition) internal { + compatibleAssert(condition, ""); + } + + function compatibleAssert(bool condition, string memory message) internal { + if (!condition) { + if (bytes(message).length != 0) console.log("Assertion failed: ", message); + else console.log("Assertion failed"); + + // for foundry to call & check + failed = true; + + // for medusa + assert(false); + } + } +} diff --git a/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/helpers/HandlerGetters.t.sol b/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/helpers/HandlerGetters.t.sol new file mode 100644 index 0000000000000..b081aa48c6bbc --- /dev/null +++ b/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/helpers/HandlerGetters.t.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-3 +pragma solidity ^0.8.24; + +import { ProtocolHandler } from "../handlers/Protocol.t.sol"; +import { EnumerableMap } from "@openzeppelin/contracts/utils/structs/EnumerableMap.sol"; + +contract HandlerGetters is ProtocolHandler { + using EnumerableMap for EnumerableMap.Bytes32ToUintMap; + + function deploySaltsLength() external view returns (uint256 length) { + return ghost_totalSupplyAcrossChains.length(); + } + + function totalSupplyAcrossChainsAtIndex(uint256 index) external view returns (bytes32 salt, uint256 supply) { + return ghost_totalSupplyAcrossChains.at(index); + } + + function tokensInTransitForDeploySalt(bytes32 salt) external view returns (uint256 amount) { + (, amount) = ghost_tokensInTransit.tryGet(salt); + return amount; + } +} diff --git a/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/helpers/MockL2ToL2CrossDomainMessenger.t.sol b/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/helpers/MockL2ToL2CrossDomainMessenger.t.sol new file mode 100644 index 0000000000000..6eb1c30e67994 --- /dev/null +++ b/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/helpers/MockL2ToL2CrossDomainMessenger.t.sol @@ -0,0 +1,118 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.25; + +import { OptimismSuperchainERC20 } from "src/L2/OptimismSuperchainERC20.sol"; +import { SafeCall } from "src/libraries/SafeCall.sol"; + +contract MockL2ToL2CrossDomainMessenger { + //////////////////////// + // type definitions // + //////////////////////// + struct CrossChainMessage { + address crossDomainMessageSender; + address crossDomainMessageSource; + bytes payload; + address recipient; + uint256 amount; + } + + ///////////////////////////////////////////////////////// + // State vars mocking the L2toL2CrossDomainMessenger // + ///////////////////////////////////////////////////////// + address public crossDomainMessageSender; + address public crossDomainMessageSource; + + /////////////////////////////////////////////////// + // Helpers for cross-chain interaction mocking // + /////////////////////////////////////////////////// + mapping(address supertoken => bytes32 deploySalt) public superTokenInitDeploySalts; + mapping(uint256 chainId => mapping(bytes32 deploySalt => address supertoken)) public superTokenAddresses; + + CrossChainMessage[] private _messageQueue; + bool private _atomic; + + function messageQueue(uint256 rawIndex) external view returns (CrossChainMessage memory) { + return _messageQueue[rawIndex % _messageQueue.length]; + } + + function crossChainMessageReceiver( + address sender, + uint256 destinationChainId + ) + external + view + returns (OptimismSuperchainERC20) + { + return OptimismSuperchainERC20(superTokenAddresses[destinationChainId][superTokenInitDeploySalts[sender]]); + } + + function setCrossDomainMessageSender(address sender) external { + crossDomainMessageSender = sender; + } + + function registerSupertoken(bytes32 deploySalt, uint256 chainId, address token) external { + superTokenAddresses[chainId][deploySalt] = token; + superTokenInitDeploySalts[token] = deploySalt; + } + + function messageQueueLength() public view returns (uint256) { + return _messageQueue.length; + } + + function setAtomic(bool atomic) public { + _atomic = atomic; + } + + function relayMessageFromQueue(uint256 rawIndex) public { + uint256 index = rawIndex % _messageQueue.length; + CrossChainMessage memory message = _messageQueue[index]; + _messageQueue[index] = _messageQueue[_messageQueue.length - 1]; + _messageQueue.pop(); + _relayMessage(message); + } + + function _relayMessage(CrossChainMessage memory message) internal { + crossDomainMessageSender = message.crossDomainMessageSender; + crossDomainMessageSource = message.crossDomainMessageSource; + SafeCall.call(crossDomainMessageSender, 0, message.payload); + crossDomainMessageSender = address(0); + crossDomainMessageSource = address(0); + } + + //////////////////////////////////////////////////////// + // Functions mocking the L2toL2CrossDomainMessenger // + //////////////////////////////////////////////////////// + + /// @notice recipient will not be used since in normal execution it's the same + /// address on a different chain, but here we have to compute it to mock + /// cross-chain messaging + function sendMessage(uint256 chainId, address, /*recipient*/ bytes calldata data) external { + address crossChainRecipient = superTokenAddresses[chainId][superTokenInitDeploySalts[msg.sender]]; + if (crossChainRecipient == msg.sender) { + require(false, "same chain"); + } + (address recipient, uint256 amount) = _decodePayload(data); + + CrossChainMessage memory message = CrossChainMessage({ + crossDomainMessageSender: crossChainRecipient, + crossDomainMessageSource: msg.sender, + payload: data, + recipient: recipient, + amount: amount + }); + + if (_atomic) { + _relayMessage(message); + } else { + _messageQueue.push(message); + } + } + + //////////////////////// + // Internal helpers // + //////////////////////// + + function _decodePayload(bytes calldata payload) internal pure returns (address recipient, uint256 amount) { + (, recipient, amount) = abi.decode(payload[4:], (address, address, uint256)); + } +} diff --git a/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/helpers/OptimismSuperchainERC20ForToBProperties.t.sol b/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/helpers/OptimismSuperchainERC20ForToBProperties.t.sol new file mode 100644 index 0000000000000..9f80cda92fcc4 --- /dev/null +++ b/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/helpers/OptimismSuperchainERC20ForToBProperties.t.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: AGPL-3 +pragma solidity ^0.8.25; + +import { OptimismSuperchainERC20 } from "src/L2/OptimismSuperchainERC20.sol"; + +contract OptimismSuperchainERC20ForToBProperties is OptimismSuperchainERC20 { + /// @notice This is used by CryticERC20ExternalBasicProperties (only used + /// in Medusa testing campaign)to know which properties to test, and + /// remains here so Medusa and Foundry test campaigns can use a single + /// setup + bool public constant isMintableOrBurnable = true; +} diff --git a/packages/contracts-bedrock/test/invariants/ResourceMetering.t.sol b/packages/contracts-bedrock/test/invariants/ResourceMetering.t.sol index 39e54590efbbd..4652f9b9e36e8 100644 --- a/packages/contracts-bedrock/test/invariants/ResourceMetering.t.sol +++ b/packages/contracts-bedrock/test/invariants/ResourceMetering.t.sol @@ -8,6 +8,7 @@ import { StdInvariant } from "forge-std/StdInvariant.sol"; import { Arithmetic } from "src/libraries/Arithmetic.sol"; import { ResourceMetering } from "src/L1/ResourceMetering.sol"; +import { IResourceMetering } from "src/L1/interfaces/IResourceMetering.sol"; import { Constants } from "src/libraries/Constants.sol"; import { InvariantTest } from "test/invariants/InvariantTest.sol"; @@ -35,9 +36,11 @@ contract ResourceMetering_User is StdUtils, ResourceMetering { return _resourceConfig(); } - function _resourceConfig() internal pure override returns (ResourceMetering.ResourceConfig memory) { - ResourceMetering.ResourceConfig memory rcfg = Constants.DEFAULT_RESOURCE_CONFIG(); - return rcfg; + function _resourceConfig() internal pure override returns (ResourceMetering.ResourceConfig memory config_) { + IResourceMetering.ResourceConfig memory rcfg = Constants.DEFAULT_RESOURCE_CONFIG(); + assembly ("memory-safe") { + config_ := rcfg + } } /// @notice Takes the necessary parameters to allow us to burn arbitrary amounts of gas to test diff --git a/packages/contracts-bedrock/test/invariants/SuperchainWETH.t.sol b/packages/contracts-bedrock/test/invariants/SuperchainWETH.t.sol index aeb250bcc36a0..1e761b7ea1621 100644 --- a/packages/contracts-bedrock/test/invariants/SuperchainWETH.t.sol +++ b/packages/contracts-bedrock/test/invariants/SuperchainWETH.t.sol @@ -1,14 +1,17 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Testing import { StdUtils } from "forge-std/Test.sol"; import { Vm } from "forge-std/Vm.sol"; +import { CommonTest } from "test/setup/CommonTest.sol"; +// Libraries import { Predeploys } from "src/libraries/Predeploys.sol"; -import { SuperchainWETH } from "src/L2/SuperchainWETH.sol"; -import { IL2ToL2CrossDomainMessenger } from "src/L2/IL2ToL2CrossDomainMessenger.sol"; -import { CommonTest } from "test/setup/CommonTest.sol"; +// Interfaces +import { ISuperchainWETH } from "src/L2/interfaces/ISuperchainWETH.sol"; +import { IL2ToL2CrossDomainMessenger } from "src/L2/interfaces/IL2ToL2CrossDomainMessenger.sol"; /// @title SuperchainWETH_User /// @notice Actor contract that interacts with the SuperchainWETH contract. @@ -26,7 +29,7 @@ contract SuperchainWETH_User is StdUtils { Vm internal vm; /// @notice The SuperchainWETH contract. - SuperchainWETH internal weth; + ISuperchainWETH internal weth; /// @notice Mapping of sent messages. mapping(bytes32 => bool) internal sent; @@ -37,7 +40,7 @@ contract SuperchainWETH_User is StdUtils { /// @param _vm The Vm contract. /// @param _weth The SuperchainWETH contract. /// @param _balance The initial balance of the contract. - constructor(Vm _vm, SuperchainWETH _weth, uint256 _balance) { + constructor(Vm _vm, ISuperchainWETH _weth, uint256 _balance) { vm = _vm; weth = _weth; vm.deal(address(this), _balance); diff --git a/packages/contracts-bedrock/test/invariants/SystemConfig.t.sol b/packages/contracts-bedrock/test/invariants/SystemConfig.t.sol index 8419113917f41..1321499462b71 100644 --- a/packages/contracts-bedrock/test/invariants/SystemConfig.t.sol +++ b/packages/contracts-bedrock/test/invariants/SystemConfig.t.sol @@ -3,15 +3,16 @@ pragma solidity 0.8.15; import { Test } from "forge-std/Test.sol"; import { SystemConfig } from "src/L1/SystemConfig.sol"; +import { ISystemConfig } from "src/L1/interfaces/ISystemConfig.sol"; import { Proxy } from "src/universal/Proxy.sol"; import { Constants } from "src/libraries/Constants.sol"; contract SystemConfig_GasLimitBoundaries_Invariant is Test { - SystemConfig public config; + ISystemConfig public config; function setUp() external { Proxy proxy = new Proxy(msg.sender); - SystemConfig configImpl = new SystemConfig(); + ISystemConfig configImpl = ISystemConfig(address(new SystemConfig())); vm.prank(msg.sender); proxy.upgradeToAndCall( @@ -27,7 +28,7 @@ contract SystemConfig_GasLimitBoundaries_Invariant is Test { address(1), // unsafe block signer Constants.DEFAULT_RESOURCE_CONFIG(), address(0), // _batchInbox - SystemConfig.Addresses({ // _addrs + ISystemConfig.Addresses({ // _addrs l1CrossDomainMessenger: address(0), l1ERC721Bridge: address(0), l1StandardBridge: address(0), @@ -40,7 +41,7 @@ contract SystemConfig_GasLimitBoundaries_Invariant is Test { ) ); - config = SystemConfig(address(proxy)); + config = ISystemConfig(address(proxy)); // Set the target contract to the `config` targetContract(address(config)); diff --git a/packages/contracts-bedrock/test/kontrol/README.md b/packages/contracts-bedrock/test/kontrol/README.md index 489a9017e3c70..0a6dcec7c79ba 100644 --- a/packages/contracts-bedrock/test/kontrol/README.md +++ b/packages/contracts-bedrock/test/kontrol/README.md @@ -37,8 +37,6 @@ The directory is structured as follows ├── <a href="./pausability-lemmas.md">pausability-lemmas.md</a>: File containing the necessary lemmas for this project ├── <a href="./deployment">deployment</a>: Custom deploy sequence for Kontrol proofs and tests for its <a href="https://github.com/runtimeverification/kontrol/pull/271">fast summarization</a> │ ├── <a href="./deployment/KontrolDeployment.sol">KontrolDeployment.sol</a>: Deployment sequence for Kontrol proofs -│ ├── <a href="./deployment/DeploymentSummary.t.sol">DeploymentSummary.t.sol</a>: Tests for the summarization of classic deployment -│ └── <a href="./deployment/DeploymentSummaryFaultProofs.t.sol">DeploymentSummaryFaultProofs.t.sol</a>: Tests for the summarization of fault proofs deployment ├── <a href="./proofs">proofs</a>: Where the proofs (tests) themselves live │ ├── *.k.sol</a>: Symbolic property tests for contracts │ ├── <a href="./proofs/interfaces">interfaces</a>: Interface files for src contracts, to avoid unnecessary compilation of contracts diff --git a/packages/contracts-bedrock/test/kontrol/deployment/DeploymentSummary.t.sol b/packages/contracts-bedrock/test/kontrol/deployment/DeploymentSummary.t.sol deleted file mode 100644 index c9c351e143e3b..0000000000000 --- a/packages/contracts-bedrock/test/kontrol/deployment/DeploymentSummary.t.sol +++ /dev/null @@ -1,254 +0,0 @@ -// 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 view override { - // OptimismPortal opImpl = OptimismPortal(payable(deploy.mustGetAddress("OptimismPortal"))); - OptimismPortal opImpl = OptimismPortal(payable(optimismPortalAddress)); - assertEq(address(opImpl.l2Oracle()), 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 view override { - // address guardian = deploy.cfg().superchainConfigGuardian(); - address guardian = superchainConfig.guardian(); - assertEq(address(optimismPortal.l2Oracle()), address(l2OutputOracle)); - assertEq(address(optimismPortal.systemConfig()), address(systemConfig)); - 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 view 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 view 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 view 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/deployment/DeploymentSummaryFaultProofs.t.sol b/packages/contracts-bedrock/test/kontrol/deployment/DeploymentSummaryFaultProofs.t.sol deleted file mode 100644 index 2f96f31451191..0000000000000 --- a/packages/contracts-bedrock/test/kontrol/deployment/DeploymentSummaryFaultProofs.t.sol +++ /dev/null @@ -1,77 +0,0 @@ -// 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 { DisputeGameFactory } from "src/dispute/DisputeGameFactory.sol"; -import { SystemConfig } from "src/L1/SystemConfig.sol"; -import { SuperchainConfig } from "src/L1/SuperchainConfig.sol"; -import { OptimismPortal2 } from "src/L1/OptimismPortal2.sol"; -import { L1CrossDomainMessenger } from "src/L1/L1CrossDomainMessenger.sol"; -import { DeploymentSummaryFaultProofs } from "../proofs/utils/DeploymentSummaryFaultProofs.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 { OptimismPortal2_Test } from "test/L1/OptimismPortal2.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 DeploymentSummaryFaultProofs_TestOptimismPortal is DeploymentSummaryFaultProofs, OptimismPortal2_Test { - /// @notice super.setUp is not called on purpose - function setUp() public override { - // Recreate Deployment Summary state changes - DeploymentSummaryFaultProofs deploymentSummary = new DeploymentSummaryFaultProofs(); - deploymentSummary.recreateDeployment(); - - // Set summary addresses - optimismPortal2 = OptimismPortal2(payable(optimismPortalProxyAddress)); - superchainConfig = SuperchainConfig(superchainConfigProxyAddress); - disputeGameFactory = DisputeGameFactory(disputeGameFactoryProxyAddress); - 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 view override { - // OptimismPortal opImpl = OptimismPortal(payable(deploy.mustGetAddress("OptimismPortal"))); - OptimismPortal2 opImpl = OptimismPortal2(payable(optimismPortal2Address)); - assertEq(address(opImpl.disputeGameFactory()), 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 view override { - // address guardian = deploy.cfg().superchainConfigGuardian(); - address guardian = superchainConfig.guardian(); - assertEq(address(optimismPortal2.disputeGameFactory()), address(disputeGameFactory)); - assertEq(address(optimismPortal2.systemConfig()), address(systemConfig)); - assertEq(optimismPortal2.guardian(), guardian); - assertEq(address(optimismPortal2.superchainConfig()), address(superchainConfig)); - assertEq(optimismPortal2.l2Sender(), Constants.DEFAULT_L2_SENDER); - assertEq(optimismPortal2.paused(), false); - } -} diff --git a/packages/contracts-bedrock/test/kontrol/proofs/utils/DeploymentSummary.sol b/packages/contracts-bedrock/test/kontrol/proofs/utils/DeploymentSummary.sol index 12227a7daeddb..2fa5057acbd72 100644 --- a/packages/contracts-bedrock/test/kontrol/proofs/utils/DeploymentSummary.sol +++ b/packages/contracts-bedrock/test/kontrol/proofs/utils/DeploymentSummary.sol @@ -13,36 +13,36 @@ contract DeploymentSummary is DeploymentSummaryCode { Vm private constant vm = Vm(VM_ADDRESS); address internal constant addressManagerAddress = 0x50EEf481cae4250d252Ae577A09bF514f224C6C4; - address internal constant anchorStateRegistryAddress = 0x63B71B96756C693f7065345fecD9b7843b3e7C57; + address internal constant anchorStateRegistryAddress = 0xdEC4D949Cf1A2e824eE4F8B12064e166b96171dD; address internal constant anchorStateRegistryProxyAddress = 0x970670459734a83899773A0fd45941B5afC1200e; - address internal constant delayedWETHAddress = 0x2A6347EDD3C7813CDE46DD7eA61FF1Cf2290BC05; + address internal constant delayedWETHAddress = 0xe49cED258137CC5E18fB9ABA2Aa14069263D8f49; address internal constant delayedWETHProxyAddress = 0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92; - address internal constant disputeGameFactoryAddress = 0x20B168142354Cee65a32f6D8cf3033E592299765; + address internal constant disputeGameFactoryAddress = 0x8efDa795511CBBdfFC9eeca1a5bF30f5B1E1ef9E; address internal constant disputeGameFactoryProxyAddress = 0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d; - address internal constant l1CrossDomainMessengerAddress = 0x094e6508ba9d9bf1ce421fff3dE06aE56e67901b; + address internal constant l1CrossDomainMessengerAddress = 0x357B6CdA94109749a0dA475ac1BFd395a61eb908; address internal constant l1CrossDomainMessengerProxyAddress = 0xDeF3bca8c80064589E6787477FFa7Dd616B5574F; - address internal constant l1ERC721BridgeAddress = 0x5C4F5e749A61a9503c4AAE8a9393e89609a0e804; + address internal constant l1ERC721BridgeAddress = 0xA4BD7E58A30ED0477fe7372883d09bF86619Bb66; address internal constant l1ERC721BridgeProxyAddress = 0xD31598c909d9C935a9e35bA70d9a3DD47d4D5865; - address internal constant l1StandardBridgeAddress = 0xb7900B27Be8f0E0fF65d1C3A4671e1220437dd2b; + address internal constant l1StandardBridgeAddress = 0x6cb2c88ABCd6391F9496f44BE27d5D3b247E0159; address internal constant l1StandardBridgeProxyAddress = 0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D; - address internal constant l2OutputOracleAddress = 0x19652082F846171168Daf378C4fD3ee85a0D4A60; + address internal constant l2OutputOracleAddress = 0x60d37db59d0D14f7EA5c7425A2C03244E08B162D; address internal constant l2OutputOracleProxyAddress = 0x39Af23E00F1e662025aA01b0cEdA19542B78DF99; - address internal constant mipsAddress = 0x444e09fe6D839273316a87002aB0EFBeA6fe7806; - address internal constant optimismMintableERC20FactoryAddress = 0x7c06d3a0a2f45e39E1798afbd9C3330971332a4F; + address internal constant mipsAddress = 0x180CBe2EBb9F37D3a3C542DDc2546Fd160555a73; + address internal constant optimismMintableERC20FactoryAddress = 0x79c3114E5f89266e2C8842871Bce16D4e5076b1e; address internal constant optimismMintableERC20FactoryProxyAddress = 0xc7B87b2b892EA5C3CfF47168881FE168C00377FB; - address internal constant optimismPortalAddress = 0xbdD90485FCbcac869D5b5752179815a3103d8131; - address internal constant optimismPortal2Address = 0xae5DadFc48928543f706a9E6Ce25c682aaD2b63b; + address internal constant optimismPortalAddress = 0xb5A42f01EF5068F82C11fa1c4F9bBD4c8D346961; + address internal constant optimismPortal2Address = 0x150581358018524994Fc29800b1783637943b103; address internal constant optimismPortalProxyAddress = 0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4; address internal constant permissionedDelayedWETHProxyAddress = 0xd6EAF4c146261653EE059077B78ED088Add54309; - address internal constant preimageOracleAddress = 0x373d916D11cce55b548F7051002e76BCFBD7a85d; - address internal constant protocolVersionsAddress = 0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F; + address internal constant preimageOracleAddress = 0x7A9Eab4CE99d157AeE7A02E95b366E972a2D5b0b; + address internal constant protocolVersionsAddress = 0xa99F1ab91821747b76Ec0cDFA38368DF4Ba06E84; address internal constant protocolVersionsProxyAddress = 0x4C52a6277b1B84121b3072C0c92b6Be0b7CC10F1; address internal constant proxyAdminAddress = 0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1; address internal constant safeProxyFactoryAddress = 0xA8452Ec99ce0C64f20701dB7dD3abDb607c00496; address internal constant safeSingletonAddress = 0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3; - address internal constant superchainConfigAddress = 0x068E44eB31e111028c41598E4535be7468674D0A; + address internal constant superchainConfigAddress = 0xDAf629c26abd7a84B6330c369887053B75dB2AF2; address internal constant superchainConfigProxyAddress = 0x4f559F30f5eB88D635FDe1548C4267DB8FaB0351; - address internal constant systemConfigAddress = 0x67866A5052E5302aaD08e9f352331fd8622eB6DC; + address internal constant systemConfigAddress = 0xd9CEcA938f039e427Edf626FA1f377d23A6b60c9; address internal constant systemConfigProxyAddress = 0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6; address internal constant systemOwnerSafeAddress = 0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD; address internal constant acc33Address = 0xb6b1579AA54e2F61e621a40d5F2704D717B3544F; @@ -107,7 +107,7 @@ contract DeploymentSummary is DeploymentSummaryCode { value = hex"0000000000000000000000000000000000000000000000000000000000000001"; vm.store(systemOwnerSafeAddress, slot, value); slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; - value = hex"000000000000000000000000068e44eb31e111028c41598e4535be7468674d0a"; + value = hex"000000000000000000000000daf629c26abd7a84b6330c369887053b75db2af2"; vm.store(superchainConfigProxyAddress, slot, value); slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; value = hex"0000000000000000000000000000000000000000000000000000000000000001"; @@ -145,7 +145,7 @@ contract DeploymentSummary is DeploymentSummaryCode { value = hex"0000000000000000000000000000000000000000000000000000000000000002"; vm.store(systemOwnerSafeAddress, slot, value); slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; - value = hex"000000000000000000000000fbfd64a6c0257f613fefce050aa30ecc3e3d7c3f"; + value = hex"000000000000000000000000a99f1ab91821747b76ec0cdfa38368df4ba06e84"; vm.store(protocolVersionsProxyAddress, slot, value); slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; value = hex"0000000000000000000000000000000000000000000000000000000000000001"; @@ -430,7 +430,7 @@ contract DeploymentSummary is DeploymentSummaryCode { value = hex"0000000000000000000000000000000000000000000000000000000000000003"; vm.store(systemOwnerSafeAddress, slot, value); slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; - value = hex"000000000000000000000000bdd90485fcbcac869d5b5752179815a3103d8131"; + value = hex"000000000000000000000000b5a42f01ef5068f82c11fa1c4f9bbd4c8d346961"; vm.store(optimismPortalProxyAddress, slot, value); slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; value = hex"0000000000000000000000000000000000000000000000000000000000000001"; @@ -460,7 +460,7 @@ contract DeploymentSummary is DeploymentSummaryCode { value = hex"0000000000000000000000000000000000000000000000000000000000000004"; vm.store(systemOwnerSafeAddress, slot, value); slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; - value = hex"00000000000000000000000067866a5052e5302aad08e9f352331fd8622eb6dc"; + value = hex"000000000000000000000000d9ceca938f039e427edf626fa1f377d23a6b60c9"; vm.store(systemConfigProxyAddress, slot, value); slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; value = hex"0000000000000000000000000000000000000000000000000000000000000001"; @@ -529,7 +529,7 @@ contract DeploymentSummary is DeploymentSummaryCode { value = hex"0000000000000000000000000000000000000000000000000000000000000006"; vm.store(systemOwnerSafeAddress, slot, value); slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; - value = hex"000000000000000000000000b7900b27be8f0e0ff65d1c3a4671e1220437dd2b"; + value = hex"0000000000000000000000006cb2c88abcd6391f9496f44be27d5d3b247e0159"; vm.store(l1StandardBridgeProxyAddress, slot, value); slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; value = hex"0000000000000000000000000000000000000000000000000000000000000001"; @@ -556,7 +556,7 @@ contract DeploymentSummary is DeploymentSummaryCode { value = hex"0000000000000000000000000000000000000000000000000000000000000007"; vm.store(systemOwnerSafeAddress, slot, value); slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; - value = hex"0000000000000000000000005c4f5e749a61a9503c4aae8a9393e89609a0e804"; + value = hex"000000000000000000000000a4bd7e58a30ed0477fe7372883d09bf86619bb66"; vm.store(l1ERC721BridgeProxyAddress, slot, value); slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; value = hex"0000000000000000000000000000000000000000000000000000000000000001"; @@ -580,7 +580,7 @@ contract DeploymentSummary is DeploymentSummaryCode { value = hex"0000000000000000000000000000000000000000000000000000000000000008"; vm.store(systemOwnerSafeAddress, slot, value); slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; - value = hex"0000000000000000000000007c06d3a0a2f45e39e1798afbd9c3330971332a4f"; + value = hex"00000000000000000000000079c3114e5f89266e2c8842871bce16d4e5076b1e"; vm.store(optimismMintableERC20FactoryProxyAddress, slot, value); slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; value = hex"0000000000000000000000000000000000000000000000000000000000000001"; @@ -610,7 +610,7 @@ contract DeploymentSummary is DeploymentSummaryCode { value = hex"000000000000000000000000000000000000000000000000000000000000000b"; vm.store(systemOwnerSafeAddress, slot, value); slot = hex"515216935740e67dfdda5cf8e248ea32b3277787818ab59153061ac875c9385e"; - value = hex"000000000000000000000000094e6508ba9d9bf1ce421fff3de06ae56e67901b"; + value = hex"000000000000000000000000357b6cda94109749a0da475ac1bfd395a61eb908"; vm.store(addressManagerAddress, slot, value); slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; value = hex"0000000000000000000000010000000000000000000000000000000000000000"; @@ -640,7 +640,7 @@ contract DeploymentSummary is DeploymentSummaryCode { value = hex"000000000000000000000000000000000000000000000000000000000000000c"; vm.store(systemOwnerSafeAddress, slot, value); slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; - value = hex"00000000000000000000000019652082f846171168daf378c4fd3ee85a0d4a60"; + value = hex"00000000000000000000000060d37db59d0d14f7ea5c7425a2c03244e08b162d"; vm.store(l2OutputOracleProxyAddress, slot, value); slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; value = hex"0000000000000000000000000000000000000000000000000000000000000001"; @@ -676,7 +676,7 @@ contract DeploymentSummary is DeploymentSummaryCode { value = hex"000000000000000000000000000000000000000000000000000000000000000d"; vm.store(systemOwnerSafeAddress, slot, value); slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; - value = hex"00000000000000000000000020b168142354cee65a32f6d8cf3033e592299765"; + value = hex"0000000000000000000000008efda795511cbbdffc9eeca1a5bf30f5b1e1ef9e"; vm.store(disputeGameFactoryProxyAddress, slot, value); slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; value = hex"0000000000000000000000000000000000000000000000000000000000000001"; @@ -697,7 +697,7 @@ contract DeploymentSummary is DeploymentSummaryCode { value = hex"000000000000000000000000000000000000000000000000000000000000000e"; vm.store(systemOwnerSafeAddress, slot, value); slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; - value = hex"0000000000000000000000002a6347edd3c7813cde46dd7ea61ff1cf2290bc05"; + value = hex"000000000000000000000000e49ced258137cc5e18fb9aba2aa14069263d8f49"; vm.store(delayedWETHProxyAddress, slot, value); slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; value = hex"0000000000000000000000000000000000000000000000000000000000000001"; @@ -721,7 +721,7 @@ contract DeploymentSummary is DeploymentSummaryCode { value = hex"000000000000000000000000000000000000000000000000000000000000000f"; vm.store(systemOwnerSafeAddress, slot, value); slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; - value = hex"0000000000000000000000002a6347edd3c7813cde46dd7ea61ff1cf2290bc05"; + value = hex"000000000000000000000000e49ced258137cc5e18fb9aba2aa14069263d8f49"; vm.store(permissionedDelayedWETHProxyAddress, slot, value); slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; value = hex"0000000000000000000000000000000000000000000000000000000000000001"; @@ -745,7 +745,7 @@ contract DeploymentSummary is DeploymentSummaryCode { value = hex"0000000000000000000000000000000000000000000000000000000000000010"; vm.store(systemOwnerSafeAddress, slot, value); slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; - value = hex"00000000000000000000000063b71b96756c693f7065345fecd9b7843b3e7c57"; + value = hex"000000000000000000000000dec4d949cf1a2e824ee4f8b12064e166b96171dd"; vm.store(anchorStateRegistryProxyAddress, slot, value); slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; value = hex"0000000000000000000000000000000000000000000000000000000000000001"; diff --git a/packages/contracts-bedrock/test/kontrol/proofs/utils/DeploymentSummaryCode.sol b/packages/contracts-bedrock/test/kontrol/proofs/utils/DeploymentSummaryCode.sol index 025c7485cd936..153fef71fb87b 100644 --- a/packages/contracts-bedrock/test/kontrol/proofs/utils/DeploymentSummaryCode.sol +++ b/packages/contracts-bedrock/test/kontrol/proofs/utils/DeploymentSummaryCode.sol @@ -17,11 +17,11 @@ contract DeploymentSummaryCode { bytes internal constant superchainConfigProxyCode = hex"60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a"; bytes internal constant superchainConfigCode = - hex"608060405234801561001057600080fd5b50600436106100885760003560e01c80635c975abb1161005b5780635c975abb146101255780636da663551461013d5780637fbf7b6a14610150578063c23a451a1461016657600080fd5b80633f4ba83a1461008d578063400ada7514610097578063452a9320146100aa57806354fd4d50146100dc575b600080fd5b61009561016e565b005b6100956100a5366004610746565b610294565b6100b261046d565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6101186040518060400160405280600581526020017f312e312e3000000000000000000000000000000000000000000000000000000081525081565b6040516100d39190610808565b61012d6104a6565b60405190151581526020016100d3565b61009561014b366004610851565b6104d6565b6101586105a4565b6040519081526020016100d3565b6101586105d2565b61017661046d565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610235576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f5375706572636861696e436f6e6669673a206f6e6c7920677561726469616e2060448201527f63616e20756e706175736500000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61026961026360017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b60009055565b6040517fa45f47fdea8a1efdd9029a5691c7f759c32b7c698632b563573e155625d1693390600090a1565b600054610100900460ff16158080156102b45750600054600160ff909116105b806102ce5750303b1580156102ce575060005460ff166001145b61035a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161022c565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156103b857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6103c18361061d565b8115610405576104056040518060400160405280601281526020017f496e697469616c697a65722070617573656400000000000000000000000000008152506106d8565b801561046857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b60006104a161049d60017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69610920565b5490565b905090565b60006104a161049d60017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b6104de61046d565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610598576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f5375706572636861696e436f6e6669673a206f6e6c7920677561726469616e2060448201527f63616e2070617573650000000000000000000000000000000000000000000000606482015260840161022c565b6105a1816106d8565b50565b6105cf60017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b81565b6105cf60017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69610920565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b9055565b61065061064b60017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69610920565b829055565b60006040805173ffffffffffffffffffffffffffffffffffffffff841660208201527f7b743789cff01dafdeae47739925425aab5dfd02d0c8229e4a508bcd2b9f42bb9101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526106cd91610808565b60405180910390a250565b61070c61070660017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b60019055565b7fc32e6d5d6d1de257f64eac19ddb1f700ba13527983849c9486b1ab007ea283818160405161073b9190610808565b60405180910390a150565b6000806040838503121561075957600080fd5b823573ffffffffffffffffffffffffffffffffffffffff8116811461077d57600080fd5b91506020830135801515811461079257600080fd5b809150509250929050565b6000815180845260005b818110156107c3576020818501810151868301820152016107a7565b818111156107d5576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061081b602083018461079d565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561086357600080fd5b813567ffffffffffffffff8082111561087b57600080fd5b818401915084601f83011261088f57600080fd5b8135818111156108a1576108a1610822565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156108e7576108e7610822565b8160405282815287602084870101111561090057600080fd5b826020860160208301376000928101602001929092525095945050505050565b600082821015610959577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50039056fea164736f6c634300080f000a"; + hex"608060405234801561001057600080fd5b50600436106100885760003560e01c80635c975abb1161005b5780635c975abb146101255780636da663551461013d5780637fbf7b6a14610150578063c23a451a1461016657600080fd5b80633f4ba83a1461008d578063400ada7514610097578063452a9320146100aa57806354fd4d50146100dc575b600080fd5b61009561016e565b005b6100956100a5366004610746565b610294565b6100b261046d565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6101186040518060400160405280600c81526020017f312e312e312d626574612e31000000000000000000000000000000000000000081525081565b6040516100d39190610808565b61012d6104a6565b60405190151581526020016100d3565b61009561014b366004610851565b6104d6565b6101586105a4565b6040519081526020016100d3565b6101586105d2565b61017661046d565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610235576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f5375706572636861696e436f6e6669673a206f6e6c7920677561726469616e2060448201527f63616e20756e706175736500000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61026961026360017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b60009055565b6040517fa45f47fdea8a1efdd9029a5691c7f759c32b7c698632b563573e155625d1693390600090a1565b600054610100900460ff16158080156102b45750600054600160ff909116105b806102ce5750303b1580156102ce575060005460ff166001145b61035a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161022c565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156103b857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6103c18361061d565b8115610405576104056040518060400160405280601281526020017f496e697469616c697a65722070617573656400000000000000000000000000008152506106d8565b801561046857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b60006104a161049d60017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69610920565b5490565b905090565b60006104a161049d60017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b6104de61046d565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610598576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f5375706572636861696e436f6e6669673a206f6e6c7920677561726469616e2060448201527f63616e2070617573650000000000000000000000000000000000000000000000606482015260840161022c565b6105a1816106d8565b50565b6105cf60017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b81565b6105cf60017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69610920565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b9055565b61065061064b60017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69610920565b829055565b60006040805173ffffffffffffffffffffffffffffffffffffffff841660208201527f7b743789cff01dafdeae47739925425aab5dfd02d0c8229e4a508bcd2b9f42bb9101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526106cd91610808565b60405180910390a250565b61070c61070660017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b60019055565b7fc32e6d5d6d1de257f64eac19ddb1f700ba13527983849c9486b1ab007ea283818160405161073b9190610808565b60405180910390a150565b6000806040838503121561075957600080fd5b823573ffffffffffffffffffffffffffffffffffffffff8116811461077d57600080fd5b91506020830135801515811461079257600080fd5b809150509250929050565b6000815180845260005b818110156107c3576020818501810151868301820152016107a7565b818111156107d5576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061081b602083018461079d565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561086357600080fd5b813567ffffffffffffffff8082111561087b57600080fd5b818401915084601f83011261088f57600080fd5b8135818111156108a1576108a1610822565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156108e7576108e7610822565b8160405282815287602084870101111561090057600080fd5b826020860160208301376000928101602001929092525095945050505050565b600082821015610959577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50039056fea164736f6c634300080f000a"; bytes internal constant protocolVersionsProxyCode = hex"60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a"; bytes internal constant protocolVersionsCode = - hex"608060405234801561001057600080fd5b50600436106100d45760003560e01c80638da5cb5b11610081578063f2fde38b1161005b578063f2fde38b146101b8578063f7d12760146101cb578063ffa1ad74146101d357600080fd5b80638da5cb5b14610180578063d798b1ac146101a8578063dc8452cd146101b057600080fd5b80635fd579af116100b25780635fd579af14610152578063715018a6146101655780637a1ac61e1461016d57600080fd5b80630457d6f2146100d9578063206a8300146100ee57806354fd4d5014610109575b600080fd5b6100ec6100e73660046108c3565b6101db565b005b6100f66101ef565b6040519081526020015b60405180910390f35b6101456040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516101009190610947565b6100ec6101603660046108c3565b61021d565b6100ec61022e565b6100ec61017b36600461098a565b610242565b60335460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610100565b6100f66103f7565b6100f6610430565b6100ec6101c63660046109bd565b610460565b6100f6610514565b6100f6600081565b6101e361055f565b6101ec816105e0565b50565b61021a60017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16109d8565b81565b61022561055f565b6101ec81610698565b61023661055f565b6102406000610712565b565b600054610100900460ff16158080156102625750600054600160ff909116105b8061027c5750303b15801561027c575060005460ff166001145b61030d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561036b57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610373610789565b61037c84610460565b610385836105e0565b61038e82610698565b80156103f157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b600061042b61042760017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6109d8565b5490565b905090565b600061042b61042760017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16109d8565b61046861055f565b73ffffffffffffffffffffffffffffffffffffffff811661050b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610304565b6101ec81610712565b61021a60017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6109d8565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b9055565b60335473ffffffffffffffffffffffffffffffffffffffff163314610240576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610304565b61061361060e60017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16109d8565b829055565b60008160405160200161062891815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060005b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be8360405161068c9190610947565b60405180910390a35050565b6106c661060e60017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6109d8565b6000816040516020016106db91815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529050600161065b565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16610820576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610304565b610240600054610100900460ff166108ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610304565b61024033610712565b6000602082840312156108d557600080fd5b5035919050565b6000815180845260005b81811015610902576020818501810151868301820152016108e6565b81811115610914576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061095a60208301846108dc565b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461098557600080fd5b919050565b60008060006060848603121561099f57600080fd5b6109a884610961565b95602085013595506040909401359392505050565b6000602082840312156109cf57600080fd5b61095a82610961565b600082821015610a11577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50039056fea164736f6c634300080f000a"; + hex"608060405234801561001057600080fd5b50600436106100d45760003560e01c80638da5cb5b11610081578063f2fde38b1161005b578063f2fde38b146101b8578063f7d12760146101cb578063ffa1ad74146101d357600080fd5b80638da5cb5b14610180578063d798b1ac146101a8578063dc8452cd146101b057600080fd5b80635fd579af116100b25780635fd579af14610152578063715018a6146101655780637a1ac61e1461016d57600080fd5b80630457d6f2146100d9578063206a8300146100ee57806354fd4d5014610109575b600080fd5b6100ec6100e73660046108c3565b6101db565b005b6100f66101ef565b6040519081526020015b60405180910390f35b6101456040518060400160405280600c81526020017f312e302e312d626574612e31000000000000000000000000000000000000000081525081565b6040516101009190610947565b6100ec6101603660046108c3565b61021d565b6100ec61022e565b6100ec61017b36600461098a565b610242565b60335460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610100565b6100f66103f7565b6100f6610430565b6100ec6101c63660046109bd565b610460565b6100f6610514565b6100f6600081565b6101e361055f565b6101ec816105e0565b50565b61021a60017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16109d8565b81565b61022561055f565b6101ec81610698565b61023661055f565b6102406000610712565b565b600054610100900460ff16158080156102625750600054600160ff909116105b8061027c5750303b15801561027c575060005460ff166001145b61030d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561036b57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610373610789565b61037c84610460565b610385836105e0565b61038e82610698565b80156103f157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b600061042b61042760017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6109d8565b5490565b905090565b600061042b61042760017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16109d8565b61046861055f565b73ffffffffffffffffffffffffffffffffffffffff811661050b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610304565b6101ec81610712565b61021a60017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6109d8565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b9055565b60335473ffffffffffffffffffffffffffffffffffffffff163314610240576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610304565b61061361060e60017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16109d8565b829055565b60008160405160200161062891815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060005b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be8360405161068c9190610947565b60405180910390a35050565b6106c661060e60017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6109d8565b6000816040516020016106db91815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529050600161065b565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16610820576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610304565b610240600054610100900460ff166108ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610304565b61024033610712565b6000602082840312156108d557600080fd5b5035919050565b6000815180845260005b81811015610902576020818501810151868301820152016108e6565b81811115610914576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061095a60208301846108dc565b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461098557600080fd5b919050565b60008060006060848603121561099f57600080fd5b6109a884610961565b95602085013595506040909401359392505050565b6000602082840312156109cf57600080fd5b61095a82610961565b600082821015610a11577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50039056fea164736f6c634300080f000a"; bytes internal constant optimismPortalProxyCode = hex"60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a"; bytes internal constant systemConfigProxyCode = @@ -45,33 +45,33 @@ contract DeploymentSummaryCode { bytes internal constant anchorStateRegistryProxyCode = hex"60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a"; bytes internal constant l1CrossDomainMessengerCode = - hex"60806040526004361061018b5760003560e01c80636425666b116100d6578063b1b1b2091161007f578063d764ad0b11610059578063d764ad0b1461049b578063db505d80146104ae578063ecc70428146104db57600080fd5b8063b1b1b2091461042b578063b28ade251461045b578063c0c53b8b1461047b57600080fd5b80638cbeeef2116100b05780638cbeeef2146102d05780639fce812c146103d0578063a4e7f8bd146103fb57600080fd5b80636425666b146103775780636e296e45146103a457806383a74074146103b957600080fd5b80633dbb202b1161013857806354fd4d501161011257806354fd4d50146102e65780635644cfdf1461033c5780635c975abb1461035257600080fd5b80633dbb202b146102935780633f827a5a146102a85780634c1d6a69146102d057600080fd5b80632828d7e8116101695780632828d7e81461022457806333d7e2bd1461023957806335e80ab31461026657600080fd5b8063028f85f7146101905780630c568498146101c35780630ff754ea146101d8575b600080fd5b34801561019c57600080fd5b506101a5601081565b60405167ffffffffffffffff90911681526020015b60405180910390f35b3480156101cf57600080fd5b506101a5603f81565b3480156101e457600080fd5b5060fc5473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101ba565b34801561023057600080fd5b506101a5604081565b34801561024557600080fd5b5060fd546101ff9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561027257600080fd5b5060fb546101ff9073ffffffffffffffffffffffffffffffffffffffff1681565b6102a66102a1366004611bdd565b610540565b005b3480156102b457600080fd5b506102bd600181565b60405161ffff90911681526020016101ba565b3480156102dc57600080fd5b506101a5619c4081565b3480156102f257600080fd5b5061032f6040518060400160405280600581526020017f322e342e3000000000000000000000000000000000000000000000000000000081525081565b6040516101ba9190611caf565b34801561034857600080fd5b506101a561138881565b34801561035e57600080fd5b5061036761083d565b60405190151581526020016101ba565b34801561038357600080fd5b5060fc546101ff9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156103b057600080fd5b506101ff6108d6565b3480156103c557600080fd5b506101a562030d4081565b3480156103dc57600080fd5b5060cf5473ffffffffffffffffffffffffffffffffffffffff166101ff565b34801561040757600080fd5b50610367610416366004611cc9565b60ce6020526000908152604090205460ff1681565b34801561043757600080fd5b50610367610446366004611cc9565b60cb6020526000908152604090205460ff1681565b34801561046757600080fd5b506101a5610476366004611ce2565b6109bd565b34801561048757600080fd5b506102a6610496366004611d36565b610a2b565b6102a66104a9366004611d81565b610ca2565b3480156104ba57600080fd5b5060cf546101ff9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156104e757600080fd5b5061053260cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b6040519081526020016101ba565b6105486115d3565b156105e05734156105e0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f43726f7373446f6d61696e4d657373656e6765723a2063616e6e6f742073656e60448201527f642076616c7565207769746820637573746f6d2067617320746f6b656e00000060648201526084015b60405180910390fd5b60cf546107129073ffffffffffffffffffffffffffffffffffffffff166106088585856109bd565b347fd764ad0b0000000000000000000000000000000000000000000000000000000061067460cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b338a34898c8c6040516024016106909796959493929190611e50565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611612565b8373ffffffffffffffffffffffffffffffffffffffff167fcb0f7ffd78f9aee47a248fae8db181db6eee833039123e026dcbff529522e52a33858561079760cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b866040516107a9959493929190611eaf565b60405180910390a260405134815233907f8ebb2ec2465bdb2a06a66fc37a0963af8a2a6a1479d81d56fdb8cbb98096d5469060200160405180910390a2505060cd80547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808216600101167fffff0000000000000000000000000000000000000000000000000000000000009091161790555050565b60fb54604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa1580156108ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108d19190611efd565b905090565b60cc5460009073ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2153016109a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f43726f7373446f6d61696e4d657373656e6765723a2078446f6d61696e4d657360448201527f7361676553656e646572206973206e6f7420736574000000000000000000000060648201526084016105d7565b5060cc5473ffffffffffffffffffffffffffffffffffffffff1690565b6000611388619c4080603f6109d9604063ffffffff8816611f4e565b6109e39190611f7e565b6109ee601088611f4e565b6109fb9062030d40611fcc565b610a059190611fcc565b610a0f9190611fcc565b610a199190611fcc565b610a239190611fcc565b949350505050565b6000547501000000000000000000000000000000000000000000900460ff1615808015610a76575060005460017401000000000000000000000000000000000000000090910460ff16105b80610aa85750303b158015610aa8575060005474010000000000000000000000000000000000000000900460ff166001145b610b34576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016105d7565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790558015610bba57600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000001790555b60fb805473ffffffffffffffffffffffffffffffffffffffff8087167fffffffffffffffffffffffff00000000000000000000000000000000000000009283161790925560fc805486841690831617905560fd805492851692909116919091179055610c397342000000000000000000000000000000000000076116ab565b8015610c9c57600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b610caa61083d565b15610d11576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f43726f7373446f6d61696e4d657373656e6765723a207061757365640000000060448201526064016105d7565b60f087901c60028110610dcc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f43726f7373446f6d61696e4d657373656e6765723a206f6e6c7920766572736960448201527f6f6e2030206f722031206d657373616765732061726520737570706f7274656460648201527f20617420746869732074696d6500000000000000000000000000000000000000608482015260a4016105d7565b8061ffff16600003610ec1576000610e1d878986868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508f92506117e7915050565b600081815260cb602052604090205490915060ff1615610ebf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f43726f7373446f6d61696e4d657373656e6765723a206c65676163792077697460448201527f6864726177616c20616c72656164792072656c6179656400000000000000000060648201526084016105d7565b505b6000610f07898989898989898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061180692505050565b9050610f11611829565b15610f4957853414610f2557610f25611ff8565b600081815260ce602052604090205460ff1615610f4457610f44611ff8565b61109b565b3415610ffd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605060248201527f43726f7373446f6d61696e4d657373656e6765723a2076616c7565206d75737460448201527f206265207a65726f20756e6c657373206d6573736167652069732066726f6d2060648201527f612073797374656d206164647265737300000000000000000000000000000000608482015260a4016105d7565b600081815260ce602052604090205460ff1661109b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520636160448201527f6e6e6f74206265207265706c617965640000000000000000000000000000000060648201526084016105d7565b6110a487611905565b15611157576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f43726f7373446f6d61696e4d657373656e6765723a2063616e6e6f742073656e60448201527f64206d65737361676520746f20626c6f636b65642073797374656d206164647260648201527f6573730000000000000000000000000000000000000000000000000000000000608482015260a4016105d7565b600081815260cb602052604090205460ff16156111f6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520686160448201527f7320616c7265616479206265656e2072656c617965640000000000000000000060648201526084016105d7565b61121785611208611388619c40611fcc565b67ffffffffffffffff1661194b565b158061123d575060cc5473ffffffffffffffffffffffffffffffffffffffff1661dead14155b1561135657600081815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555182917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff320161134f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d6573736167650000000000000000000000000000000000000060648201526084016105d7565b50506115ae565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8a1617905560006113e788619c405a6113aa9190612027565b8988888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061196992505050565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790559050801561149d57600082815260cb602052604090205460ff161561143a5761143a611ff8565b600082815260cb602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f4641df4a962071e12719d8c8c8e5ac7fc4d97b927346a3d7a335b1f7517e133c91a26115aa565b600082815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff32016115aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d6573736167650000000000000000000000000000000000000060648201526084016105d7565b5050505b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6000806115de611981565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b60fc546040517fe9e05c4200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063e9e05c4290849061167390889083908990600090899060040161203e565b6000604051808303818588803b15801561168c57600080fd5b505af11580156116a0573d6000803e3d6000fd5b505050505050505050565b6000547501000000000000000000000000000000000000000000900460ff16611756576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016105d7565b60cc5473ffffffffffffffffffffffffffffffffffffffff166117a05760cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790555b60cf80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60006117f585858585611a1e565b805190602001209050949350505050565b6000611816878787878787611ab7565b8051906020012090509695505050505050565b60fc5460009073ffffffffffffffffffffffffffffffffffffffff16331480156108d1575060cf5460fc54604080517f9bf62d82000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9384169390921691639bf62d82916004808201926020929091908290030181865afa1580156118c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118e99190612096565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b600073ffffffffffffffffffffffffffffffffffffffff8216301480611945575060fc5473ffffffffffffffffffffffffffffffffffffffff8381169116145b92915050565b600080603f83619c4001026040850201603f5a021015949350505050565b6000806000835160208501868989f195945050505050565b60fd54604080517f4397dfef0000000000000000000000000000000000000000000000000000000081528151600093849373ffffffffffffffffffffffffffffffffffffffff90911692634397dfef92600480830193928290030181865afa1580156119f1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a1591906120b3565b90939092509050565b606084848484604051602401611a3794939291906120f3565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fcbd4ece9000000000000000000000000000000000000000000000000000000001790529050949350505050565b6060868686868686604051602401611ad49695949392919061213d565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd764ad0b0000000000000000000000000000000000000000000000000000000017905290509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff81168114611b7857600080fd5b50565b60008083601f840112611b8d57600080fd5b50813567ffffffffffffffff811115611ba557600080fd5b602083019150836020828501011115611bbd57600080fd5b9250929050565b803563ffffffff81168114611bd857600080fd5b919050565b60008060008060608587031215611bf357600080fd5b8435611bfe81611b56565b9350602085013567ffffffffffffffff811115611c1a57600080fd5b611c2687828801611b7b565b9094509250611c39905060408601611bc4565b905092959194509250565b6000815180845260005b81811015611c6a57602081850181015186830182015201611c4e565b81811115611c7c576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611cc26020830184611c44565b9392505050565b600060208284031215611cdb57600080fd5b5035919050565b600080600060408486031215611cf757600080fd5b833567ffffffffffffffff811115611d0e57600080fd5b611d1a86828701611b7b565b9094509250611d2d905060208501611bc4565b90509250925092565b600080600060608486031215611d4b57600080fd5b8335611d5681611b56565b92506020840135611d6681611b56565b91506040840135611d7681611b56565b809150509250925092565b600080600080600080600060c0888a031215611d9c57600080fd5b873596506020880135611dae81611b56565b95506040880135611dbe81611b56565b9450606088013593506080880135925060a088013567ffffffffffffffff811115611de857600080fd5b611df48a828b01611b7b565b989b979a50959850939692959293505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b878152600073ffffffffffffffffffffffffffffffffffffffff808916602084015280881660408401525085606083015263ffffffff8516608083015260c060a0830152611ea260c083018486611e07565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff86168152608060208201526000611edf608083018688611e07565b905083604083015263ffffffff831660608301529695505050505050565b600060208284031215611f0f57600080fd5b81518015158114611cc257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff80831681851681830481118215151615611f7557611f75611f1f565b02949350505050565b600067ffffffffffffffff80841680611fc0577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b92169190910492915050565b600067ffffffffffffffff808316818516808303821115611fef57611fef611f1f565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b60008282101561203957612039611f1f565b500390565b73ffffffffffffffffffffffffffffffffffffffff8616815284602082015267ffffffffffffffff84166040820152821515606082015260a06080820152600061208b60a0830184611c44565b979650505050505050565b6000602082840312156120a857600080fd5b8151611cc281611b56565b600080604083850312156120c657600080fd5b82516120d181611b56565b602084015190925060ff811681146120e857600080fd5b809150509250929050565b600073ffffffffffffffffffffffffffffffffffffffff80871683528086166020840152506080604083015261212c6080830185611c44565b905082606083015295945050505050565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a083015261218860c0830184611c44565b9897505050505050505056fea164736f6c634300080f000a"; + hex"60806040526004361061018b5760003560e01c80636425666b116100d6578063b1b1b2091161007f578063d764ad0b11610059578063d764ad0b1461049b578063db505d80146104ae578063ecc70428146104db57600080fd5b8063b1b1b2091461042b578063b28ade251461045b578063c0c53b8b1461047b57600080fd5b80638cbeeef2116100b05780638cbeeef2146102d05780639fce812c146103d0578063a4e7f8bd146103fb57600080fd5b80636425666b146103775780636e296e45146103a457806383a74074146103b957600080fd5b80633dbb202b1161013857806354fd4d501161011257806354fd4d50146102e65780635644cfdf1461033c5780635c975abb1461035257600080fd5b80633dbb202b146102935780633f827a5a146102a85780634c1d6a69146102d057600080fd5b80632828d7e8116101695780632828d7e81461022457806333d7e2bd1461023957806335e80ab31461026657600080fd5b8063028f85f7146101905780630c568498146101c35780630ff754ea146101d8575b600080fd5b34801561019c57600080fd5b506101a5601081565b60405167ffffffffffffffff90911681526020015b60405180910390f35b3480156101cf57600080fd5b506101a5603f81565b3480156101e457600080fd5b5060fc5473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101ba565b34801561023057600080fd5b506101a5604081565b34801561024557600080fd5b5060fd546101ff9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561027257600080fd5b5060fb546101ff9073ffffffffffffffffffffffffffffffffffffffff1681565b6102a66102a1366004611bdd565b610540565b005b3480156102b457600080fd5b506102bd600181565b60405161ffff90911681526020016101ba565b3480156102dc57600080fd5b506101a5619c4081565b3480156102f257600080fd5b5061032f6040518060400160405280600c81526020017f322e342e312d626574612e31000000000000000000000000000000000000000081525081565b6040516101ba9190611caf565b34801561034857600080fd5b506101a561138881565b34801561035e57600080fd5b5061036761083d565b60405190151581526020016101ba565b34801561038357600080fd5b5060fc546101ff9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156103b057600080fd5b506101ff6108d6565b3480156103c557600080fd5b506101a562030d4081565b3480156103dc57600080fd5b5060cf5473ffffffffffffffffffffffffffffffffffffffff166101ff565b34801561040757600080fd5b50610367610416366004611cc9565b60ce6020526000908152604090205460ff1681565b34801561043757600080fd5b50610367610446366004611cc9565b60cb6020526000908152604090205460ff1681565b34801561046757600080fd5b506101a5610476366004611ce2565b6109bd565b34801561048757600080fd5b506102a6610496366004611d36565b610a2b565b6102a66104a9366004611d81565b610ca2565b3480156104ba57600080fd5b5060cf546101ff9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156104e757600080fd5b5061053260cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b6040519081526020016101ba565b6105486115d3565b156105e05734156105e0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f43726f7373446f6d61696e4d657373656e6765723a2063616e6e6f742073656e60448201527f642076616c7565207769746820637573746f6d2067617320746f6b656e00000060648201526084015b60405180910390fd5b60cf546107129073ffffffffffffffffffffffffffffffffffffffff166106088585856109bd565b347fd764ad0b0000000000000000000000000000000000000000000000000000000061067460cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b338a34898c8c6040516024016106909796959493929190611e50565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611612565b8373ffffffffffffffffffffffffffffffffffffffff167fcb0f7ffd78f9aee47a248fae8db181db6eee833039123e026dcbff529522e52a33858561079760cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b866040516107a9959493929190611eaf565b60405180910390a260405134815233907f8ebb2ec2465bdb2a06a66fc37a0963af8a2a6a1479d81d56fdb8cbb98096d5469060200160405180910390a2505060cd80547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808216600101167fffff0000000000000000000000000000000000000000000000000000000000009091161790555050565b60fb54604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa1580156108ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108d19190611efd565b905090565b60cc5460009073ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2153016109a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f43726f7373446f6d61696e4d657373656e6765723a2078446f6d61696e4d657360448201527f7361676553656e646572206973206e6f7420736574000000000000000000000060648201526084016105d7565b5060cc5473ffffffffffffffffffffffffffffffffffffffff1690565b6000611388619c4080603f6109d9604063ffffffff8816611f4e565b6109e39190611f7e565b6109ee601088611f4e565b6109fb9062030d40611fcc565b610a059190611fcc565b610a0f9190611fcc565b610a199190611fcc565b610a239190611fcc565b949350505050565b6000547501000000000000000000000000000000000000000000900460ff1615808015610a76575060005460017401000000000000000000000000000000000000000090910460ff16105b80610aa85750303b158015610aa8575060005474010000000000000000000000000000000000000000900460ff166001145b610b34576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016105d7565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790558015610bba57600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000001790555b60fb805473ffffffffffffffffffffffffffffffffffffffff8087167fffffffffffffffffffffffff00000000000000000000000000000000000000009283161790925560fc805486841690831617905560fd805492851692909116919091179055610c397342000000000000000000000000000000000000076116ab565b8015610c9c57600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b610caa61083d565b15610d11576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f43726f7373446f6d61696e4d657373656e6765723a207061757365640000000060448201526064016105d7565b60f087901c60028110610dcc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f43726f7373446f6d61696e4d657373656e6765723a206f6e6c7920766572736960448201527f6f6e2030206f722031206d657373616765732061726520737570706f7274656460648201527f20617420746869732074696d6500000000000000000000000000000000000000608482015260a4016105d7565b8061ffff16600003610ec1576000610e1d878986868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508f92506117e7915050565b600081815260cb602052604090205490915060ff1615610ebf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f43726f7373446f6d61696e4d657373656e6765723a206c65676163792077697460448201527f6864726177616c20616c72656164792072656c6179656400000000000000000060648201526084016105d7565b505b6000610f07898989898989898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061180692505050565b9050610f11611829565b15610f4957853414610f2557610f25611ff8565b600081815260ce602052604090205460ff1615610f4457610f44611ff8565b61109b565b3415610ffd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605060248201527f43726f7373446f6d61696e4d657373656e6765723a2076616c7565206d75737460448201527f206265207a65726f20756e6c657373206d6573736167652069732066726f6d2060648201527f612073797374656d206164647265737300000000000000000000000000000000608482015260a4016105d7565b600081815260ce602052604090205460ff1661109b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520636160448201527f6e6e6f74206265207265706c617965640000000000000000000000000000000060648201526084016105d7565b6110a487611905565b15611157576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f43726f7373446f6d61696e4d657373656e6765723a2063616e6e6f742073656e60448201527f64206d65737361676520746f20626c6f636b65642073797374656d206164647260648201527f6573730000000000000000000000000000000000000000000000000000000000608482015260a4016105d7565b600081815260cb602052604090205460ff16156111f6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520686160448201527f7320616c7265616479206265656e2072656c617965640000000000000000000060648201526084016105d7565b61121785611208611388619c40611fcc565b67ffffffffffffffff1661194b565b158061123d575060cc5473ffffffffffffffffffffffffffffffffffffffff1661dead14155b1561135657600081815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555182917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff320161134f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d6573736167650000000000000000000000000000000000000060648201526084016105d7565b50506115ae565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8a1617905560006113e788619c405a6113aa9190612027565b8988888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061196992505050565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790559050801561149d57600082815260cb602052604090205460ff161561143a5761143a611ff8565b600082815260cb602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f4641df4a962071e12719d8c8c8e5ac7fc4d97b927346a3d7a335b1f7517e133c91a26115aa565b600082815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff32016115aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d6573736167650000000000000000000000000000000000000060648201526084016105d7565b5050505b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6000806115de611981565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b60fc546040517fe9e05c4200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063e9e05c4290849061167390889083908990600090899060040161203e565b6000604051808303818588803b15801561168c57600080fd5b505af11580156116a0573d6000803e3d6000fd5b505050505050505050565b6000547501000000000000000000000000000000000000000000900460ff16611756576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016105d7565b60cc5473ffffffffffffffffffffffffffffffffffffffff166117a05760cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790555b60cf80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60006117f585858585611a1e565b805190602001209050949350505050565b6000611816878787878787611ab7565b8051906020012090509695505050505050565b60fc5460009073ffffffffffffffffffffffffffffffffffffffff16331480156108d1575060cf5460fc54604080517f9bf62d82000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9384169390921691639bf62d82916004808201926020929091908290030181865afa1580156118c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118e99190612096565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b600073ffffffffffffffffffffffffffffffffffffffff8216301480611945575060fc5473ffffffffffffffffffffffffffffffffffffffff8381169116145b92915050565b600080603f83619c4001026040850201603f5a021015949350505050565b6000806000835160208501868989f195945050505050565b60fd54604080517f4397dfef0000000000000000000000000000000000000000000000000000000081528151600093849373ffffffffffffffffffffffffffffffffffffffff90911692634397dfef92600480830193928290030181865afa1580156119f1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a1591906120b3565b90939092509050565b606084848484604051602401611a3794939291906120f3565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fcbd4ece9000000000000000000000000000000000000000000000000000000001790529050949350505050565b6060868686868686604051602401611ad49695949392919061213d565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd764ad0b0000000000000000000000000000000000000000000000000000000017905290509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff81168114611b7857600080fd5b50565b60008083601f840112611b8d57600080fd5b50813567ffffffffffffffff811115611ba557600080fd5b602083019150836020828501011115611bbd57600080fd5b9250929050565b803563ffffffff81168114611bd857600080fd5b919050565b60008060008060608587031215611bf357600080fd5b8435611bfe81611b56565b9350602085013567ffffffffffffffff811115611c1a57600080fd5b611c2687828801611b7b565b9094509250611c39905060408601611bc4565b905092959194509250565b6000815180845260005b81811015611c6a57602081850181015186830182015201611c4e565b81811115611c7c576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611cc26020830184611c44565b9392505050565b600060208284031215611cdb57600080fd5b5035919050565b600080600060408486031215611cf757600080fd5b833567ffffffffffffffff811115611d0e57600080fd5b611d1a86828701611b7b565b9094509250611d2d905060208501611bc4565b90509250925092565b600080600060608486031215611d4b57600080fd5b8335611d5681611b56565b92506020840135611d6681611b56565b91506040840135611d7681611b56565b809150509250925092565b600080600080600080600060c0888a031215611d9c57600080fd5b873596506020880135611dae81611b56565b95506040880135611dbe81611b56565b9450606088013593506080880135925060a088013567ffffffffffffffff811115611de857600080fd5b611df48a828b01611b7b565b989b979a50959850939692959293505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b878152600073ffffffffffffffffffffffffffffffffffffffff808916602084015280881660408401525085606083015263ffffffff8516608083015260c060a0830152611ea260c083018486611e07565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff86168152608060208201526000611edf608083018688611e07565b905083604083015263ffffffff831660608301529695505050505050565b600060208284031215611f0f57600080fd5b81518015158114611cc257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff80831681851681830481118215151615611f7557611f75611f1f565b02949350505050565b600067ffffffffffffffff80841680611fc0577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b92169190910492915050565b600067ffffffffffffffff808316818516808303821115611fef57611fef611f1f565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b60008282101561203957612039611f1f565b500390565b73ffffffffffffffffffffffffffffffffffffffff8616815284602082015267ffffffffffffffff84166040820152821515606082015260a06080820152600061208b60a0830184611c44565b979650505050505050565b6000602082840312156120a857600080fd5b8151611cc281611b56565b600080604083850312156120c657600080fd5b82516120d181611b56565b602084015190925060ff811681146120e857600080fd5b809150509250929050565b600073ffffffffffffffffffffffffffffffffffffffff80871683528086166020840152506080604083015261212c6080830185611c44565b905082606083015295945050505050565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a083015261218860c0830184611c44565b9897505050505050505056fea164736f6c634300080f000a"; bytes internal constant optimismMintableERC20FactoryCode = - hex"60806040523480156200001157600080fd5b5060043610620000935760003560e01c8063c4d66de81162000062578063c4d66de81462000175578063ce5ac90f146200018e578063e78cea9214620001a5578063ee9a31a214620001c657600080fd5b8063316b3739146200009857806354fd4d5014620000fb578063896f93d114620001475780638cf0629c146200015e575b600080fd5b620000d1620000a936600462000652565b60026020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b620001386040518060400160405280600681526020017f312e31302e30000000000000000000000000000000000000000000000000000081525081565b604051620000f29190620006e5565b620000d162000158366004620007dc565b620001e5565b620000d16200016f36600462000859565b620001fc565b6200018c6200018636600462000652565b6200041b565b005b620000d16200019f366004620007dc565b620005ed565b600154620000d19073ffffffffffffffffffffffffffffffffffffffff1681565b60015473ffffffffffffffffffffffffffffffffffffffff16620000d1565b6000620001f4848484620005ed565b949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8516620002a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d4d696e7461626c654552433230466163746f72793a206d7560448201527f73742070726f766964652072656d6f746520746f6b656e20616464726573730060648201526084015b60405180910390fd5b600085858585604051602001620002c29493929190620008f0565b604051602081830303815290604052805190602001209050600081600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168888888860405162000312906200061a565b620003229594939291906200094a565b8190604051809103906000f590508015801562000343573d6000803e3d6000fd5b5073ffffffffffffffffffffffffffffffffffffffff81811660008181526002602052604080822080547fffffffffffffffffffffffff000000000000000000000000000000000000000016948d1694851790555193945090927fceeb8e7d520d7f3b65fc11a262b91066940193b05d4f93df07cfdced0eb551cf9190a360405133815273ffffffffffffffffffffffffffffffffffffffff80891691908316907f52fe89dd5930f343d25650b62fd367bae47088bcddffd2a88350a6ecdd620cdb9060200160405180910390a39695505050505050565b600054610100900460ff16158080156200043c5750600054600160ff909116105b80620004585750303b15801562000458575060005460ff166001145b620004e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016200029e565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156200054557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84161790558015620005e957600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6000620001f48484846012620001fc565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b61178a80620009b083390190565b803573ffffffffffffffffffffffffffffffffffffffff811681146200064d57600080fd5b919050565b6000602082840312156200066557600080fd5b620006708262000628565b9392505050565b6000815180845260005b818110156200069f5760208185018101518683018201520162000681565b81811115620006b2576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600062000670602083018462000677565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126200073b57600080fd5b813567ffffffffffffffff80821115620007595762000759620006fa565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715620007a257620007a2620006fa565b81604052838152866020858801011115620007bc57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600060608486031215620007f257600080fd5b620007fd8462000628565b9250602084013567ffffffffffffffff808211156200081b57600080fd5b620008298783880162000729565b935060408601359150808211156200084057600080fd5b506200084f8682870162000729565b9150509250925092565b600080600080608085870312156200087057600080fd5b6200087b8562000628565b9350602085013567ffffffffffffffff808211156200089957600080fd5b620008a78883890162000729565b94506040870135915080821115620008be57600080fd5b50620008cd8782880162000729565b925050606085013560ff81168114620008e557600080fd5b939692955090935050565b73ffffffffffffffffffffffffffffffffffffffff8516815260806020820152600062000921608083018662000677565b828103604084015262000935818662000677565b91505060ff8316606083015295945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808816835280871660208401525060a060408301526200098560a083018662000677565b828103606084015262000999818662000677565b91505060ff83166080830152969550505050505056fe60e06040523480156200001157600080fd5b506040516200178a3803806200178a833981016040819052620000349162000163565b828260036200004483826200029e565b5060046200005382826200029e565b5050506001600160a01b039384166080529390921660a052505060ff1660c0526200036a565b80516001600160a01b03811681146200009157600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620000be57600080fd5b81516001600160401b0380821115620000db57620000db62000096565b604051601f8301601f19908116603f0116810190828211818310171562000106576200010662000096565b816040528381526020925086838588010111156200012357600080fd5b600091505b8382101562000147578582018301518183018401529082019062000128565b83821115620001595760008385830101525b9695505050505050565b600080600080600060a086880312156200017c57600080fd5b620001878662000079565b9450620001976020870162000079565b60408701519094506001600160401b0380821115620001b557600080fd5b620001c389838a01620000ac565b94506060880151915080821115620001da57600080fd5b50620001e988828901620000ac565b925050608086015160ff811681146200020157600080fd5b809150509295509295909350565b600181811c908216806200022457607f821691505b6020821081036200024557634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200029957600081815260208120601f850160051c81016020861015620002745750805b601f850160051c820191505b81811015620002955782815560010162000280565b5050505b505050565b81516001600160401b03811115620002ba57620002ba62000096565b620002d281620002cb84546200020f565b846200024b565b602080601f8311600181146200030a5760008415620002f15750858301515b600019600386901b1c1916600185901b17855562000295565b600085815260208120601f198616915b828110156200033b578886015182559484019460019091019084016200031a565b50858210156200035a5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c0516113d4620003b6600039600061024401526000818161034b015281816103e001528181610625015261075c0152600081816101a9015261037101526113d46000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063ae1f6aaf1161008c578063dd62ed3e11610066578063dd62ed3e14610395578063e78cea9214610349578063ee9a31a2146103db57600080fd5b8063ae1f6aaf14610349578063c01e1bd61461036f578063d6c0b2c41461036f57600080fd5b80639dc29fac116100bd5780639dc29fac14610310578063a457c2d714610323578063a9059cbb1461033657600080fd5b806370a08231146102d257806395d89b411461030857600080fd5b806323b872dd1161012f5780633950935111610114578063395093511461026e57806340c10f191461028157806354fd4d501461029657600080fd5b806323b872dd1461022a578063313ce5671461023d57600080fd5b806306fdde031161016057806306fdde03146101f0578063095ea7b31461020557806318160ddd1461021857600080fd5b806301ffc9a71461017c578063033964be146101a4575b600080fd5b61018f61018a36600461117d565b610402565b60405190151581526020015b60405180910390f35b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101f86104f3565b60405161019b91906111c6565b61018f610213366004611262565b610585565b6002545b60405190815260200161019b565b61018f61023836600461128c565b61059d565b60405160ff7f000000000000000000000000000000000000000000000000000000000000000016815260200161019b565b61018f61027c366004611262565b6105c1565b61029461028f366004611262565b61060d565b005b6101f86040518060400160405280600581526020017f312e332e3000000000000000000000000000000000000000000000000000000081525081565b61021c6102e03660046112c8565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101f8610735565b61029461031e366004611262565b610744565b61018f610331366004611262565b61085b565b61018f610344366004611262565b61092c565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b61021c6103a33660046112e3565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f1d1d8b63000000000000000000000000000000000000000000000000000000007fec4fc8e3000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000085168314806104bb57507fffffffff00000000000000000000000000000000000000000000000000000000858116908316145b806104ea57507fffffffff00000000000000000000000000000000000000000000000000000000858116908216145b95945050505050565b60606003805461050290611316565b80601f016020809104026020016040519081016040528092919081815260200182805461052e90611316565b801561057b5780601f106105505761010080835404028352916020019161057b565b820191906000526020600020905b81548152906001019060200180831161055e57829003601f168201915b5050505050905090565b60003361059381858561093a565b5060019392505050565b6000336105ab858285610aee565b6105b6858585610bc5565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906105939082908690610608908790611398565b61093a565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146106d7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084015b60405180910390fd5b6106e18282610e78565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d41213968858260405161072991815260200190565b60405180910390a25050565b60606004805461050290611316565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610809576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084016106ce565b6108138282610f98565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca58260405161072991815260200190565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091908381101561091f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084016106ce565b6105b6828686840361093a565b600033610593818585610bc5565b73ffffffffffffffffffffffffffffffffffffffff83166109dc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f726573730000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216610a7f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f737300000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610bbf5781811015610bb2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016106ce565b610bbf848484840361093a565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610c68576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216610d0b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f657373000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610dc1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e6365000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220858503905591851681529081208054849290610e05908490611398565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610e6b91815260200190565b60405180910390a3610bbf565b73ffffffffffffffffffffffffffffffffffffffff8216610ef5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016106ce565b8060026000828254610f079190611398565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604081208054839290610f41908490611398565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff821661103b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f730000000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260208190526040902054818110156110f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f636500000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260208190526040812083830390556002805484929061112d9084906113b0565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610ae1565b60006020828403121561118f57600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146111bf57600080fd5b9392505050565b600060208083528351808285015260005b818110156111f3578581018301518582016040015282016111d7565b81811115611205576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461125d57600080fd5b919050565b6000806040838503121561127557600080fd5b61127e83611239565b946020939093013593505050565b6000806000606084860312156112a157600080fd5b6112aa84611239565b92506112b860208501611239565b9150604084013590509250925092565b6000602082840312156112da57600080fd5b6111bf82611239565b600080604083850312156112f657600080fd5b6112ff83611239565b915061130d60208401611239565b90509250929050565b600181811c9082168061132a57607f821691505b602082108103611363577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156113ab576113ab611369565b500190565b6000828210156113c2576113c2611369565b50039056fea164736f6c634300080f000aa164736f6c634300080f000a"; + hex"60806040523480156200001157600080fd5b5060043610620000935760003560e01c8063c4d66de81162000062578063c4d66de81462000175578063ce5ac90f146200018e578063e78cea9214620001a5578063ee9a31a214620001c657600080fd5b8063316b3739146200009857806354fd4d5014620000fb578063896f93d114620001475780638cf0629c146200015e575b600080fd5b620000d1620000a936600462000652565b60026020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b620001386040518060400160405280600d81526020017f312e31302e312d626574612e310000000000000000000000000000000000000081525081565b604051620000f29190620006e5565b620000d162000158366004620007dc565b620001e5565b620000d16200016f36600462000859565b620001fc565b6200018c6200018636600462000652565b6200041b565b005b620000d16200019f366004620007dc565b620005ed565b600154620000d19073ffffffffffffffffffffffffffffffffffffffff1681565b60015473ffffffffffffffffffffffffffffffffffffffff16620000d1565b6000620001f4848484620005ed565b949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8516620002a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d4d696e7461626c654552433230466163746f72793a206d7560448201527f73742070726f766964652072656d6f746520746f6b656e20616464726573730060648201526084015b60405180910390fd5b600085858585604051602001620002c29493929190620008f0565b604051602081830303815290604052805190602001209050600081600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168888888860405162000312906200061a565b620003229594939291906200094a565b8190604051809103906000f590508015801562000343573d6000803e3d6000fd5b5073ffffffffffffffffffffffffffffffffffffffff81811660008181526002602052604080822080547fffffffffffffffffffffffff000000000000000000000000000000000000000016948d1694851790555193945090927fceeb8e7d520d7f3b65fc11a262b91066940193b05d4f93df07cfdced0eb551cf9190a360405133815273ffffffffffffffffffffffffffffffffffffffff80891691908316907f52fe89dd5930f343d25650b62fd367bae47088bcddffd2a88350a6ecdd620cdb9060200160405180910390a39695505050505050565b600054610100900460ff16158080156200043c5750600054600160ff909116105b80620004585750303b15801562000458575060005460ff166001145b620004e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016200029e565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156200054557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84161790558015620005e957600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6000620001f48484846012620001fc565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b61178a80620009b083390190565b803573ffffffffffffffffffffffffffffffffffffffff811681146200064d57600080fd5b919050565b6000602082840312156200066557600080fd5b620006708262000628565b9392505050565b6000815180845260005b818110156200069f5760208185018101518683018201520162000681565b81811115620006b2576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600062000670602083018462000677565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126200073b57600080fd5b813567ffffffffffffffff80821115620007595762000759620006fa565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715620007a257620007a2620006fa565b81604052838152866020858801011115620007bc57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600060608486031215620007f257600080fd5b620007fd8462000628565b9250602084013567ffffffffffffffff808211156200081b57600080fd5b620008298783880162000729565b935060408601359150808211156200084057600080fd5b506200084f8682870162000729565b9150509250925092565b600080600080608085870312156200087057600080fd5b6200087b8562000628565b9350602085013567ffffffffffffffff808211156200089957600080fd5b620008a78883890162000729565b94506040870135915080821115620008be57600080fd5b50620008cd8782880162000729565b925050606085013560ff81168114620008e557600080fd5b939692955090935050565b73ffffffffffffffffffffffffffffffffffffffff8516815260806020820152600062000921608083018662000677565b828103604084015262000935818662000677565b91505060ff8316606083015295945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808816835280871660208401525060a060408301526200098560a083018662000677565b828103606084015262000999818662000677565b91505060ff83166080830152969550505050505056fe60e06040523480156200001157600080fd5b506040516200178a3803806200178a833981016040819052620000349162000163565b828260036200004483826200029e565b5060046200005382826200029e565b5050506001600160a01b039384166080529390921660a052505060ff1660c0526200036a565b80516001600160a01b03811681146200009157600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620000be57600080fd5b81516001600160401b0380821115620000db57620000db62000096565b604051601f8301601f19908116603f0116810190828211818310171562000106576200010662000096565b816040528381526020925086838588010111156200012357600080fd5b600091505b8382101562000147578582018301518183018401529082019062000128565b83821115620001595760008385830101525b9695505050505050565b600080600080600060a086880312156200017c57600080fd5b620001878662000079565b9450620001976020870162000079565b60408701519094506001600160401b0380821115620001b557600080fd5b620001c389838a01620000ac565b94506060880151915080821115620001da57600080fd5b50620001e988828901620000ac565b925050608086015160ff811681146200020157600080fd5b809150509295509295909350565b600181811c908216806200022457607f821691505b6020821081036200024557634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200029957600081815260208120601f850160051c81016020861015620002745750805b601f850160051c820191505b81811015620002955782815560010162000280565b5050505b505050565b81516001600160401b03811115620002ba57620002ba62000096565b620002d281620002cb84546200020f565b846200024b565b602080601f8311600181146200030a5760008415620002f15750858301515b600019600386901b1c1916600185901b17855562000295565b600085815260208120601f198616915b828110156200033b578886015182559484019460019091019084016200031a565b50858210156200035a5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c0516113d4620003b6600039600061024401526000818161034b015281816103e001528181610625015261075c0152600081816101a9015261037101526113d46000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063ae1f6aaf1161008c578063dd62ed3e11610066578063dd62ed3e14610395578063e78cea9214610349578063ee9a31a2146103db57600080fd5b8063ae1f6aaf14610349578063c01e1bd61461036f578063d6c0b2c41461036f57600080fd5b80639dc29fac116100bd5780639dc29fac14610310578063a457c2d714610323578063a9059cbb1461033657600080fd5b806370a08231146102d257806395d89b411461030857600080fd5b806323b872dd1161012f5780633950935111610114578063395093511461026e57806340c10f191461028157806354fd4d501461029657600080fd5b806323b872dd1461022a578063313ce5671461023d57600080fd5b806306fdde031161016057806306fdde03146101f0578063095ea7b31461020557806318160ddd1461021857600080fd5b806301ffc9a71461017c578063033964be146101a4575b600080fd5b61018f61018a36600461117d565b610402565b60405190151581526020015b60405180910390f35b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101f86104f3565b60405161019b91906111c6565b61018f610213366004611262565b610585565b6002545b60405190815260200161019b565b61018f61023836600461128c565b61059d565b60405160ff7f000000000000000000000000000000000000000000000000000000000000000016815260200161019b565b61018f61027c366004611262565b6105c1565b61029461028f366004611262565b61060d565b005b6101f86040518060400160405280600c81526020017f312e332e312d626574612e31000000000000000000000000000000000000000081525081565b61021c6102e03660046112c8565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101f8610735565b61029461031e366004611262565b610744565b61018f610331366004611262565b61085b565b61018f610344366004611262565b61092c565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b61021c6103a33660046112e3565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f1d1d8b63000000000000000000000000000000000000000000000000000000007fec4fc8e3000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000085168314806104bb57507fffffffff00000000000000000000000000000000000000000000000000000000858116908316145b806104ea57507fffffffff00000000000000000000000000000000000000000000000000000000858116908216145b95945050505050565b60606003805461050290611316565b80601f016020809104026020016040519081016040528092919081815260200182805461052e90611316565b801561057b5780601f106105505761010080835404028352916020019161057b565b820191906000526020600020905b81548152906001019060200180831161055e57829003601f168201915b5050505050905090565b60003361059381858561093a565b5060019392505050565b6000336105ab858285610aee565b6105b6858585610bc5565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906105939082908690610608908790611398565b61093a565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146106d7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084015b60405180910390fd5b6106e18282610e78565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d41213968858260405161072991815260200190565b60405180910390a25050565b60606004805461050290611316565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610809576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084016106ce565b6108138282610f98565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca58260405161072991815260200190565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091908381101561091f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084016106ce565b6105b6828686840361093a565b600033610593818585610bc5565b73ffffffffffffffffffffffffffffffffffffffff83166109dc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f726573730000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216610a7f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f737300000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610bbf5781811015610bb2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016106ce565b610bbf848484840361093a565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610c68576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216610d0b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f657373000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610dc1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e6365000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220858503905591851681529081208054849290610e05908490611398565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610e6b91815260200190565b60405180910390a3610bbf565b73ffffffffffffffffffffffffffffffffffffffff8216610ef5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016106ce565b8060026000828254610f079190611398565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604081208054839290610f41908490611398565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff821661103b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f730000000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260208190526040902054818110156110f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f636500000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260208190526040812083830390556002805484929061112d9084906113b0565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610ae1565b60006020828403121561118f57600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146111bf57600080fd5b9392505050565b600060208083528351808285015260005b818110156111f3578581018301518582016040015282016111d7565b81811115611205576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461125d57600080fd5b919050565b6000806040838503121561127557600080fd5b61127e83611239565b946020939093013593505050565b6000806000606084860312156112a157600080fd5b6112aa84611239565b92506112b860208501611239565b9150604084013590509250925092565b6000602082840312156112da57600080fd5b6111bf82611239565b600080604083850312156112f657600080fd5b6112ff83611239565b915061130d60208401611239565b90509250929050565b600181811c9082168061132a57607f821691505b602082108103611363577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156113ab576113ab611369565b500190565b6000828210156113c2576113c2611369565b50039056fea164736f6c634300080f000aa164736f6c634300080f000a"; bytes internal constant systemConfigCode = - hex"608060405234801561001057600080fd5b50600436106102de5760003560e01c8063a711986911610186578063e0e2016d116100e3578063f2fde38b11610097578063f8c68de011610071578063f8c68de0146106e2578063fd32aa0f146106ea578063ffa1ad74146106f257600080fd5b8063f2fde38b146106b2578063f45e65d8146106c5578063f68016b7146106ce57600080fd5b8063e81b2c6d116100c8578063e81b2c6d14610681578063ec7075171461068a578063f2b4e617146106aa57600080fd5b8063e0e2016d14610671578063e2a3285c1461067957600080fd5b8063c9b26f611161013a578063d84447151161011f578063d84447151461064e578063dac6e63a14610656578063db9040fa1461065e57600080fd5b8063c9b26f6114610507578063cc731b021461051a57600080fd5b8063bc49ce5f1161016b578063bc49ce5f146104c6578063bfb14fb7146104ce578063c4e8ddfa146104ff57600080fd5b8063a7119869146104ab578063b40a817c146104b357600080fd5b80634397dfef1161023f578063550fcdc9116101f35780638da5cb5b116101cd5780638da5cb5b14610472578063935f029e146104905780639b7d7f0a146104a357600080fd5b8063550fcdc91461045a5780635d73369c14610462578063715018a61461046a57600080fd5b80634add321d116102245780634add321d146103e95780634f16540b146103f157806354fd4d501461041857600080fd5b80634397dfef146103ab57806348cd4cb1146103e157600080fd5b806318d13918116102965780631fd19ee11161027b5780631fd19ee114610378578063213268491461038057806321d7fde51461039857600080fd5b806318d139181461035b57806319f5cea81461037057600080fd5b80630a49cb03116102c75780630a49cb031461032b5780630ae14b1b146103335780630c18c1621461035257600080fd5b806306c92657146102e3578063078f29cf146102fe575b600080fd5b6102eb6106fa565b6040519081526020015b60405180910390f35b610306610728565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102f5565b610306610761565b630bebc2005b60405167ffffffffffffffff90911681526020016102f5565b6102eb60655481565b61036e610369366004612241565b610791565b005b6102eb6107a5565b6103066107d0565b6103886107fa565b60405190151581526020016102f5565b61036e6103a6366004612277565b610839565b6103b361084f565b6040805173ffffffffffffffffffffffffffffffffffffffff909316835260ff9091166020830152016102f5565b6102eb610863565b610339610893565b6102eb7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c0881565b60408051808201909152600c81527f322e332e302d626574612e32000000000000000000000000000000000000000060208201525b6040516102f59190612320565b61044d6108b9565b6102eb6108c3565b61036e6108ee565b60335473ffffffffffffffffffffffffffffffffffffffff16610306565b61036e61049e366004612333565b610902565b610306610914565b610306610944565b61036e6104c136600461236d565b610974565b6102eb610985565b6068546104ea9068010000000000000000900463ffffffff1681565b60405163ffffffff90911681526020016102f5565b6103066109b0565b61036e610515366004612388565b6109e0565b6105de6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152506040805160c08101825260695463ffffffff8082168352640100000000820460ff9081166020850152650100000000008304169383019390935266010000000000008104831660608301526a0100000000000000000000810490921660808201526e0100000000000000000000000000009091046fffffffffffffffffffffffffffffffff1660a082015290565b6040516102f59190600060c08201905063ffffffff80845116835260ff602085015116602084015260ff6040850151166040840152806060850151166060840152806080850151166080840152506fffffffffffffffffffffffffffffffff60a08401511660a083015292915050565b61044d6109f1565b6103066109fb565b61036e61066c3660046124bb565b610a2b565b6102eb610e36565b6102eb610e61565b6102eb60675481565b6068546104ea906c01000000000000000000000000900463ffffffff1681565b610306610e8c565b61036e6106c0366004612241565b610ebc565b6102eb60665481565b6068546103399067ffffffffffffffff1681565b6102eb610f70565b6102eb610f9b565b6102eb600081565b61072560017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d61263d565b81565b600061075c61075860017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad637761263d565b5490565b905090565b600061075c61075860017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad61263d565b610799611201565b6107a281611282565b50565b61072560017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a861263d565b600061075c7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c085490565b60008061080561084f565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b610841611201565b61084b828261133f565b5050565b60008061085a611184565b90939092509050565b600061075c61075860017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a061263d565b60695460009061075c9063ffffffff6a0100000000000000000000820481169116612654565b606061075c61147d565b61072560017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce958063761263d565b6108f6611201565b610900600061153e565b565b61090a611201565b61084b82826115b5565b600061075c61075860017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d61263d565b600061075c61075860017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce958063761263d565b61097c611201565b6107a28161168b565b61072560017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc59861263d565b600061075c61075860017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a861263d565b6109e8611201565b6107a2816117e1565b606061075c611809565b600061075c61075860017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc59861263d565b600054610100900460ff1615808015610a4b5750600054600160ff909116105b80610a655750303b158015610a65575060005460ff166001145b610af6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610b5457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610b5c6118bf565b610b658a610ebc565b610b6e876117e1565b610b78898961133f565b610b818661168b565b610baa7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08869055565b610bdd610bd860017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc59861263d565b849055565b610c11610c0b60017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce958063761263d565b83519055565b610c48610c3f60017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a861263d565b60208401519055565b610c7f610c7660017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad637761263d565b60408401519055565b610cb6610cad60017f52322a25d9f59ea17656545543306b7aef62bc0cc53a0e65ccfa0c75b97aa90761263d565b60608401519055565b610ced610ce460017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad61263d565b60808401519055565b610d24610d1b60017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d61263d565b60a08401519055565b610d2c61195e565b610d398260c001516119c6565b610d4284611cd0565b610d4a610893565b67ffffffffffffffff168667ffffffffffffffff161015610dc7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77006044820152606401610aed565b8015610e2a57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050505050565b61072560017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a061263d565b61072560017f52322a25d9f59ea17656545543306b7aef62bc0cc53a0e65ccfa0c75b97aa90761263d565b600061075c61075860017f52322a25d9f59ea17656545543306b7aef62bc0cc53a0e65ccfa0c75b97aa90761263d565b610ec4611201565b73ffffffffffffffffffffffffffffffffffffffff8116610f67576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610aed565b6107a28161153e565b61072560017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad637761263d565b61072560017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad61263d565b9055565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b600060208251111561107a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f476173506179696e67546f6b656e3a20737472696e672063616e6e6f7420626560448201527f2067726561746572207468616e203332206279746573000000000000000000006064820152608401610aed565b6110838261115b565b92915050565b6110ef6110b760017f04adb1412b2ddc16fcc0d4538d5c8f07cf9c83abecc6b41f6f69037b708fbcec61263d565b74ff000000000000000000000000000000000000000060a086901b1673ffffffffffffffffffffffffffffffffffffffff8716179055565b61112261111d60017f657c3582c29b3176614e3a33ddd1ec48352696a04e92b3c0566d72010fa8863d61263d565b839055565b61115561115060017fa48b38a4b44951360fbdcbfaaeae5ed6ae92585412e9841b70ec72ed8cd0576461263d565b829055565b50505050565b8051602181106111735763ec92f9a36000526004601cfd5b9081015160209190910360031b1b90565b600080806111b661075860017f04adb1412b2ddc16fcc0d4538d5c8f07cf9c83abecc6b41f6f69037b708fbcec61263d565b73ffffffffffffffffffffffffffffffffffffffff811693509050826111f5575073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee92601292509050565b60a081901c9150509091565b60335473ffffffffffffffffffffffffffffffffffffffff163314610900576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610aed565b6112ab7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08829055565b6040805173ffffffffffffffffffffffffffffffffffffffff8316602082015260009101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060035b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be836040516113339190612320565b60405180910390a35050565b606880547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000063ffffffff8581169182027fffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffff16929092176c0100000000000000000000000092851692909202919091179091557f0100000000000000000000000000000000000000000000000000000000000000602083811b67ffffffff000000001690921717606681905560655460408051938401919091528201526000906060015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529050600160007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be836040516114709190612320565b60405180910390a3505050565b60606000611489611184565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff82160161150257505060408051808201909152600381527f4554480000000000000000000000000000000000000000000000000000000000602082015290565b61153861153361075860017fa48b38a4b44951360fbdcbfaaeae5ed6ae92585412e9841b70ec72ed8cd0576461263d565b612144565b91505090565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b7fff00000000000000000000000000000000000000000000000000000000000000811615611665576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f53797374656d436f6e6669673a207363616c61722065786365656473206d617860448201527f2e000000000000000000000000000000000000000000000000000000000000006064820152608401610aed565b60658290556066819055604080516020810184905290810182905260009060600161140d565b611693610893565b67ffffffffffffffff168167ffffffffffffffff161015611710576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77006044820152606401610aed565b630bebc20067ffffffffffffffff82161115611788576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f20686967686044820152606401610aed565b606880547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff83169081179091556040805160208082019390935281518082039093018352810190526002611302565b6067819055604080516020808201849052825180830390910181529082019091526000611302565b60606000611815611184565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff82160161188e57505060408051808201909152600581527f4574686572000000000000000000000000000000000000000000000000000000602082015290565b61153861153361075860017f657c3582c29b3176614e3a33ddd1ec48352696a04e92b3c0566d72010fa8863d61263d565b600054610100900460ff16611956576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610aed565b610900612178565b61198c61075860017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a061263d565b600003610900576109006119c160017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a061263d565b439055565b73ffffffffffffffffffffffffffffffffffffffff811615801590611a15575073ffffffffffffffffffffffffffffffffffffffff811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14155b8015611a265750611a246107fa565b155b156107a257601260ff168173ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a9f9190612680565b60ff1614611b2f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f53797374656d436f6e6669673a2062616420646563696d616c73206f6620676160448201527f7320706179696e6720746f6b656e0000000000000000000000000000000000006064820152608401610aed565b6000611bca8273ffffffffffffffffffffffffffffffffffffffff166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa158015611b7f573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611bc5919081019061269d565b610fe6565b90506000611c1c8373ffffffffffffffffffffffffffffffffffffffff166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015611b7f573d6000803e3d6000fd5b9050611c2b8360128484611089565b611c33610761565b6040517f71cfaa3f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015260126024830152604482018590526064820184905291909116906371cfaa3f90608401600060405180830381600087803b158015611cb357600080fd5b505af1158015611cc7573d6000803e3d6000fd5b50505050505050565b8060a001516fffffffffffffffffffffffffffffffff16816060015163ffffffff161115611d80576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f53797374656d436f6e6669673a206d696e206261736520666565206d7573742060448201527f6265206c657373207468616e206d6178206261736500000000000000000000006064820152608401610aed565b6001816040015160ff1611611e17576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f53797374656d436f6e6669673a2064656e6f6d696e61746f72206d757374206260448201527f65206c6172676572207468616e203100000000000000000000000000000000006064820152608401610aed565b6068546080820151825167ffffffffffffffff90921691611e389190612768565b63ffffffff161115611ea6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77006044820152606401610aed565b6000816020015160ff1611611f3d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f53797374656d436f6e6669673a20656c6173746963697479206d756c7469706c60448201527f6965722063616e6e6f74206265203000000000000000000000000000000000006064820152608401610aed565b8051602082015163ffffffff82169160ff90911690611f5d908290612787565b611f6791906127d1565b63ffffffff1614611ffa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f53797374656d436f6e6669673a20707265636973696f6e206c6f73732077697460448201527f6820746172676574207265736f75726365206c696d69740000000000000000006064820152608401610aed565b805160698054602084015160408501516060860151608087015160a09097015163ffffffff9687167fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009095169490941764010000000060ff94851602177fffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffff166501000000000093909216929092027fffffffffffffffffffffffffffffffffffffffffffff00000000ffffffffffff1617660100000000000091851691909102177fffff0000000000000000000000000000000000000000ffffffffffffffffffff166a010000000000000000000093909416929092027fffff00000000000000000000000000000000ffffffffffffffffffffffffffff16929092176e0100000000000000000000000000006fffffffffffffffffffffffffffffffff90921691909102179055565b60405160005b82811a1561215a5760010161214a565b80825260208201838152600082820152505060408101604052919050565b600054610100900460ff1661220f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610aed565b6109003361153e565b803573ffffffffffffffffffffffffffffffffffffffff8116811461223c57600080fd5b919050565b60006020828403121561225357600080fd5b61225c82612218565b9392505050565b803563ffffffff8116811461223c57600080fd5b6000806040838503121561228a57600080fd5b61229383612263565b91506122a160208401612263565b90509250929050565b60005b838110156122c55781810151838201526020016122ad565b838111156111555750506000910152565b600081518084526122ee8160208601602086016122aa565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061225c60208301846122d6565b6000806040838503121561234657600080fd5b50508035926020909101359150565b803567ffffffffffffffff8116811461223c57600080fd5b60006020828403121561237f57600080fd5b61225c82612355565b60006020828403121561239a57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160c0810167ffffffffffffffff811182821017156123f3576123f36123a1565b60405290565b60ff811681146107a257600080fd5b600060e0828403121561241a57600080fd5b60405160e0810181811067ffffffffffffffff8211171561243d5761243d6123a1565b60405290508061244c83612218565b815261245a60208401612218565b602082015261246b60408401612218565b604082015261247c60608401612218565b606082015261248d60808401612218565b608082015261249e60a08401612218565b60a08201526124af60c08401612218565b60c08201525092915050565b6000806000806000806000806000898b036102808112156124db57600080fd5b6124e48b612218565b99506124f260208c01612263565b985061250060408c01612263565b975060608b0135965061251560808c01612355565b955061252360a08c01612218565b945060c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff408201121561255557600080fd5b5061255e6123d0565b61256a60c08c01612263565b815260e08b013561257a816123f9565b60208201526101008b013561258e816123f9565b60408201526125a06101208c01612263565b60608201526125b26101408c01612263565b60808201526101608b01356fffffffffffffffffffffffffffffffff811681146125db57600080fd5b60a082015292506125ef6101808b01612218565b91506125ff8b6101a08c01612408565b90509295985092959850929598565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561264f5761264f61260e565b500390565b600067ffffffffffffffff8083168185168083038211156126775761267761260e565b01949350505050565b60006020828403121561269257600080fd5b815161225c816123f9565b6000602082840312156126af57600080fd5b815167ffffffffffffffff808211156126c757600080fd5b818401915084601f8301126126db57600080fd5b8151818111156126ed576126ed6123a1565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715612733576127336123a1565b8160405282815287602084870101111561274c57600080fd5b61275d8360208301602088016122aa565b979650505050505050565b600063ffffffff8083168185168083038211156126775761267761260e565b600063ffffffff808416806127c5577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b92169190910492915050565b600063ffffffff808316818516818304811182151516156127f4576127f461260e565b0294935050505056fea164736f6c634300080f000a"; + hex"608060405234801561001057600080fd5b50600436106102de5760003560e01c8063a711986911610186578063e0e2016d116100e3578063f2fde38b11610097578063f8c68de011610071578063f8c68de0146106e2578063fd32aa0f146106ea578063ffa1ad74146106f257600080fd5b8063f2fde38b146106b2578063f45e65d8146106c5578063f68016b7146106ce57600080fd5b8063e81b2c6d116100c8578063e81b2c6d14610681578063ec7075171461068a578063f2b4e617146106aa57600080fd5b8063e0e2016d14610671578063e2a3285c1461067957600080fd5b8063c9b26f611161013a578063d84447151161011f578063d84447151461064e578063dac6e63a14610656578063db9040fa1461065e57600080fd5b8063c9b26f6114610507578063cc731b021461051a57600080fd5b8063bc49ce5f1161016b578063bc49ce5f146104c6578063bfb14fb7146104ce578063c4e8ddfa146104ff57600080fd5b8063a7119869146104ab578063b40a817c146104b357600080fd5b80634397dfef1161023f578063550fcdc9116101f35780638da5cb5b116101cd5780638da5cb5b14610472578063935f029e146104905780639b7d7f0a146104a357600080fd5b8063550fcdc91461045a5780635d73369c14610462578063715018a61461046a57600080fd5b80634add321d116102245780634add321d146103e95780634f16540b146103f157806354fd4d501461041857600080fd5b80634397dfef146103ab57806348cd4cb1146103e157600080fd5b806318d13918116102965780631fd19ee11161027b5780631fd19ee114610378578063213268491461038057806321d7fde51461039857600080fd5b806318d139181461035b57806319f5cea81461037057600080fd5b80630a49cb03116102c75780630a49cb031461032b5780630ae14b1b146103335780630c18c1621461035257600080fd5b806306c92657146102e3578063078f29cf146102fe575b600080fd5b6102eb6106fa565b6040519081526020015b60405180910390f35b610306610728565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102f5565b610306610761565b630bebc2005b60405167ffffffffffffffff90911681526020016102f5565b6102eb60655481565b61036e610369366004612241565b610791565b005b6102eb6107a5565b6103066107d0565b6103886107fa565b60405190151581526020016102f5565b61036e6103a6366004612277565b610839565b6103b361084f565b6040805173ffffffffffffffffffffffffffffffffffffffff909316835260ff9091166020830152016102f5565b6102eb610863565b610339610893565b6102eb7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c0881565b60408051808201909152600c81527f322e332e302d626574612e33000000000000000000000000000000000000000060208201525b6040516102f59190612320565b61044d6108b9565b6102eb6108c3565b61036e6108ee565b60335473ffffffffffffffffffffffffffffffffffffffff16610306565b61036e61049e366004612333565b610902565b610306610914565b610306610944565b61036e6104c136600461236d565b610974565b6102eb610985565b6068546104ea9068010000000000000000900463ffffffff1681565b60405163ffffffff90911681526020016102f5565b6103066109b0565b61036e610515366004612388565b6109e0565b6105de6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152506040805160c08101825260695463ffffffff8082168352640100000000820460ff9081166020850152650100000000008304169383019390935266010000000000008104831660608301526a0100000000000000000000810490921660808201526e0100000000000000000000000000009091046fffffffffffffffffffffffffffffffff1660a082015290565b6040516102f59190600060c08201905063ffffffff80845116835260ff602085015116602084015260ff6040850151166040840152806060850151166060840152806080850151166080840152506fffffffffffffffffffffffffffffffff60a08401511660a083015292915050565b61044d6109f1565b6103066109fb565b61036e61066c3660046124bb565b610a2b565b6102eb610e36565b6102eb610e61565b6102eb60675481565b6068546104ea906c01000000000000000000000000900463ffffffff1681565b610306610e8c565b61036e6106c0366004612241565b610ebc565b6102eb60665481565b6068546103399067ffffffffffffffff1681565b6102eb610f70565b6102eb610f9b565b6102eb600081565b61072560017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d61263d565b81565b600061075c61075860017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad637761263d565b5490565b905090565b600061075c61075860017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad61263d565b610799611201565b6107a281611282565b50565b61072560017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a861263d565b600061075c7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c085490565b60008061080561084f565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b610841611201565b61084b828261133f565b5050565b60008061085a611184565b90939092509050565b600061075c61075860017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a061263d565b60695460009061075c9063ffffffff6a0100000000000000000000820481169116612654565b606061075c61147d565b61072560017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce958063761263d565b6108f6611201565b610900600061153e565b565b61090a611201565b61084b82826115b5565b600061075c61075860017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d61263d565b600061075c61075860017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce958063761263d565b61097c611201565b6107a28161168b565b61072560017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc59861263d565b600061075c61075860017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a861263d565b6109e8611201565b6107a2816117e1565b606061075c611809565b600061075c61075860017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc59861263d565b600054610100900460ff1615808015610a4b5750600054600160ff909116105b80610a655750303b158015610a65575060005460ff166001145b610af6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610b5457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610b5c6118bf565b610b658a610ebc565b610b6e876117e1565b610b78898961133f565b610b818661168b565b610baa7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08869055565b610bdd610bd860017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc59861263d565b849055565b610c11610c0b60017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce958063761263d565b83519055565b610c48610c3f60017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a861263d565b60208401519055565b610c7f610c7660017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad637761263d565b60408401519055565b610cb6610cad60017f52322a25d9f59ea17656545543306b7aef62bc0cc53a0e65ccfa0c75b97aa90761263d565b60608401519055565b610ced610ce460017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad61263d565b60808401519055565b610d24610d1b60017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d61263d565b60a08401519055565b610d2c61195e565b610d398260c001516119c6565b610d4284611cd0565b610d4a610893565b67ffffffffffffffff168667ffffffffffffffff161015610dc7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77006044820152606401610aed565b8015610e2a57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050505050565b61072560017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a061263d565b61072560017f52322a25d9f59ea17656545543306b7aef62bc0cc53a0e65ccfa0c75b97aa90761263d565b600061075c61075860017f52322a25d9f59ea17656545543306b7aef62bc0cc53a0e65ccfa0c75b97aa90761263d565b610ec4611201565b73ffffffffffffffffffffffffffffffffffffffff8116610f67576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610aed565b6107a28161153e565b61072560017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad637761263d565b61072560017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad61263d565b9055565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b600060208251111561107a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f476173506179696e67546f6b656e3a20737472696e672063616e6e6f7420626560448201527f2067726561746572207468616e203332206279746573000000000000000000006064820152608401610aed565b6110838261115b565b92915050565b6110ef6110b760017f04adb1412b2ddc16fcc0d4538d5c8f07cf9c83abecc6b41f6f69037b708fbcec61263d565b74ff000000000000000000000000000000000000000060a086901b1673ffffffffffffffffffffffffffffffffffffffff8716179055565b61112261111d60017f657c3582c29b3176614e3a33ddd1ec48352696a04e92b3c0566d72010fa8863d61263d565b839055565b61115561115060017fa48b38a4b44951360fbdcbfaaeae5ed6ae92585412e9841b70ec72ed8cd0576461263d565b829055565b50505050565b8051602181106111735763ec92f9a36000526004601cfd5b9081015160209190910360031b1b90565b600080806111b661075860017f04adb1412b2ddc16fcc0d4538d5c8f07cf9c83abecc6b41f6f69037b708fbcec61263d565b73ffffffffffffffffffffffffffffffffffffffff811693509050826111f5575073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee92601292509050565b60a081901c9150509091565b60335473ffffffffffffffffffffffffffffffffffffffff163314610900576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610aed565b6112ab7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08829055565b6040805173ffffffffffffffffffffffffffffffffffffffff8316602082015260009101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060035b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be836040516113339190612320565b60405180910390a35050565b606880547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000063ffffffff8581169182027fffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffff16929092176c0100000000000000000000000092851692909202919091179091557f0100000000000000000000000000000000000000000000000000000000000000602083811b67ffffffff000000001690921717606681905560655460408051938401919091528201526000906060015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529050600160007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be836040516114709190612320565b60405180910390a3505050565b60606000611489611184565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff82160161150257505060408051808201909152600381527f4554480000000000000000000000000000000000000000000000000000000000602082015290565b61153861153361075860017fa48b38a4b44951360fbdcbfaaeae5ed6ae92585412e9841b70ec72ed8cd0576461263d565b612144565b91505090565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b7fff00000000000000000000000000000000000000000000000000000000000000811615611665576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f53797374656d436f6e6669673a207363616c61722065786365656473206d617860448201527f2e000000000000000000000000000000000000000000000000000000000000006064820152608401610aed565b60658290556066819055604080516020810184905290810182905260009060600161140d565b611693610893565b67ffffffffffffffff168167ffffffffffffffff161015611710576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77006044820152606401610aed565b630bebc20067ffffffffffffffff82161115611788576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f20686967686044820152606401610aed565b606880547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff83169081179091556040805160208082019390935281518082039093018352810190526002611302565b6067819055604080516020808201849052825180830390910181529082019091526000611302565b60606000611815611184565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff82160161188e57505060408051808201909152600581527f4574686572000000000000000000000000000000000000000000000000000000602082015290565b61153861153361075860017f657c3582c29b3176614e3a33ddd1ec48352696a04e92b3c0566d72010fa8863d61263d565b600054610100900460ff16611956576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610aed565b610900612178565b61198c61075860017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a061263d565b600003610900576109006119c160017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a061263d565b439055565b73ffffffffffffffffffffffffffffffffffffffff811615801590611a15575073ffffffffffffffffffffffffffffffffffffffff811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14155b8015611a265750611a246107fa565b155b156107a257601260ff168173ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a9f9190612680565b60ff1614611b2f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f53797374656d436f6e6669673a2062616420646563696d616c73206f6620676160448201527f7320706179696e6720746f6b656e0000000000000000000000000000000000006064820152608401610aed565b6000611bca8273ffffffffffffffffffffffffffffffffffffffff166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa158015611b7f573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611bc5919081019061269d565b610fe6565b90506000611c1c8373ffffffffffffffffffffffffffffffffffffffff166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015611b7f573d6000803e3d6000fd5b9050611c2b8360128484611089565b611c33610761565b6040517f71cfaa3f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015260126024830152604482018590526064820184905291909116906371cfaa3f90608401600060405180830381600087803b158015611cb357600080fd5b505af1158015611cc7573d6000803e3d6000fd5b50505050505050565b8060a001516fffffffffffffffffffffffffffffffff16816060015163ffffffff161115611d80576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f53797374656d436f6e6669673a206d696e206261736520666565206d7573742060448201527f6265206c657373207468616e206d6178206261736500000000000000000000006064820152608401610aed565b6001816040015160ff1611611e17576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f53797374656d436f6e6669673a2064656e6f6d696e61746f72206d757374206260448201527f65206c6172676572207468616e203100000000000000000000000000000000006064820152608401610aed565b6068546080820151825167ffffffffffffffff90921691611e389190612768565b63ffffffff161115611ea6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77006044820152606401610aed565b6000816020015160ff1611611f3d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f53797374656d436f6e6669673a20656c6173746963697479206d756c7469706c60448201527f6965722063616e6e6f74206265203000000000000000000000000000000000006064820152608401610aed565b8051602082015163ffffffff82169160ff90911690611f5d908290612787565b611f6791906127d1565b63ffffffff1614611ffa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f53797374656d436f6e6669673a20707265636973696f6e206c6f73732077697460448201527f6820746172676574207265736f75726365206c696d69740000000000000000006064820152608401610aed565b805160698054602084015160408501516060860151608087015160a09097015163ffffffff9687167fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009095169490941764010000000060ff94851602177fffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffff166501000000000093909216929092027fffffffffffffffffffffffffffffffffffffffffffff00000000ffffffffffff1617660100000000000091851691909102177fffff0000000000000000000000000000000000000000ffffffffffffffffffff166a010000000000000000000093909416929092027fffff00000000000000000000000000000000ffffffffffffffffffffffffffff16929092176e0100000000000000000000000000006fffffffffffffffffffffffffffffffff90921691909102179055565b60405160005b82811a1561215a5760010161214a565b80825260208201838152600082820152505060408101604052919050565b600054610100900460ff1661220f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610aed565b6109003361153e565b803573ffffffffffffffffffffffffffffffffffffffff8116811461223c57600080fd5b919050565b60006020828403121561225357600080fd5b61225c82612218565b9392505050565b803563ffffffff8116811461223c57600080fd5b6000806040838503121561228a57600080fd5b61229383612263565b91506122a160208401612263565b90509250929050565b60005b838110156122c55781810151838201526020016122ad565b838111156111555750506000910152565b600081518084526122ee8160208601602086016122aa565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061225c60208301846122d6565b6000806040838503121561234657600080fd5b50508035926020909101359150565b803567ffffffffffffffff8116811461223c57600080fd5b60006020828403121561237f57600080fd5b61225c82612355565b60006020828403121561239a57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160c0810167ffffffffffffffff811182821017156123f3576123f36123a1565b60405290565b60ff811681146107a257600080fd5b600060e0828403121561241a57600080fd5b60405160e0810181811067ffffffffffffffff8211171561243d5761243d6123a1565b60405290508061244c83612218565b815261245a60208401612218565b602082015261246b60408401612218565b604082015261247c60608401612218565b606082015261248d60808401612218565b608082015261249e60a08401612218565b60a08201526124af60c08401612218565b60c08201525092915050565b6000806000806000806000806000898b036102808112156124db57600080fd5b6124e48b612218565b99506124f260208c01612263565b985061250060408c01612263565b975060608b0135965061251560808c01612355565b955061252360a08c01612218565b945060c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff408201121561255557600080fd5b5061255e6123d0565b61256a60c08c01612263565b815260e08b013561257a816123f9565b60208201526101008b013561258e816123f9565b60408201526125a06101208c01612263565b60608201526125b26101408c01612263565b60808201526101608b01356fffffffffffffffffffffffffffffffff811681146125db57600080fd5b60a082015292506125ef6101808b01612218565b91506125ff8b6101a08c01612408565b90509295985092959850929598565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561264f5761264f61260e565b500390565b600067ffffffffffffffff8083168185168083038211156126775761267761260e565b01949350505050565b60006020828403121561269257600080fd5b815161225c816123f9565b6000602082840312156126af57600080fd5b815167ffffffffffffffff808211156126c757600080fd5b818401915084601f8301126126db57600080fd5b8151818111156126ed576126ed6123a1565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715612733576127336123a1565b8160405282815287602084870101111561274c57600080fd5b61275d8360208301602088016122aa565b979650505050505050565b600063ffffffff8083168185168083038211156126775761267761260e565b600063ffffffff808416806127c5577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b92169190910492915050565b600063ffffffff808316818516818304811182151516156127f4576127f461260e565b0294935050505056fea164736f6c634300080f000a"; bytes internal constant l1StandardBridgeCode = - hex"6080604052600436106101845760003560e01c80637f46ddb2116100d65780639a2ac6d51161007f578063c0c53b8b11610059578063c0c53b8b14610529578063c89701a214610549578063e11013dd1461057657600080fd5b80639a2ac6d5146104e3578063a9f9e675146104f6578063b1a1a8821461051657600080fd5b80638f601f66116100b05780638f601f661461047257806391c49bf814610407578063927ede2d146104b857600080fd5b80637f46ddb214610407578063838b252014610432578063870876231461045257600080fd5b806335e80ab31161013857806354fd4d501161011257806354fd4d501461036c57806358a997f6146103c25780635c975abb146103e257600080fd5b806335e80ab3146102f25780633cb747bf1461031f578063540abf731461034c57600080fd5b80631532ec34116101695780631532ec34146102755780631635f5fd1461028857806333d7e2bd1461029b57600080fd5b80630166a07a1461024257806309fc88431461026257600080fd5b3661023d57333b1561021d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084015b60405180910390fd5b61023b333362030d40604051806020016040528060008152506105a5565b005b600080fd5b34801561024e57600080fd5b5061023b61025d366004612991565b6105b8565b61023b610270366004612a42565b6109d2565b61023b610283366004612a95565b610aa9565b61023b610296366004612a95565b610abd565b3480156102a757600080fd5b506033546102c89073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156102fe57600080fd5b506032546102c89073ffffffffffffffffffffffffffffffffffffffff1681565b34801561032b57600080fd5b506003546102c89073ffffffffffffffffffffffffffffffffffffffff1681565b34801561035857600080fd5b5061023b610367366004612b08565b61101b565b34801561037857600080fd5b506103b56040518060400160405280600581526020017f322e322e3000000000000000000000000000000000000000000000000000000081525081565b6040516102e99190612bf5565b3480156103ce57600080fd5b5061023b6103dd366004612c08565b611060565b3480156103ee57600080fd5b506103f7611134565b60405190151581526020016102e9565b34801561041357600080fd5b5060045473ffffffffffffffffffffffffffffffffffffffff166102c8565b34801561043e57600080fd5b5061023b61044d366004612b08565b6111cd565b34801561045e57600080fd5b5061023b61046d366004612c08565b611212565b34801561047e57600080fd5b506104aa61048d366004612c8b565b600260209081526000928352604080842090915290825290205481565b6040519081526020016102e9565b3480156104c457600080fd5b5060035473ffffffffffffffffffffffffffffffffffffffff166102c8565b61023b6104f1366004612cc4565b6112e6565b34801561050257600080fd5b5061023b610511366004612991565b611328565b61023b610524366004612a42565b611337565b34801561053557600080fd5b5061023b610544366004612d27565b611408565b34801561055557600080fd5b506004546102c89073ffffffffffffffffffffffffffffffffffffffff1681565b61023b610584366004612cc4565b611607565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6105b2848434858561164a565b50505050565b60035473ffffffffffffffffffffffffffffffffffffffff163314801561068b575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa15801561064f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106739190612d72565b73ffffffffffffffffffffffffffffffffffffffff16145b61073d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a401610214565b610745611134565b156107ac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616e646172644272696467653a20706175736564000000000000000000006044820152606401610214565b6107b5876118a9565b15610903576107c4878761190b565b610876576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a401610214565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b1580156108e657600080fd5b505af11580156108fa573d6000803e3d6000fd5b50505050610985565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054610941908490612dbe565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c1683529390529190912091909155610985908585611a2b565b6109c9878787878787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611aff92505050565b50505050505050565b333b15610a61576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610214565b610aa43333348686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061164a92505050565b505050565b610ab68585858585610abd565b5050505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610b90575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa158015610b54573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b789190612d72565b73ffffffffffffffffffffffffffffffffffffffff16145b610c42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a401610214565b610c4a611134565b15610cb1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616e646172644272696467653a20706175736564000000000000000000006044820152606401610214565b610cb9611b8d565b15610d46576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e0000000000000000006064820152608401610214565b823414610dd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e742072657175697265640000000000006064820152608401610214565b3073ffffffffffffffffffffffffffffffffffffffff851603610e7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c6600000000000000000000000000000000000000000000000000000000006064820152608401610214565b60035473ffffffffffffffffffffffffffffffffffffffff90811690851603610f25576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e6765720000000000000000000000000000000000000000000000006064820152608401610214565b610f6785858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611bcc92505050565b6000610f84855a8660405180602001604052806000815250611c3f565b905080611013576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c656400000000000000000000000000000000000000000000000000000000006064820152608401610214565b505050505050565b6109c987873388888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611c5792505050565b333b156110ef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610214565b61101386863333888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061201092505050565b603254604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa1580156111a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111c89190612dd5565b905090565b6109c987873388888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061201092505050565b333b156112a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610214565b61101386863333888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611c5792505050565b6105b233858585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506105a592505050565b6109c9878787878787876105b8565b333b156113c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610214565b610aa433338585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506105a592505050565b600054610100900460ff16158080156114285750600054600160ff909116105b806114425750303b158015611442575060005460ff166001145b6114ce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610214565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561152c57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6032805473ffffffffffffffffffffffffffffffffffffffff8086167fffffffffffffffffffffffff000000000000000000000000000000000000000092831617909255603380549285169290911691909117905561159f8473420000000000000000000000000000000000001061201f565b80156105b257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150505050565b6105b23385348686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061164a92505050565b611652611b8d565b156116df576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e0000000000000000006064820152608401610214565b82341461176e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c756500006064820152608401610214565b61177a85858584612109565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9287929116907f1635f5fd00000000000000000000000000000000000000000000000000000000906117dd908b908b9086908a90602401612df7565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b909216825261187092918890600401612e40565b6000604051808303818588803b15801561188957600080fd5b505af115801561189d573d6000803e3d6000fd5b50505050505050505050565b60006118d5827f1d1d8b630000000000000000000000000000000000000000000000000000000061217c565b806119055750611905827fec4fc8e30000000000000000000000000000000000000000000000000000000061217c565b92915050565b6000611937837f1d1d8b630000000000000000000000000000000000000000000000000000000061217c565b156119e0578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015611987573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ab9190612d72565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050611905565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611987573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052610aa49084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915261219f565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f3ceee06c1e37648fcbb6ed52e17b3e1f275a1f8c7b22a84b2b84732431e046b3868686604051611b7793929190612e85565b60405180910390a46110138686868686866122ab565b600080611b98612333565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2ac69ee804d9a7a0984249f508dfab7cb2534b465b6ce1580f99a38ba9c5e6318484604051611c2b929190612ec3565b60405180910390a36105b2848484846123d0565b6000806000835160208501868989f195945050505050565b3415611ce5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5374616e646172644272696467653a2063616e6e6f742073656e642076616c7560448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610214565b611cee876118a9565b15611e3c57611cfd878761190b565b611daf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a401610214565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b158015611e1f57600080fd5b505af1158015611e33573d6000803e3d6000fd5b50505050611ed0565b611e5e73ffffffffffffffffffffffffffffffffffffffff881686308661243d565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054611e9c908490612edc565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b611ede87878787878661249b565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9216907f0166a07a0000000000000000000000000000000000000000000000000000000090611f42908b908d908c908c908c908b90602401612ef4565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b9092168252611fd592918790600401612e40565b600060405180830381600087803b158015611fef57600080fd5b505af1158015612003573d6000803e3d6000fd5b5050505050505050505050565b6109c987878787878787611c57565b600054610100900460ff166120b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610214565b6003805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560048054929093169116179055565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f35d79ab81f2b2017e19afb5c5571778877782d7a8786f5907f93b0f4702f4f238484604051612168929190612ec3565b60405180910390a36105b284848484612529565b600061218783612588565b8015612198575061219883836125ec565b9392505050565b6000612201826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166126bb9092919063ffffffff16565b805190915015610aa4578080602001905181019061221f9190612dd5565b610aa4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610214565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd86868660405161232393929190612e85565b60405180910390a4505050505050565b603354604080517f4397dfef0000000000000000000000000000000000000000000000000000000081528151600093849373ffffffffffffffffffffffffffffffffffffffff90911692634397dfef92600480830193928290030181865afa1580156123a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123c79190612f4f565b90939092509050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d848460405161242f929190612ec3565b60405180910390a350505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526105b29085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611a7d565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f718594027abd4eaed59f95162563e0cc6d0e8d5b86b1c7be8b1b0ac3343d039686868660405161251393929190612e85565b60405180910390a46110138686868686866126d2565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af5848460405161242f929190612ec3565b60006125b4827f01ffc9a7000000000000000000000000000000000000000000000000000000006125ec565b801561190557506125e5827fffffffff000000000000000000000000000000000000000000000000000000006125ec565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d915060005190508280156126a4575060208210155b80156126b05750600081115b979650505050505050565b60606126ca848460008561274a565b949350505050565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf86868660405161232393929190612e85565b6060824710156127dc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610214565b73ffffffffffffffffffffffffffffffffffffffff85163b61285a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610214565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516128839190612f84565b60006040518083038185875af1925050503d80600081146128c0576040519150601f19603f3d011682016040523d82523d6000602084013e6128c5565b606091505b50915091506126b0828286606083156128df575081612198565b8251156128ef5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102149190612bf5565b73ffffffffffffffffffffffffffffffffffffffff8116811461294557600080fd5b50565b60008083601f84011261295a57600080fd5b50813567ffffffffffffffff81111561297257600080fd5b60208301915083602082850101111561298a57600080fd5b9250929050565b600080600080600080600060c0888a0312156129ac57600080fd5b87356129b781612923565b965060208801356129c781612923565b955060408801356129d781612923565b945060608801356129e781612923565b93506080880135925060a088013567ffffffffffffffff811115612a0a57600080fd5b612a168a828b01612948565b989b979a50959850939692959293505050565b803563ffffffff81168114612a3d57600080fd5b919050565b600080600060408486031215612a5757600080fd5b612a6084612a29565b9250602084013567ffffffffffffffff811115612a7c57600080fd5b612a8886828701612948565b9497909650939450505050565b600080600080600060808688031215612aad57600080fd5b8535612ab881612923565b94506020860135612ac881612923565b935060408601359250606086013567ffffffffffffffff811115612aeb57600080fd5b612af788828901612948565b969995985093965092949392505050565b600080600080600080600060c0888a031215612b2357600080fd5b8735612b2e81612923565b96506020880135612b3e81612923565b95506040880135612b4e81612923565b945060608801359350612b6360808901612a29565b925060a088013567ffffffffffffffff811115612a0a57600080fd5b60005b83811015612b9a578181015183820152602001612b82565b838111156105b25750506000910152565b60008151808452612bc3816020860160208601612b7f565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006121986020830184612bab565b60008060008060008060a08789031215612c2157600080fd5b8635612c2c81612923565b95506020870135612c3c81612923565b945060408701359350612c5160608801612a29565b9250608087013567ffffffffffffffff811115612c6d57600080fd5b612c7989828a01612948565b979a9699509497509295939492505050565b60008060408385031215612c9e57600080fd5b8235612ca981612923565b91506020830135612cb981612923565b809150509250929050565b60008060008060608587031215612cda57600080fd5b8435612ce581612923565b9350612cf360208601612a29565b9250604085013567ffffffffffffffff811115612d0f57600080fd5b612d1b87828801612948565b95989497509550505050565b600080600060608486031215612d3c57600080fd5b8335612d4781612923565b92506020840135612d5781612923565b91506040840135612d6781612923565b809150509250925092565b600060208284031215612d8457600080fd5b815161219881612923565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015612dd057612dd0612d8f565b500390565b600060208284031215612de757600080fd5b8151801515811461219857600080fd5b600073ffffffffffffffffffffffffffffffffffffffff808716835280861660208401525083604083015260806060830152612e366080830184612bab565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff84168152606060208201526000612e6f6060830185612bab565b905063ffffffff83166040830152949350505050565b73ffffffffffffffffffffffffffffffffffffffff84168152826020820152606060408201526000612eba6060830184612bab565b95945050505050565b8281526040602082015260006126ca6040830184612bab565b60008219821115612eef57612eef612d8f565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a0830152612f4360c0830184612bab565b98975050505050505050565b60008060408385031215612f6257600080fd5b8251612f6d81612923565b602084015190925060ff81168114612cb957600080fd5b60008251612f96818460208701612b7f565b919091019291505056fea164736f6c634300080f000a"; + hex"6080604052600436106101845760003560e01c80637f46ddb2116100d65780639a2ac6d51161007f578063c0c53b8b11610059578063c0c53b8b14610529578063c89701a214610549578063e11013dd1461057657600080fd5b80639a2ac6d5146104e3578063a9f9e675146104f6578063b1a1a8821461051657600080fd5b80638f601f66116100b05780638f601f661461047257806391c49bf814610407578063927ede2d146104b857600080fd5b80637f46ddb214610407578063838b252014610432578063870876231461045257600080fd5b806335e80ab31161013857806354fd4d501161011257806354fd4d501461036c57806358a997f6146103c25780635c975abb146103e257600080fd5b806335e80ab3146102f25780633cb747bf1461031f578063540abf731461034c57600080fd5b80631532ec34116101695780631532ec34146102755780631635f5fd1461028857806333d7e2bd1461029b57600080fd5b80630166a07a1461024257806309fc88431461026257600080fd5b3661023d57333b1561021d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084015b60405180910390fd5b61023b333362030d40604051806020016040528060008152506105a5565b005b600080fd5b34801561024e57600080fd5b5061023b61025d366004612991565b6105b8565b61023b610270366004612a42565b6109d2565b61023b610283366004612a95565b610aa9565b61023b610296366004612a95565b610abd565b3480156102a757600080fd5b506033546102c89073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156102fe57600080fd5b506032546102c89073ffffffffffffffffffffffffffffffffffffffff1681565b34801561032b57600080fd5b506003546102c89073ffffffffffffffffffffffffffffffffffffffff1681565b34801561035857600080fd5b5061023b610367366004612b08565b61101b565b34801561037857600080fd5b506103b56040518060400160405280600c81526020017f322e322e312d626574612e31000000000000000000000000000000000000000081525081565b6040516102e99190612bf5565b3480156103ce57600080fd5b5061023b6103dd366004612c08565b611060565b3480156103ee57600080fd5b506103f7611134565b60405190151581526020016102e9565b34801561041357600080fd5b5060045473ffffffffffffffffffffffffffffffffffffffff166102c8565b34801561043e57600080fd5b5061023b61044d366004612b08565b6111cd565b34801561045e57600080fd5b5061023b61046d366004612c08565b611212565b34801561047e57600080fd5b506104aa61048d366004612c8b565b600260209081526000928352604080842090915290825290205481565b6040519081526020016102e9565b3480156104c457600080fd5b5060035473ffffffffffffffffffffffffffffffffffffffff166102c8565b61023b6104f1366004612cc4565b6112e6565b34801561050257600080fd5b5061023b610511366004612991565b611328565b61023b610524366004612a42565b611337565b34801561053557600080fd5b5061023b610544366004612d27565b611408565b34801561055557600080fd5b506004546102c89073ffffffffffffffffffffffffffffffffffffffff1681565b61023b610584366004612cc4565b611607565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6105b2848434858561164a565b50505050565b60035473ffffffffffffffffffffffffffffffffffffffff163314801561068b575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa15801561064f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106739190612d72565b73ffffffffffffffffffffffffffffffffffffffff16145b61073d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a401610214565b610745611134565b156107ac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616e646172644272696467653a20706175736564000000000000000000006044820152606401610214565b6107b5876118a9565b15610903576107c4878761190b565b610876576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a401610214565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b1580156108e657600080fd5b505af11580156108fa573d6000803e3d6000fd5b50505050610985565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054610941908490612dbe565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c1683529390529190912091909155610985908585611a2b565b6109c9878787878787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611aff92505050565b50505050505050565b333b15610a61576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610214565b610aa43333348686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061164a92505050565b505050565b610ab68585858585610abd565b5050505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610b90575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa158015610b54573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b789190612d72565b73ffffffffffffffffffffffffffffffffffffffff16145b610c42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a401610214565b610c4a611134565b15610cb1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616e646172644272696467653a20706175736564000000000000000000006044820152606401610214565b610cb9611b8d565b15610d46576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e0000000000000000006064820152608401610214565b823414610dd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e742072657175697265640000000000006064820152608401610214565b3073ffffffffffffffffffffffffffffffffffffffff851603610e7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c6600000000000000000000000000000000000000000000000000000000006064820152608401610214565b60035473ffffffffffffffffffffffffffffffffffffffff90811690851603610f25576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e6765720000000000000000000000000000000000000000000000006064820152608401610214565b610f6785858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611bcc92505050565b6000610f84855a8660405180602001604052806000815250611c3f565b905080611013576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c656400000000000000000000000000000000000000000000000000000000006064820152608401610214565b505050505050565b6109c987873388888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611c5792505050565b333b156110ef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610214565b61101386863333888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061201092505050565b603254604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa1580156111a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111c89190612dd5565b905090565b6109c987873388888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061201092505050565b333b156112a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610214565b61101386863333888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611c5792505050565b6105b233858585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506105a592505050565b6109c9878787878787876105b8565b333b156113c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610214565b610aa433338585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506105a592505050565b600054610100900460ff16158080156114285750600054600160ff909116105b806114425750303b158015611442575060005460ff166001145b6114ce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610214565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561152c57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6032805473ffffffffffffffffffffffffffffffffffffffff8086167fffffffffffffffffffffffff000000000000000000000000000000000000000092831617909255603380549285169290911691909117905561159f8473420000000000000000000000000000000000001061201f565b80156105b257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150505050565b6105b23385348686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061164a92505050565b611652611b8d565b156116df576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e0000000000000000006064820152608401610214565b82341461176e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c756500006064820152608401610214565b61177a85858584612109565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9287929116907f1635f5fd00000000000000000000000000000000000000000000000000000000906117dd908b908b9086908a90602401612df7565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b909216825261187092918890600401612e40565b6000604051808303818588803b15801561188957600080fd5b505af115801561189d573d6000803e3d6000fd5b50505050505050505050565b60006118d5827f1d1d8b630000000000000000000000000000000000000000000000000000000061217c565b806119055750611905827fec4fc8e30000000000000000000000000000000000000000000000000000000061217c565b92915050565b6000611937837f1d1d8b630000000000000000000000000000000000000000000000000000000061217c565b156119e0578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015611987573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ab9190612d72565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050611905565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611987573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052610aa49084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915261219f565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f3ceee06c1e37648fcbb6ed52e17b3e1f275a1f8c7b22a84b2b84732431e046b3868686604051611b7793929190612e85565b60405180910390a46110138686868686866122ab565b600080611b98612333565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2ac69ee804d9a7a0984249f508dfab7cb2534b465b6ce1580f99a38ba9c5e6318484604051611c2b929190612ec3565b60405180910390a36105b2848484846123d0565b6000806000835160208501868989f195945050505050565b3415611ce5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5374616e646172644272696467653a2063616e6e6f742073656e642076616c7560448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610214565b611cee876118a9565b15611e3c57611cfd878761190b565b611daf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a401610214565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b158015611e1f57600080fd5b505af1158015611e33573d6000803e3d6000fd5b50505050611ed0565b611e5e73ffffffffffffffffffffffffffffffffffffffff881686308661243d565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054611e9c908490612edc565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b611ede87878787878661249b565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9216907f0166a07a0000000000000000000000000000000000000000000000000000000090611f42908b908d908c908c908c908b90602401612ef4565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b9092168252611fd592918790600401612e40565b600060405180830381600087803b158015611fef57600080fd5b505af1158015612003573d6000803e3d6000fd5b5050505050505050505050565b6109c987878787878787611c57565b600054610100900460ff166120b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610214565b6003805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560048054929093169116179055565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f35d79ab81f2b2017e19afb5c5571778877782d7a8786f5907f93b0f4702f4f238484604051612168929190612ec3565b60405180910390a36105b284848484612529565b600061218783612588565b8015612198575061219883836125ec565b9392505050565b6000612201826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166126bb9092919063ffffffff16565b805190915015610aa4578080602001905181019061221f9190612dd5565b610aa4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610214565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd86868660405161232393929190612e85565b60405180910390a4505050505050565b603354604080517f4397dfef0000000000000000000000000000000000000000000000000000000081528151600093849373ffffffffffffffffffffffffffffffffffffffff90911692634397dfef92600480830193928290030181865afa1580156123a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123c79190612f4f565b90939092509050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d848460405161242f929190612ec3565b60405180910390a350505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526105b29085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611a7d565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f718594027abd4eaed59f95162563e0cc6d0e8d5b86b1c7be8b1b0ac3343d039686868660405161251393929190612e85565b60405180910390a46110138686868686866126d2565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af5848460405161242f929190612ec3565b60006125b4827f01ffc9a7000000000000000000000000000000000000000000000000000000006125ec565b801561190557506125e5827fffffffff000000000000000000000000000000000000000000000000000000006125ec565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d915060005190508280156126a4575060208210155b80156126b05750600081115b979650505050505050565b60606126ca848460008561274a565b949350505050565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf86868660405161232393929190612e85565b6060824710156127dc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610214565b73ffffffffffffffffffffffffffffffffffffffff85163b61285a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610214565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516128839190612f84565b60006040518083038185875af1925050503d80600081146128c0576040519150601f19603f3d011682016040523d82523d6000602084013e6128c5565b606091505b50915091506126b0828286606083156128df575081612198565b8251156128ef5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102149190612bf5565b73ffffffffffffffffffffffffffffffffffffffff8116811461294557600080fd5b50565b60008083601f84011261295a57600080fd5b50813567ffffffffffffffff81111561297257600080fd5b60208301915083602082850101111561298a57600080fd5b9250929050565b600080600080600080600060c0888a0312156129ac57600080fd5b87356129b781612923565b965060208801356129c781612923565b955060408801356129d781612923565b945060608801356129e781612923565b93506080880135925060a088013567ffffffffffffffff811115612a0a57600080fd5b612a168a828b01612948565b989b979a50959850939692959293505050565b803563ffffffff81168114612a3d57600080fd5b919050565b600080600060408486031215612a5757600080fd5b612a6084612a29565b9250602084013567ffffffffffffffff811115612a7c57600080fd5b612a8886828701612948565b9497909650939450505050565b600080600080600060808688031215612aad57600080fd5b8535612ab881612923565b94506020860135612ac881612923565b935060408601359250606086013567ffffffffffffffff811115612aeb57600080fd5b612af788828901612948565b969995985093965092949392505050565b600080600080600080600060c0888a031215612b2357600080fd5b8735612b2e81612923565b96506020880135612b3e81612923565b95506040880135612b4e81612923565b945060608801359350612b6360808901612a29565b925060a088013567ffffffffffffffff811115612a0a57600080fd5b60005b83811015612b9a578181015183820152602001612b82565b838111156105b25750506000910152565b60008151808452612bc3816020860160208601612b7f565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006121986020830184612bab565b60008060008060008060a08789031215612c2157600080fd5b8635612c2c81612923565b95506020870135612c3c81612923565b945060408701359350612c5160608801612a29565b9250608087013567ffffffffffffffff811115612c6d57600080fd5b612c7989828a01612948565b979a9699509497509295939492505050565b60008060408385031215612c9e57600080fd5b8235612ca981612923565b91506020830135612cb981612923565b809150509250929050565b60008060008060608587031215612cda57600080fd5b8435612ce581612923565b9350612cf360208601612a29565b9250604085013567ffffffffffffffff811115612d0f57600080fd5b612d1b87828801612948565b95989497509550505050565b600080600060608486031215612d3c57600080fd5b8335612d4781612923565b92506020840135612d5781612923565b91506040840135612d6781612923565b809150509250925092565b600060208284031215612d8457600080fd5b815161219881612923565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015612dd057612dd0612d8f565b500390565b600060208284031215612de757600080fd5b8151801515811461219857600080fd5b600073ffffffffffffffffffffffffffffffffffffffff808716835280861660208401525083604083015260806060830152612e366080830184612bab565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff84168152606060208201526000612e6f6060830185612bab565b905063ffffffff83166040830152949350505050565b73ffffffffffffffffffffffffffffffffffffffff84168152826020820152606060408201526000612eba6060830184612bab565b95945050505050565b8281526040602082015260006126ca6040830184612bab565b60008219821115612eef57612eef612d8f565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a0830152612f4360c0830184612bab565b98975050505050505050565b60008060408385031215612f6257600080fd5b8251612f6d81612923565b602084015190925060ff81168114612cb957600080fd5b60008251612f96818460208701612b7f565b919091019291505056fea164736f6c634300080f000a"; bytes internal constant l1ERC721BridgeCode = - hex"608060405234801561001057600080fd5b50600436106100d45760003560e01c80635d93a3fc11610081578063927ede2d1161005b578063927ede2d14610231578063aa5574521461024f578063c89701a21461026257600080fd5b80635d93a3fc146101cc578063761f4493146102005780637f46ddb21461021357600080fd5b8063485cc955116100b2578063485cc9551461015857806354fd4d501461016b5780635c975abb146101b457600080fd5b806335e80ab3146100d95780633687011a146101235780633cb747bf14610138575b600080fd5b6032546100f99073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b610136610131366004610fe1565b610282565b005b6001546100f99073ffffffffffffffffffffffffffffffffffffffff1681565b610136610166366004611064565b61032e565b6101a76040518060400160405280600c81526020017f322e312e312b626574612e31000000000000000000000000000000000000000081525081565b60405161011a9190611108565b6101bc610518565b604051901515815260200161011a565b6101bc6101da366004611122565b603160209081526000938452604080852082529284528284209052825290205460ff1681565b61013661020e366004611163565b6105b1565b60025473ffffffffffffffffffffffffffffffffffffffff166100f9565b60015473ffffffffffffffffffffffffffffffffffffffff166100f9565b61013661025d3660046111fb565b610a58565b6002546100f99073ffffffffffffffffffffffffffffffffffffffff1681565b333b15610316576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4552433732314272696467653a206163636f756e74206973206e6f742065787460448201527f65726e616c6c79206f776e65640000000000000000000000000000000000000060648201526084015b60405180910390fd5b6103268686333388888888610b30565b505050505050565b600054610100900460ff161580801561034e5750600054600160ff909116105b806103685750303b158015610368575060005460ff166001145b6103f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161030d565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561045257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84161790556104b083734200000000000000000000000000000000000014610e70565b801561051357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b603254604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa158015610588573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ac9190611272565b905090565b60015473ffffffffffffffffffffffffffffffffffffffff16331480156106865750600254600154604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9384169390921691636e296e45916004808201926020929091908290030181865afa15801561064a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061066e9190611294565b73ffffffffffffffffffffffffffffffffffffffff16145b610712576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4552433732314272696467653a2066756e6374696f6e2063616e206f6e6c792060448201527f62652063616c6c65642066726f6d20746865206f746865722062726964676500606482015260840161030d565b61071a610518565b15610781576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4c314552433732314272696467653a2070617573656400000000000000000000604482015260640161030d565b3073ffffffffffffffffffffffffffffffffffffffff881603610826576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4c314552433732314272696467653a206c6f63616c20746f6b656e2063616e6e60448201527f6f742062652073656c6600000000000000000000000000000000000000000000606482015260840161030d565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152603160209081526040808320938a1683529281528282208683529052205460ff1615156001146108f5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4c314552433732314272696467653a20546f6b656e204944206973206e6f742060448201527f657363726f77656420696e20746865204c312042726964676500000000000000606482015260840161030d565b73ffffffffffffffffffffffffffffffffffffffff87811660008181526031602090815260408083208b8616845282528083208884529091529081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517f42842e0e000000000000000000000000000000000000000000000000000000008152306004820152918616602483015260448201859052906342842e0e90606401600060405180830381600087803b1580156109b557600080fd5b505af11580156109c9573d6000803e3d6000fd5b505050508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167f1f39bf6707b5d608453e0ae4c067b562bcc4c85c0f562ef5d2c774d2e7f131ac87878787604051610a4794939291906112fa565b60405180910390a450505050505050565b73ffffffffffffffffffffffffffffffffffffffff8516610afb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4552433732314272696467653a206e667420726563697069656e742063616e6e60448201527f6f74206265206164647265737328302900000000000000000000000000000000606482015260840161030d565b610b0b8787338888888888610b30565b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b73ffffffffffffffffffffffffffffffffffffffff8716610bd3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f4c314552433732314272696467653a2072656d6f746520746f6b656e2063616e60448201527f6e6f742062652061646472657373283029000000000000000000000000000000606482015260840161030d565b600063761f449360e01b888a8989898888604051602401610bfa979695949392919061133a565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000959095169490941790935273ffffffffffffffffffffffffffffffffffffffff8c81166000818152603186528381208e8416825286528381208b82529095529382902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905590517f23b872dd000000000000000000000000000000000000000000000000000000008152908a166004820152306024820152604481018890529092506323b872dd90606401600060405180830381600087803b158015610d3a57600080fd5b505af1158015610d4e573d6000803e3d6000fd5b50506001546002546040517f3dbb202b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9283169450633dbb202b9350610db1929091169085908990600401611397565b600060405180830381600087803b158015610dcb57600080fd5b505af1158015610ddf573d6000803e3d6000fd5b505050508673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff167fb7460e2a880f256ebef3406116ff3eee0cee51ebccdc2a40698f87ebb2e9c1a589898888604051610e5d94939291906112fa565b60405180910390a4505050505050505050565b600054610100900460ff16610f07576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161030d565b6001805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560028054929093169116179055565b73ffffffffffffffffffffffffffffffffffffffff81168114610f7c57600080fd5b50565b803563ffffffff81168114610f9357600080fd5b919050565b60008083601f840112610faa57600080fd5b50813567ffffffffffffffff811115610fc257600080fd5b602083019150836020828501011115610fda57600080fd5b9250929050565b60008060008060008060a08789031215610ffa57600080fd5b863561100581610f5a565b9550602087013561101581610f5a565b94506040870135935061102a60608801610f7f565b9250608087013567ffffffffffffffff81111561104657600080fd5b61105289828a01610f98565b979a9699509497509295939492505050565b6000806040838503121561107757600080fd5b823561108281610f5a565b9150602083013561109281610f5a565b809150509250929050565b6000815180845260005b818110156110c3576020818501810151868301820152016110a7565b818111156110d5576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061111b602083018461109d565b9392505050565b60008060006060848603121561113757600080fd5b833561114281610f5a565b9250602084013561115281610f5a565b929592945050506040919091013590565b600080600080600080600060c0888a03121561117e57600080fd5b873561118981610f5a565b9650602088013561119981610f5a565b955060408801356111a981610f5a565b945060608801356111b981610f5a565b93506080880135925060a088013567ffffffffffffffff8111156111dc57600080fd5b6111e88a828b01610f98565b989b979a50959850939692959293505050565b600080600080600080600060c0888a03121561121657600080fd5b873561122181610f5a565b9650602088013561123181610f5a565b9550604088013561124181610f5a565b94506060880135935061125660808901610f7f565b925060a088013567ffffffffffffffff8111156111dc57600080fd5b60006020828403121561128457600080fd5b8151801515811461111b57600080fd5b6000602082840312156112a657600080fd5b815161111b81610f5a565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff851681528360208201526060604082015260006113306060830184866112b1565b9695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff808a1683528089166020840152808816604084015280871660608401525084608083015260c060a083015261138a60c0830184866112b1565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006113c6606083018561109d565b905063ffffffff8316604083015294935050505056fea164736f6c634300080f000a"; + hex"608060405234801561001057600080fd5b50600436106100d45760003560e01c80635d93a3fc11610081578063927ede2d1161005b578063927ede2d14610231578063aa5574521461024f578063c89701a21461026257600080fd5b80635d93a3fc146101cc578063761f4493146102005780637f46ddb21461021357600080fd5b8063485cc955116100b2578063485cc9551461015857806354fd4d501461016b5780635c975abb146101b457600080fd5b806335e80ab3146100d95780633687011a146101235780633cb747bf14610138575b600080fd5b6032546100f99073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b610136610131366004610fe1565b610282565b005b6001546100f99073ffffffffffffffffffffffffffffffffffffffff1681565b610136610166366004611064565b61032e565b6101a76040518060400160405280600c81526020017f322e312e312d626574612e32000000000000000000000000000000000000000081525081565b60405161011a9190611108565b6101bc610518565b604051901515815260200161011a565b6101bc6101da366004611122565b603160209081526000938452604080852082529284528284209052825290205460ff1681565b61013661020e366004611163565b6105b1565b60025473ffffffffffffffffffffffffffffffffffffffff166100f9565b60015473ffffffffffffffffffffffffffffffffffffffff166100f9565b61013661025d3660046111fb565b610a58565b6002546100f99073ffffffffffffffffffffffffffffffffffffffff1681565b333b15610316576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4552433732314272696467653a206163636f756e74206973206e6f742065787460448201527f65726e616c6c79206f776e65640000000000000000000000000000000000000060648201526084015b60405180910390fd5b6103268686333388888888610b30565b505050505050565b600054610100900460ff161580801561034e5750600054600160ff909116105b806103685750303b158015610368575060005460ff166001145b6103f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161030d565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561045257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84161790556104b083734200000000000000000000000000000000000014610e70565b801561051357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b603254604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa158015610588573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ac9190611272565b905090565b60015473ffffffffffffffffffffffffffffffffffffffff16331480156106865750600254600154604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9384169390921691636e296e45916004808201926020929091908290030181865afa15801561064a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061066e9190611294565b73ffffffffffffffffffffffffffffffffffffffff16145b610712576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4552433732314272696467653a2066756e6374696f6e2063616e206f6e6c792060448201527f62652063616c6c65642066726f6d20746865206f746865722062726964676500606482015260840161030d565b61071a610518565b15610781576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4c314552433732314272696467653a2070617573656400000000000000000000604482015260640161030d565b3073ffffffffffffffffffffffffffffffffffffffff881603610826576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4c314552433732314272696467653a206c6f63616c20746f6b656e2063616e6e60448201527f6f742062652073656c6600000000000000000000000000000000000000000000606482015260840161030d565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152603160209081526040808320938a1683529281528282208683529052205460ff1615156001146108f5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4c314552433732314272696467653a20546f6b656e204944206973206e6f742060448201527f657363726f77656420696e20746865204c312042726964676500000000000000606482015260840161030d565b73ffffffffffffffffffffffffffffffffffffffff87811660008181526031602090815260408083208b8616845282528083208884529091529081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517f42842e0e000000000000000000000000000000000000000000000000000000008152306004820152918616602483015260448201859052906342842e0e90606401600060405180830381600087803b1580156109b557600080fd5b505af11580156109c9573d6000803e3d6000fd5b505050508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167f1f39bf6707b5d608453e0ae4c067b562bcc4c85c0f562ef5d2c774d2e7f131ac87878787604051610a4794939291906112fa565b60405180910390a450505050505050565b73ffffffffffffffffffffffffffffffffffffffff8516610afb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4552433732314272696467653a206e667420726563697069656e742063616e6e60448201527f6f74206265206164647265737328302900000000000000000000000000000000606482015260840161030d565b610b0b8787338888888888610b30565b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b73ffffffffffffffffffffffffffffffffffffffff8716610bd3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f4c314552433732314272696467653a2072656d6f746520746f6b656e2063616e60448201527f6e6f742062652061646472657373283029000000000000000000000000000000606482015260840161030d565b600063761f449360e01b888a8989898888604051602401610bfa979695949392919061133a565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000959095169490941790935273ffffffffffffffffffffffffffffffffffffffff8c81166000818152603186528381208e8416825286528381208b82529095529382902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905590517f23b872dd000000000000000000000000000000000000000000000000000000008152908a166004820152306024820152604481018890529092506323b872dd90606401600060405180830381600087803b158015610d3a57600080fd5b505af1158015610d4e573d6000803e3d6000fd5b50506001546002546040517f3dbb202b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9283169450633dbb202b9350610db1929091169085908990600401611397565b600060405180830381600087803b158015610dcb57600080fd5b505af1158015610ddf573d6000803e3d6000fd5b505050508673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff167fb7460e2a880f256ebef3406116ff3eee0cee51ebccdc2a40698f87ebb2e9c1a589898888604051610e5d94939291906112fa565b60405180910390a4505050505050505050565b600054610100900460ff16610f07576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161030d565b6001805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560028054929093169116179055565b73ffffffffffffffffffffffffffffffffffffffff81168114610f7c57600080fd5b50565b803563ffffffff81168114610f9357600080fd5b919050565b60008083601f840112610faa57600080fd5b50813567ffffffffffffffff811115610fc257600080fd5b602083019150836020828501011115610fda57600080fd5b9250929050565b60008060008060008060a08789031215610ffa57600080fd5b863561100581610f5a565b9550602087013561101581610f5a565b94506040870135935061102a60608801610f7f565b9250608087013567ffffffffffffffff81111561104657600080fd5b61105289828a01610f98565b979a9699509497509295939492505050565b6000806040838503121561107757600080fd5b823561108281610f5a565b9150602083013561109281610f5a565b809150509250929050565b6000815180845260005b818110156110c3576020818501810151868301820152016110a7565b818111156110d5576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061111b602083018461109d565b9392505050565b60008060006060848603121561113757600080fd5b833561114281610f5a565b9250602084013561115281610f5a565b929592945050506040919091013590565b600080600080600080600060c0888a03121561117e57600080fd5b873561118981610f5a565b9650602088013561119981610f5a565b955060408801356111a981610f5a565b945060608801356111b981610f5a565b93506080880135925060a088013567ffffffffffffffff8111156111dc57600080fd5b6111e88a828b01610f98565b989b979a50959850939692959293505050565b600080600080600080600060c0888a03121561121657600080fd5b873561122181610f5a565b9650602088013561123181610f5a565b9550604088013561124181610f5a565b94506060880135935061125660808901610f7f565b925060a088013567ffffffffffffffff8111156111dc57600080fd5b60006020828403121561128457600080fd5b8151801515811461111b57600080fd5b6000602082840312156112a657600080fd5b815161111b81610f5a565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff851681528360208201526060604082015260006113306060830184866112b1565b9695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff808a1683528089166020840152808816604084015280871660608401525084608083015260c060a083015261138a60c0830184866112b1565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006113c6606083018561109d565b905063ffffffff8316604083015294935050505056fea164736f6c634300080f000a"; bytes internal constant optimismPortalCode = - hex"6080604052600436106101635760003560e01c80638c3152e9116100c0578063b69ef8a811610074578063cff0ab9611610059578063cff0ab9614610444578063e965084c146104e5578063e9e05c421461057157600080fd5b8063b69ef8a814610401578063c0c53b8b1461042457600080fd5b80639bf62d82116100a55780639bf62d821461036b578063a14238e714610398578063a35d99df146103c857600080fd5b80638c3152e91461031e5780639b5f694a1461033e57600080fd5b806354fd4d50116101175780636dbffb78116100fc5780636dbffb78146102de57806371cfaa3f146102fe5780638b4c40b01461018857600080fd5b806354fd4d501461026d5780635c975abb146102b957600080fd5b806335e80ab31161014857806335e80ab314610206578063452a9320146102385780634870496f1461024d57600080fd5b8063149f2f221461018f57806333d7e2bd146101af57600080fd5b3661018a576101883334620186a060006040518060200160405280600081525061057f565b005b600080fd5b34801561019b57600080fd5b506101886101aa366004614b97565b610624565b3480156101bb57600080fd5b506037546101dc9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561021257600080fd5b506035546101dc90610100900473ffffffffffffffffffffffffffffffffffffffff1681565b34801561024457600080fd5b506101dc610865565b34801561025957600080fd5b50610188610268366004614ccb565b6108fd565b34801561027957600080fd5b50604080518082018252600c81527f322e382e312d626574612e310000000000000000000000000000000000000000602082015290516101fd9190614e1d565b3480156102c557600080fd5b506102ce610eaa565b60405190151581526020016101fd565b3480156102ea57600080fd5b506102ce6102f9366004614e30565b610f3d565b34801561030a57600080fd5b50610188610319366004614e58565b610ff8565b34801561032a57600080fd5b50610188610339366004614e9e565b6111ba565b34801561034a57600080fd5b506036546101dc9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561037757600080fd5b506032546101dc9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156103a457600080fd5b506102ce6103b3366004614e30565b60336020526000908152604090205460ff1681565b3480156103d457600080fd5b506103e86103e3366004614edb565b611c3c565b60405167ffffffffffffffff90911681526020016101fd565b34801561040d57600080fd5b50610416611c55565b6040519081526020016101fd565b34801561043057600080fd5b5061018861043f366004614ef6565b611caf565b34801561045057600080fd5b506001546104ac906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff92831660208501529116908201526060016101fd565b3480156104f157600080fd5b50610543610500366004614e30565b603460205260009081526040902080546001909101546fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041683565b604080519384526fffffffffffffffffffffffffffffffff92831660208501529116908201526060016101fd565b61018861057f366004614f41565b8260005a9050600061058f611f19565b50905073ffffffffffffffffffffffffffffffffffffffff811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee148015906105cb57503415155b15610602576040517ff2365b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610610883489898989611fb6565b5061061b8282612162565b50505050505050565b8260005a90506000610634611f19565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8216016106a6576040517f0eaf3c0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87603d60008282546106b89190614fed565b90915550506040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa15801561072a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061074e9190615005565b905061077273ffffffffffffffffffffffffffffffffffffffff831633308c61242f565b61077c8982614fed565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa1580156107e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061080a9190615005565b14610841576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61084f8a8a8a8a8a8a611fb6565b505061085b8282612162565b5050505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f8919061501e565b905090565b610905610eaa565b1561093c576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff16036109a5576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6036546040517fa25ae5570000000000000000000000000000000000000000000000000000000081526004810186905260009173ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa158015610a15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a39919061505b565b519050610a53610a4e368690038601866150c0565b61250b565b8114610ae6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f7074696d69736d506f7274616c3a20696e76616c6964206f7574707574207260448201527f6f6f742070726f6f66000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000610af187612567565b6000818152603460209081526040918290208251606081018452815481526001909101546fffffffffffffffffffffffffffffffff8082169383018490527001000000000000000000000000000000009091041692810192909252919250901580610c075750805160365460408084015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff909116600482015273ffffffffffffffffffffffffffffffffffffffff9091169063a25ae55790602401606060405180830381865afa158015610bdf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c03919061505b565b5114155b610c93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173682060448201527f68617320616c7265616479206265656e2070726f76656e0000000000000000006064820152608401610add565b60408051602081018490526000918101829052606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201209083018190529250610d5c9101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f0100000000000000000000000000000000000000000000000000000000000000602083015290610d52888a615126565b8a60400135612597565b610de8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a20696e76616c696420776974686472617760448201527f616c20696e636c7573696f6e2070726f6f6600000000000000000000000000006064820152608401610add565b604080516060810182528581526fffffffffffffffffffffffffffffffff42811660208084019182528c831684860190815260008981526034835286812095518655925190518416700100000000000000000000000000000000029316929092176001909301929092558b830151908c0151925173ffffffffffffffffffffffffffffffffffffffff918216939091169186917f67a6208cfcc0801d50f6cbe764733f4fddf66ac0b04442061a8a8c0cb6b63f629190a4505050505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f19573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f891906151aa565b6036546040517fa25ae55700000000000000000000000000000000000000000000000000000000815260048101839052600091610ff29173ffffffffffffffffffffffffffffffffffffffff9091169063a25ae55790602401606060405180830381865afa158015610fb3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fd7919061505b565b602001516fffffffffffffffffffffffffffffffff166125bb565b92915050565b60375473ffffffffffffffffffffffffffffffffffffffff163314611049576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61105562030d40612661565b60405173ffffffffffffffffffffffffffffffffffffffff8516602482015260ff8416604482015260648101839052608481018290526000907342000000000000000000000000000000000000159073deaddeaddeaddeaddeaddeaddeaddeaddead0001907fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32908490819062030d4090829060a401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f71cfaa3f000000000000000000000000000000000000000000000000000000001790529051611172969594939291016151c7565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526111aa91614e1d565b60405180910390a450505050565b565b6111c2610eaa565b156111f9576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60325473ffffffffffffffffffffffffffffffffffffffff1661dead1461124c576040517f9396d15600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061125782612567565b60008181526034602090815260408083208151606081018352815481526001909101546fffffffffffffffffffffffffffffffff80821694830185905270010000000000000000000000000000000090910416918101919091529293509003611342576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206e60448201527f6f74206265656e2070726f76656e2079657400000000000000000000000000006064820152608401610add565b603660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663887862726040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113d39190615005565b81602001516fffffffffffffffffffffffffffffffff16101561149e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604b60248201527f4f7074696d69736d506f7274616c3a207769746864726177616c2074696d657360448201527f74616d70206c657373207468616e204c32204f7261636c65207374617274696e60648201527f672074696d657374616d70000000000000000000000000000000000000000000608482015260a401610add565b6114bd81602001516fffffffffffffffffffffffffffffffff166125bb565b61156f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604560248201527f4f7074696d69736d506f7274616c3a2070726f76656e2077697468647261776160448201527f6c2066696e616c697a6174696f6e20706572696f6420686173206e6f7420656c60648201527f6170736564000000000000000000000000000000000000000000000000000000608482015260a401610add565b60365460408281015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff909116600482015260009173ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa1580156115f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061161a919061505b565b82518151919250146116d4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4f7074696d69736d506f7274616c3a206f757470757420726f6f742070726f7660448201527f656e206973206e6f74207468652073616d652061732063757272656e74206f7560648201527f7470757420726f6f740000000000000000000000000000000000000000000000608482015260a401610add565b6116f381602001516fffffffffffffffffffffffffffffffff166125bb565b6117a5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4f7074696d69736d506f7274616c3a206f75747075742070726f706f73616c2060448201527f66696e616c697a6174696f6e20706572696f6420686173206e6f7420656c617060648201527f7365640000000000000000000000000000000000000000000000000000000000608482015260a401610add565b60008381526033602052604090205460ff1615611844576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206160448201527f6c7265616479206265656e2066696e616c697a656400000000000000000000006064820152608401610add565b6000838152603360209081526040822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558501516032805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff0000000000000000000000000000000000000000909216919091179055806118cf611f19565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8216016119325761192b8660400151876080015188606001518960a001516126c3565b9150611b85565b8073ffffffffffffffffffffffffffffffffffffffff16866040015173ffffffffffffffffffffffffffffffffffffffff160361199b576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606086015115611b5c578560600151603d60008282546119bb919061522c565b90915550506040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015611a2d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a519190615005565b9050611a86876040015188606001518473ffffffffffffffffffffffffffffffffffffffff166127219092919063ffffffff16565b6060870151611a95908261522c565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015611aff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b239190615005565b14611b5a576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60a08601515115611b805761192b8660400151876080015160008960a001516126c3565b600191505b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405185907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b90611be790851515815260200190565b60405180910390a281158015611bfd5750326001145b15611c34576040517feeae4ed300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000611c49826010615243565b610ff290615208615273565b600080611c60611f19565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff821601611ca7574791505090565b5050603d5490565b600054610100900460ff1615808015611ccf5750600054600160ff909116105b80611ce95750303b158015611ce9575060005460ff166001145b611d75576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610add565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015611dd357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603680547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff8781169190911790925560378054909116858316179055603580547fffffffffffffffffffffff0000000000000000000000000000000000000000ff166101008584160217905560325416611e8c57603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790555b611e9461277c565b8015611ef757600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b603754604080517f4397dfef0000000000000000000000000000000000000000000000000000000081528151600093849373ffffffffffffffffffffffffffffffffffffffff90911692634397dfef92600480830193928290030181865afa158015611f89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fad919061529f565b90939092509050565b818015611fd8575073ffffffffffffffffffffffffffffffffffffffff861615155b1561200f576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6120198151611c3c565b67ffffffffffffffff168367ffffffffffffffff161015612066576040517f4929b80800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6201d4c0815111156120a4576040517f73052b0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b333281146120c5575033731111000000000000000000000000000000001111015b600086868686866040516020016120e09594939291906151c7565b604051602081830303815290604052905060008873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32846040516121509190614e1d565b60405180910390a45050505050505050565b600154600090612198907801000000000000000000000000000000000000000000000000900467ffffffffffffffff164361522c565b905060006121a461288f565b90506000816020015160ff16826000015163ffffffff166121c59190615308565b905082156122fc576001546000906121fc908390700100000000000000000000000000000000900467ffffffffffffffff16615370565b90506000836040015160ff168361221391906153e4565b6001546122339084906fffffffffffffffffffffffffffffffff166153e4565b61223d9190615308565b60015490915060009061228e906122679084906fffffffffffffffffffffffffffffffff166154a0565b866060015163ffffffff168760a001516fffffffffffffffffffffffffffffffff16612950565b905060018611156122bd576122ba61226782876040015160ff1660018a6122b5919061522c565b61296f565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b6001805486919060109061232f908490700100000000000000000000000000000000900467ffffffffffffffff16615273565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550816000015163ffffffff16600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff1613156123bc576040517f77ebef4d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001546000906123e8906fffffffffffffffffffffffffffffffff1667ffffffffffffffff8816615514565b905060006123fa48633b9aca006129c4565b6124049083615551565b905060005a612413908861522c565b90508082111561085b5761085b61242a828461522c565b6129db565b60405173ffffffffffffffffffffffffffffffffffffffff80851660248301528316604482015260648101829052611ef79085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612a04565b6000816000015182602001518360400151846060015160405160200161254a949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b80516020808301516040808501516060860151608087015160a0880151935160009761254a979096959101615565565b6000806125a386612b10565b90506125b181868686612b42565b9695505050505050565b603654604080517ff4daa291000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163f4daa2919160048083019260209291908290030181865afa15801561262b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061264f9190615005565b6126599083614fed565b421192915050565b6001805463ffffffff8316919060109061269a908490700100000000000000000000000000000000900467ffffffffffffffff16615273565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555050565b60008060006126d3866000612b72565b905080612709576308c379a06000526020805278185361666543616c6c3a204e6f7420656e6f756768206761736058526064601cfd5b600080855160208701888b5af1979650505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526127779084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401612489565b505050565b600054610100900460ff16612813576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610add565b6001547801000000000000000000000000000000000000000000000000900467ffffffffffffffff166000036111b85760408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b6040805160c08082018352600080835260208301819052828401819052606083018190526080830181905260a083015260375483517fcc731b020000000000000000000000000000000000000000000000000000000081529351929373ffffffffffffffffffffffffffffffffffffffff9091169263cc731b02926004808401939192918290030181865afa15801561292c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f891906155d0565b600061296561295f8585612b90565b83612ba0565b90505b9392505050565b6000670de0b6b3a76400006129b06129878583615308565b61299990670de0b6b3a7640000615370565b6129ab85670de0b6b3a76400006153e4565b612baf565b6129ba90866153e4565b6129659190615308565b6000818310156129d45781612968565b5090919050565b6000805a90505b825a6129ee908361522c565b1015612777576129fd82615673565b91506129e2565b6000612a66826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612be09092919063ffffffff16565b8051909150156127775780806020019051810190612a8491906151aa565b612777576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610add565b60608180519060200120604051602001612b2c91815260200190565b6040516020818303038152906040529050919050565b6000612b6984612b53878686612bef565b8051602091820120825192909101919091201490565b95945050505050565b600080603f83619c4001026040850201603f5a021015949350505050565b6000818312156129d45781612968565b60008183126129d45781612968565b6000612968670de0b6b3a764000083612bc78661366d565b612bd191906153e4565b612bdb9190615308565b6138b1565b60606129658484600085613af0565b60606000845111612c5c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4d65726b6c65547269653a20656d707479206b657900000000000000000000006044820152606401610add565b6000612c6784613c86565b90506000612c7486613d72565b9050600084604051602001612c8b91815260200190565b60405160208183030381529060405290506000805b84518110156135e4576000858281518110612cbd57612cbd6156ab565b602002602001015190508451831115612d58576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4d65726b6c65547269653a206b657920696e646578206578636565647320746f60448201527f74616c206b6579206c656e6774680000000000000000000000000000000000006064820152608401610add565b82600003612e115780518051602091820120604051612da692612d8092910190815260200190565b604051602081830303815290604052858051602091820120825192909101919091201490565b612e0c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4d65726b6c65547269653a20696e76616c696420726f6f7420686173680000006044820152606401610add565b612f68565b805151602011612ec75780518051602091820120604051612e3b92612d8092910190815260200190565b612e0c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d65726b6c65547269653a20696e76616c6964206c6172676520696e7465726e60448201527f616c2068617368000000000000000000000000000000000000000000000000006064820152608401610add565b805184516020808701919091208251919092012014612f68576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4d65726b6c65547269653a20696e76616c696420696e7465726e616c206e6f6460448201527f65206861736800000000000000000000000000000000000000000000000000006064820152608401610add565b612f7460106001614fed565b8160200151510361315057845183036130e857612fae8160200151601081518110612fa157612fa16156ab565b6020026020010151613dd5565b96506000875111613041576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603b60248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286272616e63682900000000006064820152608401610add565b6001865161304f919061522c565b82146130dd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286272616e6368290000000000006064820152608401610add565b505050505050612968565b60008584815181106130fc576130fc6156ab565b602001015160f81c60f81b60f81c9050600082602001518260ff1681518110613127576131276156ab565b6020026020010151905061313a81613e89565b9550613147600186614fed565b945050506135d1565b60028160200151510361354957600061316882613eae565b905060008160008151811061317f5761317f6156ab565b016020015160f81c905060006131966002836156da565b6131a19060026156fc565b905060006131b2848360ff16613ed2565b905060006131c08a89613ed2565b905060006131ce8383613f08565b905080835114613260576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a20706174682072656d61696e646572206d7573742060448201527f736861726520616c6c206e6962626c65732077697468206b65790000000000006064820152608401610add565b60ff851660021480613275575060ff85166003145b15613464578082511461330a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f4d65726b6c65547269653a206b65792072656d61696e646572206d757374206260448201527f65206964656e746963616c20746f20706174682072656d61696e6465720000006064820152608401610add565b6133248760200151600181518110612fa157612fa16156ab565b9c5060008d51116133b7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286c65616629000000000000006064820152608401610add565b60018c516133c5919061522c565b8814613453576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286c6561662900000000000000006064820152608401610add565b505050505050505050505050612968565b60ff85161580613477575060ff85166001145b156134b6576134a38760200151600181518110613496576134966156ab565b6020026020010151613e89565b99506134af818a614fed565b985061353e565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4d65726b6c65547269653a2072656365697665642061206e6f6465207769746860448201527f20616e20756e6b6e6f776e2070726566697800000000000000000000000000006064820152608401610add565b5050505050506135d1565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4d65726b6c65547269653a20726563656976656420616e20756e70617273656160448201527f626c65206e6f64650000000000000000000000000000000000000000000000006064820152608401610add565b50806135dc81615673565b915050612ca0565b506040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4d65726b6c65547269653a2072616e206f7574206f662070726f6f6620656c6560448201527f6d656e74730000000000000000000000000000000000000000000000000000006064820152608401610add565b60008082136136d8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610add565b600060606136e584613fbc565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c182136138e257506000919050565b680755bf798b4a1bf1e58212613954576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4558505f4f564552464c4f5700000000000000000000000000000000000000006044820152606401610add565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b606082471015613b82576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610add565b73ffffffffffffffffffffffffffffffffffffffff85163b613c00576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610add565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051613c29919061571f565b60006040518083038185875af1925050503d8060008114613c66576040519150601f19603f3d011682016040523d82523d6000602084013e613c6b565b606091505b5091509150613c7b828286614092565b979650505050505050565b80516060908067ffffffffffffffff811115613ca457613ca4614a8b565b604051908082528060200260200182016040528015613ce957816020015b6040805180820190915260608082526020820152815260200190600190039081613cc25790505b50915060005b81811015613d6b576040518060400160405280858381518110613d1457613d146156ab565b60200260200101518152602001613d43868481518110613d3657613d366156ab565b60200260200101516140e5565b815250838281518110613d5857613d586156ab565b6020908102919091010152600101613cef565b5050919050565b606080604051905082518060011b603f8101601f1916830160405280835250602084016020830160005b83811015613dca578060011b82018184015160001a8060041c8253600f811660018301535050600101613d9c565b509295945050505050565b60606000806000613de5856140f8565b919450925090506000816001811115613e0057613e0061573b565b14613e37576040517f1ff9b2e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613e418284614fed565b855114613e7a576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612b6985602001518484614596565b60606020826000015110613ea557613ea082613dd5565b610ff2565b610ff28261462a565b6060610ff2613ecd8360200151600081518110612fa157612fa16156ab565b613d72565b606082518210613ef15750604080516020810190915260008152610ff2565b6129688383848651613f03919061522c565b614640565b6000808251845110613f1b578251613f1e565b83515b90505b8082108015613fa55750828281518110613f3d57613f3d6156ab565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916848381518110613f7c57613f7c6156ab565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b15613fb557816001019150613f21565b5092915050565b6000808211614027576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610add565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b606083156140a1575081612968565b8251156140b15782518084602001fd5b816040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610add9190614e1d565b6060610ff26140f383614818565b614885565b6000806000836000015160000361413b576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020840151805160001a607f811161416057600060016000945094509450505061458f565b60b7811161427657600061417560808361522c565b9050808760000151116141b4576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001838101517fff0000000000000000000000000000000000000000000000000000000000000016908214801561422c57507f80000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008216105b15614263576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506001955093506000925061458f915050565b60bf81116143d457600061428b60b78361522c565b9050808760000151116142ca576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff0000000000000000000000000000000000000000000000000000000000000016600081900361432c576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c60378111614374576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61437e8184614fed565b8951116143b7576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6143c2836001614fed565b975095506000945061458f9350505050565b60f781116144395760006143e960c08361522c565b905080876000015111614428576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60019550935084925061458f915050565b600061444660f78361522c565b905080876000015111614485576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff000000000000000000000000000000000000000000000000000000000000001660008190036144e7576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c6037811161452f576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6145398184614fed565b895111614572576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61457d836001614fed565b975095506001945061458f9350505050565b9193909250565b60608167ffffffffffffffff8111156145b1576145b1614a8b565b6040519080825280601f01601f1916602001820160405280156145db576020820181803683370190505b50905081156129685760006145f08486614fed565b90506020820160005b848110156146115782810151828201526020016145f9565b84811115614620576000858301525b5050509392505050565b6060610ff2826020015160008460000151614596565b60608182601f0110156146af576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610add565b82828401101561471b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610add565b81830184511015614788576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401610add565b6060821580156147a7576040519150600082526020820160405261480f565b6040519150601f8416801560200281840101858101878315602002848b0101015b818310156147e05780518352602092830192016147c8565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b60408051808201909152600080825260208201528151600003614867576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50604080518082019091528151815260209182019181019190915290565b60606000806000614895856140f8565b9194509250905060018160018111156148b0576148b061573b565b146148e7576040517f4b9c6abe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84516148f38385614fed565b1461492a576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808252610420820190925290816020015b60408051808201909152600080825260208201528152602001906001900390816149415790505093506000835b8651811015614a2f576000806149b46040518060400160405280858c60000151614998919061522c565b8152602001858c602001516149ad9190614fed565b90526140f8565b5091509150604051806040016040528083836149d09190614fed565b8152602001848b602001516149e59190614fed565b8152508885815181106149fa576149fa6156ab565b6020908102919091010152614a10600185614fed565b9350614a1c8183614fed565b614a269084614fed565b9250505061496e565b50845250919392505050565b73ffffffffffffffffffffffffffffffffffffffff81168114614a5d57600080fd5b50565b803567ffffffffffffffff81168114614a7857600080fd5b919050565b8015158114614a5d57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614b0157614b01614a8b565b604052919050565b600082601f830112614b1a57600080fd5b813567ffffffffffffffff811115614b3457614b34614a8b565b614b6560207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614aba565b818152846020838601011115614b7a57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060008060c08789031215614bb057600080fd5b8635614bbb81614a3b565b95506020870135945060408701359350614bd760608801614a60565b92506080870135614be781614a7d565b915060a087013567ffffffffffffffff811115614c0357600080fd5b614c0f89828a01614b09565b9150509295509295509295565b600060c08284031215614c2e57600080fd5b60405160c0810167ffffffffffffffff8282108183111715614c5257614c52614a8b565b816040528293508435835260208501359150614c6d82614a3b565b81602084015260408501359150614c8382614a3b565b816040840152606085013560608401526080850135608084015260a0850135915080821115614cb157600080fd5b50614cbe85828601614b09565b60a0830152505092915050565b600080600080600085870360e0811215614ce457600080fd5b863567ffffffffffffffff80821115614cfc57600080fd5b614d088a838b01614c1c565b97506020890135965060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc084011215614d4157600080fd5b60408901955060c0890135925080831115614d5b57600080fd5b828901925089601f840112614d6f57600080fd5b8235915080821115614d8057600080fd5b508860208260051b8401011115614d9657600080fd5b959894975092955050506020019190565b60005b83811015614dc2578181015183820152602001614daa565b83811115611ef75750506000910152565b60008151808452614deb816020860160208601614da7565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006129686020830184614dd3565b600060208284031215614e4257600080fd5b5035919050565b60ff81168114614a5d57600080fd5b60008060008060808587031215614e6e57600080fd5b8435614e7981614a3b565b93506020850135614e8981614e49565b93969395505050506040820135916060013590565b600060208284031215614eb057600080fd5b813567ffffffffffffffff811115614ec757600080fd5b614ed384828501614c1c565b949350505050565b600060208284031215614eed57600080fd5b61296882614a60565b600080600060608486031215614f0b57600080fd5b8335614f1681614a3b565b92506020840135614f2681614a3b565b91506040840135614f3681614a3b565b809150509250925092565b600080600080600060a08688031215614f5957600080fd5b8535614f6481614a3b565b945060208601359350614f7960408701614a60565b92506060860135614f8981614a7d565b9150608086013567ffffffffffffffff811115614fa557600080fd5b614fb188828901614b09565b9150509295509295909350565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561500057615000614fbe565b500190565b60006020828403121561501757600080fd5b5051919050565b60006020828403121561503057600080fd5b815161296881614a3b565b80516fffffffffffffffffffffffffffffffff81168114614a7857600080fd5b60006060828403121561506d57600080fd5b6040516060810181811067ffffffffffffffff8211171561509057615090614a8b565b604052825181526150a36020840161503b565b60208201526150b46040840161503b565b60408201529392505050565b6000608082840312156150d257600080fd5b6040516080810181811067ffffffffffffffff821117156150f5576150f5614a8b565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b600067ffffffffffffffff8084111561514157615141614a8b565b8360051b6020615152818301614aba565b86815291850191818101903684111561516a57600080fd5b865b8481101561519e578035868111156151845760008081fd5b61519036828b01614b09565b84525091830191830161516c565b50979650505050505050565b6000602082840312156151bc57600080fd5b815161296881614a7d565b8581528460208201527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b16604082015282151560f81b60488201526000825161521b816049850160208701614da7565b919091016049019695505050505050565b60008282101561523e5761523e614fbe565b500390565b600067ffffffffffffffff8083168185168183048111821515161561526a5761526a614fbe565b02949350505050565b600067ffffffffffffffff80831681851680830382111561529657615296614fbe565b01949350505050565b600080604083850312156152b257600080fd5b82516152bd81614a3b565b60208401519092506152ce81614e49565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082615317576153176152d9565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f80000000000000000000000000000000000000000000000000000000000000008314161561536b5761536b614fbe565b500590565b6000808312837f8000000000000000000000000000000000000000000000000000000000000000018312811516156153aa576153aa614fbe565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0183138116156153de576153de614fbe565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60008413600084138583048511828216161561542557615425614fbe565b7f8000000000000000000000000000000000000000000000000000000000000000600087128682058812818416161561546057615460614fbe565b6000871292508782058712848416161561547c5761547c614fbe565b8785058712818416161561549257615492614fbe565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038413811516156154da576154da614fbe565b827f800000000000000000000000000000000000000000000000000000000000000003841281161561550e5761550e614fbe565b50500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561554c5761554c614fbe565b500290565b600082615560576155606152d9565b500490565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a08301526155b060c0830184614dd3565b98975050505050505050565b805163ffffffff81168114614a7857600080fd5b600060c082840312156155e257600080fd5b60405160c0810181811067ffffffffffffffff8211171561560557615605614a8b565b604052615611836155bc565b8152602083015161562181614e49565b6020820152604083015161563481614e49565b6040820152615645606084016155bc565b6060820152615656608084016155bc565b608082015261566760a0840161503b565b60a08201529392505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036156a4576156a4614fbe565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060ff8316806156ed576156ed6152d9565b8060ff84160691505092915050565b600060ff821660ff84168082101561571657615716614fbe565b90039392505050565b60008251615731818460208701614da7565b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea164736f6c634300080f000a"; + hex"6080604052600436106101635760003560e01c80638c3152e9116100c0578063b69ef8a811610074578063cff0ab9611610059578063cff0ab9614610444578063e965084c146104e5578063e9e05c421461057157600080fd5b8063b69ef8a814610401578063c0c53b8b1461042457600080fd5b80639bf62d82116100a55780639bf62d821461036b578063a14238e714610398578063a35d99df146103c857600080fd5b80638c3152e91461031e5780639b5f694a1461033e57600080fd5b806354fd4d50116101175780636dbffb78116100fc5780636dbffb78146102de57806371cfaa3f146102fe5780638b4c40b01461018857600080fd5b806354fd4d501461026d5780635c975abb146102b957600080fd5b806335e80ab31161014857806335e80ab314610206578063452a9320146102385780634870496f1461024d57600080fd5b8063149f2f221461018f57806333d7e2bd146101af57600080fd5b3661018a576101883334620186a060006040518060200160405280600081525061057f565b005b600080fd5b34801561019b57600080fd5b506101886101aa366004614c13565b610624565b3480156101bb57600080fd5b506037546101dc9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561021257600080fd5b506035546101dc90610100900473ffffffffffffffffffffffffffffffffffffffff1681565b34801561024457600080fd5b506101dc610865565b34801561025957600080fd5b50610188610268366004614d47565b6108fd565b34801561027957600080fd5b50604080518082018252600c81527f322e382e312d626574612e320000000000000000000000000000000000000000602082015290516101fd9190614e99565b3480156102c557600080fd5b506102ce610eaa565b60405190151581526020016101fd565b3480156102ea57600080fd5b506102ce6102f9366004614eac565b610f3d565b34801561030a57600080fd5b50610188610319366004614ed4565b610ff8565b34801561032a57600080fd5b50610188610339366004614f1a565b6111ba565b34801561034a57600080fd5b506036546101dc9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561037757600080fd5b506032546101dc9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156103a457600080fd5b506102ce6103b3366004614eac565b60336020526000908152604090205460ff1681565b3480156103d457600080fd5b506103e86103e3366004614f57565b611c3c565b60405167ffffffffffffffff90911681526020016101fd565b34801561040d57600080fd5b50610416611c55565b6040519081526020016101fd565b34801561043057600080fd5b5061018861043f366004614f72565b611caf565b34801561045057600080fd5b506001546104ac906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff92831660208501529116908201526060016101fd565b3480156104f157600080fd5b50610543610500366004614eac565b603460205260009081526040902080546001909101546fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041683565b604080519384526fffffffffffffffffffffffffffffffff92831660208501529116908201526060016101fd565b61018861057f366004614fbd565b8260005a9050600061058f611f19565b50905073ffffffffffffffffffffffffffffffffffffffff811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee148015906105cb57503415155b15610602576040517ff2365b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610610883489898989611fb6565b5061061b8282612162565b50505050505050565b8260005a90506000610634611f19565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8216016106a6576040517f0eaf3c0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87603d60008282546106b89190615069565b90915550506040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa15801561072a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061074e9190615081565b905061077273ffffffffffffffffffffffffffffffffffffffff831633308c61242f565b61077c8982615069565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa1580156107e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061080a9190615081565b14610841576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61084f8a8a8a8a8a8a611fb6565b505061085b8282612162565b5050505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f8919061509a565b905090565b610905610eaa565b1561093c576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff16036109a5576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6036546040517fa25ae5570000000000000000000000000000000000000000000000000000000081526004810186905260009173ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa158015610a15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a3991906150d7565b519050610a53610a4e3686900386018661513c565b61250b565b8114610ae6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f7074696d69736d506f7274616c3a20696e76616c6964206f7574707574207260448201527f6f6f742070726f6f66000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000610af187612567565b6000818152603460209081526040918290208251606081018452815481526001909101546fffffffffffffffffffffffffffffffff8082169383018490527001000000000000000000000000000000009091041692810192909252919250901580610c075750805160365460408084015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff909116600482015273ffffffffffffffffffffffffffffffffffffffff9091169063a25ae55790602401606060405180830381865afa158015610bdf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c0391906150d7565b5114155b610c93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173682060448201527f68617320616c7265616479206265656e2070726f76656e0000000000000000006064820152608401610add565b60408051602081018490526000918101829052606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201209083018190529250610d5c9101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f0100000000000000000000000000000000000000000000000000000000000000602083015290610d52888a6151a2565b8a60400135612597565b610de8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a20696e76616c696420776974686472617760448201527f616c20696e636c7573696f6e2070726f6f6600000000000000000000000000006064820152608401610add565b604080516060810182528581526fffffffffffffffffffffffffffffffff42811660208084019182528c831684860190815260008981526034835286812095518655925190518416700100000000000000000000000000000000029316929092176001909301929092558b830151908c0151925173ffffffffffffffffffffffffffffffffffffffff918216939091169186917f67a6208cfcc0801d50f6cbe764733f4fddf66ac0b04442061a8a8c0cb6b63f629190a4505050505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f19573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f89190615226565b6036546040517fa25ae55700000000000000000000000000000000000000000000000000000000815260048101839052600091610ff29173ffffffffffffffffffffffffffffffffffffffff9091169063a25ae55790602401606060405180830381865afa158015610fb3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fd791906150d7565b602001516fffffffffffffffffffffffffffffffff166125bb565b92915050565b60375473ffffffffffffffffffffffffffffffffffffffff163314611049576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61105562030d40612661565b60405173ffffffffffffffffffffffffffffffffffffffff8516602482015260ff8416604482015260648101839052608481018290526000907342000000000000000000000000000000000000159073deaddeaddeaddeaddeaddeaddeaddeaddead0001907fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32908490819062030d4090829060a401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f71cfaa3f00000000000000000000000000000000000000000000000000000000179052905161117296959493929101615243565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526111aa91614e99565b60405180910390a450505050565b565b6111c2610eaa565b156111f9576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60325473ffffffffffffffffffffffffffffffffffffffff1661dead1461124c576040517f9396d15600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061125782612567565b60008181526034602090815260408083208151606081018352815481526001909101546fffffffffffffffffffffffffffffffff80821694830185905270010000000000000000000000000000000090910416918101919091529293509003611342576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206e60448201527f6f74206265656e2070726f76656e2079657400000000000000000000000000006064820152608401610add565b603660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663887862726040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113d39190615081565b81602001516fffffffffffffffffffffffffffffffff16101561149e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604b60248201527f4f7074696d69736d506f7274616c3a207769746864726177616c2074696d657360448201527f74616d70206c657373207468616e204c32204f7261636c65207374617274696e60648201527f672074696d657374616d70000000000000000000000000000000000000000000608482015260a401610add565b6114bd81602001516fffffffffffffffffffffffffffffffff166125bb565b61156f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604560248201527f4f7074696d69736d506f7274616c3a2070726f76656e2077697468647261776160448201527f6c2066696e616c697a6174696f6e20706572696f6420686173206e6f7420656c60648201527f6170736564000000000000000000000000000000000000000000000000000000608482015260a401610add565b60365460408281015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff909116600482015260009173ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa1580156115f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061161a91906150d7565b82518151919250146116d4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4f7074696d69736d506f7274616c3a206f757470757420726f6f742070726f7660448201527f656e206973206e6f74207468652073616d652061732063757272656e74206f7560648201527f7470757420726f6f740000000000000000000000000000000000000000000000608482015260a401610add565b6116f381602001516fffffffffffffffffffffffffffffffff166125bb565b6117a5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4f7074696d69736d506f7274616c3a206f75747075742070726f706f73616c2060448201527f66696e616c697a6174696f6e20706572696f6420686173206e6f7420656c617060648201527f7365640000000000000000000000000000000000000000000000000000000000608482015260a401610add565b60008381526033602052604090205460ff1615611844576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206160448201527f6c7265616479206265656e2066696e616c697a656400000000000000000000006064820152608401610add565b6000838152603360209081526040822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558501516032805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff0000000000000000000000000000000000000000909216919091179055806118cf611f19565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8216016119325761192b8660400151876080015188606001518960a001516126c3565b9150611b85565b8073ffffffffffffffffffffffffffffffffffffffff16866040015173ffffffffffffffffffffffffffffffffffffffff160361199b576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606086015115611b5c578560600151603d60008282546119bb91906152a8565b90915550506040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015611a2d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a519190615081565b9050611a86876040015188606001518473ffffffffffffffffffffffffffffffffffffffff166127219092919063ffffffff16565b6060870151611a9590826152a8565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015611aff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b239190615081565b14611b5a576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60a08601515115611b805761192b8660400151876080015160008960a001516126c3565b600191505b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405185907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b90611be790851515815260200190565b60405180910390a281158015611bfd5750326001145b15611c34576040517feeae4ed300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000611c498260106152bf565b610ff2906152086152ef565b600080611c60611f19565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff821601611ca7574791505090565b5050603d5490565b600054610100900460ff1615808015611ccf5750600054600160ff909116105b80611ce95750303b158015611ce9575060005460ff166001145b611d75576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610add565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015611dd357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603680547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff8781169190911790925560378054909116858316179055603580547fffffffffffffffffffffff0000000000000000000000000000000000000000ff166101008584160217905560325416611e8c57603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790555b611e9461277c565b8015611ef757600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b603754604080517f4397dfef0000000000000000000000000000000000000000000000000000000081528151600093849373ffffffffffffffffffffffffffffffffffffffff90911692634397dfef92600480830193928290030181865afa158015611f89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fad919061531b565b90939092509050565b818015611fd8575073ffffffffffffffffffffffffffffffffffffffff861615155b1561200f576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6120198151611c3c565b67ffffffffffffffff168367ffffffffffffffff161015612066576040517f4929b80800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6201d4c0815111156120a4576040517f73052b0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b333281146120c5575033731111000000000000000000000000000000001111015b600086868686866040516020016120e0959493929190615243565b604051602081830303815290604052905060008873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32846040516121509190614e99565b60405180910390a45050505050505050565b600154600090612198907801000000000000000000000000000000000000000000000000900467ffffffffffffffff16436152a8565b905060006121a461288f565b90506000816020015160ff16826000015163ffffffff166121c59190615384565b905082156122fc576001546000906121fc908390700100000000000000000000000000000000900467ffffffffffffffff166153ec565b90506000836040015160ff16836122139190615460565b6001546122339084906fffffffffffffffffffffffffffffffff16615460565b61223d9190615384565b60015490915060009061228e906122679084906fffffffffffffffffffffffffffffffff1661551c565b866060015163ffffffff168760a001516fffffffffffffffffffffffffffffffff166129cc565b905060018611156122bd576122ba61226782876040015160ff1660018a6122b591906152a8565b6129eb565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b6001805486919060109061232f908490700100000000000000000000000000000000900467ffffffffffffffff166152ef565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550816000015163ffffffff16600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff1613156123bc576040517f77ebef4d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001546000906123e8906fffffffffffffffffffffffffffffffff1667ffffffffffffffff8816615590565b905060006123fa48633b9aca00612a40565b61240490836155cd565b905060005a61241390886152a8565b90508082111561085b5761085b61242a82846152a8565b612a57565b60405173ffffffffffffffffffffffffffffffffffffffff80851660248301528316604482015260648101829052611ef79085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612a80565b6000816000015182602001518360400151846060015160405160200161254a949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b80516020808301516040808501516060860151608087015160a0880151935160009761254a9790969591016155e1565b6000806125a386612b8c565b90506125b181868686612bbe565b9695505050505050565b603654604080517ff4daa291000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163f4daa2919160048083019260209291908290030181865afa15801561262b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061264f9190615081565b6126599083615069565b421192915050565b6001805463ffffffff8316919060109061269a908490700100000000000000000000000000000000900467ffffffffffffffff166152ef565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555050565b60008060006126d3866000612bee565b905080612709576308c379a06000526020805278185361666543616c6c3a204e6f7420656e6f756768206761736058526064601cfd5b600080855160208701888b5af1979650505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526127779084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401612489565b505050565b600054610100900460ff16612813576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610add565b6001547801000000000000000000000000000000000000000000000000900467ffffffffffffffff166000036111b85760408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152603754604080517fcc731b02000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163cc731b029160048083019260c09291908290030181865afa158015612931573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612955919061564c565b90506040518060c00160405280826000015163ffffffff168152602001826020015160ff168152602001826040015160ff168152602001826060015163ffffffff168152602001826080015163ffffffff1681526020018260a001516fffffffffffffffffffffffffffffffff1681525091505090565b60006129e16129db8585612c0c565b83612c1c565b90505b9392505050565b6000670de0b6b3a7640000612a2c612a038583615384565b612a1590670de0b6b3a76400006153ec565b612a2785670de0b6b3a7640000615460565b612c2b565b612a369086615460565b6129e19190615384565b600081831015612a5057816129e4565b5090919050565b6000805a90505b825a612a6a90836152a8565b101561277757612a79826156ef565b9150612a5e565b6000612ae2826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612c5c9092919063ffffffff16565b8051909150156127775780806020019051810190612b009190615226565b612777576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610add565b60608180519060200120604051602001612ba891815260200190565b6040516020818303038152906040529050919050565b6000612be584612bcf878686612c6b565b8051602091820120825192909101919091201490565b95945050505050565b600080603f83619c4001026040850201603f5a021015949350505050565b600081831215612a5057816129e4565b6000818312612a5057816129e4565b60006129e4670de0b6b3a764000083612c43866136e9565b612c4d9190615460565b612c579190615384565b61392d565b60606129e18484600085613b6c565b60606000845111612cd8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4d65726b6c65547269653a20656d707479206b657900000000000000000000006044820152606401610add565b6000612ce384613d02565b90506000612cf086613dee565b9050600084604051602001612d0791815260200190565b60405160208183030381529060405290506000805b8451811015613660576000858281518110612d3957612d39615727565b602002602001015190508451831115612dd4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4d65726b6c65547269653a206b657920696e646578206578636565647320746f60448201527f74616c206b6579206c656e6774680000000000000000000000000000000000006064820152608401610add565b82600003612e8d5780518051602091820120604051612e2292612dfc92910190815260200190565b604051602081830303815290604052858051602091820120825192909101919091201490565b612e88576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4d65726b6c65547269653a20696e76616c696420726f6f7420686173680000006044820152606401610add565b612fe4565b805151602011612f435780518051602091820120604051612eb792612dfc92910190815260200190565b612e88576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d65726b6c65547269653a20696e76616c6964206c6172676520696e7465726e60448201527f616c2068617368000000000000000000000000000000000000000000000000006064820152608401610add565b805184516020808701919091208251919092012014612fe4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4d65726b6c65547269653a20696e76616c696420696e7465726e616c206e6f6460448201527f65206861736800000000000000000000000000000000000000000000000000006064820152608401610add565b612ff060106001615069565b816020015151036131cc57845183036131645761302a816020015160108151811061301d5761301d615727565b6020026020010151613e51565b965060008751116130bd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603b60248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286272616e63682900000000006064820152608401610add565b600186516130cb91906152a8565b8214613159576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286272616e6368290000000000006064820152608401610add565b5050505050506129e4565b600085848151811061317857613178615727565b602001015160f81c60f81b60f81c9050600082602001518260ff16815181106131a3576131a3615727565b602002602001015190506131b681613f05565b95506131c3600186615069565b9450505061364d565b6002816020015151036135c55760006131e482613f2a565b90506000816000815181106131fb576131fb615727565b016020015160f81c90506000613212600283615756565b61321d906002615778565b9050600061322e848360ff16613f4e565b9050600061323c8a89613f4e565b9050600061324a8383613f84565b9050808351146132dc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a20706174682072656d61696e646572206d7573742060448201527f736861726520616c6c206e6962626c65732077697468206b65790000000000006064820152608401610add565b60ff8516600214806132f1575060ff85166003145b156134e05780825114613386576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f4d65726b6c65547269653a206b65792072656d61696e646572206d757374206260448201527f65206964656e746963616c20746f20706174682072656d61696e6465720000006064820152608401610add565b6133a0876020015160018151811061301d5761301d615727565b9c5060008d5111613433576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286c65616629000000000000006064820152608401610add565b60018c5161344191906152a8565b88146134cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286c6561662900000000000000006064820152608401610add565b5050505050505050505050506129e4565b60ff851615806134f3575060ff85166001145b156135325761351f876020015160018151811061351257613512615727565b6020026020010151613f05565b995061352b818a615069565b98506135ba565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4d65726b6c65547269653a2072656365697665642061206e6f6465207769746860448201527f20616e20756e6b6e6f776e2070726566697800000000000000000000000000006064820152608401610add565b50505050505061364d565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4d65726b6c65547269653a20726563656976656420616e20756e70617273656160448201527f626c65206e6f64650000000000000000000000000000000000000000000000006064820152608401610add565b5080613658816156ef565b915050612d1c565b506040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4d65726b6c65547269653a2072616e206f7574206f662070726f6f6620656c6560448201527f6d656e74730000000000000000000000000000000000000000000000000000006064820152608401610add565b6000808213613754576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610add565b6000606061376184614038565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c1821361395e57506000919050565b680755bf798b4a1bf1e582126139d0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4558505f4f564552464c4f5700000000000000000000000000000000000000006044820152606401610add565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b606082471015613bfe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610add565b73ffffffffffffffffffffffffffffffffffffffff85163b613c7c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610add565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051613ca5919061579b565b60006040518083038185875af1925050503d8060008114613ce2576040519150601f19603f3d011682016040523d82523d6000602084013e613ce7565b606091505b5091509150613cf782828661410e565b979650505050505050565b80516060908067ffffffffffffffff811115613d2057613d20614b07565b604051908082528060200260200182016040528015613d6557816020015b6040805180820190915260608082526020820152815260200190600190039081613d3e5790505b50915060005b81811015613de7576040518060400160405280858381518110613d9057613d90615727565b60200260200101518152602001613dbf868481518110613db257613db2615727565b6020026020010151614161565b815250838281518110613dd457613dd4615727565b6020908102919091010152600101613d6b565b5050919050565b606080604051905082518060011b603f8101601f1916830160405280835250602084016020830160005b83811015613e46578060011b82018184015160001a8060041c8253600f811660018301535050600101613e18565b509295945050505050565b60606000806000613e6185614174565b919450925090506000816001811115613e7c57613e7c6157b7565b14613eb3576040517f1ff9b2e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613ebd8284615069565b855114613ef6576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612be585602001518484614612565b60606020826000015110613f2157613f1c82613e51565b610ff2565b610ff2826146a6565b6060610ff2613f49836020015160008151811061301d5761301d615727565b613dee565b606082518210613f6d5750604080516020810190915260008152610ff2565b6129e48383848651613f7f91906152a8565b6146bc565b6000808251845110613f97578251613f9a565b83515b90505b80821080156140215750828281518110613fb957613fb9615727565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916848381518110613ff857613ff8615727565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b1561403157816001019150613f9d565b5092915050565b60008082116140a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610add565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b6060831561411d5750816129e4565b82511561412d5782518084602001fd5b816040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610add9190614e99565b6060610ff261416f83614894565b614901565b600080600083600001516000036141b7576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020840151805160001a607f81116141dc57600060016000945094509450505061460b565b60b781116142f25760006141f16080836152a8565b905080876000015111614230576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001838101517fff000000000000000000000000000000000000000000000000000000000000001690821480156142a857507f80000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008216105b156142df576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506001955093506000925061460b915050565b60bf811161445057600061430760b7836152a8565b905080876000015111614346576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff000000000000000000000000000000000000000000000000000000000000001660008190036143a8576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c603781116143f0576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6143fa8184615069565b895111614433576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61443e836001615069565b975095506000945061460b9350505050565b60f781116144b557600061446560c0836152a8565b9050808760000151116144a4576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60019550935084925061460b915050565b60006144c260f7836152a8565b905080876000015111614501576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614563576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c603781116145ab576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6145b58184615069565b8951116145ee576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6145f9836001615069565b975095506001945061460b9350505050565b9193909250565b60608167ffffffffffffffff81111561462d5761462d614b07565b6040519080825280601f01601f191660200182016040528015614657576020820181803683370190505b50905081156129e457600061466c8486615069565b90506020820160005b8481101561468d578281015182820152602001614675565b8481111561469c576000858301525b5050509392505050565b6060610ff2826020015160008460000151614612565b60608182601f01101561472b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610add565b828284011015614797576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610add565b81830184511015614804576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401610add565b606082158015614823576040519150600082526020820160405261488b565b6040519150601f8416801560200281840101858101878315602002848b0101015b8183101561485c578051835260209283019201614844565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b604080518082019091526000808252602082015281516000036148e3576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50604080518082019091528151815260209182019181019190915290565b6060600080600061491185614174565b91945092509050600181600181111561492c5761492c6157b7565b14614963576040517f4b9c6abe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845161496f8385615069565b146149a6576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808252610420820190925290816020015b60408051808201909152600080825260208201528152602001906001900390816149bd5790505093506000835b8651811015614aab57600080614a306040518060400160405280858c60000151614a1491906152a8565b8152602001858c60200151614a299190615069565b9052614174565b509150915060405180604001604052808383614a4c9190615069565b8152602001848b60200151614a619190615069565b815250888581518110614a7657614a76615727565b6020908102919091010152614a8c600185615069565b9350614a988183615069565b614aa29084615069565b925050506149ea565b50845250919392505050565b73ffffffffffffffffffffffffffffffffffffffff81168114614ad957600080fd5b50565b803567ffffffffffffffff81168114614af457600080fd5b919050565b8015158114614ad957600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614b7d57614b7d614b07565b604052919050565b600082601f830112614b9657600080fd5b813567ffffffffffffffff811115614bb057614bb0614b07565b614be160207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614b36565b818152846020838601011115614bf657600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060008060c08789031215614c2c57600080fd5b8635614c3781614ab7565b95506020870135945060408701359350614c5360608801614adc565b92506080870135614c6381614af9565b915060a087013567ffffffffffffffff811115614c7f57600080fd5b614c8b89828a01614b85565b9150509295509295509295565b600060c08284031215614caa57600080fd5b60405160c0810167ffffffffffffffff8282108183111715614cce57614cce614b07565b816040528293508435835260208501359150614ce982614ab7565b81602084015260408501359150614cff82614ab7565b816040840152606085013560608401526080850135608084015260a0850135915080821115614d2d57600080fd5b50614d3a85828601614b85565b60a0830152505092915050565b600080600080600085870360e0811215614d6057600080fd5b863567ffffffffffffffff80821115614d7857600080fd5b614d848a838b01614c98565b97506020890135965060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc084011215614dbd57600080fd5b60408901955060c0890135925080831115614dd757600080fd5b828901925089601f840112614deb57600080fd5b8235915080821115614dfc57600080fd5b508860208260051b8401011115614e1257600080fd5b959894975092955050506020019190565b60005b83811015614e3e578181015183820152602001614e26565b83811115611ef75750506000910152565b60008151808452614e67816020860160208601614e23565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006129e46020830184614e4f565b600060208284031215614ebe57600080fd5b5035919050565b60ff81168114614ad957600080fd5b60008060008060808587031215614eea57600080fd5b8435614ef581614ab7565b93506020850135614f0581614ec5565b93969395505050506040820135916060013590565b600060208284031215614f2c57600080fd5b813567ffffffffffffffff811115614f4357600080fd5b614f4f84828501614c98565b949350505050565b600060208284031215614f6957600080fd5b6129e482614adc565b600080600060608486031215614f8757600080fd5b8335614f9281614ab7565b92506020840135614fa281614ab7565b91506040840135614fb281614ab7565b809150509250925092565b600080600080600060a08688031215614fd557600080fd5b8535614fe081614ab7565b945060208601359350614ff560408701614adc565b9250606086013561500581614af9565b9150608086013567ffffffffffffffff81111561502157600080fd5b61502d88828901614b85565b9150509295509295909350565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561507c5761507c61503a565b500190565b60006020828403121561509357600080fd5b5051919050565b6000602082840312156150ac57600080fd5b81516129e481614ab7565b80516fffffffffffffffffffffffffffffffff81168114614af457600080fd5b6000606082840312156150e957600080fd5b6040516060810181811067ffffffffffffffff8211171561510c5761510c614b07565b6040528251815261511f602084016150b7565b6020820152615130604084016150b7565b60408201529392505050565b60006080828403121561514e57600080fd5b6040516080810181811067ffffffffffffffff8211171561517157615171614b07565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b600067ffffffffffffffff808411156151bd576151bd614b07565b8360051b60206151ce818301614b36565b8681529185019181810190368411156151e657600080fd5b865b8481101561521a578035868111156152005760008081fd5b61520c36828b01614b85565b8452509183019183016151e8565b50979650505050505050565b60006020828403121561523857600080fd5b81516129e481614af9565b8581528460208201527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b16604082015282151560f81b604882015260008251615297816049850160208701614e23565b919091016049019695505050505050565b6000828210156152ba576152ba61503a565b500390565b600067ffffffffffffffff808316818516818304811182151516156152e6576152e661503a565b02949350505050565b600067ffffffffffffffff8083168185168083038211156153125761531261503a565b01949350505050565b6000806040838503121561532e57600080fd5b825161533981614ab7565b602084015190925061534a81614ec5565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261539357615393615355565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f8000000000000000000000000000000000000000000000000000000000000000831416156153e7576153e761503a565b500590565b6000808312837f8000000000000000000000000000000000000000000000000000000000000000018312811516156154265761542661503a565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01831381161561545a5761545a61503a565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000841360008413858304851182821616156154a1576154a161503a565b7f800000000000000000000000000000000000000000000000000000000000000060008712868205881281841616156154dc576154dc61503a565b600087129250878205871284841616156154f8576154f861503a565b8785058712818416161561550e5761550e61503a565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038413811516156155565761555661503a565b827f800000000000000000000000000000000000000000000000000000000000000003841281161561558a5761558a61503a565b50500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156155c8576155c861503a565b500290565b6000826155dc576155dc615355565b500490565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a083015261562c60c0830184614e4f565b98975050505050505050565b805163ffffffff81168114614af457600080fd5b600060c0828403121561565e57600080fd5b60405160c0810181811067ffffffffffffffff8211171561568157615681614b07565b60405261568d83615638565b8152602083015161569d81614ec5565b602082015260408301516156b081614ec5565b60408201526156c160608401615638565b60608201526156d260808401615638565b60808201526156e360a084016150b7565b60a08201529392505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036157205761572061503a565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060ff83168061576957615769615355565b8060ff84160691505092915050565b600060ff821660ff8416808210156157925761579261503a565b90039392505050565b600082516157ad818460208701614e23565b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea164736f6c634300080f000a"; bytes internal constant l2OutputOracleCode = - hex"60806040526004361061018a5760003560e01c806389c44cbb116100d6578063ce5db8d61161007f578063dcec334811610059578063dcec33481461049b578063e1a41bcf146104b0578063f4daa291146104c657600080fd5b8063ce5db8d614610445578063cf8e5cf01461045b578063d1de856c1461047b57600080fd5b8063a25ae557116100b0578063a25ae55714610391578063a8e4fb90146103ed578063bffa7f0f1461041a57600080fd5b806389c44cbb1461034857806393991af3146103685780639aaab6481461037e57600080fd5b806369f16eec1161013857806370872aa51161011257806370872aa5146102fc5780637f00642014610312578063887862721461033257600080fd5b806369f16eec146102a75780636abcf563146102bc5780636b4d98dd146102d157600080fd5b8063529933df11610169578063529933df146101ea578063534db0e2146101ff57806354fd4d501461025157600080fd5b80622134cc1461018f5780631c89c97d146101b35780634599c788146101d5575b600080fd5b34801561019b57600080fd5b506005545b6040519081526020015b60405180910390f35b3480156101bf57600080fd5b506101d36101ce3660046113a2565b6104db565b005b3480156101e157600080fd5b506101a06108b6565b3480156101f657600080fd5b506004546101a0565b34801561020b57600080fd5b5060065461022c9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101aa565b34801561025d57600080fd5b5061029a6040518060400160405280600581526020017f312e382e3000000000000000000000000000000000000000000000000000000081525081565b6040516101aa9190611405565b3480156102b357600080fd5b506101a0610929565b3480156102c857600080fd5b506003546101a0565b3480156102dd57600080fd5b5060065473ffffffffffffffffffffffffffffffffffffffff1661022c565b34801561030857600080fd5b506101a060015481565b34801561031e57600080fd5b506101a061032d366004611478565b61093b565b34801561033e57600080fd5b506101a060025481565b34801561035457600080fd5b506101d3610363366004611478565b610b4f565b34801561037457600080fd5b506101a060055481565b6101d361038c366004611491565b610de9565b34801561039d57600080fd5b506103b16103ac366004611478565b61124a565b60408051825181526020808401516fffffffffffffffffffffffffffffffff9081169183019190915292820151909216908201526060016101aa565b3480156103f957600080fd5b5060075461022c9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561042657600080fd5b5060075473ffffffffffffffffffffffffffffffffffffffff1661022c565b34801561045157600080fd5b506101a060085481565b34801561046757600080fd5b506103b1610476366004611478565b6112de565b34801561048757600080fd5b506101a0610496366004611478565b611316565b3480156104a757600080fd5b506101a0611346565b3480156104bc57600080fd5b506101a060045481565b3480156104d257600080fd5b506008546101a0565b600054610100900460ff16158080156104fb5750600054600160ff909116105b806105155750303b158015610515575060005460ff166001145b6105a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561060457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b60008811610694576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4c324f75747075744f7261636c653a207375626d697373696f6e20696e74657260448201527f76616c206d7573742062652067726561746572207468616e2030000000000000606482015260840161059d565b60008711610724576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4c324f75747075744f7261636c653a204c3220626c6f636b2074696d65206d7560448201527f73742062652067726561746572207468616e2030000000000000000000000000606482015260840161059d565b428511156107db576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526044602482018190527f4c324f75747075744f7261636c653a207374617274696e67204c322074696d65908201527f7374616d70206d757374206265206c657373207468616e2063757272656e742060648201527f74696d6500000000000000000000000000000000000000000000000000000000608482015260a40161059d565b60048890556005879055600186905560028590556007805473ffffffffffffffffffffffffffffffffffffffff8087167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179092556006805492861692909116919091179055600882905580156108ac57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b6003546000901561092057600380546108d1906001906114f2565b815481106108e1576108e1611509565b600091825260209091206002909102016001015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16919050565b6001545b905090565b600354600090610924906001906114f2565b60006109456108b6565b8211156109fa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a2063616e6e6f7420676574206f7574707560448201527f7420666f72206120626c6f636b207468617420686173206e6f74206265656e2060648201527f70726f706f736564000000000000000000000000000000000000000000000000608482015260a40161059d565b600354610aaf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f4c324f75747075744f7261636c653a2063616e6e6f7420676574206f7574707560448201527f74206173206e6f206f7574707574732068617665206265656e2070726f706f7360648201527f6564207965740000000000000000000000000000000000000000000000000000608482015260a40161059d565b6003546000905b80821015610b485760006002610acc8385611538565b610ad69190611550565b90508460038281548110610aec57610aec611509565b600091825260209091206002909102016001015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff161015610b3e57610b37816001611538565b9250610b42565b8091505b50610ab6565b5092915050565b60065473ffffffffffffffffffffffffffffffffffffffff163314610bf6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f4c324f75747075744f7261636c653a206f6e6c7920746865206368616c6c656e60448201527f67657220616464726573732063616e2064656c657465206f7574707574730000606482015260840161059d565b6003548110610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4c324f75747075744f7261636c653a2063616e6e6f742064656c657465206f7560448201527f747075747320616674657220746865206c6174657374206f757470757420696e60648201527f6465780000000000000000000000000000000000000000000000000000000000608482015260a40161059d565b60085460038281548110610cc357610cc3611509565b6000918252602090912060016002909202010154610cf3906fffffffffffffffffffffffffffffffff16426114f2565b10610da6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f4c324f75747075744f7261636c653a2063616e6e6f742064656c657465206f7560448201527f74707574732074686174206861766520616c7265616479206265656e2066696e60648201527f616c697a65640000000000000000000000000000000000000000000000000000608482015260a40161059d565b6000610db160035490565b90508160035581817f4ee37ac2c786ec85e87592d3c5c8a1dd66f8496dda3f125d9ea8ca5f657629b660405160405180910390a35050565b60075473ffffffffffffffffffffffffffffffffffffffff163314610eb6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f4c324f75747075744f7261636c653a206f6e6c79207468652070726f706f736560448201527f7220616464726573732063616e2070726f706f7365206e6577206f757470757460648201527f7300000000000000000000000000000000000000000000000000000000000000608482015260a40161059d565b610ebe611346565b8314610f72576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a20626c6f636b206e756d626572206d757360448201527f7420626520657175616c20746f206e65787420657870656374656420626c6f6360648201527f6b206e756d626572000000000000000000000000000000000000000000000000608482015260a40161059d565b42610f7c84611316565b10611009576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f4c324f75747075744f7261636c653a2063616e6e6f742070726f706f7365204c60448201527f32206f757470757420696e207468652066757475726500000000000000000000606482015260840161059d565b83611096576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4c324f75747075744f7261636c653a204c32206f75747075742070726f706f7360448201527f616c2063616e6e6f7420626520746865207a65726f2068617368000000000000606482015260840161059d565b81156111525781814014611152576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4c324f75747075744f7261636c653a20626c6f636b206861736820646f65732060448201527f6e6f74206d61746368207468652068617368206174207468652065787065637460648201527f6564206865696768740000000000000000000000000000000000000000000000608482015260a40161059d565b8261115c60035490565b857fa7aaf2512769da4e444e3de247be2564225c2e7a8f74cfe528e46e17d24868e24260405161118e91815260200190565b60405180910390a45050604080516060810182529283526fffffffffffffffffffffffffffffffff4281166020850190815292811691840191825260038054600181018255600091909152935160029094027fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b810194909455915190518216700100000000000000000000000000000000029116177fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85c90910155565b60408051606081018252600080825260208201819052918101919091526003828154811061127a5761127a611509565b600091825260209182902060408051606081018252600290930290910180548352600101546fffffffffffffffffffffffffffffffff8082169484019490945270010000000000000000000000000000000090049092169181019190915292915050565b604080516060810182526000808252602082018190529181019190915260036113068361093b565b8154811061127a5761127a611509565b60006005546001548361132991906114f2565b611333919061158b565b6002546113409190611538565b92915050565b60006004546113536108b6565b6109249190611538565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b803573ffffffffffffffffffffffffffffffffffffffff8116811461139d57600080fd5b919050565b600080600080600080600060e0888a0312156113bd57600080fd5b873596506020880135955060408801359450606088013593506113e260808901611379565b92506113f060a08901611379565b915060c0880135905092959891949750929550565b600060208083528351808285015260005b8181101561143257858101830151858201604001528201611416565b81811115611444576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b60006020828403121561148a57600080fd5b5035919050565b600080600080608085870312156114a757600080fd5b5050823594602084013594506040840135936060013592509050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015611504576115046114c3565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000821982111561154b5761154b6114c3565b500190565b600082611586577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156115c3576115c36114c3565b50029056fea164736f6c634300080f000a"; + hex"60806040526004361061018a5760003560e01c806389c44cbb116100d6578063ce5db8d61161007f578063dcec334811610059578063dcec33481461049b578063e1a41bcf146104b0578063f4daa291146104c657600080fd5b8063ce5db8d614610445578063cf8e5cf01461045b578063d1de856c1461047b57600080fd5b8063a25ae557116100b0578063a25ae55714610391578063a8e4fb90146103ed578063bffa7f0f1461041a57600080fd5b806389c44cbb1461034857806393991af3146103685780639aaab6481461037e57600080fd5b806369f16eec1161013857806370872aa51161011257806370872aa5146102fc5780637f00642014610312578063887862721461033257600080fd5b806369f16eec146102a75780636abcf563146102bc5780636b4d98dd146102d157600080fd5b8063529933df11610169578063529933df146101ea578063534db0e2146101ff57806354fd4d501461025157600080fd5b80622134cc1461018f5780631c89c97d146101b35780634599c788146101d5575b600080fd5b34801561019b57600080fd5b506005545b6040519081526020015b60405180910390f35b3480156101bf57600080fd5b506101d36101ce3660046113a2565b6104db565b005b3480156101e157600080fd5b506101a06108b6565b3480156101f657600080fd5b506004546101a0565b34801561020b57600080fd5b5060065461022c9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101aa565b34801561025d57600080fd5b5061029a6040518060400160405280600c81526020017f312e382e312d626574612e31000000000000000000000000000000000000000081525081565b6040516101aa9190611405565b3480156102b357600080fd5b506101a0610929565b3480156102c857600080fd5b506003546101a0565b3480156102dd57600080fd5b5060065473ffffffffffffffffffffffffffffffffffffffff1661022c565b34801561030857600080fd5b506101a060015481565b34801561031e57600080fd5b506101a061032d366004611478565b61093b565b34801561033e57600080fd5b506101a060025481565b34801561035457600080fd5b506101d3610363366004611478565b610b4f565b34801561037457600080fd5b506101a060055481565b6101d361038c366004611491565b610de9565b34801561039d57600080fd5b506103b16103ac366004611478565b61124a565b60408051825181526020808401516fffffffffffffffffffffffffffffffff9081169183019190915292820151909216908201526060016101aa565b3480156103f957600080fd5b5060075461022c9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561042657600080fd5b5060075473ffffffffffffffffffffffffffffffffffffffff1661022c565b34801561045157600080fd5b506101a060085481565b34801561046757600080fd5b506103b1610476366004611478565b6112de565b34801561048757600080fd5b506101a0610496366004611478565b611316565b3480156104a757600080fd5b506101a0611346565b3480156104bc57600080fd5b506101a060045481565b3480156104d257600080fd5b506008546101a0565b600054610100900460ff16158080156104fb5750600054600160ff909116105b806105155750303b158015610515575060005460ff166001145b6105a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561060457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b60008811610694576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4c324f75747075744f7261636c653a207375626d697373696f6e20696e74657260448201527f76616c206d7573742062652067726561746572207468616e2030000000000000606482015260840161059d565b60008711610724576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4c324f75747075744f7261636c653a204c3220626c6f636b2074696d65206d7560448201527f73742062652067726561746572207468616e2030000000000000000000000000606482015260840161059d565b428511156107db576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526044602482018190527f4c324f75747075744f7261636c653a207374617274696e67204c322074696d65908201527f7374616d70206d757374206265206c657373207468616e2063757272656e742060648201527f74696d6500000000000000000000000000000000000000000000000000000000608482015260a40161059d565b60048890556005879055600186905560028590556007805473ffffffffffffffffffffffffffffffffffffffff8087167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179092556006805492861692909116919091179055600882905580156108ac57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b6003546000901561092057600380546108d1906001906114f2565b815481106108e1576108e1611509565b600091825260209091206002909102016001015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16919050565b6001545b905090565b600354600090610924906001906114f2565b60006109456108b6565b8211156109fa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a2063616e6e6f7420676574206f7574707560448201527f7420666f72206120626c6f636b207468617420686173206e6f74206265656e2060648201527f70726f706f736564000000000000000000000000000000000000000000000000608482015260a40161059d565b600354610aaf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f4c324f75747075744f7261636c653a2063616e6e6f7420676574206f7574707560448201527f74206173206e6f206f7574707574732068617665206265656e2070726f706f7360648201527f6564207965740000000000000000000000000000000000000000000000000000608482015260a40161059d565b6003546000905b80821015610b485760006002610acc8385611538565b610ad69190611550565b90508460038281548110610aec57610aec611509565b600091825260209091206002909102016001015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff161015610b3e57610b37816001611538565b9250610b42565b8091505b50610ab6565b5092915050565b60065473ffffffffffffffffffffffffffffffffffffffff163314610bf6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f4c324f75747075744f7261636c653a206f6e6c7920746865206368616c6c656e60448201527f67657220616464726573732063616e2064656c657465206f7574707574730000606482015260840161059d565b6003548110610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4c324f75747075744f7261636c653a2063616e6e6f742064656c657465206f7560448201527f747075747320616674657220746865206c6174657374206f757470757420696e60648201527f6465780000000000000000000000000000000000000000000000000000000000608482015260a40161059d565b60085460038281548110610cc357610cc3611509565b6000918252602090912060016002909202010154610cf3906fffffffffffffffffffffffffffffffff16426114f2565b10610da6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f4c324f75747075744f7261636c653a2063616e6e6f742064656c657465206f7560448201527f74707574732074686174206861766520616c7265616479206265656e2066696e60648201527f616c697a65640000000000000000000000000000000000000000000000000000608482015260a40161059d565b6000610db160035490565b90508160035581817f4ee37ac2c786ec85e87592d3c5c8a1dd66f8496dda3f125d9ea8ca5f657629b660405160405180910390a35050565b60075473ffffffffffffffffffffffffffffffffffffffff163314610eb6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f4c324f75747075744f7261636c653a206f6e6c79207468652070726f706f736560448201527f7220616464726573732063616e2070726f706f7365206e6577206f757470757460648201527f7300000000000000000000000000000000000000000000000000000000000000608482015260a40161059d565b610ebe611346565b8314610f72576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a20626c6f636b206e756d626572206d757360448201527f7420626520657175616c20746f206e65787420657870656374656420626c6f6360648201527f6b206e756d626572000000000000000000000000000000000000000000000000608482015260a40161059d565b42610f7c84611316565b10611009576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f4c324f75747075744f7261636c653a2063616e6e6f742070726f706f7365204c60448201527f32206f757470757420696e207468652066757475726500000000000000000000606482015260840161059d565b83611096576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4c324f75747075744f7261636c653a204c32206f75747075742070726f706f7360448201527f616c2063616e6e6f7420626520746865207a65726f2068617368000000000000606482015260840161059d565b81156111525781814014611152576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4c324f75747075744f7261636c653a20626c6f636b206861736820646f65732060448201527f6e6f74206d61746368207468652068617368206174207468652065787065637460648201527f6564206865696768740000000000000000000000000000000000000000000000608482015260a40161059d565b8261115c60035490565b857fa7aaf2512769da4e444e3de247be2564225c2e7a8f74cfe528e46e17d24868e24260405161118e91815260200190565b60405180910390a45050604080516060810182529283526fffffffffffffffffffffffffffffffff4281166020850190815292811691840191825260038054600181018255600091909152935160029094027fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b810194909455915190518216700100000000000000000000000000000000029116177fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85c90910155565b60408051606081018252600080825260208201819052918101919091526003828154811061127a5761127a611509565b600091825260209182902060408051606081018252600290930290910180548352600101546fffffffffffffffffffffffffffffffff8082169484019490945270010000000000000000000000000000000090049092169181019190915292915050565b604080516060810182526000808252602082018190529181019190915260036113068361093b565b8154811061127a5761127a611509565b60006005546001548361132991906114f2565b611333919061158b565b6002546113409190611538565b92915050565b60006004546113536108b6565b6109249190611538565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b803573ffffffffffffffffffffffffffffffffffffffff8116811461139d57600080fd5b919050565b600080600080600080600060e0888a0312156113bd57600080fd5b873596506020880135955060408801359450606088013593506113e260808901611379565b92506113f060a08901611379565b915060c0880135905092959891949750929550565b600060208083528351808285015260005b8181101561143257858101830151858201604001528201611416565b81811115611444576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b60006020828403121561148a57600080fd5b5035919050565b600080600080608085870312156114a757600080fd5b5050823594602084013594506040840135936060013592509050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015611504576115046114c3565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000821982111561154b5761154b6114c3565b500190565b600082611586577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156115c3576115c36114c3565b50029056fea164736f6c634300080f000a"; bytes internal constant optimismPortal2Code = - hex"6080604052600436106101d15760003560e01c80637fc48504116100f7578063a35d99df11610095578063bf653a5c11610064578063bf653a5c14610697578063cff0ab96146106ca578063e9e05c421461076b578063f2b4e6171461077e57600080fd5b8063a35d99df1461059b578063a3860f48146105bb578063b69ef8a8146105db578063bb2c727e146105f057600080fd5b80638e819e54116100d15780638e819e54146104eb578063952b27971461050b5780639bf62d821461053e578063a14238e71461056b57600080fd5b80637fc48504146104ab5780638b4c40b0146101f65780638c3152e9146104cb57600080fd5b80634870496f1161016f5780635c975abb1161013e5780635c975abb1461043657806371c1566e1461044b57806371cfaa3f1461046b5780637d6be8dc1461048b57600080fd5b80634870496f1461034d5780634fd0434c1461036d578063513747ab146103af57806354fd4d50146103ea57600080fd5b80633c9f397c116101ab5780633c9f397c146102a657806343ca1c50146102d8578063452a9320146102f857806345884d321461030d57600080fd5b8063149f2f22146101fd57806333d7e2bd1461021d57806335e80ab31461027457600080fd5b366101f8576101f63334620186a06000604051806020016040528060008152506107ab565b005b600080fd5b34801561020957600080fd5b506101f6610218366004614fe6565b610850565b34801561022957600080fd5b5060375461024a9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561028057600080fd5b5060355461024a90610100900473ffffffffffffffffffffffffffffffffffffffff1681565b3480156102b257600080fd5b50603b546102c39063ffffffff1681565b60405163ffffffff909116815260200161026b565b3480156102e457600080fd5b506101f66102f336600461511c565b610a91565b34801561030457600080fd5b5061024a610f31565b34801561031957600080fd5b5061033d61032836600461516e565b603a6020526000908152604090205460ff1681565b604051901515815260200161026b565b34801561035957600080fd5b506101f661036836600461518b565b610fc9565b34801561037957600080fd5b50603b5461039690640100000000900467ffffffffffffffff1681565b60405167ffffffffffffffff909116815260200161026b565b3480156103bb57600080fd5b506103dc6103ca366004615267565b6000908152603c602052604090205490565b60405190815260200161026b565b3480156103f657600080fd5b50604080518082018252600d81527f332e31312e302d626574612e32000000000000000000000000000000000000006020820152905161026b91906152f6565b34801561044257600080fd5b5061033d611531565b34801561045757600080fd5b506101f6610466366004615309565b6115c4565b34801561047757600080fd5b506101f661048636600461533d565b611c7f565b34801561049757600080fd5b506101f66104a636600461516e565b611e3f565b3480156104b757600080fd5b506101f66104c6366004615395565b611f22565b3480156104d757600080fd5b506101f66104e63660046153b2565b61200e565b3480156104f757600080fd5b506101f66105063660046153ef565b61205a565b34801561051757600080fd5b507f00000000000000000000000000000000000000000000000000000000000000066103dc565b34801561054a57600080fd5b5060325461024a9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561057757600080fd5b5061033d610586366004615267565b60336020526000908152604090205460ff1681565b3480156105a757600080fd5b506103966105b636600461544b565b61230f565b3480156105c757600080fd5b5061024a6105d6366004615468565b61232e565b3480156105e757600080fd5b506103dc612373565b3480156105fc57600080fd5b5061066261060b366004615309565b603960209081526000928352604080842090915290825290205473ffffffffffffffffffffffffffffffffffffffff81169074010000000000000000000000000000000000000000900467ffffffffffffffff1682565b6040805173ffffffffffffffffffffffffffffffffffffffff909316835267ffffffffffffffff90911660208301520161026b565b3480156106a357600080fd5b507f000000000000000000000000000000000000000000000000000000000000000c6103dc565b3480156106d657600080fd5b50600154610732906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff928316602085015291169082015260600161026b565b6101f661077936600461548a565b6107ab565b34801561078a57600080fd5b5060385461024a9073ffffffffffffffffffffffffffffffffffffffff1681565b8260005a905060006107bb6123e9565b50905073ffffffffffffffffffffffffffffffffffffffff811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee148015906107f757503415155b1561082e576040517ff2365b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61083c883489898989612486565b506108478282612632565b50505050505050565b8260005a905060006108606123e9565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8216016108d2576040517f0eaf3c0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87603d60008282546108e49190615538565b90915550506040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610956573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097a9190615550565b905061099e73ffffffffffffffffffffffffffffffffffffffff831633308c6128ff565b6109a88982615538565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015610a12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a369190615550565b14610a6d576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a7b8a8a8a8a8a8a612486565b5050610a878282612632565b5050505050505050565b610a99611531565b15610ad0576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60325473ffffffffffffffffffffffffffffffffffffffff1661dead14610b23576040517f9396d15600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610b2e836129e1565b9050610b3a81836115c4565b6000818152603360209081526040822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558401516032805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff000000000000000000000000000000000000000090921691909117905580610bc56123e9565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff821601610c2857610c218560400151866080015187606001518860a00151612a2e565b9150610e7b565b8073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff1603610c91576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606085015115610e52578460600151603d6000828254610cb19190615569565b90915550506040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610d23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d479190615550565b9050610d7c866040015187606001518473ffffffffffffffffffffffffffffffffffffffff16612a8c9092919063ffffffff16565b6060860151610d8b9082615569565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015610df5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e199190615550565b14610e50576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60a08501515115610e7657610c218560400151866080015160008860a00151612a2e565b600191505b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405183907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b90610edd90851515815260200190565b60405180910390a281158015610ef35750326001145b15610f2a576040517feeae4ed300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa158015610fa0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc49190615580565b905090565b610fd1611531565b15611008576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff1603611071576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6038546040517fbb8aa1fc00000000000000000000000000000000000000000000000000000000815260048101869052600091829173ffffffffffffffffffffffffffffffffffffffff9091169063bb8aa1fc90602401606060405180830381865afa1580156110e5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611109919061559d565b925050915060008173ffffffffffffffffffffffffffffffffffffffff1663bcef3b556040518163ffffffff1660e01b8152600401602060405180830381865afa15801561115b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061117f9190615550565b603b5490915063ffffffff8481169116146111c6576040517f27a10cc200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111dd6111d8368890038801886155ea565b612ae7565b8114611215576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611220896129e1565b905060018373ffffffffffffffffffffffffffffffffffffffff1663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa15801561126f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611293919061567f565b60028111156112a4576112a4615650565b036112db576040517fd357347400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051602081018390526000918101829052606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012090830181905292506113a49101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f010000000000000000000000000000000000000000000000000000000000000060208301529061139a898b6156a0565b8b60400135612b26565b15156000036113df576040517fb05e92fa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051808201825273ffffffffffffffffffffffffffffffffffffffff808716825267ffffffffffffffff4281166020808501918252600088815260398252868120338252825286812095518654935190941674010000000000000000000000000000000000000000027fffffffff0000000000000000000000000000000000000000000000000000000090931693851693909317919091179093558d840151928e01519351928216939091169185917f67a6208cfcc0801d50f6cbe764733f4fddf66ac0b04442061a8a8c0cb6b63f6291a4604051339083907f798f9f13695f8f045aa5f80ed8efebb695f3c7fe65da381969f2f28bf3c60b9790600090a3506000908152603c602090815260408220805460018101825590835291200180547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790555050505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115a0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc49190615724565b600082815260396020908152604080832073ffffffffffffffffffffffffffffffffffffffff85811685529083528184208251808401845290549182168082527401000000000000000000000000000000000000000090920467ffffffffffffffff1681850152818552603a90935292205490919060ff1615611673576040517f09550c7700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b816020015167ffffffffffffffff166000036116bb576040517f94efd49b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061173c8273ffffffffffffffffffffffffffffffffffffffff1663cf09e0d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561170b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061172f9190615741565b67ffffffffffffffff1690565b90508067ffffffffffffffff16836020015167ffffffffffffffff1611611810576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604e60248201527f4f7074696d69736d506f7274616c3a207769746864726177616c2074696d657360448201527f74616d70206c657373207468616e20646973707574652067616d65206372656160648201527f74696f6e2074696d657374616d70000000000000000000000000000000000000608482015260a4015b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000c836020015167ffffffffffffffff164261184b9190615569565b116118d8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a2070726f76656e2077697468647261776160448201527f6c20686173206e6f74206d6174757265642079657400000000000000000000006064820152608401611807565b60028273ffffffffffffffffffffffffffffffffffffffff1663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611925573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611949919061567f565b600281111561195a5761195a615650565b14611991576040517fa080a3c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603b5463ffffffff1663ffffffff16611a1b8373ffffffffffffffffffffffffffffffffffffffff1663bbdc02db6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119ee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a12919061575e565b63ffffffff1690565b63ffffffff1614611a58576040517f27a10cc200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603b5467ffffffffffffffff64010000000090910481169082161015611b26576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604b60248201527f4f7074696d69736d506f7274616c3a20646973707574652067616d652063726560448201527f61746564206265666f7265207265737065637465642067616d6520747970652060648201527f7761732075706461746564000000000000000000000000000000000000000000608482015260a401611807565b7f0000000000000000000000000000000000000000000000000000000000000006611b958373ffffffffffffffffffffffffffffffffffffffff166319effeb46040518163ffffffff1660e01b8152600401602060405180830381865afa15801561170b573d6000803e3d6000fd5b611ba99067ffffffffffffffff1642615569565b11611c36576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4f7074696d69736d506f7274616c3a206f75747075742070726f706f73616c2060448201527f696e206169722d676170000000000000000000000000000000000000000000006064820152608401611807565b60008581526033602052604090205460ff1615610f2a576040517f475a253500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60375473ffffffffffffffffffffffffffffffffffffffff163314611cd0576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611cdc62030d40612b4a565b60405173ffffffffffffffffffffffffffffffffffffffff8516602482015260ff8416604482015260648101839052608481018290526000907342000000000000000000000000000000000000159073deaddeaddeaddeaddeaddeaddeaddeaddead0001907fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32908490819062030d4090829060a401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f71cfaa3f000000000000000000000000000000000000000000000000000000001790529051611df99695949392910161577b565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815290829052611e31916152f6565b60405180910390a450505050565b611e47610f31565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611eab576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81166000818152603a602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055517f192c289026d59a41a27f5aea08f3969b57931b0589202d14f4368cded95d3cda9190a250565b611f2a610f31565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611f8e576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603b805463ffffffff83167fffffffffffffffffffffffffffffffffffffffff00000000000000000000000090911681176401000000004267ffffffffffffffff90811682029290921793849055604051930416917f049fe9dd413cdf037cce27011cc1790c753118272f3630e6e8bdfa5e8208176090600090a350565b565b612016611531565b1561204d576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6120578133610a91565b50565b600054610100900460ff161580801561207a5750600054600160ff909116105b806120945750303b158015612094575060005460ff166001145b612120576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401611807565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561217e57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603880547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff8881169190911790925560378054909116868316179055603580547fffffffffffffffffffffff0000000000000000000000000000000000000000ff16610100868416021790556032541661229e576032805461dead7fffffffffffffffffffffffff0000000000000000000000000000000000000000909116179055603b80547fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166401000000004267ffffffffffffffff16027fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000161763ffffffff84161790555b6122a6612bac565b8015610f2a57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050565b600061231c8260106157e0565b61232890615208615810565b92915050565b603c602052816000526040600020818154811061234a57600080fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff169150829050565b60008061237e6123e9565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8216016123c5574791505090565b5050603d5490565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b603754604080517f4397dfef0000000000000000000000000000000000000000000000000000000081528151600093849373ffffffffffffffffffffffffffffffffffffffff90911692634397dfef92600480830193928290030181865afa158015612459573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061247d919061583c565b90939092509050565b8180156124a8575073ffffffffffffffffffffffffffffffffffffffff861615155b156124df576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6124e9815161230f565b67ffffffffffffffff168367ffffffffffffffff161015612536576040517f4929b80800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6201d4c081511115612574576040517f73052b0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b33328114612595575033731111000000000000000000000000000000001111015b600086868686866040516020016125b095949392919061577b565b604051602081830303815290604052905060008873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c328460405161262091906152f6565b60405180910390a45050505050505050565b600154600090612668907801000000000000000000000000000000000000000000000000900467ffffffffffffffff1643615569565b90506000612674612cbf565b90506000816020015160ff16826000015163ffffffff16612695919061589a565b905082156127cc576001546000906126cc908390700100000000000000000000000000000000900467ffffffffffffffff16615902565b90506000836040015160ff16836126e39190615976565b6001546127039084906fffffffffffffffffffffffffffffffff16615976565b61270d919061589a565b60015490915060009061275e906127379084906fffffffffffffffffffffffffffffffff16615a32565b866060015163ffffffff168760a001516fffffffffffffffffffffffffffffffff16612d80565b9050600186111561278d5761278a61273782876040015160ff1660018a6127859190615569565b612d9f565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b600180548691906010906127ff908490700100000000000000000000000000000000900467ffffffffffffffff16615810565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550816000015163ffffffff16600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff16131561288c576040517f77ebef4d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001546000906128b8906fffffffffffffffffffffffffffffffff1667ffffffffffffffff8816615aa6565b905060006128ca48633b9aca00612df4565b6128d49083615ae3565b905060005a6128e39088615569565b905080821115610a8757610a876128fa8284615569565b612e0b565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526129db9085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612e34565b50505050565b80516020808301516040808501516060860151608087015160a08801519351600097612a11979096959101615af7565b604051602081830303815290604052805190602001209050919050565b6000806000612a3e866000612f40565b905080612a74576308c379a06000526020805278185361666543616c6c3a204e6f7420656e6f756768206761736058526064601cfd5b600080855160208701888b5af1979650505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052612ae29084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401612959565b505050565b60008160000151826020015183604001518460600151604051602001612a11949392919093845260208401929092526040830152606082015260800190565b600080612b3286612f5e565b9050612b4081868686612f90565b9695505050505050565b6001805463ffffffff83169190601090612b83908490700100000000000000000000000000000000900467ffffffffffffffff16615810565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555050565b600054610100900460ff16612c43576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401611807565b6001547801000000000000000000000000000000000000000000000000900467ffffffffffffffff1660000361200c5760408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b6040805160c08082018352600080835260208301819052828401819052606083018190526080830181905260a083015260375483517fcc731b020000000000000000000000000000000000000000000000000000000081529351929373ffffffffffffffffffffffffffffffffffffffff9091169263cc731b02926004808401939192918290030181865afa158015612d5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc49190615b4e565b6000612d95612d8f8585612fc0565b83612fd0565b90505b9392505050565b6000670de0b6b3a7640000612de0612db7858361589a565b612dc990670de0b6b3a7640000615902565b612ddb85670de0b6b3a7640000615976565b612fdf565b612dea9086615976565b612d95919061589a565b600081831015612e045781612d98565b5090919050565b6000805a90505b825a612e1e9083615569565b1015612ae257612e2d82615bf0565b9150612e12565b6000612e96826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166130109092919063ffffffff16565b805190915015612ae25780806020019051810190612eb49190615724565b612ae2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401611807565b600080603f83619c4001026040850201603f5a021015949350505050565b60608180519060200120604051602001612f7a91815260200190565b6040516020818303038152906040529050919050565b6000612fb784612fa187868661301f565b8051602091820120825192909101919091201490565b95945050505050565b600081831215612e045781612d98565b6000818312612e045781612d98565b6000612d98670de0b6b3a764000083612ff786613a9d565b6130019190615976565b61300b919061589a565b613ce1565b6060612d958484600085613f20565b6060600084511161308c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4d65726b6c65547269653a20656d707479206b657900000000000000000000006044820152606401611807565b6000613097846140b6565b905060006130a4866141a2565b90506000846040516020016130bb91815260200190565b60405160208183030381529060405290506000805b8451811015613a145760008582815181106130ed576130ed615c28565b602002602001015190508451831115613188576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4d65726b6c65547269653a206b657920696e646578206578636565647320746f60448201527f74616c206b6579206c656e6774680000000000000000000000000000000000006064820152608401611807565b8260000361324157805180516020918201206040516131d6926131b092910190815260200190565b604051602081830303815290604052858051602091820120825192909101919091201490565b61323c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4d65726b6c65547269653a20696e76616c696420726f6f7420686173680000006044820152606401611807565b613398565b8051516020116132f7578051805160209182012060405161326b926131b092910190815260200190565b61323c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d65726b6c65547269653a20696e76616c6964206c6172676520696e7465726e60448201527f616c2068617368000000000000000000000000000000000000000000000000006064820152608401611807565b805184516020808701919091208251919092012014613398576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4d65726b6c65547269653a20696e76616c696420696e7465726e616c206e6f6460448201527f65206861736800000000000000000000000000000000000000000000000000006064820152608401611807565b6133a460106001615538565b816020015151036135805784518303613518576133de81602001516010815181106133d1576133d1615c28565b6020026020010151614205565b96506000875111613471576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603b60248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286272616e63682900000000006064820152608401611807565b6001865161347f9190615569565b821461350d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286272616e6368290000000000006064820152608401611807565b505050505050612d98565b600085848151811061352c5761352c615c28565b602001015160f81c60f81b60f81c9050600082602001518260ff168151811061355757613557615c28565b6020026020010151905061356a816142b9565b9550613577600186615538565b94505050613a01565b600281602001515103613979576000613598826142de565b90506000816000815181106135af576135af615c28565b016020015160f81c905060006135c6600283615c57565b6135d1906002615c79565b905060006135e2848360ff16614302565b905060006135f08a89614302565b905060006135fe8383614338565b905080835114613690576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a20706174682072656d61696e646572206d7573742060448201527f736861726520616c6c206e6962626c65732077697468206b65790000000000006064820152608401611807565b60ff8516600214806136a5575060ff85166003145b15613894578082511461373a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f4d65726b6c65547269653a206b65792072656d61696e646572206d757374206260448201527f65206964656e746963616c20746f20706174682072656d61696e6465720000006064820152608401611807565b61375487602001516001815181106133d1576133d1615c28565b9c5060008d51116137e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286c65616629000000000000006064820152608401611807565b60018c516137f59190615569565b8814613883576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286c6561662900000000000000006064820152608401611807565b505050505050505050505050612d98565b60ff851615806138a7575060ff85166001145b156138e6576138d387602001516001815181106138c6576138c6615c28565b60200260200101516142b9565b99506138df818a615538565b985061396e565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4d65726b6c65547269653a2072656365697665642061206e6f6465207769746860448201527f20616e20756e6b6e6f776e2070726566697800000000000000000000000000006064820152608401611807565b505050505050613a01565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4d65726b6c65547269653a20726563656976656420616e20756e70617273656160448201527f626c65206e6f64650000000000000000000000000000000000000000000000006064820152608401611807565b5080613a0c81615bf0565b9150506130d0565b506040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4d65726b6c65547269653a2072616e206f7574206f662070726f6f6620656c6560448201527f6d656e74730000000000000000000000000000000000000000000000000000006064820152608401611807565b6000808213613b08576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401611807565b60006060613b15846143ec565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c18213613d1257506000919050565b680755bf798b4a1bf1e58212613d84576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4558505f4f564552464c4f5700000000000000000000000000000000000000006044820152606401611807565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b606082471015613fb2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401611807565b73ffffffffffffffffffffffffffffffffffffffff85163b614030576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401611807565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516140599190615c9c565b60006040518083038185875af1925050503d8060008114614096576040519150601f19603f3d011682016040523d82523d6000602084013e61409b565b606091505b50915091506140ab8282866144c2565b979650505050505050565b80516060908067ffffffffffffffff8111156140d4576140d4614eb1565b60405190808252806020026020018201604052801561411957816020015b60408051808201909152606080825260208201528152602001906001900390816140f25790505b50915060005b8181101561419b57604051806040016040528085838151811061414457614144615c28565b6020026020010151815260200161417386848151811061416657614166615c28565b6020026020010151614515565b81525083828151811061418857614188615c28565b602090810291909101015260010161411f565b5050919050565b606080604051905082518060011b603f8101601f1916830160405280835250602084016020830160005b838110156141fa578060011b82018184015160001a8060041c8253600f8116600183015350506001016141cc565b509295945050505050565b6060600080600061421585614528565b91945092509050600081600181111561423057614230615650565b14614267576040517f1ff9b2e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6142718284615538565b8551146142aa576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612fb7856020015184846149c6565b606060208260000151106142d5576142d082614205565b612328565b61232882614a5a565b60606123286142fd83602001516000815181106133d1576133d1615c28565b6141a2565b6060825182106143215750604080516020810190915260008152612328565b612d9883838486516143339190615569565b614a70565b600080825184511061434b57825161434e565b83515b90505b80821080156143d5575082828151811061436d5761436d615c28565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168483815181106143ac576143ac615c28565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b156143e557816001019150614351565b5092915050565b6000808211614457576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401611807565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b606083156144d1575081612d98565b8251156144e15782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161180791906152f6565b606061232861452383614c48565b614cb5565b6000806000836000015160000361456b576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020840151805160001a607f81116145905760006001600094509450945050506149bf565b60b781116146a65760006145a5608083615569565b9050808760000151116145e4576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001838101517fff0000000000000000000000000000000000000000000000000000000000000016908214801561465c57507f80000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008216105b15614693576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50600195509350600092506149bf915050565b60bf81116148045760006146bb60b783615569565b9050808760000151116146fa576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff0000000000000000000000000000000000000000000000000000000000000016600081900361475c576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c603781116147a4576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6147ae8184615538565b8951116147e7576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6147f2836001615538565b97509550600094506149bf9350505050565b60f7811161486957600061481960c083615569565b905080876000015111614858576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001955093508492506149bf915050565b600061487660f783615569565b9050808760000151116148b5576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614917576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c6037811161495f576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6149698184615538565b8951116149a2576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6149ad836001615538565b97509550600194506149bf9350505050565b9193909250565b60608167ffffffffffffffff8111156149e1576149e1614eb1565b6040519080825280601f01601f191660200182016040528015614a0b576020820181803683370190505b5090508115612d98576000614a208486615538565b90506020820160005b84811015614a41578281015182820152602001614a29565b84811115614a50576000858301525b5050509392505050565b60606123288260200151600084600001516149c6565b60608182601f011015614adf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401611807565b828284011015614b4b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401611807565b81830184511015614bb8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401611807565b606082158015614bd75760405191506000825260208201604052614c3f565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015614c10578051835260209283019201614bf8565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b60408051808201909152600080825260208201528151600003614c97576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50604080518082019091528151815260209182019181019190915290565b60606000806000614cc585614528565b919450925090506001816001811115614ce057614ce0615650565b14614d17576040517f4b9c6abe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8451614d238385615538565b14614d5a576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808252610420820190925290816020015b6040805180820190915260008082526020820152815260200190600190039081614d715790505093506000835b8651811015614e5f57600080614de46040518060400160405280858c60000151614dc89190615569565b8152602001858c60200151614ddd9190615538565b9052614528565b509150915060405180604001604052808383614e009190615538565b8152602001848b60200151614e159190615538565b815250888581518110614e2a57614e2a615c28565b6020908102919091010152614e40600185615538565b9350614e4c8183615538565b614e569084615538565b92505050614d9e565b50845250919392505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461205757600080fd5b67ffffffffffffffff8116811461205757600080fd5b801515811461205757600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160c0810167ffffffffffffffff81118282101715614f0357614f03614eb1565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614f5057614f50614eb1565b604052919050565b600082601f830112614f6957600080fd5b813567ffffffffffffffff811115614f8357614f83614eb1565b614fb460207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614f09565b818152846020838601011115614fc957600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060008060c08789031215614fff57600080fd5b863561500a81614e6b565b95506020870135945060408701359350606087013561502881614e8d565b9250608087013561503881614ea3565b915060a087013567ffffffffffffffff81111561505457600080fd5b61506089828a01614f58565b9150509295509295509295565b600060c0828403121561507f57600080fd5b60405160c0810167ffffffffffffffff82821081831117156150a3576150a3614eb1565b8160405282935084358352602085013591506150be82614e6b565b816020840152604085013591506150d482614e6b565b816040840152606085013560608401526080850135608084015260a085013591508082111561510257600080fd5b5061510f85828601614f58565b60a0830152505092915050565b6000806040838503121561512f57600080fd5b823567ffffffffffffffff81111561514657600080fd5b6151528582860161506d565b925050602083013561516381614e6b565b809150509250929050565b60006020828403121561518057600080fd5b8135612d9881614e6b565b600080600080600085870360e08112156151a457600080fd5b863567ffffffffffffffff808211156151bc57600080fd5b6151c88a838b0161506d565b97506020890135965060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08401121561520157600080fd5b60408901955060c089013592508083111561521b57600080fd5b828901925089601f84011261522f57600080fd5b823591508082111561524057600080fd5b508860208260051b840101111561525657600080fd5b959894975092955050506020019190565b60006020828403121561527957600080fd5b5035919050565b60005b8381101561529b578181015183820152602001615283565b838111156129db5750506000910152565b600081518084526152c4816020860160208601615280565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000612d9860208301846152ac565b6000806040838503121561531c57600080fd5b82359150602083013561516381614e6b565b60ff8116811461205757600080fd5b6000806000806080858703121561535357600080fd5b843561535e81614e6b565b9350602085013561536e8161532e565b93969395505050506040820135916060013590565b63ffffffff8116811461205757600080fd5b6000602082840312156153a757600080fd5b8135612d9881615383565b6000602082840312156153c457600080fd5b813567ffffffffffffffff8111156153db57600080fd5b6153e78482850161506d565b949350505050565b6000806000806080858703121561540557600080fd5b843561541081614e6b565b9350602085013561542081614e6b565b9250604085013561543081614e6b565b9150606085013561544081615383565b939692955090935050565b60006020828403121561545d57600080fd5b8135612d9881614e8d565b6000806040838503121561547b57600080fd5b50508035926020909101359150565b600080600080600060a086880312156154a257600080fd5b85356154ad81614e6b565b94506020860135935060408601356154c481614e8d565b925060608601356154d481614ea3565b9150608086013567ffffffffffffffff8111156154f057600080fd5b6154fc88828901614f58565b9150509295509295909350565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561554b5761554b615509565b500190565b60006020828403121561556257600080fd5b5051919050565b60008282101561557b5761557b615509565b500390565b60006020828403121561559257600080fd5b8151612d9881614e6b565b6000806000606084860312156155b257600080fd5b83516155bd81615383565b60208501519093506155ce81614e8d565b60408501519092506155df81614e6b565b809150509250925092565b6000608082840312156155fc57600080fd5b6040516080810181811067ffffffffffffffff8211171561561f5761561f614eb1565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60006020828403121561569157600080fd5b815160038110612d9857600080fd5b600067ffffffffffffffff808411156156bb576156bb614eb1565b8360051b60206156cc818301614f09565b8681529185019181810190368411156156e457600080fd5b865b84811015615718578035868111156156fe5760008081fd5b61570a36828b01614f58565b8452509183019183016156e6565b50979650505050505050565b60006020828403121561573657600080fd5b8151612d9881614ea3565b60006020828403121561575357600080fd5b8151612d9881614e8d565b60006020828403121561577057600080fd5b8151612d9881615383565b8581528460208201527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b16604082015282151560f81b6048820152600082516157cf816049850160208701615280565b919091016049019695505050505050565b600067ffffffffffffffff8083168185168183048111821515161561580757615807615509565b02949350505050565b600067ffffffffffffffff80831681851680830382111561583357615833615509565b01949350505050565b6000806040838503121561584f57600080fd5b825161585a81614e6b565b60208401519092506151638161532e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826158a9576158a961586b565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f8000000000000000000000000000000000000000000000000000000000000000831416156158fd576158fd615509565b500590565b6000808312837f80000000000000000000000000000000000000000000000000000000000000000183128115161561593c5761593c615509565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01831381161561597057615970615509565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000841360008413858304851182821616156159b7576159b7615509565b7f800000000000000000000000000000000000000000000000000000000000000060008712868205881281841616156159f2576159f2615509565b60008712925087820587128484161615615a0e57615a0e615509565b87850587128184161615615a2457615a24615509565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03841381151615615a6c57615a6c615509565b827f8000000000000000000000000000000000000000000000000000000000000000038412811615615aa057615aa0615509565b50500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615ade57615ade615509565b500290565b600082615af257615af261586b565b500490565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a0830152615b4260c08301846152ac565b98975050505050505050565b600060c08284031215615b6057600080fd5b615b68614ee0565b8251615b7381615383565b81526020830151615b838161532e565b60208201526040830151615b968161532e565b60408201526060830151615ba981615383565b60608201526080830151615bbc81615383565b608082015260a08301516fffffffffffffffffffffffffffffffff81168114615be457600080fd5b60a08201529392505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203615c2157615c21615509565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060ff831680615c6a57615c6a61586b565b8060ff84160691505092915050565b600060ff821660ff841680821015615c9357615c93615509565b90039392505050565b60008251615cae818460208701615280565b919091019291505056fea164736f6c634300080f000a"; + hex"6080604052600436106101d15760003560e01c80637fc48504116100f7578063a35d99df11610095578063bf653a5c11610064578063bf653a5c14610697578063cff0ab96146106ca578063e9e05c421461076b578063f2b4e6171461077e57600080fd5b8063a35d99df1461059b578063a3860f48146105bb578063b69ef8a8146105db578063bb2c727e146105f057600080fd5b80638e819e54116100d15780638e819e54146104eb578063952b27971461050b5780639bf62d821461053e578063a14238e71461056b57600080fd5b80637fc48504146104ab5780638b4c40b0146101f65780638c3152e9146104cb57600080fd5b80634870496f1161016f5780635c975abb1161013e5780635c975abb1461043657806371c1566e1461044b57806371cfaa3f1461046b5780637d6be8dc1461048b57600080fd5b80634870496f1461034d5780634fd0434c1461036d578063513747ab146103af57806354fd4d50146103ea57600080fd5b80633c9f397c116101ab5780633c9f397c146102a657806343ca1c50146102d8578063452a9320146102f857806345884d321461030d57600080fd5b8063149f2f22146101fd57806333d7e2bd1461021d57806335e80ab31461027457600080fd5b366101f8576101f63334620186a06000604051806020016040528060008152506107ab565b005b600080fd5b34801561020957600080fd5b506101f6610218366004614feb565b610850565b34801561022957600080fd5b5060375461024a9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561028057600080fd5b5060355461024a90610100900473ffffffffffffffffffffffffffffffffffffffff1681565b3480156102b257600080fd5b50603b546102c39063ffffffff1681565b60405163ffffffff909116815260200161026b565b3480156102e457600080fd5b506101f66102f3366004615121565b610a91565b34801561030457600080fd5b5061024a610f31565b34801561031957600080fd5b5061033d610328366004615173565b603a6020526000908152604090205460ff1681565b604051901515815260200161026b565b34801561035957600080fd5b506101f6610368366004615190565b610fc9565b34801561037957600080fd5b50603b5461039690640100000000900467ffffffffffffffff1681565b60405167ffffffffffffffff909116815260200161026b565b3480156103bb57600080fd5b506103dc6103ca36600461526c565b6000908152603c602052604090205490565b60405190815260200161026b565b3480156103f657600080fd5b50604080518082018252600d81527f332e31312e302d626574612e33000000000000000000000000000000000000006020820152905161026b91906152fb565b34801561044257600080fd5b5061033d611531565b34801561045757600080fd5b506101f661046636600461530e565b6115c4565b34801561047757600080fd5b506101f6610486366004615342565b611c7f565b34801561049757600080fd5b506101f66104a6366004615173565b611e3f565b3480156104b757600080fd5b506101f66104c636600461539a565b611f22565b3480156104d757600080fd5b506101f66104e63660046153b7565b61200e565b3480156104f757600080fd5b506101f66105063660046153f4565b61205a565b34801561051757600080fd5b507f00000000000000000000000000000000000000000000000000000000000000066103dc565b34801561054a57600080fd5b5060325461024a9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561057757600080fd5b5061033d61058636600461526c565b60336020526000908152604090205460ff1681565b3480156105a757600080fd5b506103966105b6366004615450565b61230f565b3480156105c757600080fd5b5061024a6105d636600461546d565b61232e565b3480156105e757600080fd5b506103dc612373565b3480156105fc57600080fd5b5061066261060b36600461530e565b603960209081526000928352604080842090915290825290205473ffffffffffffffffffffffffffffffffffffffff81169074010000000000000000000000000000000000000000900467ffffffffffffffff1682565b6040805173ffffffffffffffffffffffffffffffffffffffff909316835267ffffffffffffffff90911660208301520161026b565b3480156106a357600080fd5b507f000000000000000000000000000000000000000000000000000000000000000c6103dc565b3480156106d657600080fd5b50600154610732906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff928316602085015291169082015260600161026b565b6101f661077936600461548f565b6107ab565b34801561078a57600080fd5b5060385461024a9073ffffffffffffffffffffffffffffffffffffffff1681565b8260005a905060006107bb6123e9565b50905073ffffffffffffffffffffffffffffffffffffffff811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee148015906107f757503415155b1561082e576040517ff2365b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61083c883489898989612486565b506108478282612632565b50505050505050565b8260005a905060006108606123e9565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8216016108d2576040517f0eaf3c0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87603d60008282546108e4919061553d565b90915550506040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610956573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097a9190615555565b905061099e73ffffffffffffffffffffffffffffffffffffffff831633308c6128ff565b6109a8898261553d565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015610a12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a369190615555565b14610a6d576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a7b8a8a8a8a8a8a612486565b5050610a878282612632565b5050505050505050565b610a99611531565b15610ad0576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60325473ffffffffffffffffffffffffffffffffffffffff1661dead14610b23576040517f9396d15600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610b2e836129e1565b9050610b3a81836115c4565b6000818152603360209081526040822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558401516032805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff000000000000000000000000000000000000000090921691909117905580610bc56123e9565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff821601610c2857610c218560400151866080015187606001518860a00151612a2e565b9150610e7b565b8073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff1603610c91576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606085015115610e52578460600151603d6000828254610cb1919061556e565b90915550506040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610d23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d479190615555565b9050610d7c866040015187606001518473ffffffffffffffffffffffffffffffffffffffff16612a8c9092919063ffffffff16565b6060860151610d8b908261556e565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015610df5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e199190615555565b14610e50576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60a08501515115610e7657610c218560400151866080015160008860a00151612a2e565b600191505b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405183907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b90610edd90851515815260200190565b60405180910390a281158015610ef35750326001145b15610f2a576040517feeae4ed300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa158015610fa0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc49190615585565b905090565b610fd1611531565b15611008576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff1603611071576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6038546040517fbb8aa1fc00000000000000000000000000000000000000000000000000000000815260048101869052600091829173ffffffffffffffffffffffffffffffffffffffff9091169063bb8aa1fc90602401606060405180830381865afa1580156110e5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061110991906155a2565b925050915060008173ffffffffffffffffffffffffffffffffffffffff1663bcef3b556040518163ffffffff1660e01b8152600401602060405180830381865afa15801561115b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061117f9190615555565b603b5490915063ffffffff8481169116146111c6576040517f27a10cc200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111dd6111d8368890038801886155ef565b612ae7565b8114611215576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611220896129e1565b905060018373ffffffffffffffffffffffffffffffffffffffff1663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa15801561126f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112939190615684565b60028111156112a4576112a4615655565b036112db576040517fd357347400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051602081018390526000918101829052606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012090830181905292506113a49101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f010000000000000000000000000000000000000000000000000000000000000060208301529061139a898b6156a5565b8b60400135612b26565b15156000036113df576040517fb05e92fa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051808201825273ffffffffffffffffffffffffffffffffffffffff808716825267ffffffffffffffff4281166020808501918252600088815260398252868120338252825286812095518654935190941674010000000000000000000000000000000000000000027fffffffff0000000000000000000000000000000000000000000000000000000090931693851693909317919091179093558d840151928e01519351928216939091169185917f67a6208cfcc0801d50f6cbe764733f4fddf66ac0b04442061a8a8c0cb6b63f6291a4604051339083907f798f9f13695f8f045aa5f80ed8efebb695f3c7fe65da381969f2f28bf3c60b9790600090a3506000908152603c602090815260408220805460018101825590835291200180547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790555050505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115a0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc49190615729565b600082815260396020908152604080832073ffffffffffffffffffffffffffffffffffffffff85811685529083528184208251808401845290549182168082527401000000000000000000000000000000000000000090920467ffffffffffffffff1681850152818552603a90935292205490919060ff1615611673576040517f09550c7700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b816020015167ffffffffffffffff166000036116bb576040517f94efd49b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061173c8273ffffffffffffffffffffffffffffffffffffffff1663cf09e0d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561170b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061172f9190615746565b67ffffffffffffffff1690565b90508067ffffffffffffffff16836020015167ffffffffffffffff1611611810576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604e60248201527f4f7074696d69736d506f7274616c3a207769746864726177616c2074696d657360448201527f74616d70206c657373207468616e20646973707574652067616d65206372656160648201527f74696f6e2074696d657374616d70000000000000000000000000000000000000608482015260a4015b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000c836020015167ffffffffffffffff164261184b919061556e565b116118d8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a2070726f76656e2077697468647261776160448201527f6c20686173206e6f74206d6174757265642079657400000000000000000000006064820152608401611807565b60028273ffffffffffffffffffffffffffffffffffffffff1663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611925573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119499190615684565b600281111561195a5761195a615655565b14611991576040517fa080a3c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603b5463ffffffff1663ffffffff16611a1b8373ffffffffffffffffffffffffffffffffffffffff1663bbdc02db6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119ee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a129190615763565b63ffffffff1690565b63ffffffff1614611a58576040517f27a10cc200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603b5467ffffffffffffffff64010000000090910481169082161015611b26576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604b60248201527f4f7074696d69736d506f7274616c3a20646973707574652067616d652063726560448201527f61746564206265666f7265207265737065637465642067616d6520747970652060648201527f7761732075706461746564000000000000000000000000000000000000000000608482015260a401611807565b7f0000000000000000000000000000000000000000000000000000000000000006611b958373ffffffffffffffffffffffffffffffffffffffff166319effeb46040518163ffffffff1660e01b8152600401602060405180830381865afa15801561170b573d6000803e3d6000fd5b611ba99067ffffffffffffffff164261556e565b11611c36576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4f7074696d69736d506f7274616c3a206f75747075742070726f706f73616c2060448201527f696e206169722d676170000000000000000000000000000000000000000000006064820152608401611807565b60008581526033602052604090205460ff1615610f2a576040517f475a253500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60375473ffffffffffffffffffffffffffffffffffffffff163314611cd0576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611cdc62030d40612b4a565b60405173ffffffffffffffffffffffffffffffffffffffff8516602482015260ff8416604482015260648101839052608481018290526000907342000000000000000000000000000000000000159073deaddeaddeaddeaddeaddeaddeaddeaddead0001907fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32908490819062030d4090829060a401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f71cfaa3f000000000000000000000000000000000000000000000000000000001790529051611df996959493929101615780565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815290829052611e31916152fb565b60405180910390a450505050565b611e47610f31565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611eab576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81166000818152603a602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055517f192c289026d59a41a27f5aea08f3969b57931b0589202d14f4368cded95d3cda9190a250565b611f2a610f31565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611f8e576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603b805463ffffffff83167fffffffffffffffffffffffffffffffffffffffff00000000000000000000000090911681176401000000004267ffffffffffffffff90811682029290921793849055604051930416917f049fe9dd413cdf037cce27011cc1790c753118272f3630e6e8bdfa5e8208176090600090a350565b565b612016611531565b1561204d576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6120578133610a91565b50565b600054610100900460ff161580801561207a5750600054600160ff909116105b806120945750303b158015612094575060005460ff166001145b612120576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401611807565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561217e57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603880547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff8881169190911790925560378054909116868316179055603580547fffffffffffffffffffffff0000000000000000000000000000000000000000ff16610100868416021790556032541661229e576032805461dead7fffffffffffffffffffffffff0000000000000000000000000000000000000000909116179055603b80547fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166401000000004267ffffffffffffffff16027fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000161763ffffffff84161790555b6122a6612bac565b8015610f2a57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050565b600061231c8260106157e5565b61232890615208615815565b92915050565b603c602052816000526040600020818154811061234a57600080fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff169150829050565b60008061237e6123e9565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8216016123c5574791505090565b5050603d5490565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b603754604080517f4397dfef0000000000000000000000000000000000000000000000000000000081528151600093849373ffffffffffffffffffffffffffffffffffffffff90911692634397dfef92600480830193928290030181865afa158015612459573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061247d9190615841565b90939092509050565b8180156124a8575073ffffffffffffffffffffffffffffffffffffffff861615155b156124df576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6124e9815161230f565b67ffffffffffffffff168367ffffffffffffffff161015612536576040517f4929b80800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6201d4c081511115612574576040517f73052b0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b33328114612595575033731111000000000000000000000000000000001111015b600086868686866040516020016125b0959493929190615780565b604051602081830303815290604052905060008873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c328460405161262091906152fb565b60405180910390a45050505050505050565b600154600090612668907801000000000000000000000000000000000000000000000000900467ffffffffffffffff164361556e565b90506000612674612cbf565b90506000816020015160ff16826000015163ffffffff16612695919061589f565b905082156127cc576001546000906126cc908390700100000000000000000000000000000000900467ffffffffffffffff16615907565b90506000836040015160ff16836126e3919061597b565b6001546127039084906fffffffffffffffffffffffffffffffff1661597b565b61270d919061589f565b60015490915060009061275e906127379084906fffffffffffffffffffffffffffffffff16615a37565b866060015163ffffffff168760a001516fffffffffffffffffffffffffffffffff16612d85565b9050600186111561278d5761278a61273782876040015160ff1660018a612785919061556e565b612da4565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b600180548691906010906127ff908490700100000000000000000000000000000000900467ffffffffffffffff16615815565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550816000015163ffffffff16600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff16131561288c576040517f77ebef4d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001546000906128b8906fffffffffffffffffffffffffffffffff1667ffffffffffffffff8816615aab565b905060006128ca48633b9aca00612df9565b6128d49083615ae8565b905060005a6128e3908861556e565b905080821115610a8757610a876128fa828461556e565b612e10565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526129db9085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612e39565b50505050565b80516020808301516040808501516060860151608087015160a08801519351600097612a11979096959101615afc565b604051602081830303815290604052805190602001209050919050565b6000806000612a3e866000612f45565b905080612a74576308c379a06000526020805278185361666543616c6c3a204e6f7420656e6f756768206761736058526064601cfd5b600080855160208701888b5af1979650505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052612ae29084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401612959565b505050565b60008160000151826020015183604001518460600151604051602001612a11949392919093845260208401929092526040830152606082015260800190565b600080612b3286612f63565b9050612b4081868686612f95565b9695505050505050565b6001805463ffffffff83169190601090612b83908490700100000000000000000000000000000000900467ffffffffffffffff16615815565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555050565b600054610100900460ff16612c43576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401611807565b6001547801000000000000000000000000000000000000000000000000900467ffffffffffffffff1660000361200c5760408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152603754604080517fcc731b02000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163cc731b029160048083019260c09291908290030181865afa158015612d61573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123289190615b53565b6000612d9a612d948585612fc5565b83612fd5565b90505b9392505050565b6000670de0b6b3a7640000612de5612dbc858361589f565b612dce90670de0b6b3a7640000615907565b612de085670de0b6b3a764000061597b565b612fe4565b612def908661597b565b612d9a919061589f565b600081831015612e095781612d9d565b5090919050565b6000805a90505b825a612e23908361556e565b1015612ae257612e3282615bf5565b9150612e17565b6000612e9b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166130159092919063ffffffff16565b805190915015612ae25780806020019051810190612eb99190615729565b612ae2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401611807565b600080603f83619c4001026040850201603f5a021015949350505050565b60608180519060200120604051602001612f7f91815260200190565b6040516020818303038152906040529050919050565b6000612fbc84612fa6878686613024565b8051602091820120825192909101919091201490565b95945050505050565b600081831215612e095781612d9d565b6000818312612e095781612d9d565b6000612d9d670de0b6b3a764000083612ffc86613aa2565b613006919061597b565b613010919061589f565b613ce6565b6060612d9a8484600085613f25565b60606000845111613091576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4d65726b6c65547269653a20656d707479206b657900000000000000000000006044820152606401611807565b600061309c846140bb565b905060006130a9866141a7565b90506000846040516020016130c091815260200190565b60405160208183030381529060405290506000805b8451811015613a195760008582815181106130f2576130f2615c2d565b60200260200101519050845183111561318d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4d65726b6c65547269653a206b657920696e646578206578636565647320746f60448201527f74616c206b6579206c656e6774680000000000000000000000000000000000006064820152608401611807565b8260000361324657805180516020918201206040516131db926131b592910190815260200190565b604051602081830303815290604052858051602091820120825192909101919091201490565b613241576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4d65726b6c65547269653a20696e76616c696420726f6f7420686173680000006044820152606401611807565b61339d565b8051516020116132fc5780518051602091820120604051613270926131b592910190815260200190565b613241576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d65726b6c65547269653a20696e76616c6964206c6172676520696e7465726e60448201527f616c2068617368000000000000000000000000000000000000000000000000006064820152608401611807565b80518451602080870191909120825191909201201461339d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4d65726b6c65547269653a20696e76616c696420696e7465726e616c206e6f6460448201527f65206861736800000000000000000000000000000000000000000000000000006064820152608401611807565b6133a96010600161553d565b81602001515103613585578451830361351d576133e381602001516010815181106133d6576133d6615c2d565b602002602001015161420a565b96506000875111613476576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603b60248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286272616e63682900000000006064820152608401611807565b60018651613484919061556e565b8214613512576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286272616e6368290000000000006064820152608401611807565b505050505050612d9d565b600085848151811061353157613531615c2d565b602001015160f81c60f81b60f81c9050600082602001518260ff168151811061355c5761355c615c2d565b6020026020010151905061356f816142be565b955061357c60018661553d565b94505050613a06565b60028160200151510361397e57600061359d826142e3565b90506000816000815181106135b4576135b4615c2d565b016020015160f81c905060006135cb600283615c5c565b6135d6906002615c7e565b905060006135e7848360ff16614307565b905060006135f58a89614307565b90506000613603838361433d565b905080835114613695576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a20706174682072656d61696e646572206d7573742060448201527f736861726520616c6c206e6962626c65732077697468206b65790000000000006064820152608401611807565b60ff8516600214806136aa575060ff85166003145b15613899578082511461373f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f4d65726b6c65547269653a206b65792072656d61696e646572206d757374206260448201527f65206964656e746963616c20746f20706174682072656d61696e6465720000006064820152608401611807565b61375987602001516001815181106133d6576133d6615c2d565b9c5060008d51116137ec576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286c65616629000000000000006064820152608401611807565b60018c516137fa919061556e565b8814613888576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286c6561662900000000000000006064820152608401611807565b505050505050505050505050612d9d565b60ff851615806138ac575060ff85166001145b156138eb576138d887602001516001815181106138cb576138cb615c2d565b60200260200101516142be565b99506138e4818a61553d565b9850613973565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4d65726b6c65547269653a2072656365697665642061206e6f6465207769746860448201527f20616e20756e6b6e6f776e2070726566697800000000000000000000000000006064820152608401611807565b505050505050613a06565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4d65726b6c65547269653a20726563656976656420616e20756e70617273656160448201527f626c65206e6f64650000000000000000000000000000000000000000000000006064820152608401611807565b5080613a1181615bf5565b9150506130d5565b506040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4d65726b6c65547269653a2072616e206f7574206f662070726f6f6620656c6560448201527f6d656e74730000000000000000000000000000000000000000000000000000006064820152608401611807565b6000808213613b0d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401611807565b60006060613b1a846143f1565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c18213613d1757506000919050565b680755bf798b4a1bf1e58212613d89576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4558505f4f564552464c4f5700000000000000000000000000000000000000006044820152606401611807565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b606082471015613fb7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401611807565b73ffffffffffffffffffffffffffffffffffffffff85163b614035576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401611807565b6000808673ffffffffffffffffffffffffffffffffffffffff16858760405161405e9190615ca1565b60006040518083038185875af1925050503d806000811461409b576040519150601f19603f3d011682016040523d82523d6000602084013e6140a0565b606091505b50915091506140b08282866144c7565b979650505050505050565b80516060908067ffffffffffffffff8111156140d9576140d9614eb6565b60405190808252806020026020018201604052801561411e57816020015b60408051808201909152606080825260208201528152602001906001900390816140f75790505b50915060005b818110156141a057604051806040016040528085838151811061414957614149615c2d565b6020026020010151815260200161417886848151811061416b5761416b615c2d565b602002602001015161451a565b81525083828151811061418d5761418d615c2d565b6020908102919091010152600101614124565b5050919050565b606080604051905082518060011b603f8101601f1916830160405280835250602084016020830160005b838110156141ff578060011b82018184015160001a8060041c8253600f8116600183015350506001016141d1565b509295945050505050565b6060600080600061421a8561452d565b91945092509050600081600181111561423557614235615655565b1461426c576040517f1ff9b2e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614276828461553d565b8551146142af576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612fbc856020015184846149cb565b606060208260000151106142da576142d58261420a565b612328565b61232882614a5f565b606061232861430283602001516000815181106133d6576133d6615c2d565b6141a7565b6060825182106143265750604080516020810190915260008152612328565b612d9d8383848651614338919061556e565b614a75565b6000808251845110614350578251614353565b83515b90505b80821080156143da575082828151811061437257614372615c2d565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168483815181106143b1576143b1615c2d565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b156143ea57816001019150614356565b5092915050565b600080821161445c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401611807565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b606083156144d6575081612d9d565b8251156144e65782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161180791906152fb565b606061232861452883614c4d565b614cba565b60008060008360000151600003614570576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020840151805160001a607f81116145955760006001600094509450945050506149c4565b60b781116146ab5760006145aa60808361556e565b9050808760000151116145e9576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001838101517fff0000000000000000000000000000000000000000000000000000000000000016908214801561466157507f80000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008216105b15614698576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50600195509350600092506149c4915050565b60bf81116148095760006146c060b78361556e565b9050808760000151116146ff576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614761576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c603781116147a9576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6147b3818461553d565b8951116147ec576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6147f783600161553d565b97509550600094506149c49350505050565b60f7811161486e57600061481e60c08361556e565b90508087600001511161485d576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001955093508492506149c4915050565b600061487b60f78361556e565b9050808760000151116148ba576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff0000000000000000000000000000000000000000000000000000000000000016600081900361491c576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c60378111614964576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61496e818461553d565b8951116149a7576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6149b283600161553d565b97509550600194506149c49350505050565b9193909250565b60608167ffffffffffffffff8111156149e6576149e6614eb6565b6040519080825280601f01601f191660200182016040528015614a10576020820181803683370190505b5090508115612d9d576000614a25848661553d565b90506020820160005b84811015614a46578281015182820152602001614a2e565b84811115614a55576000858301525b5050509392505050565b60606123288260200151600084600001516149cb565b60608182601f011015614ae4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401611807565b828284011015614b50576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401611807565b81830184511015614bbd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401611807565b606082158015614bdc5760405191506000825260208201604052614c44565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015614c15578051835260209283019201614bfd565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b60408051808201909152600080825260208201528151600003614c9c576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50604080518082019091528151815260209182019181019190915290565b60606000806000614cca8561452d565b919450925090506001816001811115614ce557614ce5615655565b14614d1c576040517f4b9c6abe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8451614d28838561553d565b14614d5f576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808252610420820190925290816020015b6040805180820190915260008082526020820152815260200190600190039081614d765790505093506000835b8651811015614e6457600080614de96040518060400160405280858c60000151614dcd919061556e565b8152602001858c60200151614de2919061553d565b905261452d565b509150915060405180604001604052808383614e05919061553d565b8152602001848b60200151614e1a919061553d565b815250888581518110614e2f57614e2f615c2d565b6020908102919091010152614e4560018561553d565b9350614e51818361553d565b614e5b908461553d565b92505050614da3565b50845250919392505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461205757600080fd5b67ffffffffffffffff8116811461205757600080fd5b801515811461205757600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160c0810167ffffffffffffffff81118282101715614f0857614f08614eb6565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614f5557614f55614eb6565b604052919050565b600082601f830112614f6e57600080fd5b813567ffffffffffffffff811115614f8857614f88614eb6565b614fb960207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614f0e565b818152846020838601011115614fce57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060008060c0878903121561500457600080fd5b863561500f81614e70565b95506020870135945060408701359350606087013561502d81614e92565b9250608087013561503d81614ea8565b915060a087013567ffffffffffffffff81111561505957600080fd5b61506589828a01614f5d565b9150509295509295509295565b600060c0828403121561508457600080fd5b60405160c0810167ffffffffffffffff82821081831117156150a8576150a8614eb6565b8160405282935084358352602085013591506150c382614e70565b816020840152604085013591506150d982614e70565b816040840152606085013560608401526080850135608084015260a085013591508082111561510757600080fd5b5061511485828601614f5d565b60a0830152505092915050565b6000806040838503121561513457600080fd5b823567ffffffffffffffff81111561514b57600080fd5b61515785828601615072565b925050602083013561516881614e70565b809150509250929050565b60006020828403121561518557600080fd5b8135612d9d81614e70565b600080600080600085870360e08112156151a957600080fd5b863567ffffffffffffffff808211156151c157600080fd5b6151cd8a838b01615072565b97506020890135965060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08401121561520657600080fd5b60408901955060c089013592508083111561522057600080fd5b828901925089601f84011261523457600080fd5b823591508082111561524557600080fd5b508860208260051b840101111561525b57600080fd5b959894975092955050506020019190565b60006020828403121561527e57600080fd5b5035919050565b60005b838110156152a0578181015183820152602001615288565b838111156129db5750506000910152565b600081518084526152c9816020860160208601615285565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000612d9d60208301846152b1565b6000806040838503121561532157600080fd5b82359150602083013561516881614e70565b60ff8116811461205757600080fd5b6000806000806080858703121561535857600080fd5b843561536381614e70565b9350602085013561537381615333565b93969395505050506040820135916060013590565b63ffffffff8116811461205757600080fd5b6000602082840312156153ac57600080fd5b8135612d9d81615388565b6000602082840312156153c957600080fd5b813567ffffffffffffffff8111156153e057600080fd5b6153ec84828501615072565b949350505050565b6000806000806080858703121561540a57600080fd5b843561541581614e70565b9350602085013561542581614e70565b9250604085013561543581614e70565b9150606085013561544581615388565b939692955090935050565b60006020828403121561546257600080fd5b8135612d9d81614e92565b6000806040838503121561548057600080fd5b50508035926020909101359150565b600080600080600060a086880312156154a757600080fd5b85356154b281614e70565b94506020860135935060408601356154c981614e92565b925060608601356154d981614ea8565b9150608086013567ffffffffffffffff8111156154f557600080fd5b61550188828901614f5d565b9150509295509295909350565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156155505761555061550e565b500190565b60006020828403121561556757600080fd5b5051919050565b6000828210156155805761558061550e565b500390565b60006020828403121561559757600080fd5b8151612d9d81614e70565b6000806000606084860312156155b757600080fd5b83516155c281615388565b60208501519093506155d381614e92565b60408501519092506155e481614e70565b809150509250925092565b60006080828403121561560157600080fd5b6040516080810181811067ffffffffffffffff8211171561562457615624614eb6565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60006020828403121561569657600080fd5b815160038110612d9d57600080fd5b600067ffffffffffffffff808411156156c0576156c0614eb6565b8360051b60206156d1818301614f0e565b8681529185019181810190368411156156e957600080fd5b865b8481101561571d578035868111156157035760008081fd5b61570f36828b01614f5d565b8452509183019183016156eb565b50979650505050505050565b60006020828403121561573b57600080fd5b8151612d9d81614ea8565b60006020828403121561575857600080fd5b8151612d9d81614e92565b60006020828403121561577557600080fd5b8151612d9d81615388565b8581528460208201527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b16604082015282151560f81b6048820152600082516157d4816049850160208701615285565b919091016049019695505050505050565b600067ffffffffffffffff8083168185168183048111821515161561580c5761580c61550e565b02949350505050565b600067ffffffffffffffff8083168185168083038211156158385761583861550e565b01949350505050565b6000806040838503121561585457600080fd5b825161585f81614e70565b602084015190925061516881615333565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826158ae576158ae615870565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f8000000000000000000000000000000000000000000000000000000000000000831416156159025761590261550e565b500590565b6000808312837f8000000000000000000000000000000000000000000000000000000000000000018312811516156159415761594161550e565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0183138116156159755761597561550e565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000841360008413858304851182821616156159bc576159bc61550e565b7f800000000000000000000000000000000000000000000000000000000000000060008712868205881281841616156159f7576159f761550e565b60008712925087820587128484161615615a1357615a1361550e565b87850587128184161615615a2957615a2961550e565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03841381151615615a7157615a7161550e565b827f8000000000000000000000000000000000000000000000000000000000000000038412811615615aa557615aa561550e565b50500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615ae357615ae361550e565b500290565b600082615af757615af7615870565b500490565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a0830152615b4760c08301846152b1565b98975050505050505050565b600060c08284031215615b6557600080fd5b615b6d614ee5565b8251615b7881615388565b81526020830151615b8881615333565b60208201526040830151615b9b81615333565b60408201526060830151615bae81615388565b60608201526080830151615bc181615388565b608082015260a08301516fffffffffffffffffffffffffffffffff81168114615be957600080fd5b60a08201529392505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203615c2657615c2661550e565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060ff831680615c6f57615c6f615870565b8060ff84160691505092915050565b600060ff821660ff841680821015615c9857615c9861550e565b90039392505050565b60008251615cb3818460208701615285565b919091019291505056fea164736f6c634300080f000a"; bytes internal constant disputeGameFactoryCode = - hex"6080604052600436106100e85760003560e01c80636593dc6e1161008a57806396cd97201161005957806396cd972014610313578063bb8aa1fc14610333578063c4d66de814610394578063f2fde38b146103b457600080fd5b80636593dc6e14610293578063715018a6146102c057806382ecf2f6146102d55780638da5cb5b146102e857600080fd5b8063254bd683116100c6578063254bd6831461019c5780634d1975b4146101c957806354fd4d50146101e85780635f0150cb1461023e57600080fd5b806314f6b1a3146100ed5780631b685b9e1461010f5780631e3342401461017c575b600080fd5b3480156100f957600080fd5b5061010d6101083660046110c6565b6103d4565b005b34801561011b57600080fd5b5061015261012a3660046110fd565b60656020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561018857600080fd5b5061010d610197366004611118565b61045e565b3480156101a857600080fd5b506101bc6101b7366004611142565b6104aa565b60405161017391906111ef565b3480156101d557600080fd5b506068545b604051908152602001610173565b3480156101f457600080fd5b506102316040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b60405161017391906112ac565b34801561024a57600080fd5b5061025e6102593660046112bf565b6106ee565b6040805173ffffffffffffffffffffffffffffffffffffffff909316835267ffffffffffffffff909116602083015201610173565b34801561029f57600080fd5b506101da6102ae3660046110fd565b60666020526000908152604090205481565b3480156102cc57600080fd5b5061010d610741565b6101526102e33660046112bf565b610755565b3480156102f457600080fd5b5060335473ffffffffffffffffffffffffffffffffffffffff16610152565b34801561031f57600080fd5b506101da61032e3660046112bf565b6109ef565b34801561033f57600080fd5b5061035361034e366004611346565b610a28565b6040805163ffffffff909416845267ffffffffffffffff909216602084015273ffffffffffffffffffffffffffffffffffffffff1690820152606001610173565b3480156103a057600080fd5b5061010d6103af36600461135f565b610a91565b3480156103c057600080fd5b5061010d6103cf36600461135f565b610c2d565b6103dc610d00565b63ffffffff821660008181526065602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8616908117909155905190917fff513d80e2c7fa487608f70a618dfbc0cf415699dc69588c747e8c71566c88de91a35050565b610466610d00565b63ffffffff8216600081815260666020526040808220849055518392917f74d6665c4b26d5596a5aa13d3014e0c06af4d322075a797f87b03cd4c5bc91ca91a35050565b606854606090831015806104bc575081155b6106e7575060408051600583901b8101602001909152825b8381116106e5576000606882815481106104f0576104f061137c565b600091825260209091200154905060e081901c60a082901c67ffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff831663ffffffff891683036106b6576001865101865260008173ffffffffffffffffffffffffffffffffffffffff1663609d33346040518163ffffffff1660e01b8152600401600060405180830381865afa15801561058a573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526105d091908101906113da565b905060008273ffffffffffffffffffffffffffffffffffffffff1663bcef3b556040518163ffffffff1660e01b8152600401602060405180830381865afa15801561061f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064391906114a5565b90506040518060a001604052808881526020018781526020018567ffffffffffffffff168152602001828152602001838152508860018a5161068591906114be565b815181106106955761069561137c565b6020026020010181905250888851106106b3575050505050506106e5565b50505b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90920191506104d49050565b505b9392505050565b60008060006106ff878787876109ef565b60009081526067602052604090205473ffffffffffffffffffffffffffffffffffffffff81169860a09190911c67ffffffffffffffff16975095505050505050565b610749610d00565b6107536000610d81565b565b63ffffffff841660009081526065602052604081205473ffffffffffffffffffffffffffffffffffffffff16806107c5576040517f031c6de400000000000000000000000000000000000000000000000000000000815263ffffffff871660048201526024015b60405180910390fd5b63ffffffff86166000908152606660205260409020543414610813576040517f8620aa1900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006108206001436114be565b40905061088a338783888860405160200161083f9594939291906114fc565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905273ffffffffffffffffffffffffffffffffffffffff841690610df8565b92508273ffffffffffffffffffffffffffffffffffffffff16638129fc1c346040518263ffffffff1660e01b81526004016000604051808303818588803b1580156108d457600080fd5b505af11580156108e8573d6000803e3d6000fd5b505050505060006108fb888888886109ef565b60008181526067602052604090205490915015610947576040517f014f6fe5000000000000000000000000000000000000000000000000000000008152600481018290526024016107bc565b60004260a01b60e08a901b178517600083815260676020526040808220839055606880546001810182559083527fa2153420d844928b4421650203c77babc8b33d7f2e7b450e2966db0c220977530183905551919250899163ffffffff8c169173ffffffffffffffffffffffffffffffffffffffff8916917f5b565efe82411da98814f356d0e7bcb8f0219b8d970307c5afb4a6903a8b2e359190a450505050949350505050565b600084848484604051602001610a089493929190611549565b604051602081830303815290604052805190602001209050949350505050565b600080600080600080610a8160688881548110610a4757610a4761137c565b906000526020600020015460e081901c9160a082901c67ffffffffffffffff169173ffffffffffffffffffffffffffffffffffffffff1690565b9199909850909650945050505050565b600054610100900460ff1615808015610ab15750600054600160ff909116105b80610acb5750303b158015610acb575060005460ff166001145b610b57576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016107bc565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610bb557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610bbd610e06565b610bc682610d81565b8015610c2957600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b610c35610d00565b73ffffffffffffffffffffffffffffffffffffffff8116610cd8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016107bc565b610ce181610d81565b50565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b60335473ffffffffffffffffffffffffffffffffffffffff163314610753576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016107bc565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006106e760008484610ea5565b600054610100900460ff16610e9d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016107bc565b610753610feb565b600060608203516040830351602084035184518060208701018051600283016c5af43d3d93803e606057fd5bf3895289600d8a035278593da1005b363d3d373d3d3d3d610000806062363936013d738160481b1760218a03527f9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff603a8a035272fd6100003d81600a3d39f336602c57343d527f6062820160781b1761ff9e82106059018a03528060f01b8352606c8101604c8a038cf097505086610f715763301164256000526004601cfd5b905285527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08501527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08401527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa09092019190915292915050565b600054610100900460ff16611082576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016107bc565b61075333610d81565b803563ffffffff8116811461109f57600080fd5b919050565b73ffffffffffffffffffffffffffffffffffffffff81168114610ce157600080fd5b600080604083850312156110d957600080fd5b6110e28361108b565b915060208301356110f2816110a4565b809150509250929050565b60006020828403121561110f57600080fd5b6106e78261108b565b6000806040838503121561112b57600080fd5b6111348361108b565b946020939093013593505050565b60008060006060848603121561115757600080fd5b6111608461108b565b95602085013595506040909401359392505050565b60005b83811015611190578181015183820152602001611178565b8381111561119f576000848401525b50505050565b600081518084526111bd816020860160208601611175565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b8381101561129e578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc001855281518051845287810151888501528681015167ffffffffffffffff16878501526060808201519085015260809081015160a09185018290529061128a818601836111a5565b968901969450505090860190600101611216565b509098975050505050505050565b6020815260006106e760208301846111a5565b600080600080606085870312156112d557600080fd5b6112de8561108b565b935060208501359250604085013567ffffffffffffffff8082111561130257600080fd5b818701915087601f83011261131657600080fd5b81358181111561132557600080fd5b88602082850101111561133757600080fd5b95989497505060200194505050565b60006020828403121561135857600080fd5b5035919050565b60006020828403121561137157600080fd5b81356106e7816110a4565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156113ec57600080fd5b815167ffffffffffffffff8082111561140457600080fd5b818401915084601f83011261141857600080fd5b81518181111561142a5761142a6113ab565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611470576114706113ab565b8160405282815287602084870101111561148957600080fd5b61149a836020830160208801611175565b979650505050505050565b6000602082840312156114b757600080fd5b5051919050565b6000828210156114f7577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b500390565b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008660601b1681528460148201528360348201528183605483013760009101605401908152949350505050565b63ffffffff8516815283602082015260606040820152816060820152818360808301376000818301608090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101939250505056fea164736f6c634300080f000a"; + hex"6080604052600436106100e85760003560e01c80636593dc6e1161008a57806396cd97201161005957806396cd972014610313578063bb8aa1fc14610333578063c4d66de814610394578063f2fde38b146103b457600080fd5b80636593dc6e14610293578063715018a6146102c057806382ecf2f6146102d55780638da5cb5b146102e857600080fd5b8063254bd683116100c6578063254bd6831461019c5780634d1975b4146101c957806354fd4d50146101e85780635f0150cb1461023e57600080fd5b806314f6b1a3146100ed5780631b685b9e1461010f5780631e3342401461017c575b600080fd5b3480156100f957600080fd5b5061010d6101083660046110c6565b6103d4565b005b34801561011b57600080fd5b5061015261012a3660046110fd565b60656020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561018857600080fd5b5061010d610197366004611118565b61045e565b3480156101a857600080fd5b506101bc6101b7366004611142565b6104aa565b60405161017391906111ef565b3480156101d557600080fd5b506068545b604051908152602001610173565b3480156101f457600080fd5b506102316040518060400160405280600c81526020017f312e302e312d626574612e31000000000000000000000000000000000000000081525081565b60405161017391906112ac565b34801561024a57600080fd5b5061025e6102593660046112bf565b6106ee565b6040805173ffffffffffffffffffffffffffffffffffffffff909316835267ffffffffffffffff909116602083015201610173565b34801561029f57600080fd5b506101da6102ae3660046110fd565b60666020526000908152604090205481565b3480156102cc57600080fd5b5061010d610741565b6101526102e33660046112bf565b610755565b3480156102f457600080fd5b5060335473ffffffffffffffffffffffffffffffffffffffff16610152565b34801561031f57600080fd5b506101da61032e3660046112bf565b6109ef565b34801561033f57600080fd5b5061035361034e366004611346565b610a28565b6040805163ffffffff909416845267ffffffffffffffff909216602084015273ffffffffffffffffffffffffffffffffffffffff1690820152606001610173565b3480156103a057600080fd5b5061010d6103af36600461135f565b610a91565b3480156103c057600080fd5b5061010d6103cf36600461135f565b610c2d565b6103dc610d00565b63ffffffff821660008181526065602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8616908117909155905190917fff513d80e2c7fa487608f70a618dfbc0cf415699dc69588c747e8c71566c88de91a35050565b610466610d00565b63ffffffff8216600081815260666020526040808220849055518392917f74d6665c4b26d5596a5aa13d3014e0c06af4d322075a797f87b03cd4c5bc91ca91a35050565b606854606090831015806104bc575081155b6106e7575060408051600583901b8101602001909152825b8381116106e5576000606882815481106104f0576104f061137c565b600091825260209091200154905060e081901c60a082901c67ffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff831663ffffffff891683036106b6576001865101865260008173ffffffffffffffffffffffffffffffffffffffff1663609d33346040518163ffffffff1660e01b8152600401600060405180830381865afa15801561058a573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526105d091908101906113da565b905060008273ffffffffffffffffffffffffffffffffffffffff1663bcef3b556040518163ffffffff1660e01b8152600401602060405180830381865afa15801561061f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064391906114a5565b90506040518060a001604052808881526020018781526020018567ffffffffffffffff168152602001828152602001838152508860018a5161068591906114be565b815181106106955761069561137c565b6020026020010181905250888851106106b3575050505050506106e5565b50505b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90920191506104d49050565b505b9392505050565b60008060006106ff878787876109ef565b60009081526067602052604090205473ffffffffffffffffffffffffffffffffffffffff81169860a09190911c67ffffffffffffffff16975095505050505050565b610749610d00565b6107536000610d81565b565b63ffffffff841660009081526065602052604081205473ffffffffffffffffffffffffffffffffffffffff16806107c5576040517f031c6de400000000000000000000000000000000000000000000000000000000815263ffffffff871660048201526024015b60405180910390fd5b63ffffffff86166000908152606660205260409020543414610813576040517f8620aa1900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006108206001436114be565b40905061088a338783888860405160200161083f9594939291906114fc565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905273ffffffffffffffffffffffffffffffffffffffff841690610df8565b92508273ffffffffffffffffffffffffffffffffffffffff16638129fc1c346040518263ffffffff1660e01b81526004016000604051808303818588803b1580156108d457600080fd5b505af11580156108e8573d6000803e3d6000fd5b505050505060006108fb888888886109ef565b60008181526067602052604090205490915015610947576040517f014f6fe5000000000000000000000000000000000000000000000000000000008152600481018290526024016107bc565b60004260a01b60e08a901b178517600083815260676020526040808220839055606880546001810182559083527fa2153420d844928b4421650203c77babc8b33d7f2e7b450e2966db0c220977530183905551919250899163ffffffff8c169173ffffffffffffffffffffffffffffffffffffffff8916917f5b565efe82411da98814f356d0e7bcb8f0219b8d970307c5afb4a6903a8b2e359190a450505050949350505050565b600084848484604051602001610a089493929190611549565b604051602081830303815290604052805190602001209050949350505050565b600080600080600080610a8160688881548110610a4757610a4761137c565b906000526020600020015460e081901c9160a082901c67ffffffffffffffff169173ffffffffffffffffffffffffffffffffffffffff1690565b9199909850909650945050505050565b600054610100900460ff1615808015610ab15750600054600160ff909116105b80610acb5750303b158015610acb575060005460ff166001145b610b57576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016107bc565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610bb557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610bbd610e06565b610bc682610d81565b8015610c2957600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b610c35610d00565b73ffffffffffffffffffffffffffffffffffffffff8116610cd8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016107bc565b610ce181610d81565b50565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b60335473ffffffffffffffffffffffffffffffffffffffff163314610753576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016107bc565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006106e760008484610ea5565b600054610100900460ff16610e9d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016107bc565b610753610feb565b600060608203516040830351602084035184518060208701018051600283016c5af43d3d93803e606057fd5bf3895289600d8a035278593da1005b363d3d373d3d3d3d610000806062363936013d738160481b1760218a03527f9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff603a8a035272fd6100003d81600a3d39f336602c57343d527f6062820160781b1761ff9e82106059018a03528060f01b8352606c8101604c8a038cf097505086610f715763301164256000526004601cfd5b905285527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08501527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08401527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa09092019190915292915050565b600054610100900460ff16611082576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016107bc565b61075333610d81565b803563ffffffff8116811461109f57600080fd5b919050565b73ffffffffffffffffffffffffffffffffffffffff81168114610ce157600080fd5b600080604083850312156110d957600080fd5b6110e28361108b565b915060208301356110f2816110a4565b809150509250929050565b60006020828403121561110f57600080fd5b6106e78261108b565b6000806040838503121561112b57600080fd5b6111348361108b565b946020939093013593505050565b60008060006060848603121561115757600080fd5b6111608461108b565b95602085013595506040909401359392505050565b60005b83811015611190578181015183820152602001611178565b8381111561119f576000848401525b50505050565b600081518084526111bd816020860160208601611175565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b8381101561129e578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc001855281518051845287810151888501528681015167ffffffffffffffff16878501526060808201519085015260809081015160a09185018290529061128a818601836111a5565b968901969450505090860190600101611216565b509098975050505050505050565b6020815260006106e760208301846111a5565b600080600080606085870312156112d557600080fd5b6112de8561108b565b935060208501359250604085013567ffffffffffffffff8082111561130257600080fd5b818701915087601f83011261131657600080fd5b81358181111561132557600080fd5b88602082850101111561133757600080fd5b95989497505060200194505050565b60006020828403121561135857600080fd5b5035919050565b60006020828403121561137157600080fd5b81356106e7816110a4565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156113ec57600080fd5b815167ffffffffffffffff8082111561140457600080fd5b818401915084601f83011261141857600080fd5b81518181111561142a5761142a6113ab565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611470576114706113ab565b8160405282815287602084870101111561148957600080fd5b61149a836020830160208801611175565b979650505050505050565b6000602082840312156114b757600080fd5b5051919050565b6000828210156114f7577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b500390565b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008660601b1681528460148201528360348201528183605483013760009101605401908152949350505050565b63ffffffff8516815283602082015260606040820152816060820152818360808301376000818301608090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101939250505056fea164736f6c634300080f000a"; bytes internal constant delayedWETHCode = - hex"6080604052600436106101845760003560e01c8063715018a6116100d6578063a9059cbb1161007f578063dd62ed3e11610059578063dd62ed3e1461051c578063f2fde38b14610554578063f3fef3a31461057457610193565b8063a9059cbb146104a8578063cd47bde1146104c8578063d0e30db01461019357610193565b80638da5cb5b116100b05780638da5cb5b1461041757806395d89b4114610442578063977a5ec51461048857610193565b8063715018a61461039057806379502c55146103a55780637eee288d146103f757610193565b80632e1a7d4d1161013857806354fd4d501161011257806354fd4d50146102e75780636a42b8f81461033057806370a082311461036357610193565b80632e1a7d4d14610280578063313ce567146102a0578063485cc955146102c757610193565b80630ca35682116101695780630ca356821461022357806318160ddd1461024357806323b872dd1461026057610193565b806306fdde031461019b578063095ea7b3146101f357610193565b3661019357610191610594565b005b610191610594565b3480156101a757600080fd5b5060408051808201909152600d81527f577261707065642045746865720000000000000000000000000000000000000060208201525b6040516101ea91906113fd565b60405180910390f35b3480156101ff57600080fd5b5061021361020e366004611492565b6105ef565b60405190151581526020016101ea565b34801561022f57600080fd5b5061019161023e3660046114be565b610668565b34801561024f57600080fd5b50475b6040519081526020016101ea565b34801561026c57600080fd5b5061021361027b3660046114d7565b6107b9565b34801561028c57600080fd5b5061019161029b3660046114be565b6109d0565b3480156102ac57600080fd5b506102b5601281565b60405160ff90911681526020016101ea565b3480156102d357600080fd5b506101916102e2366004611518565b6109dd565b3480156102f357600080fd5b506101dd6040518060400160405280600a81526020017f312e312e302d72632e310000000000000000000000000000000000000000000081525081565b34801561033c57600080fd5b507f0000000000000000000000000000000000000000000000000000000000093a80610252565b34801561036f57600080fd5b5061025261037e366004611551565b60656020526000908152604090205481565b34801561039c57600080fd5b50610191610bb9565b3480156103b157600080fd5b506068546103d29073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101ea565b34801561040357600080fd5b50610191610412366004611492565b610bcd565b34801561042357600080fd5b5060335473ffffffffffffffffffffffffffffffffffffffff166103d2565b34801561044e57600080fd5b5060408051808201909152600481527f574554480000000000000000000000000000000000000000000000000000000060208201526101dd565b34801561049457600080fd5b506101916104a3366004611492565b610c21565b3480156104b457600080fd5b506102136104c3366004611492565b610d0e565b3480156104d457600080fd5b506105076104e3366004611518565b60676020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016101ea565b34801561052857600080fd5b50610252610537366004611518565b606660209081526000928352604080842090915290825290205481565b34801561056057600080fd5b5061019161056f366004611551565b610d22565b34801561058057600080fd5b5061019161058f366004611492565b610dd6565b33600090815260656020526040812080543492906105b390849061159d565b909155505060405134815233907fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9060200160405180910390a2565b33600081815260666020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906106579086815260200190565b60405180910390a350600192915050565b60335473ffffffffffffffffffffffffffffffffffffffff1633146106ee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f44656c61796564574554483a206e6f74206f776e65720000000000000000000060448201526064015b60405180910390fd5b60004782106106fd57476106ff565b815b604051909150600090339083908381818185875af1925050503d8060008114610744576040519150601f19603f3d011682016040523d82523d6000602084013e610749565b606091505b50509050806107b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f44656c61796564574554483a207265636f766572206661696c6564000000000060448201526064016106e5565b505050565b73ffffffffffffffffffffffffffffffffffffffff83166000908152606560205260408120548211156107eb57600080fd5b73ffffffffffffffffffffffffffffffffffffffff84163314801590610861575073ffffffffffffffffffffffffffffffffffffffff841660009081526066602090815260408083203384529091529020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14155b156108e95773ffffffffffffffffffffffffffffffffffffffff841660009081526066602090815260408083203384529091529020548211156108a357600080fd5b73ffffffffffffffffffffffffffffffffffffffff84166000908152606660209081526040808320338452909152812080548492906108e39084906115b5565b90915550505b73ffffffffffffffffffffffffffffffffffffffff84166000908152606560205260408120805484929061091e9084906115b5565b909155505073ffffffffffffffffffffffffffffffffffffffff83166000908152606560205260408120805484929061095890849061159d565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516109be91815260200190565b60405180910390a35060019392505050565b6109da3382610dd6565b50565b600054610100900460ff16158080156109fd5750600054600160ff909116105b80610a175750303b158015610a17575060005460ff166001145b610aa3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016106e5565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610b0157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610b09611120565b610b12836111bf565b606880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff841617905580156107b457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a1505050565b610bc1611236565b610bcb60006111bf565b565b33600090815260676020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091528120426001820155805490918391839190610c1790849061159d565b9091555050505050565b60335473ffffffffffffffffffffffffffffffffffffffff163314610ca2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f44656c61796564574554483a206e6f74206f776e65720000000000000000000060448201526064016106e5565b73ffffffffffffffffffffffffffffffffffffffff821660008181526066602090815260408083203380855290835292819020859055518481529192917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a35050565b6000610d1b3384846107b9565b9392505050565b610d2a611236565b73ffffffffffffffffffffffffffffffffffffffff8116610dcd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016106e5565b6109da816111bf565b606860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e6791906115cc565b15610ece576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f44656c61796564574554483a20636f6e7472616374206973207061757365640060448201526064016106e5565b33600090815260676020908152604080832073ffffffffffffffffffffffffffffffffffffffff8616845290915290208054821115610f8f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f44656c61796564574554483a20696e73756666696369656e7420756e6c6f636b60448201527f6564207769746864726177616c0000000000000000000000000000000000000060648201526084016106e5565b6000816001015411611022576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f44656c61796564574554483a207769746864726177616c206e6f7420756e6c6f60448201527f636b65640000000000000000000000000000000000000000000000000000000060648201526084016106e5565b427f0000000000000000000000000000000000000000000000000000000000093a808260010154611053919061159d565b11156110e1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f44656c61796564574554483a207769746864726177616c2064656c6179206e6f60448201527f74206d657400000000000000000000000000000000000000000000000000000060648201526084016106e5565b818160000160008282546110f591906115b5565b909155506107b49050826112b7565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b600054610100900460ff166111b7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016106e5565b610bcb61135d565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60335473ffffffffffffffffffffffffffffffffffffffff163314610bcb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106e5565b336000908152606560205260409020548111156112d357600080fd5b33600090815260656020526040812080548392906112f29084906115b5565b9091555050604051339082156108fc029083906000818181858888f19350505050158015611324573d6000803e3d6000fd5b5060405181815233907f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b659060200160405180910390a250565b600054610100900460ff166113f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016106e5565b610bcb336111bf565b600060208083528351808285015260005b8181101561142a5785810183015185820160400152820161140e565b8181111561143c576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b73ffffffffffffffffffffffffffffffffffffffff811681146109da57600080fd5b600080604083850312156114a557600080fd5b82356114b081611470565b946020939093013593505050565b6000602082840312156114d057600080fd5b5035919050565b6000806000606084860312156114ec57600080fd5b83356114f781611470565b9250602084013561150781611470565b929592945050506040919091013590565b6000806040838503121561152b57600080fd5b823561153681611470565b9150602083013561154681611470565b809150509250929050565b60006020828403121561156357600080fd5b8135610d1b81611470565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156115b0576115b061156e565b500190565b6000828210156115c7576115c761156e565b500390565b6000602082840312156115de57600080fd5b81518015158114610d1b57600080fdfea164736f6c634300080f000a"; + hex"6080604052600436106101845760003560e01c8063715018a6116100d6578063a9059cbb1161007f578063dd62ed3e11610059578063dd62ed3e1461051c578063f2fde38b14610554578063f3fef3a31461057457610193565b8063a9059cbb146104a8578063cd47bde1146104c8578063d0e30db01461019357610193565b80638da5cb5b116100b05780638da5cb5b1461041757806395d89b4114610442578063977a5ec51461048857610193565b8063715018a61461039057806379502c55146103a55780637eee288d146103f757610193565b80632e1a7d4d1161013857806354fd4d501161011257806354fd4d50146102e75780636a42b8f81461033057806370a082311461036357610193565b80632e1a7d4d14610280578063313ce567146102a0578063485cc955146102c757610193565b80630ca35682116101695780630ca356821461022357806318160ddd1461024357806323b872dd1461026057610193565b806306fdde031461019b578063095ea7b3146101f357610193565b3661019357610191610594565b005b610191610594565b3480156101a757600080fd5b5060408051808201909152600d81527f577261707065642045746865720000000000000000000000000000000000000060208201525b6040516101ea91906113fd565b60405180910390f35b3480156101ff57600080fd5b5061021361020e366004611492565b6105ef565b60405190151581526020016101ea565b34801561022f57600080fd5b5061019161023e3660046114be565b610668565b34801561024f57600080fd5b50475b6040519081526020016101ea565b34801561026c57600080fd5b5061021361027b3660046114d7565b6107b9565b34801561028c57600080fd5b5061019161029b3660046114be565b6109d0565b3480156102ac57600080fd5b506102b5601281565b60405160ff90911681526020016101ea565b3480156102d357600080fd5b506101916102e2366004611518565b6109dd565b3480156102f357600080fd5b506101dd6040518060400160405280600c81526020017f312e312e312d626574612e32000000000000000000000000000000000000000081525081565b34801561033c57600080fd5b507f0000000000000000000000000000000000000000000000000000000000093a80610252565b34801561036f57600080fd5b5061025261037e366004611551565b60656020526000908152604090205481565b34801561039c57600080fd5b50610191610bb9565b3480156103b157600080fd5b506068546103d29073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101ea565b34801561040357600080fd5b50610191610412366004611492565b610bcd565b34801561042357600080fd5b5060335473ffffffffffffffffffffffffffffffffffffffff166103d2565b34801561044e57600080fd5b5060408051808201909152600481527f574554480000000000000000000000000000000000000000000000000000000060208201526101dd565b34801561049457600080fd5b506101916104a3366004611492565b610c21565b3480156104b457600080fd5b506102136104c3366004611492565b610d0e565b3480156104d457600080fd5b506105076104e3366004611518565b60676020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016101ea565b34801561052857600080fd5b50610252610537366004611518565b606660209081526000928352604080842090915290825290205481565b34801561056057600080fd5b5061019161056f366004611551565b610d22565b34801561058057600080fd5b5061019161058f366004611492565b610dd6565b33600090815260656020526040812080543492906105b390849061159d565b909155505060405134815233907fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9060200160405180910390a2565b33600081815260666020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906106579086815260200190565b60405180910390a350600192915050565b60335473ffffffffffffffffffffffffffffffffffffffff1633146106ee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f44656c61796564574554483a206e6f74206f776e65720000000000000000000060448201526064015b60405180910390fd5b60004782106106fd57476106ff565b815b604051909150600090339083908381818185875af1925050503d8060008114610744576040519150601f19603f3d011682016040523d82523d6000602084013e610749565b606091505b50509050806107b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f44656c61796564574554483a207265636f766572206661696c6564000000000060448201526064016106e5565b505050565b73ffffffffffffffffffffffffffffffffffffffff83166000908152606560205260408120548211156107eb57600080fd5b73ffffffffffffffffffffffffffffffffffffffff84163314801590610861575073ffffffffffffffffffffffffffffffffffffffff841660009081526066602090815260408083203384529091529020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14155b156108e95773ffffffffffffffffffffffffffffffffffffffff841660009081526066602090815260408083203384529091529020548211156108a357600080fd5b73ffffffffffffffffffffffffffffffffffffffff84166000908152606660209081526040808320338452909152812080548492906108e39084906115b5565b90915550505b73ffffffffffffffffffffffffffffffffffffffff84166000908152606560205260408120805484929061091e9084906115b5565b909155505073ffffffffffffffffffffffffffffffffffffffff83166000908152606560205260408120805484929061095890849061159d565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516109be91815260200190565b60405180910390a35060019392505050565b6109da3382610dd6565b50565b600054610100900460ff16158080156109fd5750600054600160ff909116105b80610a175750303b158015610a17575060005460ff166001145b610aa3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016106e5565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610b0157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610b09611120565b610b12836111bf565b606880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff841617905580156107b457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a1505050565b610bc1611236565b610bcb60006111bf565b565b33600090815260676020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091528120426001820155805490918391839190610c1790849061159d565b9091555050505050565b60335473ffffffffffffffffffffffffffffffffffffffff163314610ca2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f44656c61796564574554483a206e6f74206f776e65720000000000000000000060448201526064016106e5565b73ffffffffffffffffffffffffffffffffffffffff821660008181526066602090815260408083203380855290835292819020859055518481529192917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a35050565b6000610d1b3384846107b9565b9392505050565b610d2a611236565b73ffffffffffffffffffffffffffffffffffffffff8116610dcd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016106e5565b6109da816111bf565b606860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e6791906115cc565b15610ece576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f44656c61796564574554483a20636f6e7472616374206973207061757365640060448201526064016106e5565b33600090815260676020908152604080832073ffffffffffffffffffffffffffffffffffffffff8616845290915290208054821115610f8f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f44656c61796564574554483a20696e73756666696369656e7420756e6c6f636b60448201527f6564207769746864726177616c0000000000000000000000000000000000000060648201526084016106e5565b6000816001015411611022576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f44656c61796564574554483a207769746864726177616c206e6f7420756e6c6f60448201527f636b65640000000000000000000000000000000000000000000000000000000060648201526084016106e5565b427f0000000000000000000000000000000000000000000000000000000000093a808260010154611053919061159d565b11156110e1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f44656c61796564574554483a207769746864726177616c2064656c6179206e6f60448201527f74206d657400000000000000000000000000000000000000000000000000000060648201526084016106e5565b818160000160008282546110f591906115b5565b909155506107b49050826112b7565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b600054610100900460ff166111b7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016106e5565b610bcb61135d565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60335473ffffffffffffffffffffffffffffffffffffffff163314610bcb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106e5565b336000908152606560205260409020548111156112d357600080fd5b33600090815260656020526040812080548392906112f29084906115b5565b9091555050604051339082156108fc029083906000818181858888f19350505050158015611324573d6000803e3d6000fd5b5060405181815233907f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b659060200160405180910390a250565b600054610100900460ff166113f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016106e5565b610bcb336111bf565b600060208083528351808285015260005b8181101561142a5785810183015185820160400152820161140e565b8181111561143c576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b73ffffffffffffffffffffffffffffffffffffffff811681146109da57600080fd5b600080604083850312156114a557600080fd5b82356114b081611470565b946020939093013593505050565b6000602082840312156114d057600080fd5b5035919050565b6000806000606084860312156114ec57600080fd5b83356114f781611470565b9250602084013561150781611470565b929592945050506040919091013590565b6000806040838503121561152b57600080fd5b823561153681611470565b9150602083013561154681611470565b809150509250929050565b60006020828403121561156357600080fd5b8135610d1b81611470565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156115b0576115b061156e565b500190565b6000828210156115c7576115c761156e565b500390565b6000602082840312156115de57600080fd5b81518015158114610d1b57600080fdfea164736f6c634300080f000a"; bytes internal constant preimageOracleCode = - hex"6080604052600436106101d85760003560e01c80639d53a64811610102578063ddcd58de11610095578063ec5efcbc11610064578063ec5efcbc14610681578063f3f480d9146106a1578063faf37bc7146106d4578063fef2b4ed146106e757600080fd5b8063ddcd58de146105d4578063e03110e11461060c578063e159261114610641578063ea7139501461066157600080fd5b8063b5e7154c116100d1578063b5e7154c14610555578063d18534b51461056c578063da35c6641461058c578063dd24f9bf146105a157600080fd5b80639d53a6481461048e5780639d7e8769146104dd578063b2e67ba8146104fd578063b4801e611461053557600080fd5b806361238bde1161017a5780637ac54767116101495780637ac54767146103ca5780638542cf50146103ea578063882856ef146104355780638dc4be111461046e57600080fd5b806361238bde1461031e5780636551927b146103565780637051472e1461038e5780637917de1d146103aa57600080fd5b80633909af5c116101b65780633909af5c146102715780634d52b4c91461029357806352f0f3ad146102a857806354fd4d50146102c857600080fd5b8063013cf08b146101dd5780630359a5631461022e5780632055b36b1461025c575b600080fd5b3480156101e957600080fd5b506101fd6101f8366004612e29565b610714565b6040805173ffffffffffffffffffffffffffffffffffffffff90931683526020830191909152015b60405180910390f35b34801561023a57600080fd5b5061024e610249366004612e6b565b610759565b604051908152602001610225565b34801561026857600080fd5b5061024e601081565b34801561027d57600080fd5b5061029161028c366004613073565b610891565b005b34801561029f57600080fd5b5061024e610ae8565b3480156102b457600080fd5b5061024e6102c336600461315f565b610b03565b3480156102d457600080fd5b506103116040518060400160405280600a81526020017f312e312e322d72632e310000000000000000000000000000000000000000000081525081565b60405161022591906131c6565b34801561032a57600080fd5b5061024e610339366004613217565b600160209081526000928352604080842090915290825290205481565b34801561036257600080fd5b5061024e610371366004612e6b565b601560209081526000928352604080842090915290825290205481565b34801561039a57600080fd5b5061024e6703782dace9d9000081565b3480156103b657600080fd5b506102916103c536600461327b565b610bd9565b3480156103d657600080fd5b5061024e6103e5366004612e29565b6110dc565b3480156103f657600080fd5b50610425610405366004613217565b600260209081526000928352604080842090915290825290205460ff1681565b6040519015158152602001610225565b34801561044157600080fd5b50610455610450366004613317565b6110f3565b60405167ffffffffffffffff9091168152602001610225565b34801561047a57600080fd5b5061029161048936600461334a565b61114d565b34801561049a57600080fd5b5061024e6104a9366004612e6b565b73ffffffffffffffffffffffffffffffffffffffff9091166000908152601860209081526040808320938352929052205490565b3480156104e957600080fd5b506102916104f8366004613396565b611248565b34801561050957600080fd5b5061024e610518366004612e6b565b601760209081526000928352604080842090915290825290205481565b34801561054157600080fd5b5061024e610550366004613317565b6113ff565b34801561056157600080fd5b5061024e620186a081565b34801561057857600080fd5b50610291610587366004613073565b611431565b34801561059857600080fd5b5060135461024e565b3480156105ad57600080fd5b507f000000000000000000000000000000000000000000000000000000000000271061024e565b3480156105e057600080fd5b5061024e6105ef366004612e6b565b601660209081526000928352604080842090915290825290205481565b34801561061857600080fd5b5061062c610627366004613217565b611840565b60408051928352602083019190915201610225565b34801561064d57600080fd5b5061029161065c36600461334a565b611931565b34801561066d57600080fd5b5061029161067c366004613422565b611a39565b34801561068d57600080fd5b5061029161069c366004613491565b611b98565b3480156106ad57600080fd5b507f000000000000000000000000000000000000000000000000000000000000007861024e565b6102916106e2366004613519565b611d1e565b3480156106f357600080fd5b5061024e610702366004612e29565b60006020819052908152604090205481565b6013818154811061072457600080fd5b60009182526020909120600290910201805460019091015473ffffffffffffffffffffffffffffffffffffffff909116915082565b73ffffffffffffffffffffffffffffffffffffffff82166000908152601560209081526040808320848452909152812054819061079c9060601c63ffffffff1690565b63ffffffff16905060005b6010811015610889578160011660010361082f5773ffffffffffffffffffffffffffffffffffffffff85166000908152601460209081526040808320878452909152902081601081106107fc576107fc613555565b01546040805160208101929092528101849052606001604051602081830303815290604052805190602001209250610870565b826003826010811061084357610843613555565b01546040805160208101939093528201526060016040516020818303038152906040528051906020012092505b60019190911c9080610881816135b3565b9150506107a7565b505092915050565b600061089d8a8a610759565b90506108c086868360208b01356108bb6108b68d6135eb565b611fea565b61202a565b80156108de57506108de83838360208801356108bb6108b68a6135eb565b610914576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b86604001358860405160200161092a91906136ba565b6040516020818303038152906040528051906020012014610977576040517f1968a90200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83602001358760200135600161098d91906136f8565b146109c4576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a0c886109d28680613710565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061208b92505050565b610a15886121e6565b836040013588604051602001610a2b91906136ba565b6040516020818303038152906040528051906020012003610a78576040517f9843145b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8a1660009081526015602090815260408083208c8452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000166001179055610adc8a8a3361298e565b50505050505050505050565b6001610af660106002613897565b610b0091906138a3565b81565b6000610b0f8686612a47565b9050610b1c8360086136f8565b82101580610b2a5750602083115b15610b61576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000602081815260c085901b82526008959095528251828252600286526040808320858452875280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558484528752808320948352938652838220558181529384905292205592915050565b60608115610bf257610beb8686612af4565b9050610c2c565b85858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050505b3360009081526014602090815260408083208b845290915280822081516102008101928390529160109082845b815481526020019060010190808311610c5957505050505090506000601560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008b81526020019081526020016000205490506000610cda8260601c63ffffffff1690565b63ffffffff169050333214610d1b576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d2b8260801c63ffffffff1690565b63ffffffff16600003610d6a576040517f87138d5c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d748260c01c90565b67ffffffffffffffff1615610db5576040517f475a253500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b898114610dee576040517f60f95d5a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610dfb89898d8886612b6d565b83516020850160888204881415608883061715610e20576307b1daf16000526004601cfd5b60405160c8810160405260005b83811015610ed0578083018051835260208101516020840152604081015160408401526060810151606084015260808101516080840152508460888301526088810460051b8b013560a883015260c882206001860195508560005b610200811015610ec5576001821615610ea55782818b0152610ec5565b8981015160009081526020938452604090209260019290921c9101610e88565b505050608801610e2d565b50505050600160106002610ee49190613897565b610eee91906138a3565b811115610f27576040517f6229572300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f9c610f3a8360401c63ffffffff1690565b610f4a9063ffffffff168a6136f8565b60401b7fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff606084901b167fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff8516171790565b915084156110295777ffffffffffffffffffffffffffffffffffffffffffffffff82164260c01b179150610fd68260801c63ffffffff1690565b63ffffffff16610fec8360401c63ffffffff1690565b63ffffffff1614611029576040517f7b1dafd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360009081526014602090815260408083208e8452909152902061104f90846010612d9f565b503360008181526018602090815260408083208f8452825280832080546001810182559084528284206004820401805460039092166008026101000a67ffffffffffffffff818102199093164390931602919091179055838352601582528083208f8452909152812084905560609190911b81523690601437366014016000a05050505050505050505050565b600381601081106110ec57600080fd5b0154905081565b6018602052826000526040600020602052816000526040600020818154811061111b57600080fd5b906000526020600020906004918282040191900660080292509250509054906101000a900467ffffffffffffffff1681565b60443560008060088301861061116b5763fe2549876000526004601cfd5b60c083901b60805260888386823786600882030151915060206000858360025afa90508061119857600080fd5b50600080517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0400000000000000000000000000000000000000000000000000000000000000178082526002602090815260408084208a8552825280842080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558385528252808420998452988152888320939093558152908190529490942055505050565b600080603087600037602060006030600060025afa806112705763f91129696000526004601cfd5b6000517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f010000000000000000000000000000000000000000000000000000000000000017608081815260a08c905260c08b905260308a60e037603088609083013760008060c083600a5afa9250826112f2576309bde3396000526004601cfd5b602886106113085763fe2549876000526004601cfd5b6000602882015278200000000000000000000000000000000000000000000000008152600881018b905285810151935060308a8237603081019b909b52505060509098207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0500000000000000000000000000000000000000000000000000000000000000176000818152600260209081526040808320868452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845282528083209583529481528482209a909a559081528089529190912096909655505050505050565b6014602052826000526040600020602052816000526040600020816010811061142757600080fd5b0154925083915050565b73ffffffffffffffffffffffffffffffffffffffff891660009081526015602090815260408083208b845290915290205467ffffffffffffffff8116156114a4576040517fc334f06900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6114ae8160c01c90565b67ffffffffffffffff166000036114f1576040517f55d4cbf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000007861151c8260c01c90565b6115309067ffffffffffffffff16426138a3565b11611567576040517f55d4cbf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006115738b8b610759565b905061158c87878360208c01356108bb6108b68e6135eb565b80156115aa57506115aa84848360208901356108bb6108b68b6135eb565b6115e0576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8760400135896040516020016115f691906136ba565b6040516020818303038152906040528051906020012014611643576040517f1968a90200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84602001358860200135600161165991906136f8565b14158061168b575060016116738360601c63ffffffff1690565b61167d91906138ba565b63ffffffff16856020013514155b156116c2576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6116d0896109d28780613710565b6116d9896121e6565b60006116e48a612cc0565b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0200000000000000000000000000000000000000000000000000000000000000179050600061173b8460a01c63ffffffff1690565b67ffffffffffffffff169050600160026000848152602001908152602001600020600083815260200190815260200160002060006101000a81548160ff021916908315150217905550601760008e73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008d8152602001908152602001600020546001600084815260200190815260200160002060008381526020019081526020016000208190555061180d8460801c63ffffffff1690565b600083815260208190526040902063ffffffff9190911690556118318d8d8161298e565b50505050505050505050505050565b6000828152600260209081526040808320848452909152812054819060ff166118c9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f7072652d696d616765206d757374206578697374000000000000000000000000604482015260640160405180910390fd5b50600083815260208181526040909120546118e58160086136f8565b6118f08560206136f8565b1061190e57836119018260086136f8565b61190b91906138a3565b91505b506000938452600160209081526040808620948652939052919092205492909150565b60443560008060088301861061194f5763fe2549876000526004601cfd5b60c083901b6080526088838682378087017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80151908490207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f02000000000000000000000000000000000000000000000000000000000000001760008181526002602090815260408083208b8452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845282528083209a83529981528982209390935590815290819052959095209190915550505050565b60008060008060808860601b81528760c01b6014820152858782601c0137601c860181207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0600000000000000000000000000000000000000000000000000000000000000179350604088026260216001603f5a021015611ac35763dd629f866000526004601cfd5b6000808783601c018c5afa94503d6001019150600882018a10611aee5763fe2549876000526004601cfd5b60c082901b81526008018481533d6000600183013e89017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8015160008481526002602090815260408083208d8452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915587845282528083209c83529b81528b8220929092559384528390529790912096909655505050505050565b6000611ba48686610759565b9050611bbd83838360208801356108bb6108b68a6135eb565b611bf3576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602084013515611c2f576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611c37612ddd565b611c45816109d28780613710565b611c4e816121e6565b846040013581604051602001611c6491906136ba565b6040516020818303038152906040528051906020012003611cb1576040517f9843145b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff87166000908152601560209081526040808320898452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000166001179055611d1587873361298e565b50505050505050565b6703782dace9d90000341015611d60576040517fe92c469f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b333214611d99576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611da48160086138df565b63ffffffff168263ffffffff1610611de8576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000027108163ffffffff161015611e48576040517f7b1dafd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152601560209081526040808320868452909152902054611e738160801c63ffffffff1690565b63ffffffff1615611eb0576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b608082901b7fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff60a085901b167fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff83161717336000818152601560209081526040808320898452825280832094909455835180850185528381528082018981526013805460018101825590855291517f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a090600290930292830180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909216919091179055517f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a0919091015591815260168252828120968152959052909320349055505050565b600081600001518260200151836040015160405160200161200d93929190613907565b604051602081830303815290604052805190602001209050919050565b60008160005b601081101561207e578060051b880135600186831c16600181146120635760008481526020839052604090209350612074565b600082815260208590526040902093505b5050600101612030565b5090931495945050505050565b608881511461209957600080fd5b602081016020830161211a565b8260031b8201518060001a8160011a60081b178160021a60101b8260031a60181b17178160041a60201b8260051a60281b178260061a60301b8360071a60381b1717179050612114816120ff868560059190911b015190565b1867ffffffffffffffff16600586901b840152565b50505050565b612126600083836120a6565b612132600183836120a6565b61213e600283836120a6565b61214a600383836120a6565b612156600483836120a6565b612162600583836120a6565b61216e600683836120a6565b61217a600783836120a6565b612186600883836120a6565b612192600983836120a6565b61219e600a83836120a6565b6121aa600b83836120a6565b6121b6600c83836120a6565b6121c2600d83836120a6565b6121ce600e83836120a6565b6121da600f83836120a6565b612114601083836120a6565b6040805178010000000000008082800000000000808a8000000080008000602082015279808b00000000800000018000000080008081800000000000800991810191909152788a00000000000000880000000080008009000000008000000a60608201527b8000808b800000000000008b8000000000008089800000000000800360808201527f80000000000080028000000000000080000000000000800a800000008000000a60a08201527f800000008000808180000000000080800000000080000001800000008000800860c082015260009060e0016040516020818303038152906040529050602082016020820161286e565b6102808101516101e082015161014083015160a0840151845118189118186102a082015161020083015161016084015160c0850151602086015118189118186102c083015161022084015161018085015160e0860151604087015118189118186102e08401516102408501516101a0860151610100870151606088015118189118186103008501516102608601516101c0870151610120880151608089015118189118188084603f1c6123998660011b67ffffffffffffffff1690565b18188584603f1c6123b48660011b67ffffffffffffffff1690565b18188584603f1c6123cf8660011b67ffffffffffffffff1690565b181895508483603f1c6123ec8560011b67ffffffffffffffff1690565b181894508387603f1c6124098960011b67ffffffffffffffff1690565b60208b01518b51861867ffffffffffffffff168c5291189190911897508118600181901b603f9190911c18935060c08801518118601481901c602c9190911b1867ffffffffffffffff1660208901526101208801518718602c81901c60149190911b1867ffffffffffffffff1660c08901526102c08801518618600381901c603d9190911b1867ffffffffffffffff166101208901526101c08801518718601981901c60279190911b1867ffffffffffffffff166102c08901526102808801518218602e81901c60129190911b1867ffffffffffffffff166101c089015260408801518618600281901c603e9190911b1867ffffffffffffffff166102808901526101808801518618601581901c602b9190911b1867ffffffffffffffff1660408901526101a08801518518602781901c60199190911b1867ffffffffffffffff166101808901526102608801518718603881901c60089190911b1867ffffffffffffffff166101a08901526102e08801518518600881901c60389190911b1867ffffffffffffffff166102608901526101e08801518218601781901c60299190911b1867ffffffffffffffff166102e089015260808801518718602581901c601b9190911b1867ffffffffffffffff166101e08901526103008801518718603281901c600e9190911b1867ffffffffffffffff1660808901526102a08801518118603e81901c60029190911b1867ffffffffffffffff166103008901526101008801518518600981901c60379190911b1867ffffffffffffffff166102a08901526102008801518118601381901c602d9190911b1867ffffffffffffffff1661010089015260a08801518218601c81901c60249190911b1867ffffffffffffffff1661020089015260608801518518602481901c601c9190911b1867ffffffffffffffff1660a08901526102408801518518602b81901c60159190911b1867ffffffffffffffff1660608901526102208801518618603181901c600f9190911b1867ffffffffffffffff166102408901526101608801518118603681901c600a9190911b1867ffffffffffffffff166102208901525060e08701518518603a81901c60069190911b1867ffffffffffffffff166101608801526101408701518118603d81901c60039190911b1867ffffffffffffffff1660e0880152505067ffffffffffffffff81166101408601525b5050505050565b600582811b8201805160018501831b8401805160028701851b8601805160038901871b8801805160048b0190981b8901805167ffffffffffffffff861985168918811690995283198a16861889169096528819861683188816909352841986168818871690528419831684189095169052919391929190611d15565b612808600082612781565b612813600582612781565b61281e600a82612781565b612829600f82612781565b612834601482612781565b50565b612840816122dc565b612849816127fd565b600383901b820151815160c09190911c9061211490821867ffffffffffffffff168352565b61287a60008284612837565b61288660018284612837565b61289260028284612837565b61289e60038284612837565b6128aa60048284612837565b6128b660058284612837565b6128c260068284612837565b6128ce60078284612837565b6128da60088284612837565b6128e660098284612837565b6128f2600a8284612837565b6128fe600b8284612837565b61290a600c8284612837565b612916600d8284612837565b612922600e8284612837565b61292e600f8284612837565b61293a60108284612837565b61294660118284612837565b61295260128284612837565b61295e60138284612837565b61296a60148284612837565b61297660158284612837565b61298260168284612837565b61211460178284612837565b73ffffffffffffffffffffffffffffffffffffffff83811660009081526016602090815260408083208684529091528082208054908390559051909284169083908381818185875af1925050503d8060008114612a07576040519150601f19603f3d011682016040523d82523d6000602084013e612a0c565b606091505b505090508061277a576040517f83e6cc6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f01000000000000000000000000000000000000000000000000000000000000007effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831617612aed818360408051600093845233602052918152606090922091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790565b9392505050565b6060604051905081602082018181018286833760888306808015612b3d5760888290038501848101848103803687375060806001820353506001845160001a1784538652612b54565b608836843760018353608060878401536088850186525b5050505050601f19603f82510116810160405292915050565b6000612b7f8260a01c63ffffffff1690565b67ffffffffffffffff1690506000612b9d8360801c63ffffffff1690565b63ffffffff1690506000612bb78460401c63ffffffff1690565b63ffffffff169050600883108015612bcd575080155b15612c015760c082901b6000908152883560085283513382526017602090815260408084208a855290915290912055612cb6565b60088310158015612c1f575080612c196008856138a3565b93508310155b8015612c335750612c3087826136f8565b83105b15612cb6576000612c4482856138a3565b905087612c528260206136f8565b10158015612c5e575085155b15612c95576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360009081526017602090815260408083208a845290915290209089013590555b5050505050505050565b6000612d43565b66ff00ff00ff00ff8160081c1667ff00ff00ff00ff00612cf18360081b67ffffffffffffffff1690565b1617905065ffff0000ffff8160101c1667ffff0000ffff0000612d1e8360101b67ffffffffffffffff1690565b1617905060008160201c612d3c8360201b67ffffffffffffffff1690565b1792915050565b60808201516020830190612d5b90612cc7565b612cc7565b6040820151612d6990612cc7565b60401b17612d81612d5660018460059190911b015190565b825160809190911b90612d9390612cc7565b60c01b17179392505050565b8260108101928215612dcd579160200282015b82811115612dcd578251825591602001919060010190612db2565b50612dd9929150612df5565b5090565b6040518060200160405280612df0612e0a565b905290565b5b80821115612dd95760008155600101612df6565b6040518061032001604052806019906020820280368337509192915050565b600060208284031215612e3b57600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114612e6657600080fd5b919050565b60008060408385031215612e7e57600080fd5b612e8783612e42565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610320810167ffffffffffffffff81118282101715612ee857612ee8612e95565b60405290565b6040516060810167ffffffffffffffff81118282101715612ee857612ee8612e95565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715612f5857612f58612e95565b604052919050565b803567ffffffffffffffff81168114612e6657600080fd5b6000610320808385031215612f8c57600080fd5b604051602080820182811067ffffffffffffffff82111715612fb057612fb0612e95565b806040525081935085601f860112612fc757600080fd5b612fcf612ec4565b928501928087851115612fe157600080fd5b865b8581101561300157612ff481612f60565b8352918301918301612fe3565b509092525091949350505050565b60006060828403121561302157600080fd5b50919050565b60008083601f84011261303957600080fd5b50813567ffffffffffffffff81111561305157600080fd5b6020830191508360208260051b850101111561306c57600080fd5b9250929050565b60008060008060008060008060006103e08a8c03121561309257600080fd5b61309b8a612e42565b985060208a013597506130b18b60408c01612f78565b96506103608a013567ffffffffffffffff808211156130cf57600080fd5b6130db8d838e0161300f565b97506103808c01359150808211156130f257600080fd5b6130fe8d838e01613027565b90975095506103a08c013591508082111561311857600080fd5b6131248d838e0161300f565b94506103c08c013591508082111561313b57600080fd5b506131488c828d01613027565b915080935050809150509295985092959850929598565b600080600080600060a0868803121561317757600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b60005b838110156131b557818101518382015260200161319d565b838111156121145750506000910152565b60208152600082518060208401526131e581604085016020870161319a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b6000806040838503121561322a57600080fd5b50508035926020909101359150565b60008083601f84011261324b57600080fd5b50813567ffffffffffffffff81111561326357600080fd5b60208301915083602082850101111561306c57600080fd5b600080600080600080600060a0888a03121561329657600080fd5b8735965060208801359550604088013567ffffffffffffffff808211156132bc57600080fd5b6132c88b838c01613239565b909750955060608a01359150808211156132e157600080fd5b506132ee8a828b01613027565b9094509250506080880135801515811461330757600080fd5b8091505092959891949750929550565b60008060006060848603121561332c57600080fd5b61333584612e42565b95602085013595506040909401359392505050565b60008060006040848603121561335f57600080fd5b83359250602084013567ffffffffffffffff81111561337d57600080fd5b61338986828701613239565b9497909650939450505050565b600080600080600080600060a0888a0312156133b157600080fd5b8735965060208801359550604088013567ffffffffffffffff808211156133d757600080fd5b6133e38b838c01613239565b909750955060608a01359150808211156133fc57600080fd5b506134098a828b01613239565b989b979a50959894979596608090950135949350505050565b60008060008060006080868803121561343a57600080fd5b8535945061344a60208701612e42565b935061345860408701612f60565b9250606086013567ffffffffffffffff81111561347457600080fd5b61348088828901613239565b969995985093965092949392505050565b6000806000806000608086880312156134a957600080fd5b6134b286612e42565b945060208601359350604086013567ffffffffffffffff808211156134d657600080fd5b6134e289838a0161300f565b945060608801359150808211156134f857600080fd5b5061348088828901613027565b803563ffffffff81168114612e6657600080fd5b60008060006060848603121561352e57600080fd5b8335925061353e60208501613505565b915061354c60408501613505565b90509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036135e4576135e4613584565b5060010190565b6000606082360312156135fd57600080fd5b613605612eee565b823567ffffffffffffffff8082111561361d57600080fd5b9084019036601f83011261363057600080fd5b813560208282111561364457613644612e95565b613674817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f85011601612f11565b9250818352368183860101111561368a57600080fd5b81818501828501376000918301810191909152908352848101359083015250604092830135928101929092525090565b81516103208201908260005b60198110156136ef57825167ffffffffffffffff168252602092830192909101906001016136c6565b50505092915050565b6000821982111561370b5761370b613584565b500190565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261374557600080fd5b83018035915067ffffffffffffffff82111561376057600080fd5b60200191503681900382131561306c57600080fd5b600181815b808511156137ce57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156137b4576137b4613584565b808516156137c157918102915b93841c939080029061377a565b509250929050565b6000826137e557506001613891565b816137f257506000613891565b816001811461380857600281146138125761382e565b6001915050613891565b60ff84111561382357613823613584565b50506001821b613891565b5060208310610133831016604e8410600b8410161715613851575081810a613891565b61385b8383613775565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561388d5761388d613584565b0290505b92915050565b6000612aed83836137d6565b6000828210156138b5576138b5613584565b500390565b600063ffffffff838116908316818110156138d7576138d7613584565b039392505050565b600063ffffffff8083168185168083038211156138fe576138fe613584565b01949350505050565b6000845161391981846020890161319a565b9190910192835250602082015260400191905056fea164736f6c634300080f000a"; + hex"6080604052600436106101d85760003560e01c80639d53a64811610102578063ddcd58de11610095578063ec5efcbc11610064578063ec5efcbc14610681578063f3f480d9146106a1578063faf37bc7146106d4578063fef2b4ed146106e757600080fd5b8063ddcd58de146105d4578063e03110e11461060c578063e159261114610641578063ea7139501461066157600080fd5b8063b5e7154c116100d1578063b5e7154c14610555578063d18534b51461056c578063da35c6641461058c578063dd24f9bf146105a157600080fd5b80639d53a6481461048e5780639d7e8769146104dd578063b2e67ba8146104fd578063b4801e611461053557600080fd5b806361238bde1161017a5780637ac54767116101495780637ac54767146103ca5780638542cf50146103ea578063882856ef146104355780638dc4be111461046e57600080fd5b806361238bde1461031e5780636551927b146103565780637051472e1461038e5780637917de1d146103aa57600080fd5b80633909af5c116101b65780633909af5c146102715780634d52b4c91461029357806352f0f3ad146102a857806354fd4d50146102c857600080fd5b8063013cf08b146101dd5780630359a5631461022e5780632055b36b1461025c575b600080fd5b3480156101e957600080fd5b506101fd6101f8366004612e29565b610714565b6040805173ffffffffffffffffffffffffffffffffffffffff90931683526020830191909152015b60405180910390f35b34801561023a57600080fd5b5061024e610249366004612e6b565b610759565b604051908152602001610225565b34801561026857600080fd5b5061024e601081565b34801561027d57600080fd5b5061029161028c366004613073565b610891565b005b34801561029f57600080fd5b5061024e610ae8565b3480156102b457600080fd5b5061024e6102c336600461315f565b610b03565b3480156102d457600080fd5b506103116040518060400160405280600c81526020017f312e312e332d626574612e32000000000000000000000000000000000000000081525081565b60405161022591906131c6565b34801561032a57600080fd5b5061024e610339366004613217565b600160209081526000928352604080842090915290825290205481565b34801561036257600080fd5b5061024e610371366004612e6b565b601560209081526000928352604080842090915290825290205481565b34801561039a57600080fd5b5061024e6703782dace9d9000081565b3480156103b657600080fd5b506102916103c536600461327b565b610bd9565b3480156103d657600080fd5b5061024e6103e5366004612e29565b6110dc565b3480156103f657600080fd5b50610425610405366004613217565b600260209081526000928352604080842090915290825290205460ff1681565b6040519015158152602001610225565b34801561044157600080fd5b50610455610450366004613317565b6110f3565b60405167ffffffffffffffff9091168152602001610225565b34801561047a57600080fd5b5061029161048936600461334a565b61114d565b34801561049a57600080fd5b5061024e6104a9366004612e6b565b73ffffffffffffffffffffffffffffffffffffffff9091166000908152601860209081526040808320938352929052205490565b3480156104e957600080fd5b506102916104f8366004613396565b611248565b34801561050957600080fd5b5061024e610518366004612e6b565b601760209081526000928352604080842090915290825290205481565b34801561054157600080fd5b5061024e610550366004613317565b6113ff565b34801561056157600080fd5b5061024e620186a081565b34801561057857600080fd5b50610291610587366004613073565b611431565b34801561059857600080fd5b5060135461024e565b3480156105ad57600080fd5b507f000000000000000000000000000000000000000000000000000000000000271061024e565b3480156105e057600080fd5b5061024e6105ef366004612e6b565b601660209081526000928352604080842090915290825290205481565b34801561061857600080fd5b5061062c610627366004613217565b611840565b60408051928352602083019190915201610225565b34801561064d57600080fd5b5061029161065c36600461334a565b611931565b34801561066d57600080fd5b5061029161067c366004613422565b611a39565b34801561068d57600080fd5b5061029161069c366004613491565b611b98565b3480156106ad57600080fd5b507f000000000000000000000000000000000000000000000000000000000000007861024e565b6102916106e2366004613519565b611d1e565b3480156106f357600080fd5b5061024e610702366004612e29565b60006020819052908152604090205481565b6013818154811061072457600080fd5b60009182526020909120600290910201805460019091015473ffffffffffffffffffffffffffffffffffffffff909116915082565b73ffffffffffffffffffffffffffffffffffffffff82166000908152601560209081526040808320848452909152812054819061079c9060601c63ffffffff1690565b63ffffffff16905060005b6010811015610889578160011660010361082f5773ffffffffffffffffffffffffffffffffffffffff85166000908152601460209081526040808320878452909152902081601081106107fc576107fc613555565b01546040805160208101929092528101849052606001604051602081830303815290604052805190602001209250610870565b826003826010811061084357610843613555565b01546040805160208101939093528201526060016040516020818303038152906040528051906020012092505b60019190911c9080610881816135b3565b9150506107a7565b505092915050565b600061089d8a8a610759565b90506108c086868360208b01356108bb6108b68d6135eb565b611fea565b61202a565b80156108de57506108de83838360208801356108bb6108b68a6135eb565b610914576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b86604001358860405160200161092a91906136ba565b6040516020818303038152906040528051906020012014610977576040517f1968a90200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83602001358760200135600161098d91906136f8565b146109c4576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a0c886109d28680613710565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061208b92505050565b610a15886121e6565b836040013588604051602001610a2b91906136ba565b6040516020818303038152906040528051906020012003610a78576040517f9843145b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8a1660009081526015602090815260408083208c8452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000166001179055610adc8a8a3361298e565b50505050505050505050565b6001610af660106002613897565b610b0091906138a3565b81565b6000610b0f8686612a47565b9050610b1c8360086136f8565b82101580610b2a5750602083115b15610b61576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000602081815260c085901b82526008959095528251828252600286526040808320858452875280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558484528752808320948352938652838220558181529384905292205592915050565b60608115610bf257610beb8686612af4565b9050610c2c565b85858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050505b3360009081526014602090815260408083208b845290915280822081516102008101928390529160109082845b815481526020019060010190808311610c5957505050505090506000601560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008b81526020019081526020016000205490506000610cda8260601c63ffffffff1690565b63ffffffff169050333214610d1b576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d2b8260801c63ffffffff1690565b63ffffffff16600003610d6a576040517f87138d5c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d748260c01c90565b67ffffffffffffffff1615610db5576040517f475a253500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b898114610dee576040517f60f95d5a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610dfb89898d8886612b6d565b83516020850160888204881415608883061715610e20576307b1daf16000526004601cfd5b60405160c8810160405260005b83811015610ed0578083018051835260208101516020840152604081015160408401526060810151606084015260808101516080840152508460888301526088810460051b8b013560a883015260c882206001860195508560005b610200811015610ec5576001821615610ea55782818b0152610ec5565b8981015160009081526020938452604090209260019290921c9101610e88565b505050608801610e2d565b50505050600160106002610ee49190613897565b610eee91906138a3565b811115610f27576040517f6229572300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f9c610f3a8360401c63ffffffff1690565b610f4a9063ffffffff168a6136f8565b60401b7fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff606084901b167fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff8516171790565b915084156110295777ffffffffffffffffffffffffffffffffffffffffffffffff82164260c01b179150610fd68260801c63ffffffff1690565b63ffffffff16610fec8360401c63ffffffff1690565b63ffffffff1614611029576040517f7b1dafd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360009081526014602090815260408083208e8452909152902061104f90846010612d9f565b503360008181526018602090815260408083208f8452825280832080546001810182559084528284206004820401805460039092166008026101000a67ffffffffffffffff818102199093164390931602919091179055838352601582528083208f8452909152812084905560609190911b81523690601437366014016000a05050505050505050505050565b600381601081106110ec57600080fd5b0154905081565b6018602052826000526040600020602052816000526040600020818154811061111b57600080fd5b906000526020600020906004918282040191900660080292509250509054906101000a900467ffffffffffffffff1681565b60443560008060088301861061116b5763fe2549876000526004601cfd5b60c083901b60805260888386823786600882030151915060206000858360025afa90508061119857600080fd5b50600080517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0400000000000000000000000000000000000000000000000000000000000000178082526002602090815260408084208a8552825280842080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558385528252808420998452988152888320939093558152908190529490942055505050565b600080603087600037602060006030600060025afa806112705763f91129696000526004601cfd5b6000517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f010000000000000000000000000000000000000000000000000000000000000017608081815260a08c905260c08b905260308a60e037603088609083013760008060c083600a5afa9250826112f2576309bde3396000526004601cfd5b602886106113085763fe2549876000526004601cfd5b6000602882015278200000000000000000000000000000000000000000000000008152600881018b905285810151935060308a8237603081019b909b52505060509098207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0500000000000000000000000000000000000000000000000000000000000000176000818152600260209081526040808320868452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845282528083209583529481528482209a909a559081528089529190912096909655505050505050565b6014602052826000526040600020602052816000526040600020816010811061142757600080fd5b0154925083915050565b73ffffffffffffffffffffffffffffffffffffffff891660009081526015602090815260408083208b845290915290205467ffffffffffffffff8116156114a4576040517fc334f06900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6114ae8160c01c90565b67ffffffffffffffff166000036114f1576040517f55d4cbf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000007861151c8260c01c90565b6115309067ffffffffffffffff16426138a3565b11611567576040517f55d4cbf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006115738b8b610759565b905061158c87878360208c01356108bb6108b68e6135eb565b80156115aa57506115aa84848360208901356108bb6108b68b6135eb565b6115e0576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8760400135896040516020016115f691906136ba565b6040516020818303038152906040528051906020012014611643576040517f1968a90200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84602001358860200135600161165991906136f8565b14158061168b575060016116738360601c63ffffffff1690565b61167d91906138ba565b63ffffffff16856020013514155b156116c2576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6116d0896109d28780613710565b6116d9896121e6565b60006116e48a612cc0565b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0200000000000000000000000000000000000000000000000000000000000000179050600061173b8460a01c63ffffffff1690565b67ffffffffffffffff169050600160026000848152602001908152602001600020600083815260200190815260200160002060006101000a81548160ff021916908315150217905550601760008e73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008d8152602001908152602001600020546001600084815260200190815260200160002060008381526020019081526020016000208190555061180d8460801c63ffffffff1690565b600083815260208190526040902063ffffffff9190911690556118318d8d8161298e565b50505050505050505050505050565b6000828152600260209081526040808320848452909152812054819060ff166118c9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f7072652d696d616765206d757374206578697374000000000000000000000000604482015260640160405180910390fd5b50600083815260208181526040909120546118e58160086136f8565b6118f08560206136f8565b1061190e57836119018260086136f8565b61190b91906138a3565b91505b506000938452600160209081526040808620948652939052919092205492909150565b60443560008060088301861061194f5763fe2549876000526004601cfd5b60c083901b6080526088838682378087017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80151908490207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f02000000000000000000000000000000000000000000000000000000000000001760008181526002602090815260408083208b8452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845282528083209a83529981528982209390935590815290819052959095209190915550505050565b60008060008060808860601b81528760c01b6014820152858782601c0137601c860181207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0600000000000000000000000000000000000000000000000000000000000000179350604088026260216001603f5a021015611ac35763dd629f866000526004601cfd5b6000808783601c018c5afa94503d6001019150600882018a10611aee5763fe2549876000526004601cfd5b60c082901b81526008018481533d6000600183013e89017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8015160008481526002602090815260408083208d8452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915587845282528083209c83529b81528b8220929092559384528390529790912096909655505050505050565b6000611ba48686610759565b9050611bbd83838360208801356108bb6108b68a6135eb565b611bf3576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602084013515611c2f576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611c37612ddd565b611c45816109d28780613710565b611c4e816121e6565b846040013581604051602001611c6491906136ba565b6040516020818303038152906040528051906020012003611cb1576040517f9843145b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff87166000908152601560209081526040808320898452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000166001179055611d1587873361298e565b50505050505050565b6703782dace9d90000341015611d60576040517fe92c469f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b333214611d99576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611da48160086138df565b63ffffffff168263ffffffff1610611de8576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000027108163ffffffff161015611e48576040517f7b1dafd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152601560209081526040808320868452909152902054611e738160801c63ffffffff1690565b63ffffffff1615611eb0576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b608082901b7fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff60a085901b167fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff83161717336000818152601560209081526040808320898452825280832094909455835180850185528381528082018981526013805460018101825590855291517f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a090600290930292830180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909216919091179055517f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a0919091015591815260168252828120968152959052909320349055505050565b600081600001518260200151836040015160405160200161200d93929190613907565b604051602081830303815290604052805190602001209050919050565b60008160005b601081101561207e578060051b880135600186831c16600181146120635760008481526020839052604090209350612074565b600082815260208590526040902093505b5050600101612030565b5090931495945050505050565b608881511461209957600080fd5b602081016020830161211a565b8260031b8201518060001a8160011a60081b178160021a60101b8260031a60181b17178160041a60201b8260051a60281b178260061a60301b8360071a60381b1717179050612114816120ff868560059190911b015190565b1867ffffffffffffffff16600586901b840152565b50505050565b612126600083836120a6565b612132600183836120a6565b61213e600283836120a6565b61214a600383836120a6565b612156600483836120a6565b612162600583836120a6565b61216e600683836120a6565b61217a600783836120a6565b612186600883836120a6565b612192600983836120a6565b61219e600a83836120a6565b6121aa600b83836120a6565b6121b6600c83836120a6565b6121c2600d83836120a6565b6121ce600e83836120a6565b6121da600f83836120a6565b612114601083836120a6565b6040805178010000000000008082800000000000808a8000000080008000602082015279808b00000000800000018000000080008081800000000000800991810191909152788a00000000000000880000000080008009000000008000000a60608201527b8000808b800000000000008b8000000000008089800000000000800360808201527f80000000000080028000000000000080000000000000800a800000008000000a60a08201527f800000008000808180000000000080800000000080000001800000008000800860c082015260009060e0016040516020818303038152906040529050602082016020820161286e565b6102808101516101e082015161014083015160a0840151845118189118186102a082015161020083015161016084015160c0850151602086015118189118186102c083015161022084015161018085015160e0860151604087015118189118186102e08401516102408501516101a0860151610100870151606088015118189118186103008501516102608601516101c0870151610120880151608089015118189118188084603f1c6123998660011b67ffffffffffffffff1690565b18188584603f1c6123b48660011b67ffffffffffffffff1690565b18188584603f1c6123cf8660011b67ffffffffffffffff1690565b181895508483603f1c6123ec8560011b67ffffffffffffffff1690565b181894508387603f1c6124098960011b67ffffffffffffffff1690565b60208b01518b51861867ffffffffffffffff168c5291189190911897508118600181901b603f9190911c18935060c08801518118601481901c602c9190911b1867ffffffffffffffff1660208901526101208801518718602c81901c60149190911b1867ffffffffffffffff1660c08901526102c08801518618600381901c603d9190911b1867ffffffffffffffff166101208901526101c08801518718601981901c60279190911b1867ffffffffffffffff166102c08901526102808801518218602e81901c60129190911b1867ffffffffffffffff166101c089015260408801518618600281901c603e9190911b1867ffffffffffffffff166102808901526101808801518618601581901c602b9190911b1867ffffffffffffffff1660408901526101a08801518518602781901c60199190911b1867ffffffffffffffff166101808901526102608801518718603881901c60089190911b1867ffffffffffffffff166101a08901526102e08801518518600881901c60389190911b1867ffffffffffffffff166102608901526101e08801518218601781901c60299190911b1867ffffffffffffffff166102e089015260808801518718602581901c601b9190911b1867ffffffffffffffff166101e08901526103008801518718603281901c600e9190911b1867ffffffffffffffff1660808901526102a08801518118603e81901c60029190911b1867ffffffffffffffff166103008901526101008801518518600981901c60379190911b1867ffffffffffffffff166102a08901526102008801518118601381901c602d9190911b1867ffffffffffffffff1661010089015260a08801518218601c81901c60249190911b1867ffffffffffffffff1661020089015260608801518518602481901c601c9190911b1867ffffffffffffffff1660a08901526102408801518518602b81901c60159190911b1867ffffffffffffffff1660608901526102208801518618603181901c600f9190911b1867ffffffffffffffff166102408901526101608801518118603681901c600a9190911b1867ffffffffffffffff166102208901525060e08701518518603a81901c60069190911b1867ffffffffffffffff166101608801526101408701518118603d81901c60039190911b1867ffffffffffffffff1660e0880152505067ffffffffffffffff81166101408601525b5050505050565b600582811b8201805160018501831b8401805160028701851b8601805160038901871b8801805160048b0190981b8901805167ffffffffffffffff861985168918811690995283198a16861889169096528819861683188816909352841986168818871690528419831684189095169052919391929190611d15565b612808600082612781565b612813600582612781565b61281e600a82612781565b612829600f82612781565b612834601482612781565b50565b612840816122dc565b612849816127fd565b600383901b820151815160c09190911c9061211490821867ffffffffffffffff168352565b61287a60008284612837565b61288660018284612837565b61289260028284612837565b61289e60038284612837565b6128aa60048284612837565b6128b660058284612837565b6128c260068284612837565b6128ce60078284612837565b6128da60088284612837565b6128e660098284612837565b6128f2600a8284612837565b6128fe600b8284612837565b61290a600c8284612837565b612916600d8284612837565b612922600e8284612837565b61292e600f8284612837565b61293a60108284612837565b61294660118284612837565b61295260128284612837565b61295e60138284612837565b61296a60148284612837565b61297660158284612837565b61298260168284612837565b61211460178284612837565b73ffffffffffffffffffffffffffffffffffffffff83811660009081526016602090815260408083208684529091528082208054908390559051909284169083908381818185875af1925050503d8060008114612a07576040519150601f19603f3d011682016040523d82523d6000602084013e612a0c565b606091505b505090508061277a576040517f83e6cc6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f01000000000000000000000000000000000000000000000000000000000000007effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831617612aed818360408051600093845233602052918152606090922091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790565b9392505050565b6060604051905081602082018181018286833760888306808015612b3d5760888290038501848101848103803687375060806001820353506001845160001a1784538652612b54565b608836843760018353608060878401536088850186525b5050505050601f19603f82510116810160405292915050565b6000612b7f8260a01c63ffffffff1690565b67ffffffffffffffff1690506000612b9d8360801c63ffffffff1690565b63ffffffff1690506000612bb78460401c63ffffffff1690565b63ffffffff169050600883108015612bcd575080155b15612c015760c082901b6000908152883560085283513382526017602090815260408084208a855290915290912055612cb6565b60088310158015612c1f575080612c196008856138a3565b93508310155b8015612c335750612c3087826136f8565b83105b15612cb6576000612c4482856138a3565b905087612c528260206136f8565b10158015612c5e575085155b15612c95576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360009081526017602090815260408083208a845290915290209089013590555b5050505050505050565b6000612d43565b66ff00ff00ff00ff8160081c1667ff00ff00ff00ff00612cf18360081b67ffffffffffffffff1690565b1617905065ffff0000ffff8160101c1667ffff0000ffff0000612d1e8360101b67ffffffffffffffff1690565b1617905060008160201c612d3c8360201b67ffffffffffffffff1690565b1792915050565b60808201516020830190612d5b90612cc7565b612cc7565b6040820151612d6990612cc7565b60401b17612d81612d5660018460059190911b015190565b825160809190911b90612d9390612cc7565b60c01b17179392505050565b8260108101928215612dcd579160200282015b82811115612dcd578251825591602001919060010190612db2565b50612dd9929150612df5565b5090565b6040518060200160405280612df0612e0a565b905290565b5b80821115612dd95760008155600101612df6565b6040518061032001604052806019906020820280368337509192915050565b600060208284031215612e3b57600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114612e6657600080fd5b919050565b60008060408385031215612e7e57600080fd5b612e8783612e42565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610320810167ffffffffffffffff81118282101715612ee857612ee8612e95565b60405290565b6040516060810167ffffffffffffffff81118282101715612ee857612ee8612e95565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715612f5857612f58612e95565b604052919050565b803567ffffffffffffffff81168114612e6657600080fd5b6000610320808385031215612f8c57600080fd5b604051602080820182811067ffffffffffffffff82111715612fb057612fb0612e95565b806040525081935085601f860112612fc757600080fd5b612fcf612ec4565b928501928087851115612fe157600080fd5b865b8581101561300157612ff481612f60565b8352918301918301612fe3565b509092525091949350505050565b60006060828403121561302157600080fd5b50919050565b60008083601f84011261303957600080fd5b50813567ffffffffffffffff81111561305157600080fd5b6020830191508360208260051b850101111561306c57600080fd5b9250929050565b60008060008060008060008060006103e08a8c03121561309257600080fd5b61309b8a612e42565b985060208a013597506130b18b60408c01612f78565b96506103608a013567ffffffffffffffff808211156130cf57600080fd5b6130db8d838e0161300f565b97506103808c01359150808211156130f257600080fd5b6130fe8d838e01613027565b90975095506103a08c013591508082111561311857600080fd5b6131248d838e0161300f565b94506103c08c013591508082111561313b57600080fd5b506131488c828d01613027565b915080935050809150509295985092959850929598565b600080600080600060a0868803121561317757600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b60005b838110156131b557818101518382015260200161319d565b838111156121145750506000910152565b60208152600082518060208401526131e581604085016020870161319a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b6000806040838503121561322a57600080fd5b50508035926020909101359150565b60008083601f84011261324b57600080fd5b50813567ffffffffffffffff81111561326357600080fd5b60208301915083602082850101111561306c57600080fd5b600080600080600080600060a0888a03121561329657600080fd5b8735965060208801359550604088013567ffffffffffffffff808211156132bc57600080fd5b6132c88b838c01613239565b909750955060608a01359150808211156132e157600080fd5b506132ee8a828b01613027565b9094509250506080880135801515811461330757600080fd5b8091505092959891949750929550565b60008060006060848603121561332c57600080fd5b61333584612e42565b95602085013595506040909401359392505050565b60008060006040848603121561335f57600080fd5b83359250602084013567ffffffffffffffff81111561337d57600080fd5b61338986828701613239565b9497909650939450505050565b600080600080600080600060a0888a0312156133b157600080fd5b8735965060208801359550604088013567ffffffffffffffff808211156133d757600080fd5b6133e38b838c01613239565b909750955060608a01359150808211156133fc57600080fd5b506134098a828b01613239565b989b979a50959894979596608090950135949350505050565b60008060008060006080868803121561343a57600080fd5b8535945061344a60208701612e42565b935061345860408701612f60565b9250606086013567ffffffffffffffff81111561347457600080fd5b61348088828901613239565b969995985093965092949392505050565b6000806000806000608086880312156134a957600080fd5b6134b286612e42565b945060208601359350604086013567ffffffffffffffff808211156134d657600080fd5b6134e289838a0161300f565b945060608801359150808211156134f857600080fd5b5061348088828901613027565b803563ffffffff81168114612e6657600080fd5b60008060006060848603121561352e57600080fd5b8335925061353e60208501613505565b915061354c60408501613505565b90509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036135e4576135e4613584565b5060010190565b6000606082360312156135fd57600080fd5b613605612eee565b823567ffffffffffffffff8082111561361d57600080fd5b9084019036601f83011261363057600080fd5b813560208282111561364457613644612e95565b613674817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f85011601612f11565b9250818352368183860101111561368a57600080fd5b81818501828501376000918301810191909152908352848101359083015250604092830135928101929092525090565b81516103208201908260005b60198110156136ef57825167ffffffffffffffff168252602092830192909101906001016136c6565b50505092915050565b6000821982111561370b5761370b613584565b500190565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261374557600080fd5b83018035915067ffffffffffffffff82111561376057600080fd5b60200191503681900382131561306c57600080fd5b600181815b808511156137ce57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156137b4576137b4613584565b808516156137c157918102915b93841c939080029061377a565b509250929050565b6000826137e557506001613891565b816137f257506000613891565b816001811461380857600281146138125761382e565b6001915050613891565b60ff84111561382357613823613584565b50506001821b613891565b5060208310610133831016604e8410600b8410161715613851575081810a613891565b61385b8383613775565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561388d5761388d613584565b0290505b92915050565b6000612aed83836137d6565b6000828210156138b5576138b5613584565b500390565b600063ffffffff838116908316818110156138d7576138d7613584565b039392505050565b600063ffffffff8083168185168083038211156138fe576138fe613584565b01949350505050565b6000845161391981846020890161319a565b9190910192835250602082015260400191905056fea164736f6c634300080f000a"; bytes internal constant mipsCode = - hex"608060405234801561001057600080fd5b50600436106100415760003560e01c806354fd4d50146100465780637dc0d1d014610098578063e14ced32146100dc575b600080fd5b6100826040518060400160405280600a81526020017f312e312e302d72632e310000000000000000000000000000000000000000000081525081565b60405161008f91906121ee565b60405180910390f35b60405173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000373d916d11cce55b548f7051002e76bcfbd7a85d16815260200161008f565b6100ef6100ea3660046122a3565b6100fd565b60405190815260200161008f565b6000610107612164565b6080811461011457600080fd5b6040516106001461012457600080fd5b6084871461013157600080fd5b6101a4851461013f57600080fd5b8635608052602087013560a052604087013560e090811c60c09081526044890135821c82526048890135821c61010052604c890135821c610120526050890135821c61014052605489013590911c61016052605888013560f890811c610180526059890135901c6101a0819052605a89013590911c6101c05260628801906101e09060018111156101f5576040517f0136cc76000000000000000000000000000000000000000000000000000000008152600481fd5b506020810181511461020657600080fd5b60200160005b602081101561023057823560e01c825260049092019160209091019060010161020c565b5050508061012001511561024e576102466103a6565b91505061039d565b6101408101805160010167ffffffffffffffff16905260006101a49050600080600061028385606001518660000151866104f7565b9250925092508163ffffffff1660001480156102a557508063ffffffff16600c145b156102bf576102b387610521565b9550505050505061039d565b6000610339866040805160808101825260008082526020820181905291810182905260608101919091526040518060800160405280836060015163ffffffff168152602001836080015163ffffffff1681526020018360a0015163ffffffff1681526020018360c0015163ffffffff168152509050919050565b6101608701518751919250610356918391906105248888886108f9565b8652805163ffffffff9081166060808901919091526020830151821660808901526040830151821660a08901528201511660c08701526103946103a6565b96505050505050505b95945050505050565b60408051608051815260a051602082015260dc519181019190915260fc51604482015261011c51604882015261013c51604c82015261015c51605082015261017c5160548201526101805161019f5160588301526101a0516101bf5160598401526101d851605a8401526000926102009290916062830191906001811115610453576040517f0136cc76000000000000000000000000000000000000000000000000000000008152600481fd5b60005b602081101561047a57601c8601518452602090950194600490930192600101610456565b506000835283830384a060009450806001811461049a57600395506104c2565b8280156104b257600181146104bb57600296506104c0565b600096506104c0565b600196505b505b50505081900390207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1660f89190911b17919050565b6000806000610507858786610cdf565b925050603f601a83901c8116915082165b93509350939050565b600061052b612164565b608090506000806000806105628561016001516040810151608082015160a083015160c084015160e0909401519294919390929091565b509350935093509350600080610ffa63ffffffff168663ffffffff16036105a75761059285858960e00151610d93565b63ffffffff1660e08a01529092509050610808565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03363ffffffff8716016105e05763400000009150610808565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefe863ffffffff8716016106165760019150610808565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffef6a63ffffffff87160161066a57600161012088015260ff851661010088015261065d6103a6565b9998505050505050505050565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff05d63ffffffff8716016107665760006040518061012001604052808763ffffffff1681526020018663ffffffff1681526020018563ffffffff16815260200189602001518152602001896040015163ffffffff1681526020018b81526020017f000000000000000000000000373d916d11cce55b548f7051002e76bcfbd7a85d73ffffffffffffffffffffffffffffffffffffffff1681526020016107386101a4600160ff16610380020190565b81528951602090910152905061074d81610e27565b8b5263ffffffff1660408b015290935091506108089050565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff05c63ffffffff8716016107cb57602087015160408801516107b1918791879187916105248d5161109f565b63ffffffff1660408b015260208a01529092509050610808565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff02963ffffffff871601610808576108028585611195565b90925090505b6000610882886040805160808101825260008082526020820181905291810182905260608101919091526040518060800160405280836060015163ffffffff168152602001836080015163ffffffff1681526020018360a0015163ffffffff1681526020018360c0015163ffffffff168152509050919050565b61016089015163ffffffff85811660408084019190915285821660e0909301929092526020830180518083168086526004909101831682526060808e01919091529051821660808d015291830151811660a08c0152908201511660c08a015290506108eb6103a6565b9a9950505050505050505050565b84600263ffffffff8416148061091557508263ffffffff166003145b156109675760006002856303ffffff1663ffffffff16901b896020015163f00000001617905061096189898663ffffffff1660021461095557601f610958565b60005b60ff168461124a565b50610cd4565b600080601f601087901c8116908a90601589901c166020811061098c5761098c612317565b602002015192508063ffffffff871615806109ad57508663ffffffff16601c145b156109df578a8263ffffffff16602081106109ca576109ca612317565b6020020151925050601f600b88901c16610a96565b60208763ffffffff161015610a41578663ffffffff16600c1480610a0957508663ffffffff16600d145b80610a1a57508663ffffffff16600e145b15610a2b578761ffff169250610a96565b610a3a8861ffff166010611322565b9250610a96565b60288763ffffffff16101580610a5d57508663ffffffff166022145b80610a6e57508663ffffffff166026145b15610a96578a8263ffffffff1660208110610a8b57610a8b612317565b602002015192508190505b60048763ffffffff1610158015610ab3575060088763ffffffff16105b80610ac457508663ffffffff166001145b15610ae057610ad78c8c898b8689611395565b50505050610cd4565b63ffffffff6000602089831610610b4557610b008a61ffff166010611322565b9095019463fffffffc8616610b168d828e610cdf565b915060288a63ffffffff1610158015610b3657508963ffffffff16603014155b15610b4357809250600093505b505b6000610b558b8b8b8a8a87611583565b63ffffffff1690508963ffffffff166000148015610b7a575060088963ffffffff1610155b8015610b8c5750601c8963ffffffff16105b15610c54578863ffffffff1660081480610bac57508863ffffffff166009145b15610bdf57610bd38f8f8b63ffffffff16600814610bca5786610bcd565b60005b8a61124a565b50505050505050610cd4565b8863ffffffff16600a03610c0157610bd38f8f868a63ffffffff8b1615611ca0565b8863ffffffff16600b03610c2457610bd38f8f868a63ffffffff8b161515611ca0565b60108963ffffffff1610158015610c415750601c8963ffffffff16105b15610c5457610bd38f8f8b8a8a89611d70565b8963ffffffff166038148015610c6f575063ffffffff851615155b15610c9f5760018e8663ffffffff1660208110610c8e57610c8e612317565b63ffffffff90921660209290920201525b8263ffffffff1663ffffffff14610cbe57610cbb838d83612029565b97505b610ccc8f8f86846001611ca0565b505050505050505b979650505050505050565b6000610cea826120cb565b6003831615610cf857600080fd5b6020820191358360051c8160005b601b811015610d5e5760208601953583821c6001168015610d2e5760018114610d4357610d54565b60008481526020839052604090209350610d54565b600082815260208590526040902093505b5050600101610d06565b50868114610d7457630badf00d60005260206000fd5b5050601f93909316601c0360031b9290921c63ffffffff169392505050565b6000808284610fff811615610dad57610fff811661100003015b8663ffffffff16600003610e195784935090810190636000000063ffffffff83161180610de557508463ffffffff168263ffffffff16105b80610dfb57508563ffffffff168163ffffffff16105b15610e14575063ffffffff925060169150839050610518565b610e1d565b8693505b5093509350939050565b6101008101516080820151825160009283929163ffffffff161561109857845163ffffffff167ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb01611052576000610e93866101000151876020015163fffffffc168860e00151610cdf565b606087015190915060001a600103610f1557610f0f86606001518760a0015160408051600093845233602052918152606090922091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790565b60608701525b6000808760c0015173ffffffffffffffffffffffffffffffffffffffff1663e03110e189606001518a608001516040518363ffffffff1660e01b8152600401610f6e92919091825263ffffffff16602082015260400190565b6040805180830381865afa158015610f8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fae9190612346565b60208a015160408b01519294509092509060038216600481900384811015610fd4578094505b5083821015610fe1578193505b8460088502610100031c9450846008828660040303021b9450600180600883600403021b036001806008878560040303021b0391508119811690508581198816179650505061103f8a6020015163fffffffc168b60e0015187612029565b9298505050938601939250611098915050565b845163ffffffff167ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd0161108c5784604001519350611098565b63ffffffff9350600992505b9193509193565b600080858563ffffffff8b16600114806110bf575063ffffffff8b166002145b806110d0575063ffffffff8b166004145b156110dd57889350611187565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa63ffffffff8c160161117b57600061111d868c63fffffffc1689610cdf565b90508860038c166004038b81101561113357809b505b8b965086900360089081029290921c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600193880293841b0116911b17915060009050611187565b63ffffffff9350600992505b975097509750979350505050565b60008063ffffffff83166003036112385763ffffffff841615806111bf575063ffffffff84166005145b806111d0575063ffffffff84166003145b156111de5760009150611243565b63ffffffff8416600114806111f9575063ffffffff84166002145b8061120a575063ffffffff84166006145b8061121b575063ffffffff84166004145b156112295760019150611243565b5063ffffffff90506009611243565b5063ffffffff905060165b9250929050565b836000015160040163ffffffff16846020015163ffffffff16146112cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6a756d7020696e2064656c617920736c6f74000000000000000000000000000060448201526064015b60405180910390fd5b835160208501805163ffffffff908116875283811690915283161561131b5780600801848463ffffffff166020811061130a5761130a612317565b63ffffffff90921660209290920201525b5050505050565b600063ffffffff8381167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80850183169190911c821615159160016020869003821681901b830191861691821b92911b018261137f576000611381565b815b90861663ffffffff16179250505092915050565b6000866000015160040163ffffffff16876020015163ffffffff1614611417576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f6272616e636820696e2064656c617920736c6f7400000000000000000000000060448201526064016112c6565b8463ffffffff166004148061143257508463ffffffff166005145b156114a9576000868463ffffffff166020811061145157611451612317565b602002015190508063ffffffff168363ffffffff1614801561147957508563ffffffff166004145b806114a157508063ffffffff168363ffffffff16141580156114a157508563ffffffff166005145b915050611526565b8463ffffffff166006036114c65760008260030b13159050611526565b8463ffffffff166007036114e25760008260030b139050611526565b8463ffffffff1660010361152657601f601085901c16600081900361150b5760008360030b1291505b8063ffffffff166001036115245760008360030b121591505b505b8651602088015163ffffffff168852811561156757600261154c8661ffff166010611322565b63ffffffff90811690911b8201600401166020890152611579565b60208801805160040163ffffffff1690525b5050505050505050565b600063ffffffff861615806115b0575060088663ffffffff16101580156115b05750600f8663ffffffff16105b156119b05785600881146115f357600981146115fc57600a811461160557600b811461160e57600c811461161757600d811461162057600e81146116295761162e565b6020955061162e565b6021955061162e565b602a955061162e565b602b955061162e565b6024955061162e565b6025955061162e565b602695505b508463ffffffff16600003611653575063ffffffff8216601f600688901c161b611c96565b8463ffffffff16600203611677575063ffffffff8216601f600688901c161c611c96565b8463ffffffff166003036116ab57601f600688901c166116a363ffffffff8516821c6020839003611322565b915050611c96565b8463ffffffff166004036116cb575063ffffffff8216601f84161b611c96565b8463ffffffff166006036116eb575063ffffffff8216601f84161c611c96565b8463ffffffff1660070361171357601f84166116a363ffffffff8516821c6020839003611322565b8463ffffffff16600803611728575082611c96565b8463ffffffff1660090361173d575082611c96565b8463ffffffff16600a03611752575082611c96565b8463ffffffff16600b03611767575082611c96565b8463ffffffff16600c0361177c575082611c96565b8463ffffffff16600f03611791575082611c96565b8463ffffffff166010036117a6575082611c96565b8463ffffffff166011036117bb575082611c96565b8463ffffffff166012036117d0575082611c96565b8463ffffffff166013036117e5575082611c96565b8463ffffffff166018036117fa575082611c96565b8463ffffffff1660190361180f575082611c96565b8463ffffffff16601a03611824575082611c96565b8463ffffffff16601b03611839575082611c96565b8463ffffffff166020036118505750828201611c96565b8463ffffffff166021036118675750828201611c96565b8463ffffffff1660220361187e5750818303611c96565b8463ffffffff166023036118955750818303611c96565b8463ffffffff166024036118ac5750828216611c96565b8463ffffffff166025036118c35750828217611c96565b8463ffffffff166026036118da5750828218611c96565b8463ffffffff166027036118f2575082821719611c96565b8463ffffffff16602a03611921578260030b8460030b12611914576000611917565b60015b60ff169050611c96565b8463ffffffff16602b03611949578263ffffffff168463ffffffff1610611914576000611917565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f696e76616c696420696e737472756374696f6e0000000000000000000000000060448201526064016112c6565b611949565b8563ffffffff16601c03611a30578463ffffffff166002036119d55750828202611c96565b8463ffffffff16602014806119f057508463ffffffff166021145b156119ab578463ffffffff16602003611a07579219925b60005b6380000000851615611a29576401fffffffe600195861b169401611a0a565b9050611c96565b8563ffffffff16600f03611a51575065ffffffff0000601083901b16611c96565b8563ffffffff16602003611a8557611a298460031660080260180363ffffffff168363ffffffff16901c60ff166008611322565b8563ffffffff16602103611aba57611a298460021660080260100363ffffffff168363ffffffff16901c61ffff166010611322565b8563ffffffff16602203611ae8575063ffffffff60086003851602811681811b198416918316901b17611c96565b8563ffffffff16602303611afd575080611c96565b8563ffffffff16602403611b2e578360031660080260180363ffffffff168263ffffffff16901c60ff169050611c96565b8563ffffffff16602503611b60578360021660080260100363ffffffff168263ffffffff16901c61ffff169050611c96565b8563ffffffff16602603611b91575063ffffffff60086003851602601803811681811c198416918316901c17611c96565b8563ffffffff16602803611bc6575060ff63ffffffff60086003861602601803811682811b9091188316918416901b17611c96565b8563ffffffff16602903611bfc575061ffff63ffffffff60086002861602601003811682811b9091188316918416901b17611c96565b8563ffffffff16602a03611c2a575063ffffffff60086003851602811681811c198316918416901c17611c96565b8563ffffffff16602b03611c3f575081611c96565b8563ffffffff16602e03611c70575063ffffffff60086003851602601803811681811b198316918416901b17611c96565b8563ffffffff16603003611c85575080611c96565b8563ffffffff166038036119495750815b9695505050505050565b60208363ffffffff1610611d10576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f76616c696420726567697374657200000000000000000000000000000000000060448201526064016112c6565b63ffffffff831615801590611d225750805b15611d515781848463ffffffff1660208110611d4057611d40612317565b63ffffffff90921660209290920201525b5050505060208101805163ffffffff8082169093526004019091169052565b60008463ffffffff16601003611d8b57506060860151611fd1565b8463ffffffff16601103611daa5763ffffffff84166060880152611fd1565b8463ffffffff16601203611dc357506040860151611fd1565b8463ffffffff16601303611de25763ffffffff84166040880152611fd1565b8463ffffffff16601803611e165763ffffffff600385810b9085900b02602081901c821660608a0152166040880152611fd1565b8463ffffffff16601903611e475763ffffffff84811681851602602081901c821660608a0152166040880152611fd1565b8463ffffffff16601a03611f0a578260030b600003611ec2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d4950533a206469766973696f6e206279207a65726f0000000000000000000060448201526064016112c6565b8260030b8460030b81611ed757611ed761236a565b0763ffffffff166060880152600383810b9085900b81611ef957611ef961236a565b0563ffffffff166040880152611fd1565b8463ffffffff16601b03611fd1578263ffffffff16600003611f88576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d4950533a206469766973696f6e206279207a65726f0000000000000000000060448201526064016112c6565b8263ffffffff168463ffffffff1681611fa357611fa361236a565b0663ffffffff908116606089015283811690851681611fc457611fc461236a565b0463ffffffff1660408801525b63ffffffff8216156120075780868363ffffffff1660208110611ff657611ff6612317565b63ffffffff90921660209290920201525b50505060208401805163ffffffff808216909652600401909416909352505050565b6000612034836120cb565b600384161561204257600080fd5b6020830192601f8516601c0360031b83811b913563ffffffff90911b1916178460051c60005b601b8110156120c05760208601953582821c600116801561209057600181146120a5576120b6565b600085815260208390526040902094506120b6565b600082815260208690526040902094505b5050600101612068565b509095945050505050565b366103808201811015612160576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f636865636b207468617420746865726520697320656e6f7567682063616c6c6460448201527f617461000000000000000000000000000000000000000000000000000000000060648201526084016112c6565b5050565b6040805161018081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081018290526101008101829052610120810182905261014081019190915261016081016121ca6121cf565b905290565b6040518061040001604052806020906020820280368337509192915050565b600060208083528351808285015260005b8181101561221b578581018301518582016040015282016121ff565b8181111561222d576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b60008083601f84011261227357600080fd5b50813567ffffffffffffffff81111561228b57600080fd5b60208301915083602082850101111561124357600080fd5b6000806000806000606086880312156122bb57600080fd5b853567ffffffffffffffff808211156122d357600080fd5b6122df89838a01612261565b909750955060208801359150808211156122f857600080fd5b5061230588828901612261565b96999598509660400135949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000806040838503121561235957600080fd5b505080516020909101519092909150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fdfea164736f6c634300080f000a"; + hex"608060405234801561001057600080fd5b50600436106100415760003560e01c806354fd4d50146100465780637dc0d1d014610098578063e14ced32146100dc575b600080fd5b6100826040518060400160405280600c81526020017f312e312e312d626574612e33000000000000000000000000000000000000000081525081565b60405161008f9190612237565b60405180910390f35b60405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000007a9eab4ce99d157aee7a02e95b366e972a2d5b0b16815260200161008f565b6100ef6100ea3660046122ec565b6100fd565b60405190815260200161008f565b60006101076121ad565b6080811461011457600080fd5b6040516106001461012457600080fd5b6084871461013157600080fd5b6101a4851461013f57600080fd5b8635608052602087013560a052604087013560e090811c60c09081526044890135821c82526048890135821c61010052604c890135821c610120526050890135821c61014052605489013590911c61016052605888013560f890811c610180526059890135901c6101a0819052605a89013590911c6101c05260628801906101e09060018111156101f5576040517f0136cc76000000000000000000000000000000000000000000000000000000008152600481fd5b506020810181511461020657600080fd5b60200160005b602081101561023057823560e01c825260049092019160209091019060010161020c565b5050508061012001511561024e576102466103a6565b91505061039d565b6101408101805160010167ffffffffffffffff16905260006101a49050600080600061028385606001518660000151866104f7565b9250925092508163ffffffff1660001480156102a557508063ffffffff16600c145b156102bf576102b387610521565b9550505050505061039d565b6000610339866040805160808101825260008082526020820181905291810182905260608101919091526040518060800160405280836060015163ffffffff168152602001836080015163ffffffff1681526020018360a0015163ffffffff1681526020018360c0015163ffffffff168152509050919050565b6101608701518751919250610356918391906105248888886108f9565b8652805163ffffffff9081166060808901919091526020830151821660808901526040830151821660a08901528201511660c08701526103946103a6565b96505050505050505b95945050505050565b60408051608051815260a051602082015260dc519181019190915260fc51604482015261011c51604882015261013c51604c82015261015c51605082015261017c5160548201526101805161019f5160588301526101a0516101bf5160598401526101d851605a8401526000926102009290916062830191906001811115610453576040517f0136cc76000000000000000000000000000000000000000000000000000000008152600481fd5b60005b602081101561047a57601c8601518452602090950194600490930192600101610456565b506000835283830384a060009450806001811461049a57600395506104c2565b8280156104b257600181146104bb57600296506104c0565b600096506104c0565b600196505b505b50505081900390207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1660f89190911b17919050565b6000806000610507858786610cdf565b925050603f601a83901c8116915082165b93509350939050565b600061052b6121ad565b608090506000806000806105628561016001516040810151608082015160a083015160c084015160e0909401519294919390929091565b509350935093509350600080610ffa63ffffffff168663ffffffff16036105a75761059285858960e00151610d31565b63ffffffff1660e08a01529092509050610808565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03363ffffffff8716016105e05763400000009150610808565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefe863ffffffff8716016106165760019150610808565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffef6a63ffffffff87160161066a57600161012088015260ff851661010088015261065d6103a6565b9998505050505050505050565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff05d63ffffffff8716016107665760006040518061012001604052808763ffffffff1681526020018663ffffffff1681526020018563ffffffff16815260200189602001518152602001896040015163ffffffff1681526020018b81526020017f0000000000000000000000007a9eab4ce99d157aee7a02e95b366e972a2d5b0b73ffffffffffffffffffffffffffffffffffffffff1681526020016107386101a4600160ff16610380020190565b81528951602090910152905061074d81610dc5565b8b5263ffffffff1660408b015290935091506108089050565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff05c63ffffffff8716016107cb57602087015160408801516107b1918791879187916105248d5161103d565b63ffffffff1660408b015260208a01529092509050610808565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff02963ffffffff871601610808576108028585611133565b90925090505b6000610882886040805160808101825260008082526020820181905291810182905260608101919091526040518060800160405280836060015163ffffffff168152602001836080015163ffffffff1681526020018360a0015163ffffffff1681526020018360c0015163ffffffff168152509050919050565b61016089015163ffffffff85811660408084019190915285821660e0909301929092526020830180518083168086526004909101831682526060808e01919091529051821660808d015291830151811660a08c0152908201511660c08a015290506108eb6103a6565b9a9950505050505050505050565b84600263ffffffff8416148061091557508263ffffffff166003145b156109675760006002856303ffffff1663ffffffff16901b896020015163f00000001617905061096189898663ffffffff1660021461095557601f610958565b60005b60ff16846111e8565b50610cd4565b600080601f601087901c8116908a90601589901c166020811061098c5761098c612360565b602002015192508063ffffffff871615806109ad57508663ffffffff16601c145b156109df578a8263ffffffff16602081106109ca576109ca612360565b6020020151925050601f600b88901c16610a96565b60208763ffffffff161015610a41578663ffffffff16600c1480610a0957508663ffffffff16600d145b80610a1a57508663ffffffff16600e145b15610a2b578761ffff169250610a96565b610a3a8861ffff1660106112c0565b9250610a96565b60288763ffffffff16101580610a5d57508663ffffffff166022145b80610a6e57508663ffffffff166026145b15610a96578a8263ffffffff1660208110610a8b57610a8b612360565b602002015192508190505b60048763ffffffff1610158015610ab3575060088763ffffffff16105b80610ac457508663ffffffff166001145b15610ae057610ad78c8c898b8689611333565b50505050610cd4565b63ffffffff6000602089831610610b4557610b008a61ffff1660106112c0565b9095019463fffffffc8616610b168d828e610cdf565b915060288a63ffffffff1610158015610b3657508963ffffffff16603014155b15610b4357809250600093505b505b6000610b558b8b8b8a8a87611521565b63ffffffff1690508963ffffffff166000148015610b7a575060088963ffffffff1610155b8015610b8c5750601c8963ffffffff16105b15610c54578863ffffffff1660081480610bac57508863ffffffff166009145b15610bdf57610bd38f8f8b63ffffffff16600814610bca5786610bcd565b60005b8a6111e8565b50505050505050610cd4565b8863ffffffff16600a03610c0157610bd38f8f868a63ffffffff8b1615611c3e565b8863ffffffff16600b03610c2457610bd38f8f868a63ffffffff8b161515611c3e565b60108963ffffffff1610158015610c415750601c8963ffffffff16105b15610c5457610bd38f8f8b8a8a89611d0e565b8963ffffffff166038148015610c6f575063ffffffff851615155b15610c9f5760018e8663ffffffff1660208110610c8e57610c8e612360565b63ffffffff90921660209290920201525b8263ffffffff1663ffffffff14610cbe57610cbb838d83611fc7565b97505b610ccc8f8f86846001611c3e565b505050505050505b979650505050505050565b600080610ced858585612069565b909250905080610d29576040517f8e77b2b700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b509392505050565b6000808284610fff811615610d4b57610fff811661100003015b8663ffffffff16600003610db75784935090810190636000000063ffffffff83161180610d8357508463ffffffff168263ffffffff16105b80610d9957508563ffffffff168163ffffffff16105b15610db2575063ffffffff925060169150839050610518565b610dbb565b8693505b5093509350939050565b6101008101516080820151825160009283929163ffffffff161561103657845163ffffffff167ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb01610ff0576000610e31866101000151876020015163fffffffc168860e00151610cdf565b606087015190915060001a600103610eb357610ead86606001518760a0015160408051600093845233602052918152606090922091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790565b60608701525b6000808760c0015173ffffffffffffffffffffffffffffffffffffffff1663e03110e189606001518a608001516040518363ffffffff1660e01b8152600401610f0c92919091825263ffffffff16602082015260400190565b6040805180830381865afa158015610f28573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4c919061238f565b60208a015160408b01519294509092509060038216600481900384811015610f72578094505b5083821015610f7f578193505b8460088502610100031c9450846008828660040303021b9450600180600883600403021b036001806008878560040303021b03915081198116905085811988161796505050610fdd8a6020015163fffffffc168b60e0015187611fc7565b9298505050938601939250611036915050565b845163ffffffff167ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd0161102a5784604001519350611036565b63ffffffff9350600992505b9193509193565b600080858563ffffffff8b166001148061105d575063ffffffff8b166002145b8061106e575063ffffffff8b166004145b1561107b57889350611125565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa63ffffffff8c16016111195760006110bb868c63fffffffc1689610cdf565b90508860038c166004038b8110156110d157809b505b8b965086900360089081029290921c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600193880293841b0116911b17915060009050611125565b63ffffffff9350600992505b975097509750979350505050565b60008063ffffffff83166003036111d65763ffffffff8416158061115d575063ffffffff84166005145b8061116e575063ffffffff84166003145b1561117c57600091506111e1565b63ffffffff841660011480611197575063ffffffff84166002145b806111a8575063ffffffff84166006145b806111b9575063ffffffff84166004145b156111c757600191506111e1565b5063ffffffff905060096111e1565b5063ffffffff905060165b9250929050565b836000015160040163ffffffff16846020015163ffffffff161461126d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6a756d7020696e2064656c617920736c6f74000000000000000000000000000060448201526064015b60405180910390fd5b835160208501805163ffffffff90811687528381169091528316156112b95780600801848463ffffffff16602081106112a8576112a8612360565b63ffffffff90921660209290920201525b5050505050565b600063ffffffff8381167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80850183169190911c821615159160016020869003821681901b830191861691821b92911b018261131d57600061131f565b815b90861663ffffffff16179250505092915050565b6000866000015160040163ffffffff16876020015163ffffffff16146113b5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f6272616e636820696e2064656c617920736c6f740000000000000000000000006044820152606401611264565b8463ffffffff16600414806113d057508463ffffffff166005145b15611447576000868463ffffffff16602081106113ef576113ef612360565b602002015190508063ffffffff168363ffffffff1614801561141757508563ffffffff166004145b8061143f57508063ffffffff168363ffffffff161415801561143f57508563ffffffff166005145b9150506114c4565b8463ffffffff166006036114645760008260030b131590506114c4565b8463ffffffff166007036114805760008260030b1390506114c4565b8463ffffffff166001036114c457601f601085901c1660008190036114a95760008360030b1291505b8063ffffffff166001036114c25760008360030b121591505b505b8651602088015163ffffffff16885281156115055760026114ea8661ffff1660106112c0565b63ffffffff90811690911b8201600401166020890152611517565b60208801805160040163ffffffff1690525b5050505050505050565b600063ffffffff8616158061154e575060088663ffffffff161015801561154e5750600f8663ffffffff16105b1561194e578560088114611591576009811461159a57600a81146115a357600b81146115ac57600c81146115b557600d81146115be57600e81146115c7576115cc565b602095506115cc565b602195506115cc565b602a95506115cc565b602b95506115cc565b602495506115cc565b602595506115cc565b602695505b508463ffffffff166000036115f1575063ffffffff8216601f600688901c161b611c34565b8463ffffffff16600203611615575063ffffffff8216601f600688901c161c611c34565b8463ffffffff1660030361164957601f600688901c1661164163ffffffff8516821c60208390036112c0565b915050611c34565b8463ffffffff16600403611669575063ffffffff8216601f84161b611c34565b8463ffffffff16600603611689575063ffffffff8216601f84161c611c34565b8463ffffffff166007036116b157601f841661164163ffffffff8516821c60208390036112c0565b8463ffffffff166008036116c6575082611c34565b8463ffffffff166009036116db575082611c34565b8463ffffffff16600a036116f0575082611c34565b8463ffffffff16600b03611705575082611c34565b8463ffffffff16600c0361171a575082611c34565b8463ffffffff16600f0361172f575082611c34565b8463ffffffff16601003611744575082611c34565b8463ffffffff16601103611759575082611c34565b8463ffffffff1660120361176e575082611c34565b8463ffffffff16601303611783575082611c34565b8463ffffffff16601803611798575082611c34565b8463ffffffff166019036117ad575082611c34565b8463ffffffff16601a036117c2575082611c34565b8463ffffffff16601b036117d7575082611c34565b8463ffffffff166020036117ee5750828201611c34565b8463ffffffff166021036118055750828201611c34565b8463ffffffff1660220361181c5750818303611c34565b8463ffffffff166023036118335750818303611c34565b8463ffffffff1660240361184a5750828216611c34565b8463ffffffff166025036118615750828217611c34565b8463ffffffff166026036118785750828218611c34565b8463ffffffff16602703611890575082821719611c34565b8463ffffffff16602a036118bf578260030b8460030b126118b25760006118b5565b60015b60ff169050611c34565b8463ffffffff16602b036118e7578263ffffffff168463ffffffff16106118b25760006118b5565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f696e76616c696420696e737472756374696f6e000000000000000000000000006044820152606401611264565b6118e7565b8563ffffffff16601c036119ce578463ffffffff166002036119735750828202611c34565b8463ffffffff166020148061198e57508463ffffffff166021145b15611949578463ffffffff166020036119a5579219925b60005b63800000008516156119c7576401fffffffe600195861b1694016119a8565b9050611c34565b8563ffffffff16600f036119ef575065ffffffff0000601083901b16611c34565b8563ffffffff16602003611a23576119c78460031660080260180363ffffffff168363ffffffff16901c60ff1660086112c0565b8563ffffffff16602103611a58576119c78460021660080260100363ffffffff168363ffffffff16901c61ffff1660106112c0565b8563ffffffff16602203611a86575063ffffffff60086003851602811681811b198416918316901b17611c34565b8563ffffffff16602303611a9b575080611c34565b8563ffffffff16602403611acc578360031660080260180363ffffffff168263ffffffff16901c60ff169050611c34565b8563ffffffff16602503611afe578360021660080260100363ffffffff168263ffffffff16901c61ffff169050611c34565b8563ffffffff16602603611b2f575063ffffffff60086003851602601803811681811c198416918316901c17611c34565b8563ffffffff16602803611b64575060ff63ffffffff60086003861602601803811682811b9091188316918416901b17611c34565b8563ffffffff16602903611b9a575061ffff63ffffffff60086002861602601003811682811b9091188316918416901b17611c34565b8563ffffffff16602a03611bc8575063ffffffff60086003851602811681811c198316918416901c17611c34565b8563ffffffff16602b03611bdd575081611c34565b8563ffffffff16602e03611c0e575063ffffffff60086003851602601803811681811b198316918416901b17611c34565b8563ffffffff16603003611c23575080611c34565b8563ffffffff166038036118e75750815b9695505050505050565b60208363ffffffff1610611cae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f76616c69642072656769737465720000000000000000000000000000000000006044820152606401611264565b63ffffffff831615801590611cc05750805b15611cef5781848463ffffffff1660208110611cde57611cde612360565b63ffffffff90921660209290920201525b5050505060208101805163ffffffff8082169093526004019091169052565b60008463ffffffff16601003611d2957506060860151611f6f565b8463ffffffff16601103611d485763ffffffff84166060880152611f6f565b8463ffffffff16601203611d6157506040860151611f6f565b8463ffffffff16601303611d805763ffffffff84166040880152611f6f565b8463ffffffff16601803611db45763ffffffff600385810b9085900b02602081901c821660608a0152166040880152611f6f565b8463ffffffff16601903611de55763ffffffff84811681851602602081901c821660608a0152166040880152611f6f565b8463ffffffff16601a03611ea8578260030b600003611e60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d4950533a206469766973696f6e206279207a65726f000000000000000000006044820152606401611264565b8260030b8460030b81611e7557611e756123b3565b0763ffffffff166060880152600383810b9085900b81611e9757611e976123b3565b0563ffffffff166040880152611f6f565b8463ffffffff16601b03611f6f578263ffffffff16600003611f26576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d4950533a206469766973696f6e206279207a65726f000000000000000000006044820152606401611264565b8263ffffffff168463ffffffff1681611f4157611f416123b3565b0663ffffffff908116606089015283811690851681611f6257611f626123b3565b0463ffffffff1660408801525b63ffffffff821615611fa55780868363ffffffff1660208110611f9457611f94612360565b63ffffffff90921660209290920201525b50505060208401805163ffffffff808216909652600401909416909352505050565b6000611fd283612114565b6003841615611fe057600080fd5b6020830192601f8516601c0360031b83811b913563ffffffff90911b1916178460051c60005b601b81101561205e5760208601953582821c600116801561202e576001811461204357612054565b60008581526020839052604090209450612054565b600082815260208690526040902094505b5050600101612006565b509095945050505050565b60008061207583612114565b600384161561208357600080fd5b6020830192358460051c8160005b601b8110156120e95760208701963583821c60011680156120b957600181146120ce576120df565b600084815260208390526040902093506120df565b600082815260208590526040902093505b5050600101612091565b508714925050811561210b57601f8516601c0360031b81901c63ffffffff1692505b50935093915050565b3661038082018110156121a9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f636865636b207468617420746865726520697320656e6f7567682063616c6c6460448201527f61746100000000000000000000000000000000000000000000000000000000006064820152608401611264565b5050565b6040805161018081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101919091526101608101612213612218565b905290565b6040518061040001604052806020906020820280368337509192915050565b600060208083528351808285015260005b8181101561226457858101830151858201604001528201612248565b81811115612276576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b60008083601f8401126122bc57600080fd5b50813567ffffffffffffffff8111156122d457600080fd5b6020830191508360208285010111156111e157600080fd5b60008060008060006060868803121561230457600080fd5b853567ffffffffffffffff8082111561231c57600080fd5b61232889838a016122aa565b9097509550602088013591508082111561234157600080fd5b5061234e888289016122aa565b96999598509660400135949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600080604083850312156123a257600080fd5b505080516020909101519092909150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fdfea164736f6c634300080f000a"; bytes internal constant anchorStateRegistryCode = - hex"608060405234801561001057600080fd5b506004361061007d5760003560e01c80635e05fbd01161005b5780635e05fbd01461012a5780637258a8071461013d578063838c2d1e14610179578063f2b4e6171461018157600080fd5b806317cf21a91461008257806335e80ab31461009757806354fd4d50146100e1575b600080fd5b610095610090366004610b4c565b6101a7565b005b6002546100b79073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b61011d6040518060400160405280600a81526020017f322e302e302d72632e310000000000000000000000000000000000000000000081525081565b6040516100d89190610bea565b610095610138366004610cc6565b61061c565b61016461014b366004610df0565b6001602081905260009182526040909120805491015482565b604080519283526020830191909152016100d8565b610095610853565b7f0000000000000000000000005207cfa0166e8de0fcdfd78b4d17b68587be306d6100b7565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa158015610214573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102389190610e0d565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461029c576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060008373ffffffffffffffffffffffffffffffffffffffff1663fa24f7436040518163ffffffff1660e01b8152600401600060405180830381865afa1580156102ec573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526103329190810190610e2a565b92509250925060007f0000000000000000000000005207cfa0166e8de0fcdfd78b4d17b68587be306d73ffffffffffffffffffffffffffffffffffffffff16635f0150cb8585856040518463ffffffff1660e01b815260040161039793929190610efb565b6040805180830381865afa1580156103b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103d79190610f29565b5090508473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461043f576040517f6b0f689100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60028573ffffffffffffffffffffffffffffffffffffffff1663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa15801561048c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104b09190610f9f565b60028111156104c1576104c1610f70565b146104f8576040517f8f8af25f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052806105788773ffffffffffffffffffffffffffffffffffffffff1663bcef3b556040518163ffffffff1660e01b8152600401602060405180830381865afa158015610551573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105759190610fc0565b90565b81526020018673ffffffffffffffffffffffffffffffffffffffff16638b85902b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ec9190610fc0565b905263ffffffff909416600090815260016020818152604090922086518155959091015194019390935550505050565b600054610100900460ff161580801561063c5750600054600160ff909116105b806106565750303b158015610656575060005460ff166001145b6106e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561074457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b60005b83518110156107aa57600084828151811061076457610764610fd9565b60209081029190910181015180820151905163ffffffff1660009081526001808452604090912082518155919092015191015550806107a281611008565b915050610747565b50600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8416179055801561084e57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b600033905060008060008373ffffffffffffffffffffffffffffffffffffffff1663fa24f7436040518163ffffffff1660e01b8152600401600060405180830381865afa1580156108a8573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526108ee9190810190610e2a565b92509250925060007f0000000000000000000000005207cfa0166e8de0fcdfd78b4d17b68587be306d73ffffffffffffffffffffffffffffffffffffffff16635f0150cb8585856040518463ffffffff1660e01b815260040161095393929190610efb565b6040805180830381865afa15801561096f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109939190610f29565b5090508473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146109fb576040517f6b0f689100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160008563ffffffff1663ffffffff168152602001908152602001600020600101548573ffffffffffffffffffffffffffffffffffffffff16638b85902b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8d9190610fc0565b11610a99575050505050565b60028573ffffffffffffffffffffffffffffffffffffffff1663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ae6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b0a9190610f9f565b6002811115610b1b57610b1b610f70565b146104f8575050505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610b4957600080fd5b50565b600060208284031215610b5e57600080fd5b8135610b6981610b27565b9392505050565b60005b83811015610b8b578181015183820152602001610b73565b83811115610b9a576000848401525b50505050565b60008151808452610bb8816020860160208601610b70565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610b696020830184610ba0565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715610c4f57610c4f610bfd565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610c9c57610c9c610bfd565b604052919050565b63ffffffff81168114610b4957600080fd5b8035610cc181610b27565b919050565b6000806040808486031215610cda57600080fd5b833567ffffffffffffffff80821115610cf257600080fd5b818601915086601f830112610d0657600080fd5b8135602082821115610d1a57610d1a610bfd565b610d28818360051b01610c55565b8281528181019350606092830285018201928a841115610d4757600080fd5b948201945b83861015610dd457858b0381811215610d655760008081fd5b610d6d610c2c565b8735610d7881610ca4565b81527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08201891315610daa5760008081fd5b610db2610c2c565b8886013581528989013586820152818601528652509485019493820193610d4c565b509650610de2888201610cb6565b955050505050509250929050565b600060208284031215610e0257600080fd5b8135610b6981610ca4565b600060208284031215610e1f57600080fd5b8151610b6981610b27565b600080600060608486031215610e3f57600080fd5b8351610e4a81610ca4565b60208501516040860151919450925067ffffffffffffffff80821115610e6f57600080fd5b818601915086601f830112610e8357600080fd5b815181811115610e9557610e95610bfd565b610ec660207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601610c55565b9150808252876020828501011115610edd57600080fd5b610eee816020840160208601610b70565b5080925050509250925092565b63ffffffff84168152826020820152606060408201526000610f206060830184610ba0565b95945050505050565b60008060408385031215610f3c57600080fd5b8251610f4781610b27565b602084015190925067ffffffffffffffff81168114610f6557600080fd5b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600060208284031215610fb157600080fd5b815160038110610b6957600080fd5b600060208284031215610fd257600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611060577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b506001019056fea164736f6c634300080f000a"; + hex"608060405234801561001057600080fd5b506004361061007d5760003560e01c80635e05fbd01161005b5780635e05fbd01461012a5780637258a8071461013d578063838c2d1e14610179578063f2b4e6171461018157600080fd5b806317cf21a91461008257806335e80ab31461009757806354fd4d50146100e1575b600080fd5b610095610090366004610b4c565b6101a7565b005b6002546100b79073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b61011d6040518060400160405280600c81526020017f322e302e312d626574612e32000000000000000000000000000000000000000081525081565b6040516100d89190610bea565b610095610138366004610cc6565b61061c565b61016461014b366004610df0565b6001602081905260009182526040909120805491015482565b604080519283526020830191909152016100d8565b610095610853565b7f0000000000000000000000005207cfa0166e8de0fcdfd78b4d17b68587be306d6100b7565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa158015610214573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102389190610e0d565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461029c576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060008373ffffffffffffffffffffffffffffffffffffffff1663fa24f7436040518163ffffffff1660e01b8152600401600060405180830381865afa1580156102ec573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526103329190810190610e2a565b92509250925060007f0000000000000000000000005207cfa0166e8de0fcdfd78b4d17b68587be306d73ffffffffffffffffffffffffffffffffffffffff16635f0150cb8585856040518463ffffffff1660e01b815260040161039793929190610efb565b6040805180830381865afa1580156103b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103d79190610f29565b5090508473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461043f576040517f6b0f689100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60028573ffffffffffffffffffffffffffffffffffffffff1663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa15801561048c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104b09190610f9f565b60028111156104c1576104c1610f70565b146104f8576040517f8f8af25f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052806105788773ffffffffffffffffffffffffffffffffffffffff1663bcef3b556040518163ffffffff1660e01b8152600401602060405180830381865afa158015610551573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105759190610fc0565b90565b81526020018673ffffffffffffffffffffffffffffffffffffffff16638b85902b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ec9190610fc0565b905263ffffffff909416600090815260016020818152604090922086518155959091015194019390935550505050565b600054610100900460ff161580801561063c5750600054600160ff909116105b806106565750303b158015610656575060005460ff166001145b6106e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561074457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b60005b83518110156107aa57600084828151811061076457610764610fd9565b60209081029190910181015180820151905163ffffffff1660009081526001808452604090912082518155919092015191015550806107a281611008565b915050610747565b50600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8416179055801561084e57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b600033905060008060008373ffffffffffffffffffffffffffffffffffffffff1663fa24f7436040518163ffffffff1660e01b8152600401600060405180830381865afa1580156108a8573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526108ee9190810190610e2a565b92509250925060007f0000000000000000000000005207cfa0166e8de0fcdfd78b4d17b68587be306d73ffffffffffffffffffffffffffffffffffffffff16635f0150cb8585856040518463ffffffff1660e01b815260040161095393929190610efb565b6040805180830381865afa15801561096f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109939190610f29565b5090508473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146109fb576040517f6b0f689100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160008563ffffffff1663ffffffff168152602001908152602001600020600101548573ffffffffffffffffffffffffffffffffffffffff16638b85902b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8d9190610fc0565b11610a99575050505050565b60028573ffffffffffffffffffffffffffffffffffffffff1663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ae6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b0a9190610f9f565b6002811115610b1b57610b1b610f70565b146104f8575050505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610b4957600080fd5b50565b600060208284031215610b5e57600080fd5b8135610b6981610b27565b9392505050565b60005b83811015610b8b578181015183820152602001610b73565b83811115610b9a576000848401525b50505050565b60008151808452610bb8816020860160208601610b70565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610b696020830184610ba0565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715610c4f57610c4f610bfd565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610c9c57610c9c610bfd565b604052919050565b63ffffffff81168114610b4957600080fd5b8035610cc181610b27565b919050565b6000806040808486031215610cda57600080fd5b833567ffffffffffffffff80821115610cf257600080fd5b818601915086601f830112610d0657600080fd5b8135602082821115610d1a57610d1a610bfd565b610d28818360051b01610c55565b8281528181019350606092830285018201928a841115610d4757600080fd5b948201945b83861015610dd457858b0381811215610d655760008081fd5b610d6d610c2c565b8735610d7881610ca4565b81527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08201891315610daa5760008081fd5b610db2610c2c565b8886013581528989013586820152818601528652509485019493820193610d4c565b509650610de2888201610cb6565b955050505050509250929050565b600060208284031215610e0257600080fd5b8135610b6981610ca4565b600060208284031215610e1f57600080fd5b8151610b6981610b27565b600080600060608486031215610e3f57600080fd5b8351610e4a81610ca4565b60208501516040860151919450925067ffffffffffffffff80821115610e6f57600080fd5b818601915086601f830112610e8357600080fd5b815181811115610e9557610e95610bfd565b610ec660207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601610c55565b9150808252876020828501011115610edd57600080fd5b610eee816020840160208601610b70565b5080925050509250925092565b63ffffffff84168152826020820152606060408201526000610f206060830184610ba0565b95945050505050565b60008060408385031215610f3c57600080fd5b8251610f4781610b27565b602084015190925067ffffffffffffffff81168114610f6557600080fd5b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600060208284031215610fb157600080fd5b815160038110610b6957600080fd5b600060208284031215610fd257600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611060577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b506001019056fea164736f6c634300080f000a"; bytes internal constant acc33Code = - hex"6080604052600436106102f25760003560e01c806370872aa51161018f578063c6f0308c116100e1578063ec5e63081161008a578063fa24f74311610064578063fa24f74314610b18578063fa315aa914610b3c578063fe2bbeb214610b6f57600080fd5b8063ec5e630814610a95578063eff0f59214610ac8578063f8f43ff614610af857600080fd5b8063d6ae3cd5116100bb578063d6ae3cd514610a0f578063d8cc1a3c14610a42578063dabd396d14610a6257600080fd5b8063c6f0308c14610937578063cf09e0d0146109c1578063d5d44d80146109e257600080fd5b80638d450a9511610143578063bcef3b551161011d578063bcef3b55146108b7578063bd8da956146108f7578063c395e1ca1461091757600080fd5b80638d450a9514610777578063a445ece6146107aa578063bbdc02db1461087657600080fd5b80638129fc1c116101745780638129fc1c1461071a5780638980e0cc146107225780638b85902b1461073757600080fd5b806370872aa5146106f25780637b0f0adc1461070757600080fd5b80633fc8cef3116102485780635c0cba33116101fc5780636361506d116101d65780636361506d1461066c5780636b6716c0146106ac5780636f034409146106df57600080fd5b80635c0cba3314610604578063609d33341461063757806360e274641461064c57600080fd5b806354fd4d501161022d57806354fd4d501461055e57806357da950e146105b45780635a5fa2d9146105e457600080fd5b80633fc8cef314610518578063472777c61461054b57600080fd5b80632810e1d6116102aa57806337b1b2291161028457806337b1b229146104655780633a768463146104a55780633e3ac912146104d857600080fd5b80632810e1d6146103de5780632ad69aeb146103f357806330dbe5701461041357600080fd5b806319effeb4116102db57806319effeb414610339578063200d2ed21461038457806325fc2ace146103bf57600080fd5b806301935130146102f757806303c2924d14610319575b600080fd5b34801561030357600080fd5b506103176103123660046154e2565b610b9f565b005b34801561032557600080fd5b5061031761033436600461553d565b610ec0565b34801561034557600080fd5b506000546103669068010000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020015b60405180910390f35b34801561039057600080fd5b506000546103b290700100000000000000000000000000000000900460ff1681565b60405161037b919061558e565b3480156103cb57600080fd5b506008545b60405190815260200161037b565b3480156103ea57600080fd5b506103b2611566565b3480156103ff57600080fd5b506103d061040e36600461553d565b61180b565b34801561041f57600080fd5b506001546104409073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161037b565b34801561047157600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90033560601c610440565b3480156104b157600080fd5b507f000000000000000000000000444e09fe6d839273316a87002ab0efbea6fe7806610440565b3480156104e457600080fd5b50600054610508907201000000000000000000000000000000000000900460ff1681565b604051901515815260200161037b565b34801561052457600080fd5b507f000000000000000000000000ef179756ea6525afade217ca5ab0b1b5cfe0fd92610440565b6103176105593660046155cf565b611841565b34801561056a57600080fd5b506105a76040518060400160405280600a81526020017f312e332e302d72632e310000000000000000000000000000000000000000000081525081565b60405161037b9190615666565b3480156105c057600080fd5b506008546009546105cf919082565b6040805192835260208301919091520161037b565b3480156105f057600080fd5b506103d06105ff366004615679565b611853565b34801561061057600080fd5b507f000000000000000000000000970670459734a83899773a0fd45941b5afc1200e610440565b34801561064357600080fd5b506105a761188d565b34801561065857600080fd5b506103176106673660046156b7565b61189b565b34801561067857600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003603401356103d0565b3480156106b857600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610366565b6103176106ed3660046156e9565b611a42565b3480156106fe57600080fd5b506009546103d0565b6103176107153660046155cf565b61251b565b610317612528565b34801561072e57600080fd5b506002546103d0565b34801561074357600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401356103d0565b34801561078357600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006103d0565b3480156107b657600080fd5b506108226107c5366004615679565b6007602052600090815260409020805460019091015460ff821691610100810463ffffffff1691650100000000009091046fffffffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff1684565b60408051941515855263ffffffff90931660208501526fffffffffffffffffffffffffffffffff9091169183019190915273ffffffffffffffffffffffffffffffffffffffff16606082015260800161037b565b34801561088257600080fd5b5060405163ffffffff7f000000000000000000000000000000000000000000000000000000000000000016815260200161037b565b3480156108c357600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003601401356103d0565b34801561090357600080fd5b50610366610912366004615679565b612a81565b34801561092357600080fd5b506103d0610932366004615728565b612c60565b34801561094357600080fd5b50610957610952366004615679565b612e43565b6040805163ffffffff909816885273ffffffffffffffffffffffffffffffffffffffff968716602089015295909416948601949094526fffffffffffffffffffffffffffffffff9182166060860152608085015291821660a08401521660c082015260e00161037b565b3480156109cd57600080fd5b506000546103669067ffffffffffffffff1681565b3480156109ee57600080fd5b506103d06109fd3660046156b7565b60036020526000908152604090205481565b348015610a1b57600080fd5b507f00000000000000000000000000000000000000000000000000000000000003856103d0565b348015610a4e57600080fd5b50610317610a5d36600461575a565b612eda565b348015610a6e57600080fd5b507f00000000000000000000000000000000000000000000000000000000000004b0610366565b348015610aa157600080fd5b507f00000000000000000000000000000000000000000000000000000000000000046103d0565b348015610ad457600080fd5b50610508610ae3366004615679565b60046020526000908152604090205460ff1681565b348015610b0457600080fd5b50610317610b133660046155cf565b613509565b348015610b2457600080fd5b50610b2d6139c6565b60405161037b939291906157e4565b348015610b4857600080fd5b507f00000000000000000000000000000000000000000000000000000000000000086103d0565b348015610b7b57600080fd5b50610508610b8a366004615679565b60066020526000908152604090205460ff1681565b60008054700100000000000000000000000000000000900460ff166002811115610bcb57610bcb61555f565b14610c02576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000547201000000000000000000000000000000000000900460ff1615610c55576040517f0ea2e75200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610c8c367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013590565b90565b610ca3610c9e36869003860186615838565b613a41565b14610cda576040517f9cc00b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82606001358282604051610cef9291906158c5565b604051809103902014610d2e576040517fd81d583b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610d77610d7284848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613a9d92505050565b613b0a565b90506000610d9e82600881518110610d9157610d916158d5565b6020026020010151613cc0565b9050602081511115610ddc576040517fd81d583b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602081810151825190910360031b1c367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401358103610e51576040517fb8ed883000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050600180547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790555050600080547fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff1672010000000000000000000000000000000000001790555050565b60008054700100000000000000000000000000000000900460ff166002811115610eec57610eec61555f565b14610f23576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028381548110610f3857610f386158d5565b906000526020600020906005020190506000610f5384612a81565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b081169082161015610fbc576040517ff2440b5300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008481526006602052604090205460ff1615611005576040517ff1a9458100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600084815260056020526040902080548015801561102257508515155b156110bd578354640100000000900473ffffffffffffffffffffffffffffffffffffffff16600081156110555781611071565b600186015473ffffffffffffffffffffffffffffffffffffffff165b905061107d8187613d74565b50505060009485525050600660205250506040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b6000868152600760209081526040918290208251608081018452815460ff81161515808352610100820463ffffffff16948301949094526501000000000090046fffffffffffffffffffffffffffffffff16938101939093526001015473ffffffffffffffffffffffffffffffffffffffff166060830152611160576fffffffffffffffffffffffffffffffff6040820152600181526000869003611160578195505b600086826020015163ffffffff166111789190615933565b90506000838211611189578161118b565b835b602084015190915063ffffffff165b818110156112d75760008682815481106111b6576111b66158d5565b6000918252602080832090910154808352600690915260409091205490915060ff1661120e576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028281548110611223576112236158d5565b600091825260209091206005909102018054909150640100000000900473ffffffffffffffffffffffffffffffffffffffff161580156112805750600481015460408701516fffffffffffffffffffffffffffffffff9182169116115b156112c257600181015473ffffffffffffffffffffffffffffffffffffffff16606087015260048101546fffffffffffffffffffffffffffffffff1660408701525b505080806112cf9061594b565b91505061119a565b5063ffffffff818116602085810191825260008c81526007909152604090819020865181549351928801517fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009094169015157fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ff161761010092909416918202939093177fffffffffffffffffffffff00000000000000000000000000000000ffffffffff16650100000000006fffffffffffffffffffffffffffffffff909316929092029190911782556060850151600190920180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9093169290921790915584900361155b57606083015160008a815260066020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558915801561145757506000547201000000000000000000000000000000000000900460ff165b156114cc5760015473ffffffffffffffffffffffffffffffffffffffff1661147f818a613d74565b885473ffffffffffffffffffffffffffffffffffffffff909116640100000000027fffffffffffffffff0000000000000000000000000000000000000000ffffffff909116178855611559565b61151373ffffffffffffffffffffffffffffffffffffffff8216156114f1578161150d565b600189015473ffffffffffffffffffffffffffffffffffffffff165b89613d74565b87547fffffffffffffffff0000000000000000000000000000000000000000ffffffff1664010000000073ffffffffffffffffffffffffffffffffffffffff8316021788555b505b505050505050505050565b600080600054700100000000000000000000000000000000900460ff1660028111156115945761159461555f565b146115cb576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000805260066020527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f85460ff1661162f576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600260008154811061165b5761165b6158d5565b6000918252602090912060059091020154640100000000900473ffffffffffffffffffffffffffffffffffffffff1614611696576001611699565b60025b6000805467ffffffffffffffff421668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff82168117835592935083927fffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffff000000000000000000ffffffffffffffff9091161770010000000000000000000000000000000083600281111561174a5761174a61555f565b02179055600281111561175f5761175f61555f565b6040517f5e186f09b9c93491f14e277eea7faa5de6a2d4bda75a79af7a3684fbfb42da6090600090a27f000000000000000000000000970670459734a83899773a0fd45941b5afc1200e73ffffffffffffffffffffffffffffffffffffffff1663838c2d1e6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156117f057600080fd5b505af1158015611804573d6000803e3d6000fd5b5050505090565b6005602052816000526040600020818154811061182757600080fd5b90600052602060002001600091509150505481565b905090565b61184e8383836001611a42565b505050565b6000818152600760209081526040808320600590925282208054825461188490610100900463ffffffff1682615983565b95945050505050565b606061183c60546020613e75565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260036020526040812080549082905590819003611900576040517f17bfe5f700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517ff3fef3a300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152602482018390527f000000000000000000000000ef179756ea6525afade217ca5ab0b1b5cfe0fd92169063f3fef3a390604401600060405180830381600087803b15801561199057600080fd5b505af11580156119a4573d6000803e3d6000fd5b5050505060008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114611a02576040519150601f19603f3d011682016040523d82523d6000602084013e611a07565b606091505b505090508061184e576040517f83e6cc6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008054700100000000000000000000000000000000900460ff166002811115611a6e57611a6e61555f565b14611aa5576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028481548110611aba57611aba6158d5565b60009182526020918290206040805160e0810182526005909302909101805463ffffffff8116845273ffffffffffffffffffffffffffffffffffffffff64010000000090910481169484019490945260018101549093169082015260028201546fffffffffffffffffffffffffffffffff908116606083015260038301546080830181905260049093015480821660a084015270010000000000000000000000000000000090041660c082015291508514611ba1576040517f3014033200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60a0810151600083156fffffffffffffffffffffffffffffffff83161760011b90506000611c61826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169050861580611c9c5750611c997f00000000000000000000000000000000000000000000000000000000000000046002615933565b81145b8015611ca6575084155b15611cdd576040517fa42637bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000547201000000000000000000000000000000000000900460ff168015611d03575086155b15611d3a576040517f0ea2e75200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000008811115611d94576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611dbf7f00000000000000000000000000000000000000000000000000000000000000046001615933565b8103611dd157611dd186888588613ec7565b34611ddb83612c60565b14611e12576040517f8620aa1900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611e1d88612a81565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b0811690821603611e85576040517f3381d11400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611eb260017f0000000000000000000000000000000000000000000000000000000000000008615983565b8303611ff0577f000000000000000000000000444e09fe6d839273316a87002ab0efbea6fe780673ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f47919061599a565b73ffffffffffffffffffffffffffffffffffffffff1663f3f480d96040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f91573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fb591906159b7565b611fe9907f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff166159d0565b9050612083565b61201b60017f0000000000000000000000000000000000000000000000000000000000000004615983565b830361205657611fe97f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1660026159fc565b507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff165b6120b7817f00000000000000000000000000000000000000000000000000000000000004b067ffffffffffffffff16615a2c565b67ffffffffffffffff166120d28367ffffffffffffffff1690565b67ffffffffffffffff16111561211957612116817f00000000000000000000000000000000000000000000000000000000000004b067ffffffffffffffff16615a2c565b91505b6000604083901b421760008a8152608087901b6fffffffffffffffffffffffffffffffff8d1617602052604081209192509060008181526004602052604090205490915060ff1615612197576040517f80497e3b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60016004600083815260200190815260200160002060006101000a81548160ff02191690831515021790555060026040518060e001604052808d63ffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020013373ffffffffffffffffffffffffffffffffffffffff168152602001346fffffffffffffffffffffffffffffffff1681526020018c8152602001886fffffffffffffffffffffffffffffffff168152602001846fffffffffffffffffffffffffffffffff16815250908060018154018082558091505060019003906000526020600020906005020160009091909190915060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060608201518160020160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055506080820151816003015560a08201518160040160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555060c08201518160040160106101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055505050600560008c8152602001908152602001600020600160028054905061242d9190615983565b81546001810183556000928352602083200155604080517fd0e30db0000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ef179756ea6525afade217ca5ab0b1b5cfe0fd92169263d0e30db09234926004808301939282900301818588803b1580156124c557600080fd5b505af11580156124d9573d6000803e3d6000fd5b50506040513393508d92508e91507f9b3245740ec3b155098a55be84957a4da13eaf7f14a8bc6f53126c0b9350f2be90600090a4505050505050505050505050565b61184e8383836000611a42565b60005471010000000000000000000000000000000000900460ff161561257a576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f7258a80700000000000000000000000000000000000000000000000000000000815263ffffffff7f0000000000000000000000000000000000000000000000000000000000000000166004820152600090819073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000970670459734a83899773a0fd45941b5afc1200e1690637258a807906024016040805180830381865afa15801561262e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126529190615a55565b90925090508161268e576040517f6a6bc3b200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518082019091528281526020018190526008829055600981905536607a146126c157639824bdab6000526004601cfd5b80367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401351161275b576040517ff40239db000000000000000000000000000000000000000000000000000000008152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013560048201526024015b60405180910390fd5b6040805160e08101825263ffffffff8082526000602083018181527ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe369081013560f01c90038035606090811c868801908152346fffffffffffffffffffffffffffffffff81811693890193845260149094013560808901908152600160a08a0181815242871660c08c019081526002805493840181558a529a5160059092027f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace81018054995173ffffffffffffffffffffffffffffffffffffffff908116640100000000027fffffffffffffffff000000000000000000000000000000000000000000000000909b1694909c16939093179890981790915592517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5acf87018054918a167fffffffffffffffffffffffff000000000000000000000000000000000000000090921691909117905592517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad0860180549186167fffffffffffffffffffffffffffffffff0000000000000000000000000000000090921691909117905591517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad185015551955182167001000000000000000000000000000000000295909116949094177f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad29091015580547fffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffff167101000000000000000000000000000000000017815583517fd0e30db000000000000000000000000000000000000000000000000000000000815293517f000000000000000000000000ef179756ea6525afade217ca5ab0b1b5cfe0fd929092169363d0e30db093926004828101939282900301818588803b158015612a3057600080fd5b505af1158015612a44573d6000803e3d6000fd5b5050600080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000164267ffffffffffffffff161790555050505050565b600080600054700100000000000000000000000000000000900460ff166002811115612aaf57612aaf61555f565b14612ae6576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028381548110612afb57612afb6158d5565b600091825260208220600590910201805490925063ffffffff90811614612b6a57815460028054909163ffffffff16908110612b3957612b396158d5565b906000526020600020906005020160040160109054906101000a90046fffffffffffffffffffffffffffffffff1690505b6004820154600090612ba290700100000000000000000000000000000000900467ffffffffffffffff165b67ffffffffffffffff1690565b612bb69067ffffffffffffffff1642615983565b612bd5612b95846fffffffffffffffffffffffffffffffff1660401c90565b67ffffffffffffffff16612be99190615933565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b01667ffffffffffffffff168167ffffffffffffffff1611612c365780611884565b7f00000000000000000000000000000000000000000000000000000000000004b095945050505050565b600080612cff836fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690507f0000000000000000000000000000000000000000000000000000000000000008811115612d5e576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b642e90edd00062061a806311e1a3006000612d798383615aa8565b9050670de0b6b3a76400006000612db0827f0000000000000000000000000000000000000000000000000000000000000008615abc565b90506000612dce612dc9670de0b6b3a764000086615abc565b614078565b90506000612ddc84846142d3565b90506000612dea8383614322565b90506000612df782614350565b90506000612e1682612e11670de0b6b3a76400008f615abc565b614538565b90506000612e248b83614322565b9050612e30818d615abc565b9f9e505050505050505050505050505050565b60028181548110612e5357600080fd5b60009182526020909120600590910201805460018201546002830154600384015460049094015463ffffffff8416955064010000000090930473ffffffffffffffffffffffffffffffffffffffff908116949216926fffffffffffffffffffffffffffffffff91821692918082169170010000000000000000000000000000000090041687565b60008054700100000000000000000000000000000000900460ff166002811115612f0657612f0661555f565b14612f3d576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028781548110612f5257612f526158d5565b6000918252602082206005919091020160048101549092506fffffffffffffffffffffffffffffffff16908715821760011b9050612fb17f00000000000000000000000000000000000000000000000000000000000000086001615933565b61304d826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1614613087576040517f5f53dd9800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080891561317e576130da7f00000000000000000000000000000000000000000000000000000000000000047f0000000000000000000000000000000000000000000000000000000000000008615983565b6001901b6130f9846fffffffffffffffffffffffffffffffff16614569565b6fffffffffffffffffffffffffffffffff166131159190615af9565b156131525761314961313a60016fffffffffffffffffffffffffffffffff8716615b0d565b865463ffffffff166000614608565b60030154613174565b7f00000000000000000000000000000000000000000000000000000000000000005b91508490506131a8565b600385015491506131a561313a6fffffffffffffffffffffffffffffffff86166001615b36565b90505b600882901b60088a8a6040516131bf9291906158c5565b6040518091039020901b14613200576040517f696550ff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061320b8c6146ec565b9050600061321a836003015490565b6040517fe14ced320000000000000000000000000000000000000000000000000000000081527f000000000000000000000000444e09fe6d839273316a87002ab0efbea6fe780673ffffffffffffffffffffffffffffffffffffffff169063e14ced3290613294908f908f908f908f908a90600401615baa565b6020604051808303816000875af11580156132b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132d791906159b7565b600485015491149150600090600290613382906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b61341e896fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b6134289190615be4565b6134329190615c07565b60ff161590508115158103613473576040517ffb4e40dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8754640100000000900473ffffffffffffffffffffffffffffffffffffffff16156134ca576040517f9071e6af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505085547fffffffffffffffff0000000000000000000000000000000000000000ffffffff163364010000000002179095555050505050505050505050565b60008054700100000000000000000000000000000000900460ff1660028111156135355761353561555f565b1461356c576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060008061357b8661471b565b9350935093509350600061359185858585614b24565b905060007f000000000000000000000000444e09fe6d839273316a87002ab0efbea6fe780673ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015613600573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613624919061599a565b90506001890361371c5773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a84613680367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036034013590565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815260048101939093526024830191909152604482015260206064820152608481018a905260a4015b6020604051808303816000875af11580156136f2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061371691906159b7565b5061155b565b600289036137485773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a8489613680565b600389036137745773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a8487613680565b600489036138fb5760006137ba6fffffffffffffffffffffffffffffffff85167f0000000000000000000000000000000000000000000000000000000000000004614bde565b6009546137c79190615933565b6137d2906001615933565b9050367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360540135811061383b57367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036054013561383d565b805b905073ffffffffffffffffffffffffffffffffffffffff82166352f0f3ad8b8560405160e084901b7fffffffff000000000000000000000000000000000000000000000000000000001681526004810192909252602482015260c084901b604482015260086064820152608481018b905260a4016020604051808303816000875af11580156138d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138f491906159b7565b505061155b565b60058903613994576040517f52f0f3ad000000000000000000000000000000000000000000000000000000008152600481018a9052602481018390527f000000000000000000000000000000000000000000000000000000000000038560c01b6044820152600860648201526084810188905273ffffffffffffffffffffffffffffffffffffffff8216906352f0f3ad9060a4016136d3565b6040517fff137e6500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000000367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003601401356060613a1f61188d565b9050909192565b600081831015613a365781613a38565b825b90505b92915050565b60008160000151826020015183604001518460600151604051602001613a80949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b60408051808201909152600080825260208201528151600003613aec576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50604080518082019091528151815260209182019181019190915290565b60606000806000613b1a85614c8c565b919450925090506001816001811115613b3557613b3561555f565b14613b6c576040517f4b9c6abe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8451613b788385615933565b14613baf576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808252610420820190925290816020015b6040805180820190915260008082526020820152815260200190600190039081613bc65790505093506000835b8651811015613cb457600080613c396040518060400160405280858c60000151613c1d9190615983565b8152602001858c60200151613c329190615933565b9052614c8c565b509150915060405180604001604052808383613c559190615933565b8152602001848b60200151613c6a9190615933565b815250888581518110613c7f57613c7f6158d5565b6020908102919091010152613c95600185615933565b9350613ca18183615933565b613cab9084615933565b92505050613bf3565b50845250919392505050565b60606000806000613cd085614c8c565b919450925090506000816001811115613ceb57613ceb61555f565b14613d22576040517f1ff9b2e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613d2c8284615933565b855114613d65576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6118848560200151848461512a565b600281015473ffffffffffffffffffffffffffffffffffffffff8316600090815260036020526040812080546fffffffffffffffffffffffffffffffff90931692839290613dc3908490615933565b90915550506040517f7eee288d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018390527f000000000000000000000000ef179756ea6525afade217ca5ab0b1b5cfe0fd921690637eee288d90604401600060405180830381600087803b158015613e5857600080fd5b505af1158015613e6c573d6000803e3d6000fd5b50505050505050565b604051818152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90038284820160208401378260208301016000815260208101604052505092915050565b6000613ee66fffffffffffffffffffffffffffffffff84166001615b36565b90506000613ef682866001614608565b9050600086901a8380613fe25750613f2f60027f0000000000000000000000000000000000000000000000000000000000000004615af9565b6004830154600290613fd3906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b613fdd9190615c07565b60ff16145b1561403a5760ff811660011480613ffc575060ff81166002145b614035576040517ff40239db00000000000000000000000000000000000000000000000000000000815260048101889052602401612752565b613e6c565b60ff811615613e6c576040517ff40239db00000000000000000000000000000000000000000000000000000000815260048101889052602401612752565b6fffffffffffffffffffffffffffffffff811160071b81811c67ffffffffffffffff1060061b1781811c63ffffffff1060051b1781811c61ffff1060041b1781811c60ff1060031b17600082136140d757631615e6386000526004601cfd5b7ff8f9f9faf9fdfafbf9fdfcfdfafbfcfef9fafdfafcfcfbfefafafcfbffffffff6f8421084210842108cc6318c6db6d54be83831c1c601f161a1890811b609f90811c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506029190037d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b302017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d90565b60007812725dd1d243aba0e75fe645cc4873f9e65afe688c928e1f218311670de0b6b3a76400000215820261431057637c5f487d6000526004601cfd5b50670de0b6b3a7640000919091020490565b6000816000190483118202156143405763bac65e5b6000526004601cfd5b50670de0b6b3a764000091020490565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdc0d0570925a462d7821361437e57919050565b680755bf798b4a1bf1e5821261439c5763a37bfec96000526004601cfd5b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b6000613a38670de0b6b3a76400008361455086614078565b61455a9190615c29565b6145649190615ce5565b614350565b6000806145f6837e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b600160ff919091161b90920392915050565b600080826146515761464c6fffffffffffffffffffffffffffffffff86167f00000000000000000000000000000000000000000000000000000000000000046151bf565b61466c565b61466c856fffffffffffffffffffffffffffffffff1661534b565b905060028481548110614681576146816158d5565b906000526020600020906005020191505b60048201546fffffffffffffffffffffffffffffffff8281169116146146e457815460028054909163ffffffff169081106146cf576146cf6158d5565b90600052602060002090600502019150614692565b509392505050565b60008060008060006146fd8661471b565b935093509350935061471184848484614b24565b9695505050505050565b600080600080600085905060006002828154811061473b5761473b6158d5565b600091825260209091206004600590920201908101549091507f000000000000000000000000000000000000000000000000000000000000000490614812906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff161161484c576040517fb34b5c2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000815b60048301547f000000000000000000000000000000000000000000000000000000000000000490614913906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff16925082111561498857825463ffffffff166149527f00000000000000000000000000000000000000000000000000000000000000046001615933565b830361495c578391505b6002818154811061496f5761496f6158d5565b9060005260206000209060050201935080945050614850565b600481810154908401546fffffffffffffffffffffffffffffffff91821691166000816fffffffffffffffffffffffffffffffff166149f16149dc856fffffffffffffffffffffffffffffffff1660011c90565b6fffffffffffffffffffffffffffffffff1690565b6fffffffffffffffffffffffffffffffff161490508015614ac0576000614a29836fffffffffffffffffffffffffffffffff16614569565b6fffffffffffffffffffffffffffffffff161115614a94576000614a6b614a6360016fffffffffffffffffffffffffffffffff8616615b0d565b896001614608565b6003810154600490910154909c506fffffffffffffffffffffffffffffffff169a50614a9a9050565b6008549a505b600386015460048701549099506fffffffffffffffffffffffffffffffff169750614b16565b6000614ae2614a636fffffffffffffffffffffffffffffffff85166001615b36565b6003808901546004808b015492840154930154909e506fffffffffffffffffffffffffffffffff9182169d50919b50169850505b505050505050509193509193565b60006fffffffffffffffffffffffffffffffff841615614b915760408051602081018790526fffffffffffffffffffffffffffffffff8087169282019290925260608101859052908316608082015260a00160405160208183030381529060405280519060200120611884565b8282604051602001614bbf9291909182526fffffffffffffffffffffffffffffffff16602082015260400190565b6040516020818303038152906040528051906020012095945050505050565b600080614c6b847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690508083036001841b600180831b0386831b17039250505092915050565b60008060008360000151600003614ccf576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020840151805160001a607f8111614cf4576000600160009450945094505050615123565b60b78111614e0a576000614d09608083615983565b905080876000015111614d48576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001838101517fff00000000000000000000000000000000000000000000000000000000000000169082148015614dc057507f80000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008216105b15614df7576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5060019550935060009250615123915050565b60bf8111614f68576000614e1f60b783615983565b905080876000015111614e5e576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614ec0576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c60378111614f08576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614f128184615933565b895111614f4b576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614f56836001615933565b97509550600094506151239350505050565b60f78111614fcd576000614f7d60c083615983565b905080876000015111614fbc576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600195509350849250615123915050565b6000614fda60f783615983565b905080876000015111615019576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff0000000000000000000000000000000000000000000000000000000000000016600081900361507b576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c603781116150c3576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6150cd8184615933565b895111615106576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b615111836001615933565b97509550600194506151239350505050565b9193909250565b60608167ffffffffffffffff81111561514557615145615809565b6040519080825280601f01601f19166020018201604052801561516f576020820181803683370190505b50905081156151b85760006151848486615933565b90506020820160005b848110156151a557828101518282015260200161518d565b848111156151b4576000858301525b5050505b9392505050565b60008161525e846fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff16116152745763b34b5c226000526004601cfd5b61527d8361534b565b90508161531c826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1611613a3b57613a38615332836001615933565b6fffffffffffffffffffffffffffffffff8316906153f0565b600081196001830116816153df827e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169390931c8015179392505050565b60008061547d847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169050808303600180821b0385821b179250505092915050565b60008083601f8401126154ab57600080fd5b50813567ffffffffffffffff8111156154c357600080fd5b6020830191508360208285010111156154db57600080fd5b9250929050565b600080600083850360a08112156154f857600080fd5b608081121561550657600080fd5b50839250608084013567ffffffffffffffff81111561552457600080fd5b61553086828701615499565b9497909650939450505050565b6000806040838503121561555057600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60208101600383106155c9577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b6000806000606084860312156155e457600080fd5b505081359360208301359350604090920135919050565b6000815180845260005b8181101561562157602081850181015186830182015201615605565b81811115615633576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000613a3860208301846155fb565b60006020828403121561568b57600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff811681146156b457600080fd5b50565b6000602082840312156156c957600080fd5b81356151b881615692565b803580151581146156e457600080fd5b919050565b600080600080608085870312156156ff57600080fd5b84359350602085013592506040850135915061571d606086016156d4565b905092959194509250565b60006020828403121561573a57600080fd5b81356fffffffffffffffffffffffffffffffff811681146151b857600080fd5b6000806000806000806080878903121561577357600080fd5b86359550615783602088016156d4565b9450604087013567ffffffffffffffff808211156157a057600080fd5b6157ac8a838b01615499565b909650945060608901359150808211156157c557600080fd5b506157d289828a01615499565b979a9699509497509295939492505050565b63ffffffff8416815282602082015260606040820152600061188460608301846155fb565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006080828403121561584a57600080fd5b6040516080810181811067ffffffffffffffff82111715615894577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561594657615946615904565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361597c5761597c615904565b5060010190565b60008282101561599557615995615904565b500390565b6000602082840312156159ac57600080fd5b81516151b881615692565b6000602082840312156159c957600080fd5b5051919050565b600067ffffffffffffffff8083168185168083038211156159f3576159f3615904565b01949350505050565b600067ffffffffffffffff80831681851681830481118215151615615a2357615a23615904565b02949350505050565b600067ffffffffffffffff83811690831681811015615a4d57615a4d615904565b039392505050565b60008060408385031215615a6857600080fd5b505080516020909101519092909150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082615ab757615ab7615a79565b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615af457615af4615904565b500290565b600082615b0857615b08615a79565b500690565b60006fffffffffffffffffffffffffffffffff83811690831681811015615a4d57615a4d615904565b60006fffffffffffffffffffffffffffffffff8083168185168083038211156159f3576159f3615904565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b606081526000615bbe606083018789615b61565b8281036020840152615bd1818688615b61565b9150508260408301529695505050505050565b600060ff821660ff841680821015615bfe57615bfe615904565b90039392505050565b600060ff831680615c1a57615c1a615a79565b8060ff84160691505092915050565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600084136000841385830485118282161615615c6a57615c6a615904565b7f80000000000000000000000000000000000000000000000000000000000000006000871286820588128184161615615ca557615ca5615904565b60008712925087820587128484161615615cc157615cc1615904565b87850587128184161615615cd757615cd7615904565b505050929093029392505050565b600082615cf457615cf4615a79565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f800000000000000000000000000000000000000000000000000000000000000083141615615d4857615d48615904565b50059056fea164736f6c634300080f000a"; + hex"6080604052600436106102f25760003560e01c806370872aa51161018f578063c6f0308c116100e1578063ec5e63081161008a578063fa24f74311610064578063fa24f74314610b18578063fa315aa914610b3c578063fe2bbeb214610b6f57600080fd5b8063ec5e630814610a95578063eff0f59214610ac8578063f8f43ff614610af857600080fd5b8063d6ae3cd5116100bb578063d6ae3cd514610a0f578063d8cc1a3c14610a42578063dabd396d14610a6257600080fd5b8063c6f0308c14610937578063cf09e0d0146109c1578063d5d44d80146109e257600080fd5b80638d450a9511610143578063bcef3b551161011d578063bcef3b55146108b7578063bd8da956146108f7578063c395e1ca1461091757600080fd5b80638d450a9514610777578063a445ece6146107aa578063bbdc02db1461087657600080fd5b80638129fc1c116101745780638129fc1c1461071a5780638980e0cc146107225780638b85902b1461073757600080fd5b806370872aa5146106f25780637b0f0adc1461070757600080fd5b80633fc8cef3116102485780635c0cba33116101fc5780636361506d116101d65780636361506d1461066c5780636b6716c0146106ac5780636f034409146106df57600080fd5b80635c0cba3314610604578063609d33341461063757806360e274641461064c57600080fd5b806354fd4d501161022d57806354fd4d501461055e57806357da950e146105b45780635a5fa2d9146105e457600080fd5b80633fc8cef314610518578063472777c61461054b57600080fd5b80632810e1d6116102aa57806337b1b2291161028457806337b1b229146104655780633a768463146104a55780633e3ac912146104d857600080fd5b80632810e1d6146103de5780632ad69aeb146103f357806330dbe5701461041357600080fd5b806319effeb4116102db57806319effeb414610339578063200d2ed21461038457806325fc2ace146103bf57600080fd5b806301935130146102f757806303c2924d14610319575b600080fd5b34801561030357600080fd5b506103176103123660046154e2565b610b9f565b005b34801561032557600080fd5b5061031761033436600461553d565b610ec0565b34801561034557600080fd5b506000546103669068010000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020015b60405180910390f35b34801561039057600080fd5b506000546103b290700100000000000000000000000000000000900460ff1681565b60405161037b919061558e565b3480156103cb57600080fd5b506008545b60405190815260200161037b565b3480156103ea57600080fd5b506103b2611566565b3480156103ff57600080fd5b506103d061040e36600461553d565b61180b565b34801561041f57600080fd5b506001546104409073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161037b565b34801561047157600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90033560601c610440565b3480156104b157600080fd5b507f000000000000000000000000180cbe2ebb9f37d3a3c542ddc2546fd160555a73610440565b3480156104e457600080fd5b50600054610508907201000000000000000000000000000000000000900460ff1681565b604051901515815260200161037b565b34801561052457600080fd5b507f000000000000000000000000ef179756ea6525afade217ca5ab0b1b5cfe0fd92610440565b6103176105593660046155cf565b611841565b34801561056a57600080fd5b506105a76040518060400160405280600c81526020017f312e332e312d626574612e32000000000000000000000000000000000000000081525081565b60405161037b9190615666565b3480156105c057600080fd5b506008546009546105cf919082565b6040805192835260208301919091520161037b565b3480156105f057600080fd5b506103d06105ff366004615679565b611853565b34801561061057600080fd5b507f000000000000000000000000970670459734a83899773a0fd45941b5afc1200e610440565b34801561064357600080fd5b506105a761188d565b34801561065857600080fd5b506103176106673660046156b7565b61189b565b34801561067857600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003603401356103d0565b3480156106b857600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610366565b6103176106ed3660046156e9565b611a42565b3480156106fe57600080fd5b506009546103d0565b6103176107153660046155cf565b61251b565b610317612528565b34801561072e57600080fd5b506002546103d0565b34801561074357600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401356103d0565b34801561078357600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006103d0565b3480156107b657600080fd5b506108226107c5366004615679565b6007602052600090815260409020805460019091015460ff821691610100810463ffffffff1691650100000000009091046fffffffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff1684565b60408051941515855263ffffffff90931660208501526fffffffffffffffffffffffffffffffff9091169183019190915273ffffffffffffffffffffffffffffffffffffffff16606082015260800161037b565b34801561088257600080fd5b5060405163ffffffff7f000000000000000000000000000000000000000000000000000000000000000016815260200161037b565b3480156108c357600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003601401356103d0565b34801561090357600080fd5b50610366610912366004615679565b612a81565b34801561092357600080fd5b506103d0610932366004615728565b612c60565b34801561094357600080fd5b50610957610952366004615679565b612e43565b6040805163ffffffff909816885273ffffffffffffffffffffffffffffffffffffffff968716602089015295909416948601949094526fffffffffffffffffffffffffffffffff9182166060860152608085015291821660a08401521660c082015260e00161037b565b3480156109cd57600080fd5b506000546103669067ffffffffffffffff1681565b3480156109ee57600080fd5b506103d06109fd3660046156b7565b60036020526000908152604090205481565b348015610a1b57600080fd5b507f00000000000000000000000000000000000000000000000000000000000003856103d0565b348015610a4e57600080fd5b50610317610a5d36600461575a565b612eda565b348015610a6e57600080fd5b507f00000000000000000000000000000000000000000000000000000000000004b0610366565b348015610aa157600080fd5b507f00000000000000000000000000000000000000000000000000000000000000046103d0565b348015610ad457600080fd5b50610508610ae3366004615679565b60046020526000908152604090205460ff1681565b348015610b0457600080fd5b50610317610b133660046155cf565b613509565b348015610b2457600080fd5b50610b2d6139c6565b60405161037b939291906157e4565b348015610b4857600080fd5b507f00000000000000000000000000000000000000000000000000000000000000086103d0565b348015610b7b57600080fd5b50610508610b8a366004615679565b60066020526000908152604090205460ff1681565b60008054700100000000000000000000000000000000900460ff166002811115610bcb57610bcb61555f565b14610c02576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000547201000000000000000000000000000000000000900460ff1615610c55576040517f0ea2e75200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610c8c367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013590565b90565b610ca3610c9e36869003860186615838565b613a41565b14610cda576040517f9cc00b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82606001358282604051610cef9291906158c5565b604051809103902014610d2e576040517fd81d583b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610d77610d7284848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613a9d92505050565b613b0a565b90506000610d9e82600881518110610d9157610d916158d5565b6020026020010151613cc0565b9050602081511115610ddc576040517fd81d583b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602081810151825190910360031b1c367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401358103610e51576040517fb8ed883000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050600180547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790555050600080547fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff1672010000000000000000000000000000000000001790555050565b60008054700100000000000000000000000000000000900460ff166002811115610eec57610eec61555f565b14610f23576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028381548110610f3857610f386158d5565b906000526020600020906005020190506000610f5384612a81565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b081169082161015610fbc576040517ff2440b5300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008481526006602052604090205460ff1615611005576040517ff1a9458100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600084815260056020526040902080548015801561102257508515155b156110bd578354640100000000900473ffffffffffffffffffffffffffffffffffffffff16600081156110555781611071565b600186015473ffffffffffffffffffffffffffffffffffffffff165b905061107d8187613d74565b50505060009485525050600660205250506040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b6000868152600760209081526040918290208251608081018452815460ff81161515808352610100820463ffffffff16948301949094526501000000000090046fffffffffffffffffffffffffffffffff16938101939093526001015473ffffffffffffffffffffffffffffffffffffffff166060830152611160576fffffffffffffffffffffffffffffffff6040820152600181526000869003611160578195505b600086826020015163ffffffff166111789190615933565b90506000838211611189578161118b565b835b602084015190915063ffffffff165b818110156112d75760008682815481106111b6576111b66158d5565b6000918252602080832090910154808352600690915260409091205490915060ff1661120e576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028281548110611223576112236158d5565b600091825260209091206005909102018054909150640100000000900473ffffffffffffffffffffffffffffffffffffffff161580156112805750600481015460408701516fffffffffffffffffffffffffffffffff9182169116115b156112c257600181015473ffffffffffffffffffffffffffffffffffffffff16606087015260048101546fffffffffffffffffffffffffffffffff1660408701525b505080806112cf9061594b565b91505061119a565b5063ffffffff818116602085810191825260008c81526007909152604090819020865181549351928801517fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009094169015157fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ff161761010092909416918202939093177fffffffffffffffffffffff00000000000000000000000000000000ffffffffff16650100000000006fffffffffffffffffffffffffffffffff909316929092029190911782556060850151600190920180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9093169290921790915584900361155b57606083015160008a815260066020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558915801561145757506000547201000000000000000000000000000000000000900460ff165b156114cc5760015473ffffffffffffffffffffffffffffffffffffffff1661147f818a613d74565b885473ffffffffffffffffffffffffffffffffffffffff909116640100000000027fffffffffffffffff0000000000000000000000000000000000000000ffffffff909116178855611559565b61151373ffffffffffffffffffffffffffffffffffffffff8216156114f1578161150d565b600189015473ffffffffffffffffffffffffffffffffffffffff165b89613d74565b87547fffffffffffffffff0000000000000000000000000000000000000000ffffffff1664010000000073ffffffffffffffffffffffffffffffffffffffff8316021788555b505b505050505050505050565b600080600054700100000000000000000000000000000000900460ff1660028111156115945761159461555f565b146115cb576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000805260066020527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f85460ff1661162f576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600260008154811061165b5761165b6158d5565b6000918252602090912060059091020154640100000000900473ffffffffffffffffffffffffffffffffffffffff1614611696576001611699565b60025b6000805467ffffffffffffffff421668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff82168117835592935083927fffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffff000000000000000000ffffffffffffffff9091161770010000000000000000000000000000000083600281111561174a5761174a61555f565b02179055600281111561175f5761175f61555f565b6040517f5e186f09b9c93491f14e277eea7faa5de6a2d4bda75a79af7a3684fbfb42da6090600090a27f000000000000000000000000970670459734a83899773a0fd45941b5afc1200e73ffffffffffffffffffffffffffffffffffffffff1663838c2d1e6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156117f057600080fd5b505af1158015611804573d6000803e3d6000fd5b5050505090565b6005602052816000526040600020818154811061182757600080fd5b90600052602060002001600091509150505481565b905090565b61184e8383836001611a42565b505050565b6000818152600760209081526040808320600590925282208054825461188490610100900463ffffffff1682615983565b95945050505050565b606061183c60546020613e75565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260036020526040812080549082905590819003611900576040517f17bfe5f700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517ff3fef3a300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152602482018390527f000000000000000000000000ef179756ea6525afade217ca5ab0b1b5cfe0fd92169063f3fef3a390604401600060405180830381600087803b15801561199057600080fd5b505af11580156119a4573d6000803e3d6000fd5b5050505060008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114611a02576040519150601f19603f3d011682016040523d82523d6000602084013e611a07565b606091505b505090508061184e576040517f83e6cc6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008054700100000000000000000000000000000000900460ff166002811115611a6e57611a6e61555f565b14611aa5576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028481548110611aba57611aba6158d5565b60009182526020918290206040805160e0810182526005909302909101805463ffffffff8116845273ffffffffffffffffffffffffffffffffffffffff64010000000090910481169484019490945260018101549093169082015260028201546fffffffffffffffffffffffffffffffff908116606083015260038301546080830181905260049093015480821660a084015270010000000000000000000000000000000090041660c082015291508514611ba1576040517f3014033200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60a0810151600083156fffffffffffffffffffffffffffffffff83161760011b90506000611c61826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169050861580611c9c5750611c997f00000000000000000000000000000000000000000000000000000000000000046002615933565b81145b8015611ca6575084155b15611cdd576040517fa42637bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000547201000000000000000000000000000000000000900460ff168015611d03575086155b15611d3a576040517f0ea2e75200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000008811115611d94576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611dbf7f00000000000000000000000000000000000000000000000000000000000000046001615933565b8103611dd157611dd186888588613ec7565b34611ddb83612c60565b14611e12576040517f8620aa1900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611e1d88612a81565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b0811690821603611e85576040517f3381d11400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611eb260017f0000000000000000000000000000000000000000000000000000000000000008615983565b8303611ff0577f000000000000000000000000180cbe2ebb9f37d3a3c542ddc2546fd160555a7373ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f47919061599a565b73ffffffffffffffffffffffffffffffffffffffff1663f3f480d96040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f91573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fb591906159b7565b611fe9907f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff166159d0565b9050612083565b61201b60017f0000000000000000000000000000000000000000000000000000000000000004615983565b830361205657611fe97f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1660026159fc565b507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff165b6120b7817f00000000000000000000000000000000000000000000000000000000000004b067ffffffffffffffff16615a2c565b67ffffffffffffffff166120d28367ffffffffffffffff1690565b67ffffffffffffffff16111561211957612116817f00000000000000000000000000000000000000000000000000000000000004b067ffffffffffffffff16615a2c565b91505b6000604083901b421760008a8152608087901b6fffffffffffffffffffffffffffffffff8d1617602052604081209192509060008181526004602052604090205490915060ff1615612197576040517f80497e3b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60016004600083815260200190815260200160002060006101000a81548160ff02191690831515021790555060026040518060e001604052808d63ffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020013373ffffffffffffffffffffffffffffffffffffffff168152602001346fffffffffffffffffffffffffffffffff1681526020018c8152602001886fffffffffffffffffffffffffffffffff168152602001846fffffffffffffffffffffffffffffffff16815250908060018154018082558091505060019003906000526020600020906005020160009091909190915060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060608201518160020160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055506080820151816003015560a08201518160040160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555060c08201518160040160106101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055505050600560008c8152602001908152602001600020600160028054905061242d9190615983565b81546001810183556000928352602083200155604080517fd0e30db0000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ef179756ea6525afade217ca5ab0b1b5cfe0fd92169263d0e30db09234926004808301939282900301818588803b1580156124c557600080fd5b505af11580156124d9573d6000803e3d6000fd5b50506040513393508d92508e91507f9b3245740ec3b155098a55be84957a4da13eaf7f14a8bc6f53126c0b9350f2be90600090a4505050505050505050505050565b61184e8383836000611a42565b60005471010000000000000000000000000000000000900460ff161561257a576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f7258a80700000000000000000000000000000000000000000000000000000000815263ffffffff7f0000000000000000000000000000000000000000000000000000000000000000166004820152600090819073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000970670459734a83899773a0fd45941b5afc1200e1690637258a807906024016040805180830381865afa15801561262e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126529190615a55565b90925090508161268e576040517f6a6bc3b200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518082019091528281526020018190526008829055600981905536607a146126c157639824bdab6000526004601cfd5b80367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401351161275b576040517ff40239db000000000000000000000000000000000000000000000000000000008152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013560048201526024015b60405180910390fd5b6040805160e08101825263ffffffff8082526000602083018181527ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe369081013560f01c90038035606090811c868801908152346fffffffffffffffffffffffffffffffff81811693890193845260149094013560808901908152600160a08a0181815242871660c08c019081526002805493840181558a529a5160059092027f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace81018054995173ffffffffffffffffffffffffffffffffffffffff908116640100000000027fffffffffffffffff000000000000000000000000000000000000000000000000909b1694909c16939093179890981790915592517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5acf87018054918a167fffffffffffffffffffffffff000000000000000000000000000000000000000090921691909117905592517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad0860180549186167fffffffffffffffffffffffffffffffff0000000000000000000000000000000090921691909117905591517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad185015551955182167001000000000000000000000000000000000295909116949094177f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad29091015580547fffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffff167101000000000000000000000000000000000017815583517fd0e30db000000000000000000000000000000000000000000000000000000000815293517f000000000000000000000000ef179756ea6525afade217ca5ab0b1b5cfe0fd929092169363d0e30db093926004828101939282900301818588803b158015612a3057600080fd5b505af1158015612a44573d6000803e3d6000fd5b5050600080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000164267ffffffffffffffff161790555050505050565b600080600054700100000000000000000000000000000000900460ff166002811115612aaf57612aaf61555f565b14612ae6576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028381548110612afb57612afb6158d5565b600091825260208220600590910201805490925063ffffffff90811614612b6a57815460028054909163ffffffff16908110612b3957612b396158d5565b906000526020600020906005020160040160109054906101000a90046fffffffffffffffffffffffffffffffff1690505b6004820154600090612ba290700100000000000000000000000000000000900467ffffffffffffffff165b67ffffffffffffffff1690565b612bb69067ffffffffffffffff1642615983565b612bd5612b95846fffffffffffffffffffffffffffffffff1660401c90565b67ffffffffffffffff16612be99190615933565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b01667ffffffffffffffff168167ffffffffffffffff1611612c365780611884565b7f00000000000000000000000000000000000000000000000000000000000004b095945050505050565b600080612cff836fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690507f0000000000000000000000000000000000000000000000000000000000000008811115612d5e576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b642e90edd00062061a806311e1a3006000612d798383615aa8565b9050670de0b6b3a76400006000612db0827f0000000000000000000000000000000000000000000000000000000000000008615abc565b90506000612dce612dc9670de0b6b3a764000086615abc565b614078565b90506000612ddc84846142d3565b90506000612dea8383614322565b90506000612df782614350565b90506000612e1682612e11670de0b6b3a76400008f615abc565b614538565b90506000612e248b83614322565b9050612e30818d615abc565b9f9e505050505050505050505050505050565b60028181548110612e5357600080fd5b60009182526020909120600590910201805460018201546002830154600384015460049094015463ffffffff8416955064010000000090930473ffffffffffffffffffffffffffffffffffffffff908116949216926fffffffffffffffffffffffffffffffff91821692918082169170010000000000000000000000000000000090041687565b60008054700100000000000000000000000000000000900460ff166002811115612f0657612f0661555f565b14612f3d576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028781548110612f5257612f526158d5565b6000918252602082206005919091020160048101549092506fffffffffffffffffffffffffffffffff16908715821760011b9050612fb17f00000000000000000000000000000000000000000000000000000000000000086001615933565b61304d826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1614613087576040517f5f53dd9800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080891561317e576130da7f00000000000000000000000000000000000000000000000000000000000000047f0000000000000000000000000000000000000000000000000000000000000008615983565b6001901b6130f9846fffffffffffffffffffffffffffffffff16614569565b6fffffffffffffffffffffffffffffffff166131159190615af9565b156131525761314961313a60016fffffffffffffffffffffffffffffffff8716615b0d565b865463ffffffff166000614608565b60030154613174565b7f00000000000000000000000000000000000000000000000000000000000000005b91508490506131a8565b600385015491506131a561313a6fffffffffffffffffffffffffffffffff86166001615b36565b90505b600882901b60088a8a6040516131bf9291906158c5565b6040518091039020901b14613200576040517f696550ff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061320b8c6146ec565b9050600061321a836003015490565b6040517fe14ced320000000000000000000000000000000000000000000000000000000081527f000000000000000000000000180cbe2ebb9f37d3a3c542ddc2546fd160555a7373ffffffffffffffffffffffffffffffffffffffff169063e14ced3290613294908f908f908f908f908a90600401615baa565b6020604051808303816000875af11580156132b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132d791906159b7565b600485015491149150600090600290613382906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b61341e896fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b6134289190615be4565b6134329190615c07565b60ff161590508115158103613473576040517ffb4e40dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8754640100000000900473ffffffffffffffffffffffffffffffffffffffff16156134ca576040517f9071e6af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505085547fffffffffffffffff0000000000000000000000000000000000000000ffffffff163364010000000002179095555050505050505050505050565b60008054700100000000000000000000000000000000900460ff1660028111156135355761353561555f565b1461356c576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060008061357b8661471b565b9350935093509350600061359185858585614b24565b905060007f000000000000000000000000180cbe2ebb9f37d3a3c542ddc2546fd160555a7373ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015613600573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613624919061599a565b90506001890361371c5773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a84613680367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036034013590565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815260048101939093526024830191909152604482015260206064820152608481018a905260a4015b6020604051808303816000875af11580156136f2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061371691906159b7565b5061155b565b600289036137485773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a8489613680565b600389036137745773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a8487613680565b600489036138fb5760006137ba6fffffffffffffffffffffffffffffffff85167f0000000000000000000000000000000000000000000000000000000000000004614bde565b6009546137c79190615933565b6137d2906001615933565b9050367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360540135811061383b57367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036054013561383d565b805b905073ffffffffffffffffffffffffffffffffffffffff82166352f0f3ad8b8560405160e084901b7fffffffff000000000000000000000000000000000000000000000000000000001681526004810192909252602482015260c084901b604482015260086064820152608481018b905260a4016020604051808303816000875af11580156138d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138f491906159b7565b505061155b565b60058903613994576040517f52f0f3ad000000000000000000000000000000000000000000000000000000008152600481018a9052602481018390527f000000000000000000000000000000000000000000000000000000000000038560c01b6044820152600860648201526084810188905273ffffffffffffffffffffffffffffffffffffffff8216906352f0f3ad9060a4016136d3565b6040517fff137e6500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000000367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003601401356060613a1f61188d565b9050909192565b600081831015613a365781613a38565b825b90505b92915050565b60008160000151826020015183604001518460600151604051602001613a80949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b60408051808201909152600080825260208201528151600003613aec576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50604080518082019091528151815260209182019181019190915290565b60606000806000613b1a85614c8c565b919450925090506001816001811115613b3557613b3561555f565b14613b6c576040517f4b9c6abe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8451613b788385615933565b14613baf576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808252610420820190925290816020015b6040805180820190915260008082526020820152815260200190600190039081613bc65790505093506000835b8651811015613cb457600080613c396040518060400160405280858c60000151613c1d9190615983565b8152602001858c60200151613c329190615933565b9052614c8c565b509150915060405180604001604052808383613c559190615933565b8152602001848b60200151613c6a9190615933565b815250888581518110613c7f57613c7f6158d5565b6020908102919091010152613c95600185615933565b9350613ca18183615933565b613cab9084615933565b92505050613bf3565b50845250919392505050565b60606000806000613cd085614c8c565b919450925090506000816001811115613ceb57613ceb61555f565b14613d22576040517f1ff9b2e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613d2c8284615933565b855114613d65576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6118848560200151848461512a565b600281015473ffffffffffffffffffffffffffffffffffffffff8316600090815260036020526040812080546fffffffffffffffffffffffffffffffff90931692839290613dc3908490615933565b90915550506040517f7eee288d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018390527f000000000000000000000000ef179756ea6525afade217ca5ab0b1b5cfe0fd921690637eee288d90604401600060405180830381600087803b158015613e5857600080fd5b505af1158015613e6c573d6000803e3d6000fd5b50505050505050565b604051818152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90038284820160208401378260208301016000815260208101604052505092915050565b6000613ee66fffffffffffffffffffffffffffffffff84166001615b36565b90506000613ef682866001614608565b9050600086901a8380613fe25750613f2f60027f0000000000000000000000000000000000000000000000000000000000000004615af9565b6004830154600290613fd3906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b613fdd9190615c07565b60ff16145b1561403a5760ff811660011480613ffc575060ff81166002145b614035576040517ff40239db00000000000000000000000000000000000000000000000000000000815260048101889052602401612752565b613e6c565b60ff811615613e6c576040517ff40239db00000000000000000000000000000000000000000000000000000000815260048101889052602401612752565b6fffffffffffffffffffffffffffffffff811160071b81811c67ffffffffffffffff1060061b1781811c63ffffffff1060051b1781811c61ffff1060041b1781811c60ff1060031b17600082136140d757631615e6386000526004601cfd5b7ff8f9f9faf9fdfafbf9fdfcfdfafbfcfef9fafdfafcfcfbfefafafcfbffffffff6f8421084210842108cc6318c6db6d54be83831c1c601f161a1890811b609f90811c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506029190037d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b302017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d90565b60007812725dd1d243aba0e75fe645cc4873f9e65afe688c928e1f218311670de0b6b3a76400000215820261431057637c5f487d6000526004601cfd5b50670de0b6b3a7640000919091020490565b6000816000190483118202156143405763bac65e5b6000526004601cfd5b50670de0b6b3a764000091020490565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdc0d0570925a462d7821361437e57919050565b680755bf798b4a1bf1e5821261439c5763a37bfec96000526004601cfd5b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b6000613a38670de0b6b3a76400008361455086614078565b61455a9190615c29565b6145649190615ce5565b614350565b6000806145f6837e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b600160ff919091161b90920392915050565b600080826146515761464c6fffffffffffffffffffffffffffffffff86167f00000000000000000000000000000000000000000000000000000000000000046151bf565b61466c565b61466c856fffffffffffffffffffffffffffffffff1661534b565b905060028481548110614681576146816158d5565b906000526020600020906005020191505b60048201546fffffffffffffffffffffffffffffffff8281169116146146e457815460028054909163ffffffff169081106146cf576146cf6158d5565b90600052602060002090600502019150614692565b509392505050565b60008060008060006146fd8661471b565b935093509350935061471184848484614b24565b9695505050505050565b600080600080600085905060006002828154811061473b5761473b6158d5565b600091825260209091206004600590920201908101549091507f000000000000000000000000000000000000000000000000000000000000000490614812906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff161161484c576040517fb34b5c2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000815b60048301547f000000000000000000000000000000000000000000000000000000000000000490614913906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff16925082111561498857825463ffffffff166149527f00000000000000000000000000000000000000000000000000000000000000046001615933565b830361495c578391505b6002818154811061496f5761496f6158d5565b9060005260206000209060050201935080945050614850565b600481810154908401546fffffffffffffffffffffffffffffffff91821691166000816fffffffffffffffffffffffffffffffff166149f16149dc856fffffffffffffffffffffffffffffffff1660011c90565b6fffffffffffffffffffffffffffffffff1690565b6fffffffffffffffffffffffffffffffff161490508015614ac0576000614a29836fffffffffffffffffffffffffffffffff16614569565b6fffffffffffffffffffffffffffffffff161115614a94576000614a6b614a6360016fffffffffffffffffffffffffffffffff8616615b0d565b896001614608565b6003810154600490910154909c506fffffffffffffffffffffffffffffffff169a50614a9a9050565b6008549a505b600386015460048701549099506fffffffffffffffffffffffffffffffff169750614b16565b6000614ae2614a636fffffffffffffffffffffffffffffffff85166001615b36565b6003808901546004808b015492840154930154909e506fffffffffffffffffffffffffffffffff9182169d50919b50169850505b505050505050509193509193565b60006fffffffffffffffffffffffffffffffff841615614b915760408051602081018790526fffffffffffffffffffffffffffffffff8087169282019290925260608101859052908316608082015260a00160405160208183030381529060405280519060200120611884565b8282604051602001614bbf9291909182526fffffffffffffffffffffffffffffffff16602082015260400190565b6040516020818303038152906040528051906020012095945050505050565b600080614c6b847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690508083036001841b600180831b0386831b17039250505092915050565b60008060008360000151600003614ccf576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020840151805160001a607f8111614cf4576000600160009450945094505050615123565b60b78111614e0a576000614d09608083615983565b905080876000015111614d48576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001838101517fff00000000000000000000000000000000000000000000000000000000000000169082148015614dc057507f80000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008216105b15614df7576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5060019550935060009250615123915050565b60bf8111614f68576000614e1f60b783615983565b905080876000015111614e5e576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614ec0576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c60378111614f08576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614f128184615933565b895111614f4b576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614f56836001615933565b97509550600094506151239350505050565b60f78111614fcd576000614f7d60c083615983565b905080876000015111614fbc576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600195509350849250615123915050565b6000614fda60f783615983565b905080876000015111615019576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff0000000000000000000000000000000000000000000000000000000000000016600081900361507b576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c603781116150c3576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6150cd8184615933565b895111615106576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b615111836001615933565b97509550600194506151239350505050565b9193909250565b60608167ffffffffffffffff81111561514557615145615809565b6040519080825280601f01601f19166020018201604052801561516f576020820181803683370190505b50905081156151b85760006151848486615933565b90506020820160005b848110156151a557828101518282015260200161518d565b848111156151b4576000858301525b5050505b9392505050565b60008161525e846fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff16116152745763b34b5c226000526004601cfd5b61527d8361534b565b90508161531c826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1611613a3b57613a38615332836001615933565b6fffffffffffffffffffffffffffffffff8316906153f0565b600081196001830116816153df827e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169390931c8015179392505050565b60008061547d847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169050808303600180821b0385821b179250505092915050565b60008083601f8401126154ab57600080fd5b50813567ffffffffffffffff8111156154c357600080fd5b6020830191508360208285010111156154db57600080fd5b9250929050565b600080600083850360a08112156154f857600080fd5b608081121561550657600080fd5b50839250608084013567ffffffffffffffff81111561552457600080fd5b61553086828701615499565b9497909650939450505050565b6000806040838503121561555057600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60208101600383106155c9577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b6000806000606084860312156155e457600080fd5b505081359360208301359350604090920135919050565b6000815180845260005b8181101561562157602081850181015186830182015201615605565b81811115615633576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000613a3860208301846155fb565b60006020828403121561568b57600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff811681146156b457600080fd5b50565b6000602082840312156156c957600080fd5b81356151b881615692565b803580151581146156e457600080fd5b919050565b600080600080608085870312156156ff57600080fd5b84359350602085013592506040850135915061571d606086016156d4565b905092959194509250565b60006020828403121561573a57600080fd5b81356fffffffffffffffffffffffffffffffff811681146151b857600080fd5b6000806000806000806080878903121561577357600080fd5b86359550615783602088016156d4565b9450604087013567ffffffffffffffff808211156157a057600080fd5b6157ac8a838b01615499565b909650945060608901359150808211156157c557600080fd5b506157d289828a01615499565b979a9699509497509295939492505050565b63ffffffff8416815282602082015260606040820152600061188460608301846155fb565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006080828403121561584a57600080fd5b6040516080810181811067ffffffffffffffff82111715615894577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561594657615946615904565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361597c5761597c615904565b5060010190565b60008282101561599557615995615904565b500390565b6000602082840312156159ac57600080fd5b81516151b881615692565b6000602082840312156159c957600080fd5b5051919050565b600067ffffffffffffffff8083168185168083038211156159f3576159f3615904565b01949350505050565b600067ffffffffffffffff80831681851681830481118215151615615a2357615a23615904565b02949350505050565b600067ffffffffffffffff83811690831681811015615a4d57615a4d615904565b039392505050565b60008060408385031215615a6857600080fd5b505080516020909101519092909150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082615ab757615ab7615a79565b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615af457615af4615904565b500290565b600082615b0857615b08615a79565b500690565b60006fffffffffffffffffffffffffffffffff83811690831681811015615a4d57615a4d615904565b60006fffffffffffffffffffffffffffffffff8083168185168083038211156159f3576159f3615904565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b606081526000615bbe606083018789615b61565b8281036020840152615bd1818688615b61565b9150508260408301529695505050505050565b600060ff821660ff841680821015615bfe57615bfe615904565b90039392505050565b600060ff831680615c1a57615c1a615a79565b8060ff84160691505092915050565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600084136000841385830485118282161615615c6a57615c6a615904565b7f80000000000000000000000000000000000000000000000000000000000000006000871286820588128184161615615ca557615ca5615904565b60008712925087820587128484161615615cc157615cc1615904565b87850587128184161615615cd757615cd7615904565b505050929093029392505050565b600082615cf457615cf4615a79565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f800000000000000000000000000000000000000000000000000000000000000083141615615d4857615d48615904565b50059056fea164736f6c634300080f000a"; bytes internal constant acc34Code = - hex"6080604052600436106103085760003560e01c806370872aa51161019a578063c6f0308c116100e1578063ec5e63081161008a578063fa24f74311610064578063fa24f74314610b94578063fa315aa914610bb8578063fe2bbeb214610beb57600080fd5b8063ec5e630814610b11578063eff0f59214610b44578063f8f43ff614610b7457600080fd5b8063d6ae3cd5116100bb578063d6ae3cd514610a8b578063d8cc1a3c14610abe578063dabd396d14610ade57600080fd5b8063c6f0308c146109b3578063cf09e0d014610a3d578063d5d44d8014610a5e57600080fd5b8063a445ece611610143578063bcef3b551161011d578063bcef3b5514610933578063bd8da95614610973578063c395e1ca1461099357600080fd5b8063a445ece6146107f3578063a8e4fb90146108bf578063bbdc02db146108f257600080fd5b80638980e0cc116101745780638980e0cc1461076b5780638b85902b146107805780638d450a95146107c057600080fd5b806370872aa51461073b5780637b0f0adc146107505780638129fc1c1461076357600080fd5b80633fc8cef31161025e5780635c0cba33116102075780636361506d116101e15780636361506d146106b55780636b6716c0146106f55780636f0344091461072857600080fd5b80635c0cba331461064d578063609d33341461068057806360e274641461069557600080fd5b806354fd4d501161023857806354fd4d50146105a757806357da950e146105fd5780635a5fa2d91461062d57600080fd5b80633fc8cef31461052e578063472777c614610561578063534db0e21461057457600080fd5b80632810e1d6116102c057806337b1b2291161029a57806337b1b2291461047b5780633a768463146104bb5780633e3ac912146104ee57600080fd5b80632810e1d6146103f45780632ad69aeb1461040957806330dbe5701461042957600080fd5b806319effeb4116102f157806319effeb41461034f578063200d2ed21461039a57806325fc2ace146103d557600080fd5b8063019351301461030d57806303c2924d1461032f575b600080fd5b34801561031957600080fd5b5061032d61032836600461575d565b610c1b565b005b34801561033b57600080fd5b5061032d61034a3660046157b8565b610f3c565b34801561035b57600080fd5b5060005461037c9068010000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020015b60405180910390f35b3480156103a657600080fd5b506000546103c890700100000000000000000000000000000000900460ff1681565b6040516103919190615809565b3480156103e157600080fd5b506008545b604051908152602001610391565b34801561040057600080fd5b506103c86115e2565b34801561041557600080fd5b506103e66104243660046157b8565b611887565b34801561043557600080fd5b506001546104569073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610391565b34801561048757600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90033560601c610456565b3480156104c757600080fd5b507f000000000000000000000000444e09fe6d839273316a87002ab0efbea6fe7806610456565b3480156104fa57600080fd5b5060005461051e907201000000000000000000000000000000000000900460ff1681565b6040519015158152602001610391565b34801561053a57600080fd5b507f000000000000000000000000d6eaf4c146261653ee059077b78ed088add54309610456565b61032d61056f36600461584a565b6118bd565b34801561058057600080fd5b507f0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b63610456565b3480156105b357600080fd5b506105f06040518060400160405280600a81526020017f312e332e302d72632e310000000000000000000000000000000000000000000081525081565b60405161039191906158e1565b34801561060957600080fd5b50600854600954610618919082565b60408051928352602083019190915201610391565b34801561063957600080fd5b506103e66106483660046158f4565b6118cf565b34801561065957600080fd5b507f000000000000000000000000970670459734a83899773a0fd45941b5afc1200e610456565b34801561068c57600080fd5b506105f0611909565b3480156106a157600080fd5b5061032d6106b0366004615932565b611917565b3480156106c157600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003603401356103e6565b34801561070157600080fd5b507f000000000000000000000000000000000000000000000000000000000000000061037c565b61032d610736366004615964565b611abe565b34801561074757600080fd5b506009546103e6565b61032d61075e36600461584a565b611b7f565b61032d611b8c565b34801561077757600080fd5b506002546103e6565b34801561078c57600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401356103e6565b3480156107cc57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006103e6565b3480156107ff57600080fd5b5061086b61080e3660046158f4565b6007602052600090815260409020805460019091015460ff821691610100810463ffffffff1691650100000000009091046fffffffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff1684565b60408051941515855263ffffffff90931660208501526fffffffffffffffffffffffffffffffff9091169183019190915273ffffffffffffffffffffffffffffffffffffffff166060820152608001610391565b3480156108cb57600080fd5b507f00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8610456565b3480156108fe57600080fd5b5060405163ffffffff7f0000000000000000000000000000000000000000000000000000000000000001168152602001610391565b34801561093f57600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003601401356103e6565b34801561097f57600080fd5b5061037c61098e3660046158f4565b611c05565b34801561099f57600080fd5b506103e66109ae3660046159a3565b611de4565b3480156109bf57600080fd5b506109d36109ce3660046158f4565b611fc7565b6040805163ffffffff909816885273ffffffffffffffffffffffffffffffffffffffff968716602089015295909416948601949094526fffffffffffffffffffffffffffffffff9182166060860152608085015291821660a08401521660c082015260e001610391565b348015610a4957600080fd5b5060005461037c9067ffffffffffffffff1681565b348015610a6a57600080fd5b506103e6610a79366004615932565b60036020526000908152604090205481565b348015610a9757600080fd5b507f00000000000000000000000000000000000000000000000000000000000003856103e6565b348015610aca57600080fd5b5061032d610ad93660046159d5565b61205e565b348015610aea57600080fd5b507f00000000000000000000000000000000000000000000000000000000000004b061037c565b348015610b1d57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000046103e6565b348015610b5057600080fd5b5061051e610b5f3660046158f4565b60046020526000908152604090205460ff1681565b348015610b8057600080fd5b5061032d610b8f36600461584a565b612123565b348015610ba057600080fd5b50610ba96125e0565b60405161039193929190615a5f565b348015610bc457600080fd5b507f00000000000000000000000000000000000000000000000000000000000000086103e6565b348015610bf757600080fd5b5061051e610c063660046158f4565b60066020526000908152604090205460ff1681565b60008054700100000000000000000000000000000000900460ff166002811115610c4757610c476157da565b14610c7e576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000547201000000000000000000000000000000000000900460ff1615610cd1576040517f0ea2e75200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d08367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013590565b90565b610d1f610d1a36869003860186615ab3565b61265b565b14610d56576040517f9cc00b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82606001358282604051610d6b929190615b40565b604051809103902014610daa576040517fd81d583b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610df3610dee84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506126b792505050565b612724565b90506000610e1a82600881518110610e0d57610e0d615b50565b60200260200101516128da565b9050602081511115610e58576040517fd81d583b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602081810151825190910360031b1c367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401358103610ecd576040517fb8ed883000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050600180547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790555050600080547fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff1672010000000000000000000000000000000000001790555050565b60008054700100000000000000000000000000000000900460ff166002811115610f6857610f686157da565b14610f9f576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028381548110610fb457610fb4615b50565b906000526020600020906005020190506000610fcf84611c05565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b081169082161015611038576040517ff2440b5300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008481526006602052604090205460ff1615611081576040517ff1a9458100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600084815260056020526040902080548015801561109e57508515155b15611139578354640100000000900473ffffffffffffffffffffffffffffffffffffffff16600081156110d157816110ed565b600186015473ffffffffffffffffffffffffffffffffffffffff165b90506110f9818761298e565b50505060009485525050600660205250506040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b6000868152600760209081526040918290208251608081018452815460ff81161515808352610100820463ffffffff16948301949094526501000000000090046fffffffffffffffffffffffffffffffff16938101939093526001015473ffffffffffffffffffffffffffffffffffffffff1660608301526111dc576fffffffffffffffffffffffffffffffff60408201526001815260008690036111dc578195505b600086826020015163ffffffff166111f49190615bae565b905060008382116112055781611207565b835b602084015190915063ffffffff165b8181101561135357600086828154811061123257611232615b50565b6000918252602080832090910154808352600690915260409091205490915060ff1661128a576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006002828154811061129f5761129f615b50565b600091825260209091206005909102018054909150640100000000900473ffffffffffffffffffffffffffffffffffffffff161580156112fc5750600481015460408701516fffffffffffffffffffffffffffffffff9182169116115b1561133e57600181015473ffffffffffffffffffffffffffffffffffffffff16606087015260048101546fffffffffffffffffffffffffffffffff1660408701525b5050808061134b90615bc6565b915050611216565b5063ffffffff818116602085810191825260008c81526007909152604090819020865181549351928801517fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009094169015157fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ff161761010092909416918202939093177fffffffffffffffffffffff00000000000000000000000000000000ffffffffff16650100000000006fffffffffffffffffffffffffffffffff909316929092029190911782556060850151600190920180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909316929092179091558490036115d757606083015160008a815260066020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055891580156114d357506000547201000000000000000000000000000000000000900460ff165b156115485760015473ffffffffffffffffffffffffffffffffffffffff166114fb818a61298e565b885473ffffffffffffffffffffffffffffffffffffffff909116640100000000027fffffffffffffffff0000000000000000000000000000000000000000ffffffff9091161788556115d5565b61158f73ffffffffffffffffffffffffffffffffffffffff82161561156d5781611589565b600189015473ffffffffffffffffffffffffffffffffffffffff165b8961298e565b87547fffffffffffffffff0000000000000000000000000000000000000000ffffffff1664010000000073ffffffffffffffffffffffffffffffffffffffff8316021788555b505b505050505050505050565b600080600054700100000000000000000000000000000000900460ff166002811115611610576116106157da565b14611647576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000805260066020527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f85460ff166116ab576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660026000815481106116d7576116d7615b50565b6000918252602090912060059091020154640100000000900473ffffffffffffffffffffffffffffffffffffffff1614611712576001611715565b60025b6000805467ffffffffffffffff421668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff82168117835592935083927fffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffff000000000000000000ffffffffffffffff909116177001000000000000000000000000000000008360028111156117c6576117c66157da565b0217905560028111156117db576117db6157da565b6040517f5e186f09b9c93491f14e277eea7faa5de6a2d4bda75a79af7a3684fbfb42da6090600090a27f000000000000000000000000970670459734a83899773a0fd45941b5afc1200e73ffffffffffffffffffffffffffffffffffffffff1663838c2d1e6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561186c57600080fd5b505af1158015611880573d6000803e3d6000fd5b5050505090565b600560205281600052604060002081815481106118a357600080fd5b90600052602060002001600091509150505481565b905090565b6118ca8383836001611abe565b505050565b6000818152600760209081526040808320600590925282208054825461190090610100900463ffffffff1682615bfe565b95945050505050565b60606118b860546020612a8f565b73ffffffffffffffffffffffffffffffffffffffff811660009081526003602052604081208054908290559081900361197c576040517f17bfe5f700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517ff3fef3a300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152602482018390527f000000000000000000000000d6eaf4c146261653ee059077b78ed088add54309169063f3fef3a390604401600060405180830381600087803b158015611a0c57600080fd5b505af1158015611a20573d6000803e3d6000fd5b5050505060008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114611a7e576040519150601f19603f3d011682016040523d82523d6000602084013e611a83565b606091505b50509050806118ca576040517f83e6cc6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8161480611b3757503373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b6316145b611b6d576040517fd386ef3e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611b7984848484612ae1565b50505050565b6118ca8383836000611abe565b3273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c81614611bfb576040517fd386ef3e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611c036135ba565b565b600080600054700100000000000000000000000000000000900460ff166002811115611c3357611c336157da565b14611c6a576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028381548110611c7f57611c7f615b50565b600091825260208220600590910201805490925063ffffffff90811614611cee57815460028054909163ffffffff16908110611cbd57611cbd615b50565b906000526020600020906005020160040160109054906101000a90046fffffffffffffffffffffffffffffffff1690505b6004820154600090611d2690700100000000000000000000000000000000900467ffffffffffffffff165b67ffffffffffffffff1690565b611d3a9067ffffffffffffffff1642615bfe565b611d59611d19846fffffffffffffffffffffffffffffffff1660401c90565b67ffffffffffffffff16611d6d9190615bae565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b01667ffffffffffffffff168167ffffffffffffffff1611611dba5780611900565b7f00000000000000000000000000000000000000000000000000000000000004b095945050505050565b600080611e83836fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690507f0000000000000000000000000000000000000000000000000000000000000008811115611ee2576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b642e90edd00062061a806311e1a3006000611efd8383615c44565b9050670de0b6b3a76400006000611f34827f0000000000000000000000000000000000000000000000000000000000000008615c58565b90506000611f52611f4d670de0b6b3a764000086615c58565b613b13565b90506000611f608484613d6e565b90506000611f6e8383613dbd565b90506000611f7b82613deb565b90506000611f9a82611f95670de0b6b3a76400008f615c58565b613fd3565b90506000611fa88b83613dbd565b9050611fb4818d615c58565b9f9e505050505050505050505050505050565b60028181548110611fd757600080fd5b60009182526020909120600590910201805460018201546002830154600384015460049094015463ffffffff8416955064010000000090930473ffffffffffffffffffffffffffffffffffffffff908116949216926fffffffffffffffffffffffffffffffff91821692918082169170010000000000000000000000000000000090041687565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c81614806120d757503373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b6316145b61210d576040517fd386ef3e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61211b868686868686614004565b505050505050565b60008054700100000000000000000000000000000000900460ff16600281111561214f5761214f6157da565b14612186576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060008061219586614633565b935093509350935060006121ab85858585614a3c565b905060007f000000000000000000000000444e09fe6d839273316a87002ab0efbea6fe780673ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561221a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061223e9190615c95565b9050600189036123365773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a8461229a367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036034013590565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815260048101939093526024830191909152604482015260206064820152608481018a905260a4015b6020604051808303816000875af115801561230c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123309190615cb2565b506115d7565b600289036123625773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a848961229a565b6003890361238e5773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a848761229a565b600489036125155760006123d46fffffffffffffffffffffffffffffffff85167f0000000000000000000000000000000000000000000000000000000000000004614af6565b6009546123e19190615bae565b6123ec906001615bae565b9050367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360540135811061245557367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360540135612457565b805b905073ffffffffffffffffffffffffffffffffffffffff82166352f0f3ad8b8560405160e084901b7fffffffff000000000000000000000000000000000000000000000000000000001681526004810192909252602482015260c084901b604482015260086064820152608481018b905260a4016020604051808303816000875af11580156124ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061250e9190615cb2565b50506115d7565b600589036125ae576040517f52f0f3ad000000000000000000000000000000000000000000000000000000008152600481018a9052602481018390527f000000000000000000000000000000000000000000000000000000000000038560c01b6044820152600860648201526084810188905273ffffffffffffffffffffffffffffffffffffffff8216906352f0f3ad9060a4016122ed565b6040517fff137e6500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000001367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003601401356060612639611909565b9050909192565b6000818310156126505781612652565b825b90505b92915050565b6000816000015182602001518360400151846060015160405160200161269a949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b60408051808201909152600080825260208201528151600003612706576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50604080518082019091528151815260209182019181019190915290565b6060600080600061273485614ba4565b91945092509050600181600181111561274f5761274f6157da565b14612786576040517f4b9c6abe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84516127928385615bae565b146127c9576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808252610420820190925290816020015b60408051808201909152600080825260208201528152602001906001900390816127e05790505093506000835b86518110156128ce576000806128536040518060400160405280858c600001516128379190615bfe565b8152602001858c6020015161284c9190615bae565b9052614ba4565b50915091506040518060400160405280838361286f9190615bae565b8152602001848b602001516128849190615bae565b81525088858151811061289957612899615b50565b60209081029190910101526128af600185615bae565b93506128bb8183615bae565b6128c59084615bae565b9250505061280d565b50845250919392505050565b606060008060006128ea85614ba4565b919450925090506000816001811115612905576129056157da565b1461293c576040517f1ff9b2e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6129468284615bae565b85511461297f576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61190085602001518484615042565b600281015473ffffffffffffffffffffffffffffffffffffffff8316600090815260036020526040812080546fffffffffffffffffffffffffffffffff909316928392906129dd908490615bae565b90915550506040517f7eee288d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018390527f000000000000000000000000d6eaf4c146261653ee059077b78ed088add543091690637eee288d90604401600060405180830381600087803b158015612a7257600080fd5b505af1158015612a86573d6000803e3d6000fd5b50505050505050565b604051818152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90038284820160208401378260208301016000815260208101604052505092915050565b60008054700100000000000000000000000000000000900460ff166002811115612b0d57612b0d6157da565b14612b44576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028481548110612b5957612b59615b50565b60009182526020918290206040805160e0810182526005909302909101805463ffffffff8116845273ffffffffffffffffffffffffffffffffffffffff64010000000090910481169484019490945260018101549093169082015260028201546fffffffffffffffffffffffffffffffff908116606083015260038301546080830181905260049093015480821660a084015270010000000000000000000000000000000090041660c082015291508514612c40576040517f3014033200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60a0810151600083156fffffffffffffffffffffffffffffffff83161760011b90506000612d00826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169050861580612d3b5750612d387f00000000000000000000000000000000000000000000000000000000000000046002615bae565b81145b8015612d45575084155b15612d7c576040517fa42637bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000547201000000000000000000000000000000000000900460ff168015612da2575086155b15612dd9576040517f0ea2e75200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000008811115612e33576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612e5e7f00000000000000000000000000000000000000000000000000000000000000046001615bae565b8103612e7057612e70868885886150d7565b34612e7a83611de4565b14612eb1576040517f8620aa1900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612ebc88611c05565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b0811690821603612f24576040517f3381d11400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612f5160017f0000000000000000000000000000000000000000000000000000000000000008615bfe565b830361308f577f000000000000000000000000444e09fe6d839273316a87002ab0efbea6fe780673ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015612fc2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fe69190615c95565b73ffffffffffffffffffffffffffffffffffffffff1663f3f480d96040518163ffffffff1660e01b8152600401602060405180830381865afa158015613030573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130549190615cb2565b613088907f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff16615ccb565b9050613122565b6130ba60017f0000000000000000000000000000000000000000000000000000000000000004615bfe565b83036130f5576130887f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff166002615cf7565b507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff165b613156817f00000000000000000000000000000000000000000000000000000000000004b067ffffffffffffffff16615d27565b67ffffffffffffffff166131718367ffffffffffffffff1690565b67ffffffffffffffff1611156131b8576131b5817f00000000000000000000000000000000000000000000000000000000000004b067ffffffffffffffff16615d27565b91505b6000604083901b421760008a8152608087901b6fffffffffffffffffffffffffffffffff8d1617602052604081209192509060008181526004602052604090205490915060ff1615613236576040517f80497e3b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60016004600083815260200190815260200160002060006101000a81548160ff02191690831515021790555060026040518060e001604052808d63ffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020013373ffffffffffffffffffffffffffffffffffffffff168152602001346fffffffffffffffffffffffffffffffff1681526020018c8152602001886fffffffffffffffffffffffffffffffff168152602001846fffffffffffffffffffffffffffffffff16815250908060018154018082558091505060019003906000526020600020906005020160009091909190915060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060608201518160020160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055506080820151816003015560a08201518160040160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555060c08201518160040160106101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055505050600560008c815260200190815260200160002060016002805490506134cc9190615bfe565b81546001810183556000928352602083200155604080517fd0e30db0000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000d6eaf4c146261653ee059077b78ed088add54309169263d0e30db09234926004808301939282900301818588803b15801561356457600080fd5b505af1158015613578573d6000803e3d6000fd5b50506040513393508d92508e91507f9b3245740ec3b155098a55be84957a4da13eaf7f14a8bc6f53126c0b9350f2be90600090a4505050505050505050505050565b60005471010000000000000000000000000000000000900460ff161561360c576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f7258a80700000000000000000000000000000000000000000000000000000000815263ffffffff7f0000000000000000000000000000000000000000000000000000000000000001166004820152600090819073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000970670459734a83899773a0fd45941b5afc1200e1690637258a807906024016040805180830381865afa1580156136c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136e49190615d50565b909250905081613720576040517f6a6bc3b200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518082019091528281526020018190526008829055600981905536607a1461375357639824bdab6000526004601cfd5b80367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360540135116137ed576040517ff40239db000000000000000000000000000000000000000000000000000000008152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013560048201526024015b60405180910390fd5b6040805160e08101825263ffffffff8082526000602083018181527ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe369081013560f01c90038035606090811c868801908152346fffffffffffffffffffffffffffffffff81811693890193845260149094013560808901908152600160a08a0181815242871660c08c019081526002805493840181558a529a5160059092027f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace81018054995173ffffffffffffffffffffffffffffffffffffffff908116640100000000027fffffffffffffffff000000000000000000000000000000000000000000000000909b1694909c16939093179890981790915592517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5acf87018054918a167fffffffffffffffffffffffff000000000000000000000000000000000000000090921691909117905592517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad0860180549186167fffffffffffffffffffffffffffffffff0000000000000000000000000000000090921691909117905591517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad185015551955182167001000000000000000000000000000000000295909116949094177f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad29091015580547fffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffff167101000000000000000000000000000000000017815583517fd0e30db000000000000000000000000000000000000000000000000000000000815293517f000000000000000000000000d6eaf4c146261653ee059077b78ed088add543099092169363d0e30db093926004828101939282900301818588803b158015613ac257600080fd5b505af1158015613ad6573d6000803e3d6000fd5b5050600080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000164267ffffffffffffffff161790555050505050565b6fffffffffffffffffffffffffffffffff811160071b81811c67ffffffffffffffff1060061b1781811c63ffffffff1060051b1781811c61ffff1060041b1781811c60ff1060031b1760008213613b7257631615e6386000526004601cfd5b7ff8f9f9faf9fdfafbf9fdfcfdfafbfcfef9fafdfafcfcfbfefafafcfbffffffff6f8421084210842108cc6318c6db6d54be83831c1c601f161a1890811b609f90811c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506029190037d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b302017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d90565b60007812725dd1d243aba0e75fe645cc4873f9e65afe688c928e1f218311670de0b6b3a764000002158202613dab57637c5f487d6000526004601cfd5b50670de0b6b3a7640000919091020490565b600081600019048311820215613ddb5763bac65e5b6000526004601cfd5b50670de0b6b3a764000091020490565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdc0d0570925a462d78213613e1957919050565b680755bf798b4a1bf1e58212613e375763a37bfec96000526004601cfd5b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b6000612652670de0b6b3a764000083613feb86613b13565b613ff59190615d74565b613fff9190615e30565b613deb565b60008054700100000000000000000000000000000000900460ff166002811115614030576140306157da565b14614067576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006002878154811061407c5761407c615b50565b6000918252602082206005919091020160048101549092506fffffffffffffffffffffffffffffffff16908715821760011b90506140db7f00000000000000000000000000000000000000000000000000000000000000086001615bae565b614177826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff16146141b1576040517f5f53dd9800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008089156142a8576142047f00000000000000000000000000000000000000000000000000000000000000047f0000000000000000000000000000000000000000000000000000000000000008615bfe565b6001901b614223846fffffffffffffffffffffffffffffffff16615288565b6fffffffffffffffffffffffffffffffff1661423f9190615e98565b1561427c5761427361426460016fffffffffffffffffffffffffffffffff8716615eac565b865463ffffffff166000615327565b6003015461429e565b7f00000000000000000000000000000000000000000000000000000000000000005b91508490506142d2565b600385015491506142cf6142646fffffffffffffffffffffffffffffffff86166001615ed5565b90505b600882901b60088a8a6040516142e9929190615b40565b6040518091039020901b1461432a576040517f696550ff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006143358c61540b565b90506000614344836003015490565b6040517fe14ced320000000000000000000000000000000000000000000000000000000081527f000000000000000000000000444e09fe6d839273316a87002ab0efbea6fe780673ffffffffffffffffffffffffffffffffffffffff169063e14ced32906143be908f908f908f908f908a90600401615f49565b6020604051808303816000875af11580156143dd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144019190615cb2565b6004850154911491506000906002906144ac906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b614548896fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b6145529190615f83565b61455c9190615fa6565b60ff16159050811515810361459d576040517ffb4e40dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8754640100000000900473ffffffffffffffffffffffffffffffffffffffff16156145f4576040517f9071e6af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505085547fffffffffffffffff0000000000000000000000000000000000000000ffffffff163364010000000002179095555050505050505050505050565b600080600080600085905060006002828154811061465357614653615b50565b600091825260209091206004600590920201908101549091507f00000000000000000000000000000000000000000000000000000000000000049061472a906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1611614764576040517fb34b5c2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000815b60048301547f00000000000000000000000000000000000000000000000000000000000000049061482b906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1692508211156148a057825463ffffffff1661486a7f00000000000000000000000000000000000000000000000000000000000000046001615bae565b8303614874578391505b6002818154811061488757614887615b50565b9060005260206000209060050201935080945050614768565b600481810154908401546fffffffffffffffffffffffffffffffff91821691166000816fffffffffffffffffffffffffffffffff166149096148f4856fffffffffffffffffffffffffffffffff1660011c90565b6fffffffffffffffffffffffffffffffff1690565b6fffffffffffffffffffffffffffffffff1614905080156149d8576000614941836fffffffffffffffffffffffffffffffff16615288565b6fffffffffffffffffffffffffffffffff1611156149ac57600061498361497b60016fffffffffffffffffffffffffffffffff8616615eac565b896001615327565b6003810154600490910154909c506fffffffffffffffffffffffffffffffff169a506149b29050565b6008549a505b600386015460048701549099506fffffffffffffffffffffffffffffffff169750614a2e565b60006149fa61497b6fffffffffffffffffffffffffffffffff85166001615ed5565b6003808901546004808b015492840154930154909e506fffffffffffffffffffffffffffffffff9182169d50919b50169850505b505050505050509193509193565b60006fffffffffffffffffffffffffffffffff841615614aa95760408051602081018790526fffffffffffffffffffffffffffffffff8087169282019290925260608101859052908316608082015260a00160405160208183030381529060405280519060200120611900565b8282604051602001614ad79291909182526fffffffffffffffffffffffffffffffff16602082015260400190565b6040516020818303038152906040528051906020012095945050505050565b600080614b83847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690508083036001841b600180831b0386831b17039250505092915050565b60008060008360000151600003614be7576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020840151805160001a607f8111614c0c57600060016000945094509450505061503b565b60b78111614d22576000614c21608083615bfe565b905080876000015111614c60576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001838101517fff00000000000000000000000000000000000000000000000000000000000000169082148015614cd857507f80000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008216105b15614d0f576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506001955093506000925061503b915050565b60bf8111614e80576000614d3760b783615bfe565b905080876000015111614d76576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614dd8576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c60378111614e20576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614e2a8184615bae565b895111614e63576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614e6e836001615bae565b975095506000945061503b9350505050565b60f78111614ee5576000614e9560c083615bfe565b905080876000015111614ed4576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60019550935084925061503b915050565b6000614ef260f783615bfe565b905080876000015111614f31576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614f93576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c60378111614fdb576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614fe58184615bae565b89511161501e576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b615029836001615bae565b975095506001945061503b9350505050565b9193909250565b60608167ffffffffffffffff81111561505d5761505d615a84565b6040519080825280601f01601f191660200182016040528015615087576020820181803683370190505b50905081156150d057600061509c8486615bae565b90506020820160005b848110156150bd5782810151828201526020016150a5565b848111156150cc576000858301525b5050505b9392505050565b60006150f66fffffffffffffffffffffffffffffffff84166001615ed5565b9050600061510682866001615327565b9050600086901a83806151f2575061513f60027f0000000000000000000000000000000000000000000000000000000000000004615e98565b60048301546002906151e3906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b6151ed9190615fa6565b60ff16145b1561524a5760ff81166001148061520c575060ff81166002145b615245576040517ff40239db000000000000000000000000000000000000000000000000000000008152600481018890526024016137e4565b612a86565b60ff811615612a86576040517ff40239db000000000000000000000000000000000000000000000000000000008152600481018890526024016137e4565b600080615315837e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b600160ff919091161b90920392915050565b600080826153705761536b6fffffffffffffffffffffffffffffffff86167f000000000000000000000000000000000000000000000000000000000000000461543a565b61538b565b61538b856fffffffffffffffffffffffffffffffff166155c6565b9050600284815481106153a0576153a0615b50565b906000526020600020906005020191505b60048201546fffffffffffffffffffffffffffffffff82811691161461540357815460028054909163ffffffff169081106153ee576153ee615b50565b906000526020600020906005020191506153b1565b509392505050565b600080600080600061541c86614633565b935093509350935061543084848484614a3c565b9695505050505050565b6000816154d9846fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff16116154ef5763b34b5c226000526004601cfd5b6154f8836155c6565b905081615597826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1611612655576126526155ad836001615bae565b6fffffffffffffffffffffffffffffffff83169061566b565b6000811960018301168161565a827e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169390931c8015179392505050565b6000806156f8847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169050808303600180821b0385821b179250505092915050565b60008083601f84011261572657600080fd5b50813567ffffffffffffffff81111561573e57600080fd5b60208301915083602082850101111561575657600080fd5b9250929050565b600080600083850360a081121561577357600080fd5b608081121561578157600080fd5b50839250608084013567ffffffffffffffff81111561579f57600080fd5b6157ab86828701615714565b9497909650939450505050565b600080604083850312156157cb57600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6020810160038310615844577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b60008060006060848603121561585f57600080fd5b505081359360208301359350604090920135919050565b6000815180845260005b8181101561589c57602081850181015186830182015201615880565b818111156158ae576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006126526020830184615876565b60006020828403121561590657600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff8116811461592f57600080fd5b50565b60006020828403121561594457600080fd5b81356150d08161590d565b8035801515811461595f57600080fd5b919050565b6000806000806080858703121561597a57600080fd5b8435935060208501359250604085013591506159986060860161594f565b905092959194509250565b6000602082840312156159b557600080fd5b81356fffffffffffffffffffffffffffffffff811681146150d057600080fd5b600080600080600080608087890312156159ee57600080fd5b863595506159fe6020880161594f565b9450604087013567ffffffffffffffff80821115615a1b57600080fd5b615a278a838b01615714565b90965094506060890135915080821115615a4057600080fd5b50615a4d89828a01615714565b979a9699509497509295939492505050565b63ffffffff841681528260208201526060604082015260006119006060830184615876565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600060808284031215615ac557600080fd5b6040516080810181811067ffffffffffffffff82111715615b0f577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115615bc157615bc1615b7f565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203615bf757615bf7615b7f565b5060010190565b600082821015615c1057615c10615b7f565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082615c5357615c53615c15565b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615c9057615c90615b7f565b500290565b600060208284031215615ca757600080fd5b81516150d08161590d565b600060208284031215615cc457600080fd5b5051919050565b600067ffffffffffffffff808316818516808303821115615cee57615cee615b7f565b01949350505050565b600067ffffffffffffffff80831681851681830481118215151615615d1e57615d1e615b7f565b02949350505050565b600067ffffffffffffffff83811690831681811015615d4857615d48615b7f565b039392505050565b60008060408385031215615d6357600080fd5b505080516020909101519092909150565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600084136000841385830485118282161615615db557615db5615b7f565b7f80000000000000000000000000000000000000000000000000000000000000006000871286820588128184161615615df057615df0615b7f565b60008712925087820587128484161615615e0c57615e0c615b7f565b87850587128184161615615e2257615e22615b7f565b505050929093029392505050565b600082615e3f57615e3f615c15565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f800000000000000000000000000000000000000000000000000000000000000083141615615e9357615e93615b7f565b500590565b600082615ea757615ea7615c15565b500690565b60006fffffffffffffffffffffffffffffffff83811690831681811015615d4857615d48615b7f565b60006fffffffffffffffffffffffffffffffff808316818516808303821115615cee57615cee615b7f565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b606081526000615f5d606083018789615f00565b8281036020840152615f70818688615f00565b9150508260408301529695505050505050565b600060ff821660ff841680821015615f9d57615f9d615b7f565b90039392505050565b600060ff831680615fb957615fb9615c15565b8060ff8416069150509291505056fea164736f6c634300080f000a"; + hex"6080604052600436106103085760003560e01c806370872aa51161019a578063c6f0308c116100e1578063ec5e63081161008a578063fa24f74311610064578063fa24f74314610b94578063fa315aa914610bb8578063fe2bbeb214610beb57600080fd5b8063ec5e630814610b11578063eff0f59214610b44578063f8f43ff614610b7457600080fd5b8063d6ae3cd5116100bb578063d6ae3cd514610a8b578063d8cc1a3c14610abe578063dabd396d14610ade57600080fd5b8063c6f0308c146109b3578063cf09e0d014610a3d578063d5d44d8014610a5e57600080fd5b8063a445ece611610143578063bcef3b551161011d578063bcef3b5514610933578063bd8da95614610973578063c395e1ca1461099357600080fd5b8063a445ece6146107f3578063a8e4fb90146108bf578063bbdc02db146108f257600080fd5b80638980e0cc116101745780638980e0cc1461076b5780638b85902b146107805780638d450a95146107c057600080fd5b806370872aa51461073b5780637b0f0adc146107505780638129fc1c1461076357600080fd5b80633fc8cef31161025e5780635c0cba33116102075780636361506d116101e15780636361506d146106b55780636b6716c0146106f55780636f0344091461072857600080fd5b80635c0cba331461064d578063609d33341461068057806360e274641461069557600080fd5b806354fd4d501161023857806354fd4d50146105a757806357da950e146105fd5780635a5fa2d91461062d57600080fd5b80633fc8cef31461052e578063472777c614610561578063534db0e21461057457600080fd5b80632810e1d6116102c057806337b1b2291161029a57806337b1b2291461047b5780633a768463146104bb5780633e3ac912146104ee57600080fd5b80632810e1d6146103f45780632ad69aeb1461040957806330dbe5701461042957600080fd5b806319effeb4116102f157806319effeb41461034f578063200d2ed21461039a57806325fc2ace146103d557600080fd5b8063019351301461030d57806303c2924d1461032f575b600080fd5b34801561031957600080fd5b5061032d61032836600461575d565b610c1b565b005b34801561033b57600080fd5b5061032d61034a3660046157b8565b610f3c565b34801561035b57600080fd5b5060005461037c9068010000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020015b60405180910390f35b3480156103a657600080fd5b506000546103c890700100000000000000000000000000000000900460ff1681565b6040516103919190615809565b3480156103e157600080fd5b506008545b604051908152602001610391565b34801561040057600080fd5b506103c86115e2565b34801561041557600080fd5b506103e66104243660046157b8565b611887565b34801561043557600080fd5b506001546104569073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610391565b34801561048757600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90033560601c610456565b3480156104c757600080fd5b507f000000000000000000000000180cbe2ebb9f37d3a3c542ddc2546fd160555a73610456565b3480156104fa57600080fd5b5060005461051e907201000000000000000000000000000000000000900460ff1681565b6040519015158152602001610391565b34801561053a57600080fd5b507f000000000000000000000000d6eaf4c146261653ee059077b78ed088add54309610456565b61032d61056f36600461584a565b6118bd565b34801561058057600080fd5b507f0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b63610456565b3480156105b357600080fd5b506105f06040518060400160405280600c81526020017f312e332e312d626574612e32000000000000000000000000000000000000000081525081565b60405161039191906158e1565b34801561060957600080fd5b50600854600954610618919082565b60408051928352602083019190915201610391565b34801561063957600080fd5b506103e66106483660046158f4565b6118cf565b34801561065957600080fd5b507f000000000000000000000000970670459734a83899773a0fd45941b5afc1200e610456565b34801561068c57600080fd5b506105f0611909565b3480156106a157600080fd5b5061032d6106b0366004615932565b611917565b3480156106c157600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003603401356103e6565b34801561070157600080fd5b507f000000000000000000000000000000000000000000000000000000000000000061037c565b61032d610736366004615964565b611abe565b34801561074757600080fd5b506009546103e6565b61032d61075e36600461584a565b611b7f565b61032d611b8c565b34801561077757600080fd5b506002546103e6565b34801561078c57600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401356103e6565b3480156107cc57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006103e6565b3480156107ff57600080fd5b5061086b61080e3660046158f4565b6007602052600090815260409020805460019091015460ff821691610100810463ffffffff1691650100000000009091046fffffffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff1684565b60408051941515855263ffffffff90931660208501526fffffffffffffffffffffffffffffffff9091169183019190915273ffffffffffffffffffffffffffffffffffffffff166060820152608001610391565b3480156108cb57600080fd5b507f00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8610456565b3480156108fe57600080fd5b5060405163ffffffff7f0000000000000000000000000000000000000000000000000000000000000001168152602001610391565b34801561093f57600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003601401356103e6565b34801561097f57600080fd5b5061037c61098e3660046158f4565b611c05565b34801561099f57600080fd5b506103e66109ae3660046159a3565b611de4565b3480156109bf57600080fd5b506109d36109ce3660046158f4565b611fc7565b6040805163ffffffff909816885273ffffffffffffffffffffffffffffffffffffffff968716602089015295909416948601949094526fffffffffffffffffffffffffffffffff9182166060860152608085015291821660a08401521660c082015260e001610391565b348015610a4957600080fd5b5060005461037c9067ffffffffffffffff1681565b348015610a6a57600080fd5b506103e6610a79366004615932565b60036020526000908152604090205481565b348015610a9757600080fd5b507f00000000000000000000000000000000000000000000000000000000000003856103e6565b348015610aca57600080fd5b5061032d610ad93660046159d5565b61205e565b348015610aea57600080fd5b507f00000000000000000000000000000000000000000000000000000000000004b061037c565b348015610b1d57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000046103e6565b348015610b5057600080fd5b5061051e610b5f3660046158f4565b60046020526000908152604090205460ff1681565b348015610b8057600080fd5b5061032d610b8f36600461584a565b612123565b348015610ba057600080fd5b50610ba96125e0565b60405161039193929190615a5f565b348015610bc457600080fd5b507f00000000000000000000000000000000000000000000000000000000000000086103e6565b348015610bf757600080fd5b5061051e610c063660046158f4565b60066020526000908152604090205460ff1681565b60008054700100000000000000000000000000000000900460ff166002811115610c4757610c476157da565b14610c7e576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000547201000000000000000000000000000000000000900460ff1615610cd1576040517f0ea2e75200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d08367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013590565b90565b610d1f610d1a36869003860186615ab3565b61265b565b14610d56576040517f9cc00b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82606001358282604051610d6b929190615b40565b604051809103902014610daa576040517fd81d583b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610df3610dee84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506126b792505050565b612724565b90506000610e1a82600881518110610e0d57610e0d615b50565b60200260200101516128da565b9050602081511115610e58576040517fd81d583b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602081810151825190910360031b1c367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401358103610ecd576040517fb8ed883000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050600180547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790555050600080547fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff1672010000000000000000000000000000000000001790555050565b60008054700100000000000000000000000000000000900460ff166002811115610f6857610f686157da565b14610f9f576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028381548110610fb457610fb4615b50565b906000526020600020906005020190506000610fcf84611c05565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b081169082161015611038576040517ff2440b5300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008481526006602052604090205460ff1615611081576040517ff1a9458100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600084815260056020526040902080548015801561109e57508515155b15611139578354640100000000900473ffffffffffffffffffffffffffffffffffffffff16600081156110d157816110ed565b600186015473ffffffffffffffffffffffffffffffffffffffff165b90506110f9818761298e565b50505060009485525050600660205250506040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b6000868152600760209081526040918290208251608081018452815460ff81161515808352610100820463ffffffff16948301949094526501000000000090046fffffffffffffffffffffffffffffffff16938101939093526001015473ffffffffffffffffffffffffffffffffffffffff1660608301526111dc576fffffffffffffffffffffffffffffffff60408201526001815260008690036111dc578195505b600086826020015163ffffffff166111f49190615bae565b905060008382116112055781611207565b835b602084015190915063ffffffff165b8181101561135357600086828154811061123257611232615b50565b6000918252602080832090910154808352600690915260409091205490915060ff1661128a576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006002828154811061129f5761129f615b50565b600091825260209091206005909102018054909150640100000000900473ffffffffffffffffffffffffffffffffffffffff161580156112fc5750600481015460408701516fffffffffffffffffffffffffffffffff9182169116115b1561133e57600181015473ffffffffffffffffffffffffffffffffffffffff16606087015260048101546fffffffffffffffffffffffffffffffff1660408701525b5050808061134b90615bc6565b915050611216565b5063ffffffff818116602085810191825260008c81526007909152604090819020865181549351928801517fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009094169015157fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ff161761010092909416918202939093177fffffffffffffffffffffff00000000000000000000000000000000ffffffffff16650100000000006fffffffffffffffffffffffffffffffff909316929092029190911782556060850151600190920180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909316929092179091558490036115d757606083015160008a815260066020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055891580156114d357506000547201000000000000000000000000000000000000900460ff165b156115485760015473ffffffffffffffffffffffffffffffffffffffff166114fb818a61298e565b885473ffffffffffffffffffffffffffffffffffffffff909116640100000000027fffffffffffffffff0000000000000000000000000000000000000000ffffffff9091161788556115d5565b61158f73ffffffffffffffffffffffffffffffffffffffff82161561156d5781611589565b600189015473ffffffffffffffffffffffffffffffffffffffff165b8961298e565b87547fffffffffffffffff0000000000000000000000000000000000000000ffffffff1664010000000073ffffffffffffffffffffffffffffffffffffffff8316021788555b505b505050505050505050565b600080600054700100000000000000000000000000000000900460ff166002811115611610576116106157da565b14611647576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000805260066020527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f85460ff166116ab576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660026000815481106116d7576116d7615b50565b6000918252602090912060059091020154640100000000900473ffffffffffffffffffffffffffffffffffffffff1614611712576001611715565b60025b6000805467ffffffffffffffff421668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff82168117835592935083927fffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffff000000000000000000ffffffffffffffff909116177001000000000000000000000000000000008360028111156117c6576117c66157da565b0217905560028111156117db576117db6157da565b6040517f5e186f09b9c93491f14e277eea7faa5de6a2d4bda75a79af7a3684fbfb42da6090600090a27f000000000000000000000000970670459734a83899773a0fd45941b5afc1200e73ffffffffffffffffffffffffffffffffffffffff1663838c2d1e6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561186c57600080fd5b505af1158015611880573d6000803e3d6000fd5b5050505090565b600560205281600052604060002081815481106118a357600080fd5b90600052602060002001600091509150505481565b905090565b6118ca8383836001611abe565b505050565b6000818152600760209081526040808320600590925282208054825461190090610100900463ffffffff1682615bfe565b95945050505050565b60606118b860546020612a8f565b73ffffffffffffffffffffffffffffffffffffffff811660009081526003602052604081208054908290559081900361197c576040517f17bfe5f700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517ff3fef3a300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152602482018390527f000000000000000000000000d6eaf4c146261653ee059077b78ed088add54309169063f3fef3a390604401600060405180830381600087803b158015611a0c57600080fd5b505af1158015611a20573d6000803e3d6000fd5b5050505060008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114611a7e576040519150601f19603f3d011682016040523d82523d6000602084013e611a83565b606091505b50509050806118ca576040517f83e6cc6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8161480611b3757503373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b6316145b611b6d576040517fd386ef3e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611b7984848484612ae1565b50505050565b6118ca8383836000611abe565b3273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c81614611bfb576040517fd386ef3e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611c036135ba565b565b600080600054700100000000000000000000000000000000900460ff166002811115611c3357611c336157da565b14611c6a576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028381548110611c7f57611c7f615b50565b600091825260208220600590910201805490925063ffffffff90811614611cee57815460028054909163ffffffff16908110611cbd57611cbd615b50565b906000526020600020906005020160040160109054906101000a90046fffffffffffffffffffffffffffffffff1690505b6004820154600090611d2690700100000000000000000000000000000000900467ffffffffffffffff165b67ffffffffffffffff1690565b611d3a9067ffffffffffffffff1642615bfe565b611d59611d19846fffffffffffffffffffffffffffffffff1660401c90565b67ffffffffffffffff16611d6d9190615bae565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b01667ffffffffffffffff168167ffffffffffffffff1611611dba5780611900565b7f00000000000000000000000000000000000000000000000000000000000004b095945050505050565b600080611e83836fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690507f0000000000000000000000000000000000000000000000000000000000000008811115611ee2576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b642e90edd00062061a806311e1a3006000611efd8383615c44565b9050670de0b6b3a76400006000611f34827f0000000000000000000000000000000000000000000000000000000000000008615c58565b90506000611f52611f4d670de0b6b3a764000086615c58565b613b13565b90506000611f608484613d6e565b90506000611f6e8383613dbd565b90506000611f7b82613deb565b90506000611f9a82611f95670de0b6b3a76400008f615c58565b613fd3565b90506000611fa88b83613dbd565b9050611fb4818d615c58565b9f9e505050505050505050505050505050565b60028181548110611fd757600080fd5b60009182526020909120600590910201805460018201546002830154600384015460049094015463ffffffff8416955064010000000090930473ffffffffffffffffffffffffffffffffffffffff908116949216926fffffffffffffffffffffffffffffffff91821692918082169170010000000000000000000000000000000090041687565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c81614806120d757503373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b6316145b61210d576040517fd386ef3e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61211b868686868686614004565b505050505050565b60008054700100000000000000000000000000000000900460ff16600281111561214f5761214f6157da565b14612186576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060008061219586614633565b935093509350935060006121ab85858585614a3c565b905060007f000000000000000000000000180cbe2ebb9f37d3a3c542ddc2546fd160555a7373ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561221a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061223e9190615c95565b9050600189036123365773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a8461229a367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036034013590565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815260048101939093526024830191909152604482015260206064820152608481018a905260a4015b6020604051808303816000875af115801561230c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123309190615cb2565b506115d7565b600289036123625773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a848961229a565b6003890361238e5773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a848761229a565b600489036125155760006123d46fffffffffffffffffffffffffffffffff85167f0000000000000000000000000000000000000000000000000000000000000004614af6565b6009546123e19190615bae565b6123ec906001615bae565b9050367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360540135811061245557367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360540135612457565b805b905073ffffffffffffffffffffffffffffffffffffffff82166352f0f3ad8b8560405160e084901b7fffffffff000000000000000000000000000000000000000000000000000000001681526004810192909252602482015260c084901b604482015260086064820152608481018b905260a4016020604051808303816000875af11580156124ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061250e9190615cb2565b50506115d7565b600589036125ae576040517f52f0f3ad000000000000000000000000000000000000000000000000000000008152600481018a9052602481018390527f000000000000000000000000000000000000000000000000000000000000038560c01b6044820152600860648201526084810188905273ffffffffffffffffffffffffffffffffffffffff8216906352f0f3ad9060a4016122ed565b6040517fff137e6500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000001367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003601401356060612639611909565b9050909192565b6000818310156126505781612652565b825b90505b92915050565b6000816000015182602001518360400151846060015160405160200161269a949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b60408051808201909152600080825260208201528151600003612706576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50604080518082019091528151815260209182019181019190915290565b6060600080600061273485614ba4565b91945092509050600181600181111561274f5761274f6157da565b14612786576040517f4b9c6abe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84516127928385615bae565b146127c9576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808252610420820190925290816020015b60408051808201909152600080825260208201528152602001906001900390816127e05790505093506000835b86518110156128ce576000806128536040518060400160405280858c600001516128379190615bfe565b8152602001858c6020015161284c9190615bae565b9052614ba4565b50915091506040518060400160405280838361286f9190615bae565b8152602001848b602001516128849190615bae565b81525088858151811061289957612899615b50565b60209081029190910101526128af600185615bae565b93506128bb8183615bae565b6128c59084615bae565b9250505061280d565b50845250919392505050565b606060008060006128ea85614ba4565b919450925090506000816001811115612905576129056157da565b1461293c576040517f1ff9b2e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6129468284615bae565b85511461297f576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61190085602001518484615042565b600281015473ffffffffffffffffffffffffffffffffffffffff8316600090815260036020526040812080546fffffffffffffffffffffffffffffffff909316928392906129dd908490615bae565b90915550506040517f7eee288d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018390527f000000000000000000000000d6eaf4c146261653ee059077b78ed088add543091690637eee288d90604401600060405180830381600087803b158015612a7257600080fd5b505af1158015612a86573d6000803e3d6000fd5b50505050505050565b604051818152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90038284820160208401378260208301016000815260208101604052505092915050565b60008054700100000000000000000000000000000000900460ff166002811115612b0d57612b0d6157da565b14612b44576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028481548110612b5957612b59615b50565b60009182526020918290206040805160e0810182526005909302909101805463ffffffff8116845273ffffffffffffffffffffffffffffffffffffffff64010000000090910481169484019490945260018101549093169082015260028201546fffffffffffffffffffffffffffffffff908116606083015260038301546080830181905260049093015480821660a084015270010000000000000000000000000000000090041660c082015291508514612c40576040517f3014033200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60a0810151600083156fffffffffffffffffffffffffffffffff83161760011b90506000612d00826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169050861580612d3b5750612d387f00000000000000000000000000000000000000000000000000000000000000046002615bae565b81145b8015612d45575084155b15612d7c576040517fa42637bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000547201000000000000000000000000000000000000900460ff168015612da2575086155b15612dd9576040517f0ea2e75200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000008811115612e33576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612e5e7f00000000000000000000000000000000000000000000000000000000000000046001615bae565b8103612e7057612e70868885886150d7565b34612e7a83611de4565b14612eb1576040517f8620aa1900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612ebc88611c05565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b0811690821603612f24576040517f3381d11400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612f5160017f0000000000000000000000000000000000000000000000000000000000000008615bfe565b830361308f577f000000000000000000000000180cbe2ebb9f37d3a3c542ddc2546fd160555a7373ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015612fc2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fe69190615c95565b73ffffffffffffffffffffffffffffffffffffffff1663f3f480d96040518163ffffffff1660e01b8152600401602060405180830381865afa158015613030573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130549190615cb2565b613088907f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff16615ccb565b9050613122565b6130ba60017f0000000000000000000000000000000000000000000000000000000000000004615bfe565b83036130f5576130887f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff166002615cf7565b507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff165b613156817f00000000000000000000000000000000000000000000000000000000000004b067ffffffffffffffff16615d27565b67ffffffffffffffff166131718367ffffffffffffffff1690565b67ffffffffffffffff1611156131b8576131b5817f00000000000000000000000000000000000000000000000000000000000004b067ffffffffffffffff16615d27565b91505b6000604083901b421760008a8152608087901b6fffffffffffffffffffffffffffffffff8d1617602052604081209192509060008181526004602052604090205490915060ff1615613236576040517f80497e3b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60016004600083815260200190815260200160002060006101000a81548160ff02191690831515021790555060026040518060e001604052808d63ffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020013373ffffffffffffffffffffffffffffffffffffffff168152602001346fffffffffffffffffffffffffffffffff1681526020018c8152602001886fffffffffffffffffffffffffffffffff168152602001846fffffffffffffffffffffffffffffffff16815250908060018154018082558091505060019003906000526020600020906005020160009091909190915060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060608201518160020160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055506080820151816003015560a08201518160040160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555060c08201518160040160106101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055505050600560008c815260200190815260200160002060016002805490506134cc9190615bfe565b81546001810183556000928352602083200155604080517fd0e30db0000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000d6eaf4c146261653ee059077b78ed088add54309169263d0e30db09234926004808301939282900301818588803b15801561356457600080fd5b505af1158015613578573d6000803e3d6000fd5b50506040513393508d92508e91507f9b3245740ec3b155098a55be84957a4da13eaf7f14a8bc6f53126c0b9350f2be90600090a4505050505050505050505050565b60005471010000000000000000000000000000000000900460ff161561360c576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f7258a80700000000000000000000000000000000000000000000000000000000815263ffffffff7f0000000000000000000000000000000000000000000000000000000000000001166004820152600090819073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000970670459734a83899773a0fd45941b5afc1200e1690637258a807906024016040805180830381865afa1580156136c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136e49190615d50565b909250905081613720576040517f6a6bc3b200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518082019091528281526020018190526008829055600981905536607a1461375357639824bdab6000526004601cfd5b80367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360540135116137ed576040517ff40239db000000000000000000000000000000000000000000000000000000008152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013560048201526024015b60405180910390fd5b6040805160e08101825263ffffffff8082526000602083018181527ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe369081013560f01c90038035606090811c868801908152346fffffffffffffffffffffffffffffffff81811693890193845260149094013560808901908152600160a08a0181815242871660c08c019081526002805493840181558a529a5160059092027f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace81018054995173ffffffffffffffffffffffffffffffffffffffff908116640100000000027fffffffffffffffff000000000000000000000000000000000000000000000000909b1694909c16939093179890981790915592517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5acf87018054918a167fffffffffffffffffffffffff000000000000000000000000000000000000000090921691909117905592517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad0860180549186167fffffffffffffffffffffffffffffffff0000000000000000000000000000000090921691909117905591517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad185015551955182167001000000000000000000000000000000000295909116949094177f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad29091015580547fffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffff167101000000000000000000000000000000000017815583517fd0e30db000000000000000000000000000000000000000000000000000000000815293517f000000000000000000000000d6eaf4c146261653ee059077b78ed088add543099092169363d0e30db093926004828101939282900301818588803b158015613ac257600080fd5b505af1158015613ad6573d6000803e3d6000fd5b5050600080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000164267ffffffffffffffff161790555050505050565b6fffffffffffffffffffffffffffffffff811160071b81811c67ffffffffffffffff1060061b1781811c63ffffffff1060051b1781811c61ffff1060041b1781811c60ff1060031b1760008213613b7257631615e6386000526004601cfd5b7ff8f9f9faf9fdfafbf9fdfcfdfafbfcfef9fafdfafcfcfbfefafafcfbffffffff6f8421084210842108cc6318c6db6d54be83831c1c601f161a1890811b609f90811c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506029190037d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b302017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d90565b60007812725dd1d243aba0e75fe645cc4873f9e65afe688c928e1f218311670de0b6b3a764000002158202613dab57637c5f487d6000526004601cfd5b50670de0b6b3a7640000919091020490565b600081600019048311820215613ddb5763bac65e5b6000526004601cfd5b50670de0b6b3a764000091020490565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdc0d0570925a462d78213613e1957919050565b680755bf798b4a1bf1e58212613e375763a37bfec96000526004601cfd5b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b6000612652670de0b6b3a764000083613feb86613b13565b613ff59190615d74565b613fff9190615e30565b613deb565b60008054700100000000000000000000000000000000900460ff166002811115614030576140306157da565b14614067576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006002878154811061407c5761407c615b50565b6000918252602082206005919091020160048101549092506fffffffffffffffffffffffffffffffff16908715821760011b90506140db7f00000000000000000000000000000000000000000000000000000000000000086001615bae565b614177826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff16146141b1576040517f5f53dd9800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008089156142a8576142047f00000000000000000000000000000000000000000000000000000000000000047f0000000000000000000000000000000000000000000000000000000000000008615bfe565b6001901b614223846fffffffffffffffffffffffffffffffff16615288565b6fffffffffffffffffffffffffffffffff1661423f9190615e98565b1561427c5761427361426460016fffffffffffffffffffffffffffffffff8716615eac565b865463ffffffff166000615327565b6003015461429e565b7f00000000000000000000000000000000000000000000000000000000000000005b91508490506142d2565b600385015491506142cf6142646fffffffffffffffffffffffffffffffff86166001615ed5565b90505b600882901b60088a8a6040516142e9929190615b40565b6040518091039020901b1461432a576040517f696550ff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006143358c61540b565b90506000614344836003015490565b6040517fe14ced320000000000000000000000000000000000000000000000000000000081527f000000000000000000000000180cbe2ebb9f37d3a3c542ddc2546fd160555a7373ffffffffffffffffffffffffffffffffffffffff169063e14ced32906143be908f908f908f908f908a90600401615f49565b6020604051808303816000875af11580156143dd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144019190615cb2565b6004850154911491506000906002906144ac906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b614548896fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b6145529190615f83565b61455c9190615fa6565b60ff16159050811515810361459d576040517ffb4e40dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8754640100000000900473ffffffffffffffffffffffffffffffffffffffff16156145f4576040517f9071e6af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505085547fffffffffffffffff0000000000000000000000000000000000000000ffffffff163364010000000002179095555050505050505050505050565b600080600080600085905060006002828154811061465357614653615b50565b600091825260209091206004600590920201908101549091507f00000000000000000000000000000000000000000000000000000000000000049061472a906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1611614764576040517fb34b5c2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000815b60048301547f00000000000000000000000000000000000000000000000000000000000000049061482b906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1692508211156148a057825463ffffffff1661486a7f00000000000000000000000000000000000000000000000000000000000000046001615bae565b8303614874578391505b6002818154811061488757614887615b50565b9060005260206000209060050201935080945050614768565b600481810154908401546fffffffffffffffffffffffffffffffff91821691166000816fffffffffffffffffffffffffffffffff166149096148f4856fffffffffffffffffffffffffffffffff1660011c90565b6fffffffffffffffffffffffffffffffff1690565b6fffffffffffffffffffffffffffffffff1614905080156149d8576000614941836fffffffffffffffffffffffffffffffff16615288565b6fffffffffffffffffffffffffffffffff1611156149ac57600061498361497b60016fffffffffffffffffffffffffffffffff8616615eac565b896001615327565b6003810154600490910154909c506fffffffffffffffffffffffffffffffff169a506149b29050565b6008549a505b600386015460048701549099506fffffffffffffffffffffffffffffffff169750614a2e565b60006149fa61497b6fffffffffffffffffffffffffffffffff85166001615ed5565b6003808901546004808b015492840154930154909e506fffffffffffffffffffffffffffffffff9182169d50919b50169850505b505050505050509193509193565b60006fffffffffffffffffffffffffffffffff841615614aa95760408051602081018790526fffffffffffffffffffffffffffffffff8087169282019290925260608101859052908316608082015260a00160405160208183030381529060405280519060200120611900565b8282604051602001614ad79291909182526fffffffffffffffffffffffffffffffff16602082015260400190565b6040516020818303038152906040528051906020012095945050505050565b600080614b83847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690508083036001841b600180831b0386831b17039250505092915050565b60008060008360000151600003614be7576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020840151805160001a607f8111614c0c57600060016000945094509450505061503b565b60b78111614d22576000614c21608083615bfe565b905080876000015111614c60576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001838101517fff00000000000000000000000000000000000000000000000000000000000000169082148015614cd857507f80000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008216105b15614d0f576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506001955093506000925061503b915050565b60bf8111614e80576000614d3760b783615bfe565b905080876000015111614d76576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614dd8576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c60378111614e20576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614e2a8184615bae565b895111614e63576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614e6e836001615bae565b975095506000945061503b9350505050565b60f78111614ee5576000614e9560c083615bfe565b905080876000015111614ed4576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60019550935084925061503b915050565b6000614ef260f783615bfe565b905080876000015111614f31576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614f93576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c60378111614fdb576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614fe58184615bae565b89511161501e576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b615029836001615bae565b975095506001945061503b9350505050565b9193909250565b60608167ffffffffffffffff81111561505d5761505d615a84565b6040519080825280601f01601f191660200182016040528015615087576020820181803683370190505b50905081156150d057600061509c8486615bae565b90506020820160005b848110156150bd5782810151828201526020016150a5565b848111156150cc576000858301525b5050505b9392505050565b60006150f66fffffffffffffffffffffffffffffffff84166001615ed5565b9050600061510682866001615327565b9050600086901a83806151f2575061513f60027f0000000000000000000000000000000000000000000000000000000000000004615e98565b60048301546002906151e3906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b6151ed9190615fa6565b60ff16145b1561524a5760ff81166001148061520c575060ff81166002145b615245576040517ff40239db000000000000000000000000000000000000000000000000000000008152600481018890526024016137e4565b612a86565b60ff811615612a86576040517ff40239db000000000000000000000000000000000000000000000000000000008152600481018890526024016137e4565b600080615315837e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b600160ff919091161b90920392915050565b600080826153705761536b6fffffffffffffffffffffffffffffffff86167f000000000000000000000000000000000000000000000000000000000000000461543a565b61538b565b61538b856fffffffffffffffffffffffffffffffff166155c6565b9050600284815481106153a0576153a0615b50565b906000526020600020906005020191505b60048201546fffffffffffffffffffffffffffffffff82811691161461540357815460028054909163ffffffff169081106153ee576153ee615b50565b906000526020600020906005020191506153b1565b509392505050565b600080600080600061541c86614633565b935093509350935061543084848484614a3c565b9695505050505050565b6000816154d9846fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff16116154ef5763b34b5c226000526004601cfd5b6154f8836155c6565b905081615597826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1611612655576126526155ad836001615bae565b6fffffffffffffffffffffffffffffffff83169061566b565b6000811960018301168161565a827e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169390931c8015179392505050565b6000806156f8847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169050808303600180821b0385821b179250505092915050565b60008083601f84011261572657600080fd5b50813567ffffffffffffffff81111561573e57600080fd5b60208301915083602082850101111561575657600080fd5b9250929050565b600080600083850360a081121561577357600080fd5b608081121561578157600080fd5b50839250608084013567ffffffffffffffff81111561579f57600080fd5b6157ab86828701615714565b9497909650939450505050565b600080604083850312156157cb57600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6020810160038310615844577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b60008060006060848603121561585f57600080fd5b505081359360208301359350604090920135919050565b6000815180845260005b8181101561589c57602081850181015186830182015201615880565b818111156158ae576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006126526020830184615876565b60006020828403121561590657600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff8116811461592f57600080fd5b50565b60006020828403121561594457600080fd5b81356150d08161590d565b8035801515811461595f57600080fd5b919050565b6000806000806080858703121561597a57600080fd5b8435935060208501359250604085013591506159986060860161594f565b905092959194509250565b6000602082840312156159b557600080fd5b81356fffffffffffffffffffffffffffffffff811681146150d057600080fd5b600080600080600080608087890312156159ee57600080fd5b863595506159fe6020880161594f565b9450604087013567ffffffffffffffff80821115615a1b57600080fd5b615a278a838b01615714565b90965094506060890135915080821115615a4057600080fd5b50615a4d89828a01615714565b979a9699509497509295939492505050565b63ffffffff841681528260208201526060604082015260006119006060830184615876565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600060808284031215615ac557600080fd5b6040516080810181811067ffffffffffffffff82111715615b0f577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115615bc157615bc1615b7f565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203615bf757615bf7615b7f565b5060010190565b600082821015615c1057615c10615b7f565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082615c5357615c53615c15565b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615c9057615c90615b7f565b500290565b600060208284031215615ca757600080fd5b81516150d08161590d565b600060208284031215615cc457600080fd5b5051919050565b600067ffffffffffffffff808316818516808303821115615cee57615cee615b7f565b01949350505050565b600067ffffffffffffffff80831681851681830481118215151615615d1e57615d1e615b7f565b02949350505050565b600067ffffffffffffffff83811690831681811015615d4857615d48615b7f565b039392505050565b60008060408385031215615d6357600080fd5b505080516020909101519092909150565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600084136000841385830485118282161615615db557615db5615b7f565b7f80000000000000000000000000000000000000000000000000000000000000006000871286820588128184161615615df057615df0615b7f565b60008712925087820587128484161615615e0c57615e0c615b7f565b87850587128184161615615e2257615e22615b7f565b505050929093029392505050565b600082615e3f57615e3f615c15565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f800000000000000000000000000000000000000000000000000000000000000083141615615e9357615e93615b7f565b500590565b600082615ea757615ea7615c15565b500690565b60006fffffffffffffffffffffffffffffffff83811690831681811015615d4857615d48615b7f565b60006fffffffffffffffffffffffffffffffff808316818516808303821115615cee57615cee615b7f565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b606081526000615f5d606083018789615f00565b8281036020840152615f70818688615f00565b9150508260408301529695505050505050565b600060ff821660ff841680821015615f9d57615f9d615b7f565b90039392505050565b600060ff831680615fb957615fb9615c15565b8060ff8416069150509291505056fea164736f6c634300080f000a"; } diff --git a/packages/contracts-bedrock/test/kontrol/proofs/utils/DeploymentSummaryFaultProofs.sol b/packages/contracts-bedrock/test/kontrol/proofs/utils/DeploymentSummaryFaultProofs.sol index 41a56ef77bad2..3b54141df2d7b 100644 --- a/packages/contracts-bedrock/test/kontrol/proofs/utils/DeploymentSummaryFaultProofs.sol +++ b/packages/contracts-bedrock/test/kontrol/proofs/utils/DeploymentSummaryFaultProofs.sol @@ -13,36 +13,36 @@ contract DeploymentSummaryFaultProofs is DeploymentSummaryFaultProofsCode { Vm private constant vm = Vm(VM_ADDRESS); address internal constant addressManagerAddress = 0x50EEf481cae4250d252Ae577A09bF514f224C6C4; - address internal constant anchorStateRegistryAddress = 0x63B71B96756C693f7065345fecD9b7843b3e7C57; + address internal constant anchorStateRegistryAddress = 0xdEC4D949Cf1A2e824eE4F8B12064e166b96171dD; address internal constant anchorStateRegistryProxyAddress = 0x970670459734a83899773A0fd45941B5afC1200e; - address internal constant delayedWETHAddress = 0x2A6347EDD3C7813CDE46DD7eA61FF1Cf2290BC05; + address internal constant delayedWETHAddress = 0xe49cED258137CC5E18fB9ABA2Aa14069263D8f49; address internal constant delayedWETHProxyAddress = 0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92; - address internal constant disputeGameFactoryAddress = 0x20B168142354Cee65a32f6D8cf3033E592299765; + address internal constant disputeGameFactoryAddress = 0x8efDa795511CBBdfFC9eeca1a5bF30f5B1E1ef9E; address internal constant disputeGameFactoryProxyAddress = 0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d; - address internal constant l1CrossDomainMessengerAddress = 0x094e6508ba9d9bf1ce421fff3dE06aE56e67901b; + address internal constant l1CrossDomainMessengerAddress = 0x357B6CdA94109749a0dA475ac1BFd395a61eb908; address internal constant l1CrossDomainMessengerProxyAddress = 0xDeF3bca8c80064589E6787477FFa7Dd616B5574F; - address internal constant l1ERC721BridgeAddress = 0x5C4F5e749A61a9503c4AAE8a9393e89609a0e804; + address internal constant l1ERC721BridgeAddress = 0xA4BD7E58A30ED0477fe7372883d09bF86619Bb66; address internal constant l1ERC721BridgeProxyAddress = 0xD31598c909d9C935a9e35bA70d9a3DD47d4D5865; - address internal constant l1StandardBridgeAddress = 0xb7900B27Be8f0E0fF65d1C3A4671e1220437dd2b; + address internal constant l1StandardBridgeAddress = 0x6cb2c88ABCd6391F9496f44BE27d5D3b247E0159; address internal constant l1StandardBridgeProxyAddress = 0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D; - address internal constant l2OutputOracleAddress = 0x19652082F846171168Daf378C4fD3ee85a0D4A60; + address internal constant l2OutputOracleAddress = 0x60d37db59d0D14f7EA5c7425A2C03244E08B162D; address internal constant l2OutputOracleProxyAddress = 0x39Af23E00F1e662025aA01b0cEdA19542B78DF99; - address internal constant mipsAddress = 0x444e09fe6D839273316a87002aB0EFBeA6fe7806; - address internal constant optimismMintableERC20FactoryAddress = 0x7c06d3a0a2f45e39E1798afbd9C3330971332a4F; + address internal constant mipsAddress = 0x180CBe2EBb9F37D3a3C542DDc2546Fd160555a73; + address internal constant optimismMintableERC20FactoryAddress = 0x79c3114E5f89266e2C8842871Bce16D4e5076b1e; address internal constant optimismMintableERC20FactoryProxyAddress = 0xc7B87b2b892EA5C3CfF47168881FE168C00377FB; - address internal constant optimismPortalAddress = 0xbdD90485FCbcac869D5b5752179815a3103d8131; - address internal constant optimismPortal2Address = 0xae5DadFc48928543f706a9E6Ce25c682aaD2b63b; + address internal constant optimismPortalAddress = 0xb5A42f01EF5068F82C11fa1c4F9bBD4c8D346961; + address internal constant optimismPortal2Address = 0x150581358018524994Fc29800b1783637943b103; address internal constant optimismPortalProxyAddress = 0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4; address internal constant permissionedDelayedWETHProxyAddress = 0xd6EAF4c146261653EE059077B78ED088Add54309; - address internal constant preimageOracleAddress = 0x373d916D11cce55b548F7051002e76BCFBD7a85d; - address internal constant protocolVersionsAddress = 0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F; + address internal constant preimageOracleAddress = 0x7A9Eab4CE99d157AeE7A02E95b366E972a2D5b0b; + address internal constant protocolVersionsAddress = 0xa99F1ab91821747b76Ec0cDFA38368DF4Ba06E84; address internal constant protocolVersionsProxyAddress = 0x4C52a6277b1B84121b3072C0c92b6Be0b7CC10F1; address internal constant proxyAdminAddress = 0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1; address internal constant safeProxyFactoryAddress = 0xA8452Ec99ce0C64f20701dB7dD3abDb607c00496; address internal constant safeSingletonAddress = 0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3; - address internal constant superchainConfigAddress = 0x068E44eB31e111028c41598E4535be7468674D0A; + address internal constant superchainConfigAddress = 0xDAf629c26abd7a84B6330c369887053B75dB2AF2; address internal constant superchainConfigProxyAddress = 0x4f559F30f5eB88D635FDe1548C4267DB8FaB0351; - address internal constant systemConfigAddress = 0x67866A5052E5302aaD08e9f352331fd8622eB6DC; + address internal constant systemConfigAddress = 0xd9CEcA938f039e427Edf626FA1f377d23A6b60c9; address internal constant systemConfigProxyAddress = 0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6; address internal constant systemOwnerSafeAddress = 0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD; address internal constant acc33Address = 0xb6b1579AA54e2F61e621a40d5F2704D717B3544F; @@ -107,7 +107,7 @@ contract DeploymentSummaryFaultProofs is DeploymentSummaryFaultProofsCode { value = hex"0000000000000000000000000000000000000000000000000000000000000001"; vm.store(systemOwnerSafeAddress, slot, value); slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; - value = hex"000000000000000000000000068e44eb31e111028c41598e4535be7468674d0a"; + value = hex"000000000000000000000000daf629c26abd7a84b6330c369887053b75db2af2"; vm.store(superchainConfigProxyAddress, slot, value); slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; value = hex"0000000000000000000000000000000000000000000000000000000000000001"; @@ -145,7 +145,7 @@ contract DeploymentSummaryFaultProofs is DeploymentSummaryFaultProofsCode { value = hex"0000000000000000000000000000000000000000000000000000000000000002"; vm.store(systemOwnerSafeAddress, slot, value); slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; - value = hex"000000000000000000000000fbfd64a6c0257f613fefce050aa30ecc3e3d7c3f"; + value = hex"000000000000000000000000a99f1ab91821747b76ec0cdfa38368df4ba06e84"; vm.store(protocolVersionsProxyAddress, slot, value); slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; value = hex"0000000000000000000000000000000000000000000000000000000000000001"; @@ -430,7 +430,7 @@ contract DeploymentSummaryFaultProofs is DeploymentSummaryFaultProofsCode { value = hex"0000000000000000000000000000000000000000000000000000000000000003"; vm.store(systemOwnerSafeAddress, slot, value); slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; - value = hex"000000000000000000000000ae5dadfc48928543f706a9e6ce25c682aad2b63b"; + value = hex"000000000000000000000000150581358018524994fc29800b1783637943b103"; vm.store(optimismPortalProxyAddress, slot, value); slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; value = hex"0000000000000000000000000000000000000000000000000000000000000001"; @@ -463,7 +463,7 @@ contract DeploymentSummaryFaultProofs is DeploymentSummaryFaultProofsCode { value = hex"0000000000000000000000000000000000000000000000000000000000000004"; vm.store(systemOwnerSafeAddress, slot, value); slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; - value = hex"00000000000000000000000067866a5052e5302aad08e9f352331fd8622eb6dc"; + value = hex"000000000000000000000000d9ceca938f039e427edf626fa1f377d23a6b60c9"; vm.store(systemConfigProxyAddress, slot, value); slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; value = hex"0000000000000000000000000000000000000000000000000000000000000001"; @@ -532,7 +532,7 @@ contract DeploymentSummaryFaultProofs is DeploymentSummaryFaultProofsCode { value = hex"0000000000000000000000000000000000000000000000000000000000000006"; vm.store(systemOwnerSafeAddress, slot, value); slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; - value = hex"000000000000000000000000b7900b27be8f0e0ff65d1c3a4671e1220437dd2b"; + value = hex"0000000000000000000000006cb2c88abcd6391f9496f44be27d5d3b247e0159"; vm.store(l1StandardBridgeProxyAddress, slot, value); slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; value = hex"0000000000000000000000000000000000000000000000000000000000000001"; @@ -559,7 +559,7 @@ contract DeploymentSummaryFaultProofs is DeploymentSummaryFaultProofsCode { value = hex"0000000000000000000000000000000000000000000000000000000000000007"; vm.store(systemOwnerSafeAddress, slot, value); slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; - value = hex"0000000000000000000000005c4f5e749a61a9503c4aae8a9393e89609a0e804"; + value = hex"000000000000000000000000a4bd7e58a30ed0477fe7372883d09bf86619bb66"; vm.store(l1ERC721BridgeProxyAddress, slot, value); slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; value = hex"0000000000000000000000000000000000000000000000000000000000000001"; @@ -583,7 +583,7 @@ contract DeploymentSummaryFaultProofs is DeploymentSummaryFaultProofsCode { value = hex"0000000000000000000000000000000000000000000000000000000000000008"; vm.store(systemOwnerSafeAddress, slot, value); slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; - value = hex"0000000000000000000000007c06d3a0a2f45e39e1798afbd9c3330971332a4f"; + value = hex"00000000000000000000000079c3114e5f89266e2c8842871bce16d4e5076b1e"; vm.store(optimismMintableERC20FactoryProxyAddress, slot, value); slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; value = hex"0000000000000000000000000000000000000000000000000000000000000001"; @@ -613,7 +613,7 @@ contract DeploymentSummaryFaultProofs is DeploymentSummaryFaultProofsCode { value = hex"000000000000000000000000000000000000000000000000000000000000000b"; vm.store(systemOwnerSafeAddress, slot, value); slot = hex"515216935740e67dfdda5cf8e248ea32b3277787818ab59153061ac875c9385e"; - value = hex"000000000000000000000000094e6508ba9d9bf1ce421fff3de06ae56e67901b"; + value = hex"000000000000000000000000357b6cda94109749a0da475ac1bfd395a61eb908"; vm.store(addressManagerAddress, slot, value); slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; value = hex"0000000000000000000000010000000000000000000000000000000000000000"; @@ -643,7 +643,7 @@ contract DeploymentSummaryFaultProofs is DeploymentSummaryFaultProofsCode { value = hex"000000000000000000000000000000000000000000000000000000000000000c"; vm.store(systemOwnerSafeAddress, slot, value); slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; - value = hex"00000000000000000000000019652082f846171168daf378c4fd3ee85a0d4a60"; + value = hex"00000000000000000000000060d37db59d0d14f7ea5c7425a2c03244e08b162d"; vm.store(l2OutputOracleProxyAddress, slot, value); slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; value = hex"0000000000000000000000000000000000000000000000000000000000000001"; @@ -679,7 +679,7 @@ contract DeploymentSummaryFaultProofs is DeploymentSummaryFaultProofsCode { value = hex"000000000000000000000000000000000000000000000000000000000000000d"; vm.store(systemOwnerSafeAddress, slot, value); slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; - value = hex"00000000000000000000000020b168142354cee65a32f6d8cf3033e592299765"; + value = hex"0000000000000000000000008efda795511cbbdffc9eeca1a5bf30f5b1e1ef9e"; vm.store(disputeGameFactoryProxyAddress, slot, value); slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; value = hex"0000000000000000000000000000000000000000000000000000000000000001"; @@ -700,7 +700,7 @@ contract DeploymentSummaryFaultProofs is DeploymentSummaryFaultProofsCode { value = hex"000000000000000000000000000000000000000000000000000000000000000e"; vm.store(systemOwnerSafeAddress, slot, value); slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; - value = hex"0000000000000000000000002a6347edd3c7813cde46dd7ea61ff1cf2290bc05"; + value = hex"000000000000000000000000e49ced258137cc5e18fb9aba2aa14069263d8f49"; vm.store(delayedWETHProxyAddress, slot, value); slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; value = hex"0000000000000000000000000000000000000000000000000000000000000001"; @@ -724,7 +724,7 @@ contract DeploymentSummaryFaultProofs is DeploymentSummaryFaultProofsCode { value = hex"000000000000000000000000000000000000000000000000000000000000000f"; vm.store(systemOwnerSafeAddress, slot, value); slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; - value = hex"0000000000000000000000002a6347edd3c7813cde46dd7ea61ff1cf2290bc05"; + value = hex"000000000000000000000000e49ced258137cc5e18fb9aba2aa14069263d8f49"; vm.store(permissionedDelayedWETHProxyAddress, slot, value); slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; value = hex"0000000000000000000000000000000000000000000000000000000000000001"; @@ -748,7 +748,7 @@ contract DeploymentSummaryFaultProofs is DeploymentSummaryFaultProofsCode { value = hex"0000000000000000000000000000000000000000000000000000000000000010"; vm.store(systemOwnerSafeAddress, slot, value); slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; - value = hex"00000000000000000000000063b71b96756c693f7065345fecd9b7843b3e7c57"; + value = hex"000000000000000000000000dec4d949cf1a2e824ee4f8b12064e166b96171dd"; vm.store(anchorStateRegistryProxyAddress, slot, value); slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; value = hex"0000000000000000000000000000000000000000000000000000000000000001"; diff --git a/packages/contracts-bedrock/test/kontrol/proofs/utils/DeploymentSummaryFaultProofsCode.sol b/packages/contracts-bedrock/test/kontrol/proofs/utils/DeploymentSummaryFaultProofsCode.sol index d05414671296e..a2809e3348638 100644 --- a/packages/contracts-bedrock/test/kontrol/proofs/utils/DeploymentSummaryFaultProofsCode.sol +++ b/packages/contracts-bedrock/test/kontrol/proofs/utils/DeploymentSummaryFaultProofsCode.sol @@ -17,11 +17,11 @@ contract DeploymentSummaryFaultProofsCode { bytes internal constant superchainConfigProxyCode = hex"60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a"; bytes internal constant superchainConfigCode = - hex"608060405234801561001057600080fd5b50600436106100885760003560e01c80635c975abb1161005b5780635c975abb146101255780636da663551461013d5780637fbf7b6a14610150578063c23a451a1461016657600080fd5b80633f4ba83a1461008d578063400ada7514610097578063452a9320146100aa57806354fd4d50146100dc575b600080fd5b61009561016e565b005b6100956100a5366004610746565b610294565b6100b261046d565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6101186040518060400160405280600581526020017f312e312e3000000000000000000000000000000000000000000000000000000081525081565b6040516100d39190610808565b61012d6104a6565b60405190151581526020016100d3565b61009561014b366004610851565b6104d6565b6101586105a4565b6040519081526020016100d3565b6101586105d2565b61017661046d565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610235576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f5375706572636861696e436f6e6669673a206f6e6c7920677561726469616e2060448201527f63616e20756e706175736500000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61026961026360017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b60009055565b6040517fa45f47fdea8a1efdd9029a5691c7f759c32b7c698632b563573e155625d1693390600090a1565b600054610100900460ff16158080156102b45750600054600160ff909116105b806102ce5750303b1580156102ce575060005460ff166001145b61035a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161022c565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156103b857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6103c18361061d565b8115610405576104056040518060400160405280601281526020017f496e697469616c697a65722070617573656400000000000000000000000000008152506106d8565b801561046857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b60006104a161049d60017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69610920565b5490565b905090565b60006104a161049d60017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b6104de61046d565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610598576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f5375706572636861696e436f6e6669673a206f6e6c7920677561726469616e2060448201527f63616e2070617573650000000000000000000000000000000000000000000000606482015260840161022c565b6105a1816106d8565b50565b6105cf60017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b81565b6105cf60017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69610920565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b9055565b61065061064b60017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69610920565b829055565b60006040805173ffffffffffffffffffffffffffffffffffffffff841660208201527f7b743789cff01dafdeae47739925425aab5dfd02d0c8229e4a508bcd2b9f42bb9101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526106cd91610808565b60405180910390a250565b61070c61070660017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b60019055565b7fc32e6d5d6d1de257f64eac19ddb1f700ba13527983849c9486b1ab007ea283818160405161073b9190610808565b60405180910390a150565b6000806040838503121561075957600080fd5b823573ffffffffffffffffffffffffffffffffffffffff8116811461077d57600080fd5b91506020830135801515811461079257600080fd5b809150509250929050565b6000815180845260005b818110156107c3576020818501810151868301820152016107a7565b818111156107d5576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061081b602083018461079d565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561086357600080fd5b813567ffffffffffffffff8082111561087b57600080fd5b818401915084601f83011261088f57600080fd5b8135818111156108a1576108a1610822565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156108e7576108e7610822565b8160405282815287602084870101111561090057600080fd5b826020860160208301376000928101602001929092525095945050505050565b600082821015610959577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50039056fea164736f6c634300080f000a"; + hex"608060405234801561001057600080fd5b50600436106100885760003560e01c80635c975abb1161005b5780635c975abb146101255780636da663551461013d5780637fbf7b6a14610150578063c23a451a1461016657600080fd5b80633f4ba83a1461008d578063400ada7514610097578063452a9320146100aa57806354fd4d50146100dc575b600080fd5b61009561016e565b005b6100956100a5366004610746565b610294565b6100b261046d565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6101186040518060400160405280600c81526020017f312e312e312d626574612e31000000000000000000000000000000000000000081525081565b6040516100d39190610808565b61012d6104a6565b60405190151581526020016100d3565b61009561014b366004610851565b6104d6565b6101586105a4565b6040519081526020016100d3565b6101586105d2565b61017661046d565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610235576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f5375706572636861696e436f6e6669673a206f6e6c7920677561726469616e2060448201527f63616e20756e706175736500000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61026961026360017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b60009055565b6040517fa45f47fdea8a1efdd9029a5691c7f759c32b7c698632b563573e155625d1693390600090a1565b600054610100900460ff16158080156102b45750600054600160ff909116105b806102ce5750303b1580156102ce575060005460ff166001145b61035a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161022c565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156103b857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6103c18361061d565b8115610405576104056040518060400160405280601281526020017f496e697469616c697a65722070617573656400000000000000000000000000008152506106d8565b801561046857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b60006104a161049d60017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69610920565b5490565b905090565b60006104a161049d60017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b6104de61046d565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610598576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f5375706572636861696e436f6e6669673a206f6e6c7920677561726469616e2060448201527f63616e2070617573650000000000000000000000000000000000000000000000606482015260840161022c565b6105a1816106d8565b50565b6105cf60017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b81565b6105cf60017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69610920565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b9055565b61065061064b60017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69610920565b829055565b60006040805173ffffffffffffffffffffffffffffffffffffffff841660208201527f7b743789cff01dafdeae47739925425aab5dfd02d0c8229e4a508bcd2b9f42bb9101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526106cd91610808565b60405180910390a250565b61070c61070660017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b60019055565b7fc32e6d5d6d1de257f64eac19ddb1f700ba13527983849c9486b1ab007ea283818160405161073b9190610808565b60405180910390a150565b6000806040838503121561075957600080fd5b823573ffffffffffffffffffffffffffffffffffffffff8116811461077d57600080fd5b91506020830135801515811461079257600080fd5b809150509250929050565b6000815180845260005b818110156107c3576020818501810151868301820152016107a7565b818111156107d5576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061081b602083018461079d565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561086357600080fd5b813567ffffffffffffffff8082111561087b57600080fd5b818401915084601f83011261088f57600080fd5b8135818111156108a1576108a1610822565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156108e7576108e7610822565b8160405282815287602084870101111561090057600080fd5b826020860160208301376000928101602001929092525095945050505050565b600082821015610959577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50039056fea164736f6c634300080f000a"; bytes internal constant protocolVersionsProxyCode = hex"60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a"; bytes internal constant protocolVersionsCode = - hex"608060405234801561001057600080fd5b50600436106100d45760003560e01c80638da5cb5b11610081578063f2fde38b1161005b578063f2fde38b146101b8578063f7d12760146101cb578063ffa1ad74146101d357600080fd5b80638da5cb5b14610180578063d798b1ac146101a8578063dc8452cd146101b057600080fd5b80635fd579af116100b25780635fd579af14610152578063715018a6146101655780637a1ac61e1461016d57600080fd5b80630457d6f2146100d9578063206a8300146100ee57806354fd4d5014610109575b600080fd5b6100ec6100e73660046108c3565b6101db565b005b6100f66101ef565b6040519081526020015b60405180910390f35b6101456040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516101009190610947565b6100ec6101603660046108c3565b61021d565b6100ec61022e565b6100ec61017b36600461098a565b610242565b60335460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610100565b6100f66103f7565b6100f6610430565b6100ec6101c63660046109bd565b610460565b6100f6610514565b6100f6600081565b6101e361055f565b6101ec816105e0565b50565b61021a60017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16109d8565b81565b61022561055f565b6101ec81610698565b61023661055f565b6102406000610712565b565b600054610100900460ff16158080156102625750600054600160ff909116105b8061027c5750303b15801561027c575060005460ff166001145b61030d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561036b57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610373610789565b61037c84610460565b610385836105e0565b61038e82610698565b80156103f157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b600061042b61042760017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6109d8565b5490565b905090565b600061042b61042760017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16109d8565b61046861055f565b73ffffffffffffffffffffffffffffffffffffffff811661050b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610304565b6101ec81610712565b61021a60017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6109d8565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b9055565b60335473ffffffffffffffffffffffffffffffffffffffff163314610240576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610304565b61061361060e60017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16109d8565b829055565b60008160405160200161062891815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060005b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be8360405161068c9190610947565b60405180910390a35050565b6106c661060e60017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6109d8565b6000816040516020016106db91815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529050600161065b565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16610820576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610304565b610240600054610100900460ff166108ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610304565b61024033610712565b6000602082840312156108d557600080fd5b5035919050565b6000815180845260005b81811015610902576020818501810151868301820152016108e6565b81811115610914576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061095a60208301846108dc565b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461098557600080fd5b919050565b60008060006060848603121561099f57600080fd5b6109a884610961565b95602085013595506040909401359392505050565b6000602082840312156109cf57600080fd5b61095a82610961565b600082821015610a11577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50039056fea164736f6c634300080f000a"; + hex"608060405234801561001057600080fd5b50600436106100d45760003560e01c80638da5cb5b11610081578063f2fde38b1161005b578063f2fde38b146101b8578063f7d12760146101cb578063ffa1ad74146101d357600080fd5b80638da5cb5b14610180578063d798b1ac146101a8578063dc8452cd146101b057600080fd5b80635fd579af116100b25780635fd579af14610152578063715018a6146101655780637a1ac61e1461016d57600080fd5b80630457d6f2146100d9578063206a8300146100ee57806354fd4d5014610109575b600080fd5b6100ec6100e73660046108c3565b6101db565b005b6100f66101ef565b6040519081526020015b60405180910390f35b6101456040518060400160405280600c81526020017f312e302e312d626574612e31000000000000000000000000000000000000000081525081565b6040516101009190610947565b6100ec6101603660046108c3565b61021d565b6100ec61022e565b6100ec61017b36600461098a565b610242565b60335460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610100565b6100f66103f7565b6100f6610430565b6100ec6101c63660046109bd565b610460565b6100f6610514565b6100f6600081565b6101e361055f565b6101ec816105e0565b50565b61021a60017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16109d8565b81565b61022561055f565b6101ec81610698565b61023661055f565b6102406000610712565b565b600054610100900460ff16158080156102625750600054600160ff909116105b8061027c5750303b15801561027c575060005460ff166001145b61030d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561036b57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610373610789565b61037c84610460565b610385836105e0565b61038e82610698565b80156103f157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b600061042b61042760017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6109d8565b5490565b905090565b600061042b61042760017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16109d8565b61046861055f565b73ffffffffffffffffffffffffffffffffffffffff811661050b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610304565b6101ec81610712565b61021a60017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6109d8565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b9055565b60335473ffffffffffffffffffffffffffffffffffffffff163314610240576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610304565b61061361060e60017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16109d8565b829055565b60008160405160200161062891815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060005b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be8360405161068c9190610947565b60405180910390a35050565b6106c661060e60017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6109d8565b6000816040516020016106db91815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529050600161065b565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16610820576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610304565b610240600054610100900460ff166108ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610304565b61024033610712565b6000602082840312156108d557600080fd5b5035919050565b6000815180845260005b81811015610902576020818501810151868301820152016108e6565b81811115610914576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061095a60208301846108dc565b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461098557600080fd5b919050565b60008060006060848603121561099f57600080fd5b6109a884610961565b95602085013595506040909401359392505050565b6000602082840312156109cf57600080fd5b61095a82610961565b600082821015610a11577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50039056fea164736f6c634300080f000a"; bytes internal constant optimismPortalProxyCode = hex"60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a"; bytes internal constant systemConfigProxyCode = @@ -45,33 +45,33 @@ contract DeploymentSummaryFaultProofsCode { bytes internal constant anchorStateRegistryProxyCode = hex"60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a"; bytes internal constant l1CrossDomainMessengerCode = - hex"60806040526004361061018b5760003560e01c80636425666b116100d6578063b1b1b2091161007f578063d764ad0b11610059578063d764ad0b1461049b578063db505d80146104ae578063ecc70428146104db57600080fd5b8063b1b1b2091461042b578063b28ade251461045b578063c0c53b8b1461047b57600080fd5b80638cbeeef2116100b05780638cbeeef2146102d05780639fce812c146103d0578063a4e7f8bd146103fb57600080fd5b80636425666b146103775780636e296e45146103a457806383a74074146103b957600080fd5b80633dbb202b1161013857806354fd4d501161011257806354fd4d50146102e65780635644cfdf1461033c5780635c975abb1461035257600080fd5b80633dbb202b146102935780633f827a5a146102a85780634c1d6a69146102d057600080fd5b80632828d7e8116101695780632828d7e81461022457806333d7e2bd1461023957806335e80ab31461026657600080fd5b8063028f85f7146101905780630c568498146101c35780630ff754ea146101d8575b600080fd5b34801561019c57600080fd5b506101a5601081565b60405167ffffffffffffffff90911681526020015b60405180910390f35b3480156101cf57600080fd5b506101a5603f81565b3480156101e457600080fd5b5060fc5473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101ba565b34801561023057600080fd5b506101a5604081565b34801561024557600080fd5b5060fd546101ff9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561027257600080fd5b5060fb546101ff9073ffffffffffffffffffffffffffffffffffffffff1681565b6102a66102a1366004611bdd565b610540565b005b3480156102b457600080fd5b506102bd600181565b60405161ffff90911681526020016101ba565b3480156102dc57600080fd5b506101a5619c4081565b3480156102f257600080fd5b5061032f6040518060400160405280600581526020017f322e342e3000000000000000000000000000000000000000000000000000000081525081565b6040516101ba9190611caf565b34801561034857600080fd5b506101a561138881565b34801561035e57600080fd5b5061036761083d565b60405190151581526020016101ba565b34801561038357600080fd5b5060fc546101ff9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156103b057600080fd5b506101ff6108d6565b3480156103c557600080fd5b506101a562030d4081565b3480156103dc57600080fd5b5060cf5473ffffffffffffffffffffffffffffffffffffffff166101ff565b34801561040757600080fd5b50610367610416366004611cc9565b60ce6020526000908152604090205460ff1681565b34801561043757600080fd5b50610367610446366004611cc9565b60cb6020526000908152604090205460ff1681565b34801561046757600080fd5b506101a5610476366004611ce2565b6109bd565b34801561048757600080fd5b506102a6610496366004611d36565b610a2b565b6102a66104a9366004611d81565b610ca2565b3480156104ba57600080fd5b5060cf546101ff9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156104e757600080fd5b5061053260cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b6040519081526020016101ba565b6105486115d3565b156105e05734156105e0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f43726f7373446f6d61696e4d657373656e6765723a2063616e6e6f742073656e60448201527f642076616c7565207769746820637573746f6d2067617320746f6b656e00000060648201526084015b60405180910390fd5b60cf546107129073ffffffffffffffffffffffffffffffffffffffff166106088585856109bd565b347fd764ad0b0000000000000000000000000000000000000000000000000000000061067460cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b338a34898c8c6040516024016106909796959493929190611e50565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611612565b8373ffffffffffffffffffffffffffffffffffffffff167fcb0f7ffd78f9aee47a248fae8db181db6eee833039123e026dcbff529522e52a33858561079760cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b866040516107a9959493929190611eaf565b60405180910390a260405134815233907f8ebb2ec2465bdb2a06a66fc37a0963af8a2a6a1479d81d56fdb8cbb98096d5469060200160405180910390a2505060cd80547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808216600101167fffff0000000000000000000000000000000000000000000000000000000000009091161790555050565b60fb54604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa1580156108ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108d19190611efd565b905090565b60cc5460009073ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2153016109a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f43726f7373446f6d61696e4d657373656e6765723a2078446f6d61696e4d657360448201527f7361676553656e646572206973206e6f7420736574000000000000000000000060648201526084016105d7565b5060cc5473ffffffffffffffffffffffffffffffffffffffff1690565b6000611388619c4080603f6109d9604063ffffffff8816611f4e565b6109e39190611f7e565b6109ee601088611f4e565b6109fb9062030d40611fcc565b610a059190611fcc565b610a0f9190611fcc565b610a199190611fcc565b610a239190611fcc565b949350505050565b6000547501000000000000000000000000000000000000000000900460ff1615808015610a76575060005460017401000000000000000000000000000000000000000090910460ff16105b80610aa85750303b158015610aa8575060005474010000000000000000000000000000000000000000900460ff166001145b610b34576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016105d7565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790558015610bba57600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000001790555b60fb805473ffffffffffffffffffffffffffffffffffffffff8087167fffffffffffffffffffffffff00000000000000000000000000000000000000009283161790925560fc805486841690831617905560fd805492851692909116919091179055610c397342000000000000000000000000000000000000076116ab565b8015610c9c57600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b610caa61083d565b15610d11576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f43726f7373446f6d61696e4d657373656e6765723a207061757365640000000060448201526064016105d7565b60f087901c60028110610dcc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f43726f7373446f6d61696e4d657373656e6765723a206f6e6c7920766572736960448201527f6f6e2030206f722031206d657373616765732061726520737570706f7274656460648201527f20617420746869732074696d6500000000000000000000000000000000000000608482015260a4016105d7565b8061ffff16600003610ec1576000610e1d878986868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508f92506117e7915050565b600081815260cb602052604090205490915060ff1615610ebf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f43726f7373446f6d61696e4d657373656e6765723a206c65676163792077697460448201527f6864726177616c20616c72656164792072656c6179656400000000000000000060648201526084016105d7565b505b6000610f07898989898989898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061180692505050565b9050610f11611829565b15610f4957853414610f2557610f25611ff8565b600081815260ce602052604090205460ff1615610f4457610f44611ff8565b61109b565b3415610ffd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605060248201527f43726f7373446f6d61696e4d657373656e6765723a2076616c7565206d75737460448201527f206265207a65726f20756e6c657373206d6573736167652069732066726f6d2060648201527f612073797374656d206164647265737300000000000000000000000000000000608482015260a4016105d7565b600081815260ce602052604090205460ff1661109b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520636160448201527f6e6e6f74206265207265706c617965640000000000000000000000000000000060648201526084016105d7565b6110a487611905565b15611157576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f43726f7373446f6d61696e4d657373656e6765723a2063616e6e6f742073656e60448201527f64206d65737361676520746f20626c6f636b65642073797374656d206164647260648201527f6573730000000000000000000000000000000000000000000000000000000000608482015260a4016105d7565b600081815260cb602052604090205460ff16156111f6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520686160448201527f7320616c7265616479206265656e2072656c617965640000000000000000000060648201526084016105d7565b61121785611208611388619c40611fcc565b67ffffffffffffffff1661194b565b158061123d575060cc5473ffffffffffffffffffffffffffffffffffffffff1661dead14155b1561135657600081815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555182917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff320161134f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d6573736167650000000000000000000000000000000000000060648201526084016105d7565b50506115ae565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8a1617905560006113e788619c405a6113aa9190612027565b8988888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061196992505050565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790559050801561149d57600082815260cb602052604090205460ff161561143a5761143a611ff8565b600082815260cb602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f4641df4a962071e12719d8c8c8e5ac7fc4d97b927346a3d7a335b1f7517e133c91a26115aa565b600082815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff32016115aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d6573736167650000000000000000000000000000000000000060648201526084016105d7565b5050505b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6000806115de611981565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b60fc546040517fe9e05c4200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063e9e05c4290849061167390889083908990600090899060040161203e565b6000604051808303818588803b15801561168c57600080fd5b505af11580156116a0573d6000803e3d6000fd5b505050505050505050565b6000547501000000000000000000000000000000000000000000900460ff16611756576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016105d7565b60cc5473ffffffffffffffffffffffffffffffffffffffff166117a05760cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790555b60cf80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60006117f585858585611a1e565b805190602001209050949350505050565b6000611816878787878787611ab7565b8051906020012090509695505050505050565b60fc5460009073ffffffffffffffffffffffffffffffffffffffff16331480156108d1575060cf5460fc54604080517f9bf62d82000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9384169390921691639bf62d82916004808201926020929091908290030181865afa1580156118c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118e99190612096565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b600073ffffffffffffffffffffffffffffffffffffffff8216301480611945575060fc5473ffffffffffffffffffffffffffffffffffffffff8381169116145b92915050565b600080603f83619c4001026040850201603f5a021015949350505050565b6000806000835160208501868989f195945050505050565b60fd54604080517f4397dfef0000000000000000000000000000000000000000000000000000000081528151600093849373ffffffffffffffffffffffffffffffffffffffff90911692634397dfef92600480830193928290030181865afa1580156119f1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a1591906120b3565b90939092509050565b606084848484604051602401611a3794939291906120f3565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fcbd4ece9000000000000000000000000000000000000000000000000000000001790529050949350505050565b6060868686868686604051602401611ad49695949392919061213d565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd764ad0b0000000000000000000000000000000000000000000000000000000017905290509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff81168114611b7857600080fd5b50565b60008083601f840112611b8d57600080fd5b50813567ffffffffffffffff811115611ba557600080fd5b602083019150836020828501011115611bbd57600080fd5b9250929050565b803563ffffffff81168114611bd857600080fd5b919050565b60008060008060608587031215611bf357600080fd5b8435611bfe81611b56565b9350602085013567ffffffffffffffff811115611c1a57600080fd5b611c2687828801611b7b565b9094509250611c39905060408601611bc4565b905092959194509250565b6000815180845260005b81811015611c6a57602081850181015186830182015201611c4e565b81811115611c7c576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611cc26020830184611c44565b9392505050565b600060208284031215611cdb57600080fd5b5035919050565b600080600060408486031215611cf757600080fd5b833567ffffffffffffffff811115611d0e57600080fd5b611d1a86828701611b7b565b9094509250611d2d905060208501611bc4565b90509250925092565b600080600060608486031215611d4b57600080fd5b8335611d5681611b56565b92506020840135611d6681611b56565b91506040840135611d7681611b56565b809150509250925092565b600080600080600080600060c0888a031215611d9c57600080fd5b873596506020880135611dae81611b56565b95506040880135611dbe81611b56565b9450606088013593506080880135925060a088013567ffffffffffffffff811115611de857600080fd5b611df48a828b01611b7b565b989b979a50959850939692959293505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b878152600073ffffffffffffffffffffffffffffffffffffffff808916602084015280881660408401525085606083015263ffffffff8516608083015260c060a0830152611ea260c083018486611e07565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff86168152608060208201526000611edf608083018688611e07565b905083604083015263ffffffff831660608301529695505050505050565b600060208284031215611f0f57600080fd5b81518015158114611cc257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff80831681851681830481118215151615611f7557611f75611f1f565b02949350505050565b600067ffffffffffffffff80841680611fc0577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b92169190910492915050565b600067ffffffffffffffff808316818516808303821115611fef57611fef611f1f565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b60008282101561203957612039611f1f565b500390565b73ffffffffffffffffffffffffffffffffffffffff8616815284602082015267ffffffffffffffff84166040820152821515606082015260a06080820152600061208b60a0830184611c44565b979650505050505050565b6000602082840312156120a857600080fd5b8151611cc281611b56565b600080604083850312156120c657600080fd5b82516120d181611b56565b602084015190925060ff811681146120e857600080fd5b809150509250929050565b600073ffffffffffffffffffffffffffffffffffffffff80871683528086166020840152506080604083015261212c6080830185611c44565b905082606083015295945050505050565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a083015261218860c0830184611c44565b9897505050505050505056fea164736f6c634300080f000a"; + hex"60806040526004361061018b5760003560e01c80636425666b116100d6578063b1b1b2091161007f578063d764ad0b11610059578063d764ad0b1461049b578063db505d80146104ae578063ecc70428146104db57600080fd5b8063b1b1b2091461042b578063b28ade251461045b578063c0c53b8b1461047b57600080fd5b80638cbeeef2116100b05780638cbeeef2146102d05780639fce812c146103d0578063a4e7f8bd146103fb57600080fd5b80636425666b146103775780636e296e45146103a457806383a74074146103b957600080fd5b80633dbb202b1161013857806354fd4d501161011257806354fd4d50146102e65780635644cfdf1461033c5780635c975abb1461035257600080fd5b80633dbb202b146102935780633f827a5a146102a85780634c1d6a69146102d057600080fd5b80632828d7e8116101695780632828d7e81461022457806333d7e2bd1461023957806335e80ab31461026657600080fd5b8063028f85f7146101905780630c568498146101c35780630ff754ea146101d8575b600080fd5b34801561019c57600080fd5b506101a5601081565b60405167ffffffffffffffff90911681526020015b60405180910390f35b3480156101cf57600080fd5b506101a5603f81565b3480156101e457600080fd5b5060fc5473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101ba565b34801561023057600080fd5b506101a5604081565b34801561024557600080fd5b5060fd546101ff9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561027257600080fd5b5060fb546101ff9073ffffffffffffffffffffffffffffffffffffffff1681565b6102a66102a1366004611bdd565b610540565b005b3480156102b457600080fd5b506102bd600181565b60405161ffff90911681526020016101ba565b3480156102dc57600080fd5b506101a5619c4081565b3480156102f257600080fd5b5061032f6040518060400160405280600c81526020017f322e342e312d626574612e31000000000000000000000000000000000000000081525081565b6040516101ba9190611caf565b34801561034857600080fd5b506101a561138881565b34801561035e57600080fd5b5061036761083d565b60405190151581526020016101ba565b34801561038357600080fd5b5060fc546101ff9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156103b057600080fd5b506101ff6108d6565b3480156103c557600080fd5b506101a562030d4081565b3480156103dc57600080fd5b5060cf5473ffffffffffffffffffffffffffffffffffffffff166101ff565b34801561040757600080fd5b50610367610416366004611cc9565b60ce6020526000908152604090205460ff1681565b34801561043757600080fd5b50610367610446366004611cc9565b60cb6020526000908152604090205460ff1681565b34801561046757600080fd5b506101a5610476366004611ce2565b6109bd565b34801561048757600080fd5b506102a6610496366004611d36565b610a2b565b6102a66104a9366004611d81565b610ca2565b3480156104ba57600080fd5b5060cf546101ff9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156104e757600080fd5b5061053260cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b6040519081526020016101ba565b6105486115d3565b156105e05734156105e0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f43726f7373446f6d61696e4d657373656e6765723a2063616e6e6f742073656e60448201527f642076616c7565207769746820637573746f6d2067617320746f6b656e00000060648201526084015b60405180910390fd5b60cf546107129073ffffffffffffffffffffffffffffffffffffffff166106088585856109bd565b347fd764ad0b0000000000000000000000000000000000000000000000000000000061067460cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b338a34898c8c6040516024016106909796959493929190611e50565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611612565b8373ffffffffffffffffffffffffffffffffffffffff167fcb0f7ffd78f9aee47a248fae8db181db6eee833039123e026dcbff529522e52a33858561079760cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b866040516107a9959493929190611eaf565b60405180910390a260405134815233907f8ebb2ec2465bdb2a06a66fc37a0963af8a2a6a1479d81d56fdb8cbb98096d5469060200160405180910390a2505060cd80547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808216600101167fffff0000000000000000000000000000000000000000000000000000000000009091161790555050565b60fb54604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa1580156108ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108d19190611efd565b905090565b60cc5460009073ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2153016109a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f43726f7373446f6d61696e4d657373656e6765723a2078446f6d61696e4d657360448201527f7361676553656e646572206973206e6f7420736574000000000000000000000060648201526084016105d7565b5060cc5473ffffffffffffffffffffffffffffffffffffffff1690565b6000611388619c4080603f6109d9604063ffffffff8816611f4e565b6109e39190611f7e565b6109ee601088611f4e565b6109fb9062030d40611fcc565b610a059190611fcc565b610a0f9190611fcc565b610a199190611fcc565b610a239190611fcc565b949350505050565b6000547501000000000000000000000000000000000000000000900460ff1615808015610a76575060005460017401000000000000000000000000000000000000000090910460ff16105b80610aa85750303b158015610aa8575060005474010000000000000000000000000000000000000000900460ff166001145b610b34576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016105d7565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790558015610bba57600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000001790555b60fb805473ffffffffffffffffffffffffffffffffffffffff8087167fffffffffffffffffffffffff00000000000000000000000000000000000000009283161790925560fc805486841690831617905560fd805492851692909116919091179055610c397342000000000000000000000000000000000000076116ab565b8015610c9c57600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b610caa61083d565b15610d11576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f43726f7373446f6d61696e4d657373656e6765723a207061757365640000000060448201526064016105d7565b60f087901c60028110610dcc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f43726f7373446f6d61696e4d657373656e6765723a206f6e6c7920766572736960448201527f6f6e2030206f722031206d657373616765732061726520737570706f7274656460648201527f20617420746869732074696d6500000000000000000000000000000000000000608482015260a4016105d7565b8061ffff16600003610ec1576000610e1d878986868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508f92506117e7915050565b600081815260cb602052604090205490915060ff1615610ebf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f43726f7373446f6d61696e4d657373656e6765723a206c65676163792077697460448201527f6864726177616c20616c72656164792072656c6179656400000000000000000060648201526084016105d7565b505b6000610f07898989898989898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061180692505050565b9050610f11611829565b15610f4957853414610f2557610f25611ff8565b600081815260ce602052604090205460ff1615610f4457610f44611ff8565b61109b565b3415610ffd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605060248201527f43726f7373446f6d61696e4d657373656e6765723a2076616c7565206d75737460448201527f206265207a65726f20756e6c657373206d6573736167652069732066726f6d2060648201527f612073797374656d206164647265737300000000000000000000000000000000608482015260a4016105d7565b600081815260ce602052604090205460ff1661109b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520636160448201527f6e6e6f74206265207265706c617965640000000000000000000000000000000060648201526084016105d7565b6110a487611905565b15611157576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f43726f7373446f6d61696e4d657373656e6765723a2063616e6e6f742073656e60448201527f64206d65737361676520746f20626c6f636b65642073797374656d206164647260648201527f6573730000000000000000000000000000000000000000000000000000000000608482015260a4016105d7565b600081815260cb602052604090205460ff16156111f6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520686160448201527f7320616c7265616479206265656e2072656c617965640000000000000000000060648201526084016105d7565b61121785611208611388619c40611fcc565b67ffffffffffffffff1661194b565b158061123d575060cc5473ffffffffffffffffffffffffffffffffffffffff1661dead14155b1561135657600081815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555182917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff320161134f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d6573736167650000000000000000000000000000000000000060648201526084016105d7565b50506115ae565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8a1617905560006113e788619c405a6113aa9190612027565b8988888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061196992505050565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790559050801561149d57600082815260cb602052604090205460ff161561143a5761143a611ff8565b600082815260cb602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f4641df4a962071e12719d8c8c8e5ac7fc4d97b927346a3d7a335b1f7517e133c91a26115aa565b600082815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff32016115aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d6573736167650000000000000000000000000000000000000060648201526084016105d7565b5050505b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6000806115de611981565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b60fc546040517fe9e05c4200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063e9e05c4290849061167390889083908990600090899060040161203e565b6000604051808303818588803b15801561168c57600080fd5b505af11580156116a0573d6000803e3d6000fd5b505050505050505050565b6000547501000000000000000000000000000000000000000000900460ff16611756576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016105d7565b60cc5473ffffffffffffffffffffffffffffffffffffffff166117a05760cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790555b60cf80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60006117f585858585611a1e565b805190602001209050949350505050565b6000611816878787878787611ab7565b8051906020012090509695505050505050565b60fc5460009073ffffffffffffffffffffffffffffffffffffffff16331480156108d1575060cf5460fc54604080517f9bf62d82000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9384169390921691639bf62d82916004808201926020929091908290030181865afa1580156118c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118e99190612096565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b600073ffffffffffffffffffffffffffffffffffffffff8216301480611945575060fc5473ffffffffffffffffffffffffffffffffffffffff8381169116145b92915050565b600080603f83619c4001026040850201603f5a021015949350505050565b6000806000835160208501868989f195945050505050565b60fd54604080517f4397dfef0000000000000000000000000000000000000000000000000000000081528151600093849373ffffffffffffffffffffffffffffffffffffffff90911692634397dfef92600480830193928290030181865afa1580156119f1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a1591906120b3565b90939092509050565b606084848484604051602401611a3794939291906120f3565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fcbd4ece9000000000000000000000000000000000000000000000000000000001790529050949350505050565b6060868686868686604051602401611ad49695949392919061213d565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd764ad0b0000000000000000000000000000000000000000000000000000000017905290509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff81168114611b7857600080fd5b50565b60008083601f840112611b8d57600080fd5b50813567ffffffffffffffff811115611ba557600080fd5b602083019150836020828501011115611bbd57600080fd5b9250929050565b803563ffffffff81168114611bd857600080fd5b919050565b60008060008060608587031215611bf357600080fd5b8435611bfe81611b56565b9350602085013567ffffffffffffffff811115611c1a57600080fd5b611c2687828801611b7b565b9094509250611c39905060408601611bc4565b905092959194509250565b6000815180845260005b81811015611c6a57602081850181015186830182015201611c4e565b81811115611c7c576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611cc26020830184611c44565b9392505050565b600060208284031215611cdb57600080fd5b5035919050565b600080600060408486031215611cf757600080fd5b833567ffffffffffffffff811115611d0e57600080fd5b611d1a86828701611b7b565b9094509250611d2d905060208501611bc4565b90509250925092565b600080600060608486031215611d4b57600080fd5b8335611d5681611b56565b92506020840135611d6681611b56565b91506040840135611d7681611b56565b809150509250925092565b600080600080600080600060c0888a031215611d9c57600080fd5b873596506020880135611dae81611b56565b95506040880135611dbe81611b56565b9450606088013593506080880135925060a088013567ffffffffffffffff811115611de857600080fd5b611df48a828b01611b7b565b989b979a50959850939692959293505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b878152600073ffffffffffffffffffffffffffffffffffffffff808916602084015280881660408401525085606083015263ffffffff8516608083015260c060a0830152611ea260c083018486611e07565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff86168152608060208201526000611edf608083018688611e07565b905083604083015263ffffffff831660608301529695505050505050565b600060208284031215611f0f57600080fd5b81518015158114611cc257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff80831681851681830481118215151615611f7557611f75611f1f565b02949350505050565b600067ffffffffffffffff80841680611fc0577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b92169190910492915050565b600067ffffffffffffffff808316818516808303821115611fef57611fef611f1f565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b60008282101561203957612039611f1f565b500390565b73ffffffffffffffffffffffffffffffffffffffff8616815284602082015267ffffffffffffffff84166040820152821515606082015260a06080820152600061208b60a0830184611c44565b979650505050505050565b6000602082840312156120a857600080fd5b8151611cc281611b56565b600080604083850312156120c657600080fd5b82516120d181611b56565b602084015190925060ff811681146120e857600080fd5b809150509250929050565b600073ffffffffffffffffffffffffffffffffffffffff80871683528086166020840152506080604083015261212c6080830185611c44565b905082606083015295945050505050565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a083015261218860c0830184611c44565b9897505050505050505056fea164736f6c634300080f000a"; bytes internal constant optimismMintableERC20FactoryCode = - hex"60806040523480156200001157600080fd5b5060043610620000935760003560e01c8063c4d66de81162000062578063c4d66de81462000175578063ce5ac90f146200018e578063e78cea9214620001a5578063ee9a31a214620001c657600080fd5b8063316b3739146200009857806354fd4d5014620000fb578063896f93d114620001475780638cf0629c146200015e575b600080fd5b620000d1620000a936600462000652565b60026020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b620001386040518060400160405280600681526020017f312e31302e30000000000000000000000000000000000000000000000000000081525081565b604051620000f29190620006e5565b620000d162000158366004620007dc565b620001e5565b620000d16200016f36600462000859565b620001fc565b6200018c6200018636600462000652565b6200041b565b005b620000d16200019f366004620007dc565b620005ed565b600154620000d19073ffffffffffffffffffffffffffffffffffffffff1681565b60015473ffffffffffffffffffffffffffffffffffffffff16620000d1565b6000620001f4848484620005ed565b949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8516620002a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d4d696e7461626c654552433230466163746f72793a206d7560448201527f73742070726f766964652072656d6f746520746f6b656e20616464726573730060648201526084015b60405180910390fd5b600085858585604051602001620002c29493929190620008f0565b604051602081830303815290604052805190602001209050600081600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168888888860405162000312906200061a565b620003229594939291906200094a565b8190604051809103906000f590508015801562000343573d6000803e3d6000fd5b5073ffffffffffffffffffffffffffffffffffffffff81811660008181526002602052604080822080547fffffffffffffffffffffffff000000000000000000000000000000000000000016948d1694851790555193945090927fceeb8e7d520d7f3b65fc11a262b91066940193b05d4f93df07cfdced0eb551cf9190a360405133815273ffffffffffffffffffffffffffffffffffffffff80891691908316907f52fe89dd5930f343d25650b62fd367bae47088bcddffd2a88350a6ecdd620cdb9060200160405180910390a39695505050505050565b600054610100900460ff16158080156200043c5750600054600160ff909116105b80620004585750303b15801562000458575060005460ff166001145b620004e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016200029e565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156200054557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84161790558015620005e957600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6000620001f48484846012620001fc565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b61178a80620009b083390190565b803573ffffffffffffffffffffffffffffffffffffffff811681146200064d57600080fd5b919050565b6000602082840312156200066557600080fd5b620006708262000628565b9392505050565b6000815180845260005b818110156200069f5760208185018101518683018201520162000681565b81811115620006b2576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600062000670602083018462000677565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126200073b57600080fd5b813567ffffffffffffffff80821115620007595762000759620006fa565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715620007a257620007a2620006fa565b81604052838152866020858801011115620007bc57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600060608486031215620007f257600080fd5b620007fd8462000628565b9250602084013567ffffffffffffffff808211156200081b57600080fd5b620008298783880162000729565b935060408601359150808211156200084057600080fd5b506200084f8682870162000729565b9150509250925092565b600080600080608085870312156200087057600080fd5b6200087b8562000628565b9350602085013567ffffffffffffffff808211156200089957600080fd5b620008a78883890162000729565b94506040870135915080821115620008be57600080fd5b50620008cd8782880162000729565b925050606085013560ff81168114620008e557600080fd5b939692955090935050565b73ffffffffffffffffffffffffffffffffffffffff8516815260806020820152600062000921608083018662000677565b828103604084015262000935818662000677565b91505060ff8316606083015295945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808816835280871660208401525060a060408301526200098560a083018662000677565b828103606084015262000999818662000677565b91505060ff83166080830152969550505050505056fe60e06040523480156200001157600080fd5b506040516200178a3803806200178a833981016040819052620000349162000163565b828260036200004483826200029e565b5060046200005382826200029e565b5050506001600160a01b039384166080529390921660a052505060ff1660c0526200036a565b80516001600160a01b03811681146200009157600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620000be57600080fd5b81516001600160401b0380821115620000db57620000db62000096565b604051601f8301601f19908116603f0116810190828211818310171562000106576200010662000096565b816040528381526020925086838588010111156200012357600080fd5b600091505b8382101562000147578582018301518183018401529082019062000128565b83821115620001595760008385830101525b9695505050505050565b600080600080600060a086880312156200017c57600080fd5b620001878662000079565b9450620001976020870162000079565b60408701519094506001600160401b0380821115620001b557600080fd5b620001c389838a01620000ac565b94506060880151915080821115620001da57600080fd5b50620001e988828901620000ac565b925050608086015160ff811681146200020157600080fd5b809150509295509295909350565b600181811c908216806200022457607f821691505b6020821081036200024557634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200029957600081815260208120601f850160051c81016020861015620002745750805b601f850160051c820191505b81811015620002955782815560010162000280565b5050505b505050565b81516001600160401b03811115620002ba57620002ba62000096565b620002d281620002cb84546200020f565b846200024b565b602080601f8311600181146200030a5760008415620002f15750858301515b600019600386901b1c1916600185901b17855562000295565b600085815260208120601f198616915b828110156200033b578886015182559484019460019091019084016200031a565b50858210156200035a5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c0516113d4620003b6600039600061024401526000818161034b015281816103e001528181610625015261075c0152600081816101a9015261037101526113d46000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063ae1f6aaf1161008c578063dd62ed3e11610066578063dd62ed3e14610395578063e78cea9214610349578063ee9a31a2146103db57600080fd5b8063ae1f6aaf14610349578063c01e1bd61461036f578063d6c0b2c41461036f57600080fd5b80639dc29fac116100bd5780639dc29fac14610310578063a457c2d714610323578063a9059cbb1461033657600080fd5b806370a08231146102d257806395d89b411461030857600080fd5b806323b872dd1161012f5780633950935111610114578063395093511461026e57806340c10f191461028157806354fd4d501461029657600080fd5b806323b872dd1461022a578063313ce5671461023d57600080fd5b806306fdde031161016057806306fdde03146101f0578063095ea7b31461020557806318160ddd1461021857600080fd5b806301ffc9a71461017c578063033964be146101a4575b600080fd5b61018f61018a36600461117d565b610402565b60405190151581526020015b60405180910390f35b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101f86104f3565b60405161019b91906111c6565b61018f610213366004611262565b610585565b6002545b60405190815260200161019b565b61018f61023836600461128c565b61059d565b60405160ff7f000000000000000000000000000000000000000000000000000000000000000016815260200161019b565b61018f61027c366004611262565b6105c1565b61029461028f366004611262565b61060d565b005b6101f86040518060400160405280600581526020017f312e332e3000000000000000000000000000000000000000000000000000000081525081565b61021c6102e03660046112c8565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101f8610735565b61029461031e366004611262565b610744565b61018f610331366004611262565b61085b565b61018f610344366004611262565b61092c565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b61021c6103a33660046112e3565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f1d1d8b63000000000000000000000000000000000000000000000000000000007fec4fc8e3000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000085168314806104bb57507fffffffff00000000000000000000000000000000000000000000000000000000858116908316145b806104ea57507fffffffff00000000000000000000000000000000000000000000000000000000858116908216145b95945050505050565b60606003805461050290611316565b80601f016020809104026020016040519081016040528092919081815260200182805461052e90611316565b801561057b5780601f106105505761010080835404028352916020019161057b565b820191906000526020600020905b81548152906001019060200180831161055e57829003601f168201915b5050505050905090565b60003361059381858561093a565b5060019392505050565b6000336105ab858285610aee565b6105b6858585610bc5565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906105939082908690610608908790611398565b61093a565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146106d7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084015b60405180910390fd5b6106e18282610e78565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d41213968858260405161072991815260200190565b60405180910390a25050565b60606004805461050290611316565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610809576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084016106ce565b6108138282610f98565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca58260405161072991815260200190565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091908381101561091f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084016106ce565b6105b6828686840361093a565b600033610593818585610bc5565b73ffffffffffffffffffffffffffffffffffffffff83166109dc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f726573730000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216610a7f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f737300000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610bbf5781811015610bb2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016106ce565b610bbf848484840361093a565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610c68576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216610d0b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f657373000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610dc1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e6365000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220858503905591851681529081208054849290610e05908490611398565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610e6b91815260200190565b60405180910390a3610bbf565b73ffffffffffffffffffffffffffffffffffffffff8216610ef5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016106ce565b8060026000828254610f079190611398565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604081208054839290610f41908490611398565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff821661103b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f730000000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260208190526040902054818110156110f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f636500000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260208190526040812083830390556002805484929061112d9084906113b0565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610ae1565b60006020828403121561118f57600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146111bf57600080fd5b9392505050565b600060208083528351808285015260005b818110156111f3578581018301518582016040015282016111d7565b81811115611205576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461125d57600080fd5b919050565b6000806040838503121561127557600080fd5b61127e83611239565b946020939093013593505050565b6000806000606084860312156112a157600080fd5b6112aa84611239565b92506112b860208501611239565b9150604084013590509250925092565b6000602082840312156112da57600080fd5b6111bf82611239565b600080604083850312156112f657600080fd5b6112ff83611239565b915061130d60208401611239565b90509250929050565b600181811c9082168061132a57607f821691505b602082108103611363577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156113ab576113ab611369565b500190565b6000828210156113c2576113c2611369565b50039056fea164736f6c634300080f000aa164736f6c634300080f000a"; + hex"60806040523480156200001157600080fd5b5060043610620000935760003560e01c8063c4d66de81162000062578063c4d66de81462000175578063ce5ac90f146200018e578063e78cea9214620001a5578063ee9a31a214620001c657600080fd5b8063316b3739146200009857806354fd4d5014620000fb578063896f93d114620001475780638cf0629c146200015e575b600080fd5b620000d1620000a936600462000652565b60026020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b620001386040518060400160405280600d81526020017f312e31302e312d626574612e310000000000000000000000000000000000000081525081565b604051620000f29190620006e5565b620000d162000158366004620007dc565b620001e5565b620000d16200016f36600462000859565b620001fc565b6200018c6200018636600462000652565b6200041b565b005b620000d16200019f366004620007dc565b620005ed565b600154620000d19073ffffffffffffffffffffffffffffffffffffffff1681565b60015473ffffffffffffffffffffffffffffffffffffffff16620000d1565b6000620001f4848484620005ed565b949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8516620002a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d4d696e7461626c654552433230466163746f72793a206d7560448201527f73742070726f766964652072656d6f746520746f6b656e20616464726573730060648201526084015b60405180910390fd5b600085858585604051602001620002c29493929190620008f0565b604051602081830303815290604052805190602001209050600081600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168888888860405162000312906200061a565b620003229594939291906200094a565b8190604051809103906000f590508015801562000343573d6000803e3d6000fd5b5073ffffffffffffffffffffffffffffffffffffffff81811660008181526002602052604080822080547fffffffffffffffffffffffff000000000000000000000000000000000000000016948d1694851790555193945090927fceeb8e7d520d7f3b65fc11a262b91066940193b05d4f93df07cfdced0eb551cf9190a360405133815273ffffffffffffffffffffffffffffffffffffffff80891691908316907f52fe89dd5930f343d25650b62fd367bae47088bcddffd2a88350a6ecdd620cdb9060200160405180910390a39695505050505050565b600054610100900460ff16158080156200043c5750600054600160ff909116105b80620004585750303b15801562000458575060005460ff166001145b620004e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016200029e565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156200054557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84161790558015620005e957600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6000620001f48484846012620001fc565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b61178a80620009b083390190565b803573ffffffffffffffffffffffffffffffffffffffff811681146200064d57600080fd5b919050565b6000602082840312156200066557600080fd5b620006708262000628565b9392505050565b6000815180845260005b818110156200069f5760208185018101518683018201520162000681565b81811115620006b2576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600062000670602083018462000677565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126200073b57600080fd5b813567ffffffffffffffff80821115620007595762000759620006fa565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715620007a257620007a2620006fa565b81604052838152866020858801011115620007bc57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600060608486031215620007f257600080fd5b620007fd8462000628565b9250602084013567ffffffffffffffff808211156200081b57600080fd5b620008298783880162000729565b935060408601359150808211156200084057600080fd5b506200084f8682870162000729565b9150509250925092565b600080600080608085870312156200087057600080fd5b6200087b8562000628565b9350602085013567ffffffffffffffff808211156200089957600080fd5b620008a78883890162000729565b94506040870135915080821115620008be57600080fd5b50620008cd8782880162000729565b925050606085013560ff81168114620008e557600080fd5b939692955090935050565b73ffffffffffffffffffffffffffffffffffffffff8516815260806020820152600062000921608083018662000677565b828103604084015262000935818662000677565b91505060ff8316606083015295945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808816835280871660208401525060a060408301526200098560a083018662000677565b828103606084015262000999818662000677565b91505060ff83166080830152969550505050505056fe60e06040523480156200001157600080fd5b506040516200178a3803806200178a833981016040819052620000349162000163565b828260036200004483826200029e565b5060046200005382826200029e565b5050506001600160a01b039384166080529390921660a052505060ff1660c0526200036a565b80516001600160a01b03811681146200009157600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620000be57600080fd5b81516001600160401b0380821115620000db57620000db62000096565b604051601f8301601f19908116603f0116810190828211818310171562000106576200010662000096565b816040528381526020925086838588010111156200012357600080fd5b600091505b8382101562000147578582018301518183018401529082019062000128565b83821115620001595760008385830101525b9695505050505050565b600080600080600060a086880312156200017c57600080fd5b620001878662000079565b9450620001976020870162000079565b60408701519094506001600160401b0380821115620001b557600080fd5b620001c389838a01620000ac565b94506060880151915080821115620001da57600080fd5b50620001e988828901620000ac565b925050608086015160ff811681146200020157600080fd5b809150509295509295909350565b600181811c908216806200022457607f821691505b6020821081036200024557634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200029957600081815260208120601f850160051c81016020861015620002745750805b601f850160051c820191505b81811015620002955782815560010162000280565b5050505b505050565b81516001600160401b03811115620002ba57620002ba62000096565b620002d281620002cb84546200020f565b846200024b565b602080601f8311600181146200030a5760008415620002f15750858301515b600019600386901b1c1916600185901b17855562000295565b600085815260208120601f198616915b828110156200033b578886015182559484019460019091019084016200031a565b50858210156200035a5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c0516113d4620003b6600039600061024401526000818161034b015281816103e001528181610625015261075c0152600081816101a9015261037101526113d46000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063ae1f6aaf1161008c578063dd62ed3e11610066578063dd62ed3e14610395578063e78cea9214610349578063ee9a31a2146103db57600080fd5b8063ae1f6aaf14610349578063c01e1bd61461036f578063d6c0b2c41461036f57600080fd5b80639dc29fac116100bd5780639dc29fac14610310578063a457c2d714610323578063a9059cbb1461033657600080fd5b806370a08231146102d257806395d89b411461030857600080fd5b806323b872dd1161012f5780633950935111610114578063395093511461026e57806340c10f191461028157806354fd4d501461029657600080fd5b806323b872dd1461022a578063313ce5671461023d57600080fd5b806306fdde031161016057806306fdde03146101f0578063095ea7b31461020557806318160ddd1461021857600080fd5b806301ffc9a71461017c578063033964be146101a4575b600080fd5b61018f61018a36600461117d565b610402565b60405190151581526020015b60405180910390f35b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101f86104f3565b60405161019b91906111c6565b61018f610213366004611262565b610585565b6002545b60405190815260200161019b565b61018f61023836600461128c565b61059d565b60405160ff7f000000000000000000000000000000000000000000000000000000000000000016815260200161019b565b61018f61027c366004611262565b6105c1565b61029461028f366004611262565b61060d565b005b6101f86040518060400160405280600c81526020017f312e332e312d626574612e31000000000000000000000000000000000000000081525081565b61021c6102e03660046112c8565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101f8610735565b61029461031e366004611262565b610744565b61018f610331366004611262565b61085b565b61018f610344366004611262565b61092c565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b61021c6103a33660046112e3565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f1d1d8b63000000000000000000000000000000000000000000000000000000007fec4fc8e3000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000085168314806104bb57507fffffffff00000000000000000000000000000000000000000000000000000000858116908316145b806104ea57507fffffffff00000000000000000000000000000000000000000000000000000000858116908216145b95945050505050565b60606003805461050290611316565b80601f016020809104026020016040519081016040528092919081815260200182805461052e90611316565b801561057b5780601f106105505761010080835404028352916020019161057b565b820191906000526020600020905b81548152906001019060200180831161055e57829003601f168201915b5050505050905090565b60003361059381858561093a565b5060019392505050565b6000336105ab858285610aee565b6105b6858585610bc5565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906105939082908690610608908790611398565b61093a565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146106d7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084015b60405180910390fd5b6106e18282610e78565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d41213968858260405161072991815260200190565b60405180910390a25050565b60606004805461050290611316565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610809576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084016106ce565b6108138282610f98565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca58260405161072991815260200190565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091908381101561091f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084016106ce565b6105b6828686840361093a565b600033610593818585610bc5565b73ffffffffffffffffffffffffffffffffffffffff83166109dc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f726573730000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216610a7f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f737300000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610bbf5781811015610bb2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016106ce565b610bbf848484840361093a565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610c68576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216610d0b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f657373000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610dc1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e6365000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220858503905591851681529081208054849290610e05908490611398565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610e6b91815260200190565b60405180910390a3610bbf565b73ffffffffffffffffffffffffffffffffffffffff8216610ef5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016106ce565b8060026000828254610f079190611398565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604081208054839290610f41908490611398565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff821661103b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f730000000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260208190526040902054818110156110f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f636500000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260208190526040812083830390556002805484929061112d9084906113b0565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610ae1565b60006020828403121561118f57600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146111bf57600080fd5b9392505050565b600060208083528351808285015260005b818110156111f3578581018301518582016040015282016111d7565b81811115611205576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461125d57600080fd5b919050565b6000806040838503121561127557600080fd5b61127e83611239565b946020939093013593505050565b6000806000606084860312156112a157600080fd5b6112aa84611239565b92506112b860208501611239565b9150604084013590509250925092565b6000602082840312156112da57600080fd5b6111bf82611239565b600080604083850312156112f657600080fd5b6112ff83611239565b915061130d60208401611239565b90509250929050565b600181811c9082168061132a57607f821691505b602082108103611363577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156113ab576113ab611369565b500190565b6000828210156113c2576113c2611369565b50039056fea164736f6c634300080f000aa164736f6c634300080f000a"; bytes internal constant systemConfigCode = - hex"608060405234801561001057600080fd5b50600436106102de5760003560e01c8063a711986911610186578063e0e2016d116100e3578063f2fde38b11610097578063f8c68de011610071578063f8c68de0146106e2578063fd32aa0f146106ea578063ffa1ad74146106f257600080fd5b8063f2fde38b146106b2578063f45e65d8146106c5578063f68016b7146106ce57600080fd5b8063e81b2c6d116100c8578063e81b2c6d14610681578063ec7075171461068a578063f2b4e617146106aa57600080fd5b8063e0e2016d14610671578063e2a3285c1461067957600080fd5b8063c9b26f611161013a578063d84447151161011f578063d84447151461064e578063dac6e63a14610656578063db9040fa1461065e57600080fd5b8063c9b26f6114610507578063cc731b021461051a57600080fd5b8063bc49ce5f1161016b578063bc49ce5f146104c6578063bfb14fb7146104ce578063c4e8ddfa146104ff57600080fd5b8063a7119869146104ab578063b40a817c146104b357600080fd5b80634397dfef1161023f578063550fcdc9116101f35780638da5cb5b116101cd5780638da5cb5b14610472578063935f029e146104905780639b7d7f0a146104a357600080fd5b8063550fcdc91461045a5780635d73369c14610462578063715018a61461046a57600080fd5b80634add321d116102245780634add321d146103e95780634f16540b146103f157806354fd4d501461041857600080fd5b80634397dfef146103ab57806348cd4cb1146103e157600080fd5b806318d13918116102965780631fd19ee11161027b5780631fd19ee114610378578063213268491461038057806321d7fde51461039857600080fd5b806318d139181461035b57806319f5cea81461037057600080fd5b80630a49cb03116102c75780630a49cb031461032b5780630ae14b1b146103335780630c18c1621461035257600080fd5b806306c92657146102e3578063078f29cf146102fe575b600080fd5b6102eb6106fa565b6040519081526020015b60405180910390f35b610306610728565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102f5565b610306610761565b630bebc2005b60405167ffffffffffffffff90911681526020016102f5565b6102eb60655481565b61036e610369366004612241565b610791565b005b6102eb6107a5565b6103066107d0565b6103886107fa565b60405190151581526020016102f5565b61036e6103a6366004612277565b610839565b6103b361084f565b6040805173ffffffffffffffffffffffffffffffffffffffff909316835260ff9091166020830152016102f5565b6102eb610863565b610339610893565b6102eb7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c0881565b60408051808201909152600c81527f322e332e302d626574612e32000000000000000000000000000000000000000060208201525b6040516102f59190612320565b61044d6108b9565b6102eb6108c3565b61036e6108ee565b60335473ffffffffffffffffffffffffffffffffffffffff16610306565b61036e61049e366004612333565b610902565b610306610914565b610306610944565b61036e6104c136600461236d565b610974565b6102eb610985565b6068546104ea9068010000000000000000900463ffffffff1681565b60405163ffffffff90911681526020016102f5565b6103066109b0565b61036e610515366004612388565b6109e0565b6105de6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152506040805160c08101825260695463ffffffff8082168352640100000000820460ff9081166020850152650100000000008304169383019390935266010000000000008104831660608301526a0100000000000000000000810490921660808201526e0100000000000000000000000000009091046fffffffffffffffffffffffffffffffff1660a082015290565b6040516102f59190600060c08201905063ffffffff80845116835260ff602085015116602084015260ff6040850151166040840152806060850151166060840152806080850151166080840152506fffffffffffffffffffffffffffffffff60a08401511660a083015292915050565b61044d6109f1565b6103066109fb565b61036e61066c3660046124bb565b610a2b565b6102eb610e36565b6102eb610e61565b6102eb60675481565b6068546104ea906c01000000000000000000000000900463ffffffff1681565b610306610e8c565b61036e6106c0366004612241565b610ebc565b6102eb60665481565b6068546103399067ffffffffffffffff1681565b6102eb610f70565b6102eb610f9b565b6102eb600081565b61072560017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d61263d565b81565b600061075c61075860017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad637761263d565b5490565b905090565b600061075c61075860017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad61263d565b610799611201565b6107a281611282565b50565b61072560017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a861263d565b600061075c7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c085490565b60008061080561084f565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b610841611201565b61084b828261133f565b5050565b60008061085a611184565b90939092509050565b600061075c61075860017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a061263d565b60695460009061075c9063ffffffff6a0100000000000000000000820481169116612654565b606061075c61147d565b61072560017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce958063761263d565b6108f6611201565b610900600061153e565b565b61090a611201565b61084b82826115b5565b600061075c61075860017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d61263d565b600061075c61075860017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce958063761263d565b61097c611201565b6107a28161168b565b61072560017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc59861263d565b600061075c61075860017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a861263d565b6109e8611201565b6107a2816117e1565b606061075c611809565b600061075c61075860017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc59861263d565b600054610100900460ff1615808015610a4b5750600054600160ff909116105b80610a655750303b158015610a65575060005460ff166001145b610af6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610b5457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610b5c6118bf565b610b658a610ebc565b610b6e876117e1565b610b78898961133f565b610b818661168b565b610baa7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08869055565b610bdd610bd860017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc59861263d565b849055565b610c11610c0b60017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce958063761263d565b83519055565b610c48610c3f60017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a861263d565b60208401519055565b610c7f610c7660017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad637761263d565b60408401519055565b610cb6610cad60017f52322a25d9f59ea17656545543306b7aef62bc0cc53a0e65ccfa0c75b97aa90761263d565b60608401519055565b610ced610ce460017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad61263d565b60808401519055565b610d24610d1b60017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d61263d565b60a08401519055565b610d2c61195e565b610d398260c001516119c6565b610d4284611cd0565b610d4a610893565b67ffffffffffffffff168667ffffffffffffffff161015610dc7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77006044820152606401610aed565b8015610e2a57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050505050565b61072560017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a061263d565b61072560017f52322a25d9f59ea17656545543306b7aef62bc0cc53a0e65ccfa0c75b97aa90761263d565b600061075c61075860017f52322a25d9f59ea17656545543306b7aef62bc0cc53a0e65ccfa0c75b97aa90761263d565b610ec4611201565b73ffffffffffffffffffffffffffffffffffffffff8116610f67576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610aed565b6107a28161153e565b61072560017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad637761263d565b61072560017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad61263d565b9055565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b600060208251111561107a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f476173506179696e67546f6b656e3a20737472696e672063616e6e6f7420626560448201527f2067726561746572207468616e203332206279746573000000000000000000006064820152608401610aed565b6110838261115b565b92915050565b6110ef6110b760017f04adb1412b2ddc16fcc0d4538d5c8f07cf9c83abecc6b41f6f69037b708fbcec61263d565b74ff000000000000000000000000000000000000000060a086901b1673ffffffffffffffffffffffffffffffffffffffff8716179055565b61112261111d60017f657c3582c29b3176614e3a33ddd1ec48352696a04e92b3c0566d72010fa8863d61263d565b839055565b61115561115060017fa48b38a4b44951360fbdcbfaaeae5ed6ae92585412e9841b70ec72ed8cd0576461263d565b829055565b50505050565b8051602181106111735763ec92f9a36000526004601cfd5b9081015160209190910360031b1b90565b600080806111b661075860017f04adb1412b2ddc16fcc0d4538d5c8f07cf9c83abecc6b41f6f69037b708fbcec61263d565b73ffffffffffffffffffffffffffffffffffffffff811693509050826111f5575073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee92601292509050565b60a081901c9150509091565b60335473ffffffffffffffffffffffffffffffffffffffff163314610900576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610aed565b6112ab7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08829055565b6040805173ffffffffffffffffffffffffffffffffffffffff8316602082015260009101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060035b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be836040516113339190612320565b60405180910390a35050565b606880547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000063ffffffff8581169182027fffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffff16929092176c0100000000000000000000000092851692909202919091179091557f0100000000000000000000000000000000000000000000000000000000000000602083811b67ffffffff000000001690921717606681905560655460408051938401919091528201526000906060015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529050600160007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be836040516114709190612320565b60405180910390a3505050565b60606000611489611184565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff82160161150257505060408051808201909152600381527f4554480000000000000000000000000000000000000000000000000000000000602082015290565b61153861153361075860017fa48b38a4b44951360fbdcbfaaeae5ed6ae92585412e9841b70ec72ed8cd0576461263d565b612144565b91505090565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b7fff00000000000000000000000000000000000000000000000000000000000000811615611665576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f53797374656d436f6e6669673a207363616c61722065786365656473206d617860448201527f2e000000000000000000000000000000000000000000000000000000000000006064820152608401610aed565b60658290556066819055604080516020810184905290810182905260009060600161140d565b611693610893565b67ffffffffffffffff168167ffffffffffffffff161015611710576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77006044820152606401610aed565b630bebc20067ffffffffffffffff82161115611788576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f20686967686044820152606401610aed565b606880547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff83169081179091556040805160208082019390935281518082039093018352810190526002611302565b6067819055604080516020808201849052825180830390910181529082019091526000611302565b60606000611815611184565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff82160161188e57505060408051808201909152600581527f4574686572000000000000000000000000000000000000000000000000000000602082015290565b61153861153361075860017f657c3582c29b3176614e3a33ddd1ec48352696a04e92b3c0566d72010fa8863d61263d565b600054610100900460ff16611956576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610aed565b610900612178565b61198c61075860017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a061263d565b600003610900576109006119c160017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a061263d565b439055565b73ffffffffffffffffffffffffffffffffffffffff811615801590611a15575073ffffffffffffffffffffffffffffffffffffffff811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14155b8015611a265750611a246107fa565b155b156107a257601260ff168173ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a9f9190612680565b60ff1614611b2f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f53797374656d436f6e6669673a2062616420646563696d616c73206f6620676160448201527f7320706179696e6720746f6b656e0000000000000000000000000000000000006064820152608401610aed565b6000611bca8273ffffffffffffffffffffffffffffffffffffffff166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa158015611b7f573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611bc5919081019061269d565b610fe6565b90506000611c1c8373ffffffffffffffffffffffffffffffffffffffff166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015611b7f573d6000803e3d6000fd5b9050611c2b8360128484611089565b611c33610761565b6040517f71cfaa3f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015260126024830152604482018590526064820184905291909116906371cfaa3f90608401600060405180830381600087803b158015611cb357600080fd5b505af1158015611cc7573d6000803e3d6000fd5b50505050505050565b8060a001516fffffffffffffffffffffffffffffffff16816060015163ffffffff161115611d80576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f53797374656d436f6e6669673a206d696e206261736520666565206d7573742060448201527f6265206c657373207468616e206d6178206261736500000000000000000000006064820152608401610aed565b6001816040015160ff1611611e17576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f53797374656d436f6e6669673a2064656e6f6d696e61746f72206d757374206260448201527f65206c6172676572207468616e203100000000000000000000000000000000006064820152608401610aed565b6068546080820151825167ffffffffffffffff90921691611e389190612768565b63ffffffff161115611ea6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77006044820152606401610aed565b6000816020015160ff1611611f3d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f53797374656d436f6e6669673a20656c6173746963697479206d756c7469706c60448201527f6965722063616e6e6f74206265203000000000000000000000000000000000006064820152608401610aed565b8051602082015163ffffffff82169160ff90911690611f5d908290612787565b611f6791906127d1565b63ffffffff1614611ffa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f53797374656d436f6e6669673a20707265636973696f6e206c6f73732077697460448201527f6820746172676574207265736f75726365206c696d69740000000000000000006064820152608401610aed565b805160698054602084015160408501516060860151608087015160a09097015163ffffffff9687167fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009095169490941764010000000060ff94851602177fffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffff166501000000000093909216929092027fffffffffffffffffffffffffffffffffffffffffffff00000000ffffffffffff1617660100000000000091851691909102177fffff0000000000000000000000000000000000000000ffffffffffffffffffff166a010000000000000000000093909416929092027fffff00000000000000000000000000000000ffffffffffffffffffffffffffff16929092176e0100000000000000000000000000006fffffffffffffffffffffffffffffffff90921691909102179055565b60405160005b82811a1561215a5760010161214a565b80825260208201838152600082820152505060408101604052919050565b600054610100900460ff1661220f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610aed565b6109003361153e565b803573ffffffffffffffffffffffffffffffffffffffff8116811461223c57600080fd5b919050565b60006020828403121561225357600080fd5b61225c82612218565b9392505050565b803563ffffffff8116811461223c57600080fd5b6000806040838503121561228a57600080fd5b61229383612263565b91506122a160208401612263565b90509250929050565b60005b838110156122c55781810151838201526020016122ad565b838111156111555750506000910152565b600081518084526122ee8160208601602086016122aa565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061225c60208301846122d6565b6000806040838503121561234657600080fd5b50508035926020909101359150565b803567ffffffffffffffff8116811461223c57600080fd5b60006020828403121561237f57600080fd5b61225c82612355565b60006020828403121561239a57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160c0810167ffffffffffffffff811182821017156123f3576123f36123a1565b60405290565b60ff811681146107a257600080fd5b600060e0828403121561241a57600080fd5b60405160e0810181811067ffffffffffffffff8211171561243d5761243d6123a1565b60405290508061244c83612218565b815261245a60208401612218565b602082015261246b60408401612218565b604082015261247c60608401612218565b606082015261248d60808401612218565b608082015261249e60a08401612218565b60a08201526124af60c08401612218565b60c08201525092915050565b6000806000806000806000806000898b036102808112156124db57600080fd5b6124e48b612218565b99506124f260208c01612263565b985061250060408c01612263565b975060608b0135965061251560808c01612355565b955061252360a08c01612218565b945060c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff408201121561255557600080fd5b5061255e6123d0565b61256a60c08c01612263565b815260e08b013561257a816123f9565b60208201526101008b013561258e816123f9565b60408201526125a06101208c01612263565b60608201526125b26101408c01612263565b60808201526101608b01356fffffffffffffffffffffffffffffffff811681146125db57600080fd5b60a082015292506125ef6101808b01612218565b91506125ff8b6101a08c01612408565b90509295985092959850929598565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561264f5761264f61260e565b500390565b600067ffffffffffffffff8083168185168083038211156126775761267761260e565b01949350505050565b60006020828403121561269257600080fd5b815161225c816123f9565b6000602082840312156126af57600080fd5b815167ffffffffffffffff808211156126c757600080fd5b818401915084601f8301126126db57600080fd5b8151818111156126ed576126ed6123a1565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715612733576127336123a1565b8160405282815287602084870101111561274c57600080fd5b61275d8360208301602088016122aa565b979650505050505050565b600063ffffffff8083168185168083038211156126775761267761260e565b600063ffffffff808416806127c5577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b92169190910492915050565b600063ffffffff808316818516818304811182151516156127f4576127f461260e565b0294935050505056fea164736f6c634300080f000a"; + hex"608060405234801561001057600080fd5b50600436106102de5760003560e01c8063a711986911610186578063e0e2016d116100e3578063f2fde38b11610097578063f8c68de011610071578063f8c68de0146106e2578063fd32aa0f146106ea578063ffa1ad74146106f257600080fd5b8063f2fde38b146106b2578063f45e65d8146106c5578063f68016b7146106ce57600080fd5b8063e81b2c6d116100c8578063e81b2c6d14610681578063ec7075171461068a578063f2b4e617146106aa57600080fd5b8063e0e2016d14610671578063e2a3285c1461067957600080fd5b8063c9b26f611161013a578063d84447151161011f578063d84447151461064e578063dac6e63a14610656578063db9040fa1461065e57600080fd5b8063c9b26f6114610507578063cc731b021461051a57600080fd5b8063bc49ce5f1161016b578063bc49ce5f146104c6578063bfb14fb7146104ce578063c4e8ddfa146104ff57600080fd5b8063a7119869146104ab578063b40a817c146104b357600080fd5b80634397dfef1161023f578063550fcdc9116101f35780638da5cb5b116101cd5780638da5cb5b14610472578063935f029e146104905780639b7d7f0a146104a357600080fd5b8063550fcdc91461045a5780635d73369c14610462578063715018a61461046a57600080fd5b80634add321d116102245780634add321d146103e95780634f16540b146103f157806354fd4d501461041857600080fd5b80634397dfef146103ab57806348cd4cb1146103e157600080fd5b806318d13918116102965780631fd19ee11161027b5780631fd19ee114610378578063213268491461038057806321d7fde51461039857600080fd5b806318d139181461035b57806319f5cea81461037057600080fd5b80630a49cb03116102c75780630a49cb031461032b5780630ae14b1b146103335780630c18c1621461035257600080fd5b806306c92657146102e3578063078f29cf146102fe575b600080fd5b6102eb6106fa565b6040519081526020015b60405180910390f35b610306610728565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102f5565b610306610761565b630bebc2005b60405167ffffffffffffffff90911681526020016102f5565b6102eb60655481565b61036e610369366004612241565b610791565b005b6102eb6107a5565b6103066107d0565b6103886107fa565b60405190151581526020016102f5565b61036e6103a6366004612277565b610839565b6103b361084f565b6040805173ffffffffffffffffffffffffffffffffffffffff909316835260ff9091166020830152016102f5565b6102eb610863565b610339610893565b6102eb7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c0881565b60408051808201909152600c81527f322e332e302d626574612e33000000000000000000000000000000000000000060208201525b6040516102f59190612320565b61044d6108b9565b6102eb6108c3565b61036e6108ee565b60335473ffffffffffffffffffffffffffffffffffffffff16610306565b61036e61049e366004612333565b610902565b610306610914565b610306610944565b61036e6104c136600461236d565b610974565b6102eb610985565b6068546104ea9068010000000000000000900463ffffffff1681565b60405163ffffffff90911681526020016102f5565b6103066109b0565b61036e610515366004612388565b6109e0565b6105de6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152506040805160c08101825260695463ffffffff8082168352640100000000820460ff9081166020850152650100000000008304169383019390935266010000000000008104831660608301526a0100000000000000000000810490921660808201526e0100000000000000000000000000009091046fffffffffffffffffffffffffffffffff1660a082015290565b6040516102f59190600060c08201905063ffffffff80845116835260ff602085015116602084015260ff6040850151166040840152806060850151166060840152806080850151166080840152506fffffffffffffffffffffffffffffffff60a08401511660a083015292915050565b61044d6109f1565b6103066109fb565b61036e61066c3660046124bb565b610a2b565b6102eb610e36565b6102eb610e61565b6102eb60675481565b6068546104ea906c01000000000000000000000000900463ffffffff1681565b610306610e8c565b61036e6106c0366004612241565b610ebc565b6102eb60665481565b6068546103399067ffffffffffffffff1681565b6102eb610f70565b6102eb610f9b565b6102eb600081565b61072560017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d61263d565b81565b600061075c61075860017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad637761263d565b5490565b905090565b600061075c61075860017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad61263d565b610799611201565b6107a281611282565b50565b61072560017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a861263d565b600061075c7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c085490565b60008061080561084f565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b610841611201565b61084b828261133f565b5050565b60008061085a611184565b90939092509050565b600061075c61075860017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a061263d565b60695460009061075c9063ffffffff6a0100000000000000000000820481169116612654565b606061075c61147d565b61072560017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce958063761263d565b6108f6611201565b610900600061153e565b565b61090a611201565b61084b82826115b5565b600061075c61075860017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d61263d565b600061075c61075860017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce958063761263d565b61097c611201565b6107a28161168b565b61072560017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc59861263d565b600061075c61075860017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a861263d565b6109e8611201565b6107a2816117e1565b606061075c611809565b600061075c61075860017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc59861263d565b600054610100900460ff1615808015610a4b5750600054600160ff909116105b80610a655750303b158015610a65575060005460ff166001145b610af6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610b5457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610b5c6118bf565b610b658a610ebc565b610b6e876117e1565b610b78898961133f565b610b818661168b565b610baa7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08869055565b610bdd610bd860017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc59861263d565b849055565b610c11610c0b60017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce958063761263d565b83519055565b610c48610c3f60017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a861263d565b60208401519055565b610c7f610c7660017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad637761263d565b60408401519055565b610cb6610cad60017f52322a25d9f59ea17656545543306b7aef62bc0cc53a0e65ccfa0c75b97aa90761263d565b60608401519055565b610ced610ce460017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad61263d565b60808401519055565b610d24610d1b60017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d61263d565b60a08401519055565b610d2c61195e565b610d398260c001516119c6565b610d4284611cd0565b610d4a610893565b67ffffffffffffffff168667ffffffffffffffff161015610dc7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77006044820152606401610aed565b8015610e2a57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050505050565b61072560017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a061263d565b61072560017f52322a25d9f59ea17656545543306b7aef62bc0cc53a0e65ccfa0c75b97aa90761263d565b600061075c61075860017f52322a25d9f59ea17656545543306b7aef62bc0cc53a0e65ccfa0c75b97aa90761263d565b610ec4611201565b73ffffffffffffffffffffffffffffffffffffffff8116610f67576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610aed565b6107a28161153e565b61072560017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad637761263d565b61072560017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad61263d565b9055565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b600060208251111561107a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f476173506179696e67546f6b656e3a20737472696e672063616e6e6f7420626560448201527f2067726561746572207468616e203332206279746573000000000000000000006064820152608401610aed565b6110838261115b565b92915050565b6110ef6110b760017f04adb1412b2ddc16fcc0d4538d5c8f07cf9c83abecc6b41f6f69037b708fbcec61263d565b74ff000000000000000000000000000000000000000060a086901b1673ffffffffffffffffffffffffffffffffffffffff8716179055565b61112261111d60017f657c3582c29b3176614e3a33ddd1ec48352696a04e92b3c0566d72010fa8863d61263d565b839055565b61115561115060017fa48b38a4b44951360fbdcbfaaeae5ed6ae92585412e9841b70ec72ed8cd0576461263d565b829055565b50505050565b8051602181106111735763ec92f9a36000526004601cfd5b9081015160209190910360031b1b90565b600080806111b661075860017f04adb1412b2ddc16fcc0d4538d5c8f07cf9c83abecc6b41f6f69037b708fbcec61263d565b73ffffffffffffffffffffffffffffffffffffffff811693509050826111f5575073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee92601292509050565b60a081901c9150509091565b60335473ffffffffffffffffffffffffffffffffffffffff163314610900576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610aed565b6112ab7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08829055565b6040805173ffffffffffffffffffffffffffffffffffffffff8316602082015260009101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060035b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be836040516113339190612320565b60405180910390a35050565b606880547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000063ffffffff8581169182027fffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffff16929092176c0100000000000000000000000092851692909202919091179091557f0100000000000000000000000000000000000000000000000000000000000000602083811b67ffffffff000000001690921717606681905560655460408051938401919091528201526000906060015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529050600160007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be836040516114709190612320565b60405180910390a3505050565b60606000611489611184565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff82160161150257505060408051808201909152600381527f4554480000000000000000000000000000000000000000000000000000000000602082015290565b61153861153361075860017fa48b38a4b44951360fbdcbfaaeae5ed6ae92585412e9841b70ec72ed8cd0576461263d565b612144565b91505090565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b7fff00000000000000000000000000000000000000000000000000000000000000811615611665576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f53797374656d436f6e6669673a207363616c61722065786365656473206d617860448201527f2e000000000000000000000000000000000000000000000000000000000000006064820152608401610aed565b60658290556066819055604080516020810184905290810182905260009060600161140d565b611693610893565b67ffffffffffffffff168167ffffffffffffffff161015611710576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77006044820152606401610aed565b630bebc20067ffffffffffffffff82161115611788576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f20686967686044820152606401610aed565b606880547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff83169081179091556040805160208082019390935281518082039093018352810190526002611302565b6067819055604080516020808201849052825180830390910181529082019091526000611302565b60606000611815611184565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff82160161188e57505060408051808201909152600581527f4574686572000000000000000000000000000000000000000000000000000000602082015290565b61153861153361075860017f657c3582c29b3176614e3a33ddd1ec48352696a04e92b3c0566d72010fa8863d61263d565b600054610100900460ff16611956576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610aed565b610900612178565b61198c61075860017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a061263d565b600003610900576109006119c160017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a061263d565b439055565b73ffffffffffffffffffffffffffffffffffffffff811615801590611a15575073ffffffffffffffffffffffffffffffffffffffff811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14155b8015611a265750611a246107fa565b155b156107a257601260ff168173ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a9f9190612680565b60ff1614611b2f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f53797374656d436f6e6669673a2062616420646563696d616c73206f6620676160448201527f7320706179696e6720746f6b656e0000000000000000000000000000000000006064820152608401610aed565b6000611bca8273ffffffffffffffffffffffffffffffffffffffff166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa158015611b7f573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611bc5919081019061269d565b610fe6565b90506000611c1c8373ffffffffffffffffffffffffffffffffffffffff166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015611b7f573d6000803e3d6000fd5b9050611c2b8360128484611089565b611c33610761565b6040517f71cfaa3f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015260126024830152604482018590526064820184905291909116906371cfaa3f90608401600060405180830381600087803b158015611cb357600080fd5b505af1158015611cc7573d6000803e3d6000fd5b50505050505050565b8060a001516fffffffffffffffffffffffffffffffff16816060015163ffffffff161115611d80576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f53797374656d436f6e6669673a206d696e206261736520666565206d7573742060448201527f6265206c657373207468616e206d6178206261736500000000000000000000006064820152608401610aed565b6001816040015160ff1611611e17576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f53797374656d436f6e6669673a2064656e6f6d696e61746f72206d757374206260448201527f65206c6172676572207468616e203100000000000000000000000000000000006064820152608401610aed565b6068546080820151825167ffffffffffffffff90921691611e389190612768565b63ffffffff161115611ea6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77006044820152606401610aed565b6000816020015160ff1611611f3d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f53797374656d436f6e6669673a20656c6173746963697479206d756c7469706c60448201527f6965722063616e6e6f74206265203000000000000000000000000000000000006064820152608401610aed565b8051602082015163ffffffff82169160ff90911690611f5d908290612787565b611f6791906127d1565b63ffffffff1614611ffa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f53797374656d436f6e6669673a20707265636973696f6e206c6f73732077697460448201527f6820746172676574207265736f75726365206c696d69740000000000000000006064820152608401610aed565b805160698054602084015160408501516060860151608087015160a09097015163ffffffff9687167fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009095169490941764010000000060ff94851602177fffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffff166501000000000093909216929092027fffffffffffffffffffffffffffffffffffffffffffff00000000ffffffffffff1617660100000000000091851691909102177fffff0000000000000000000000000000000000000000ffffffffffffffffffff166a010000000000000000000093909416929092027fffff00000000000000000000000000000000ffffffffffffffffffffffffffff16929092176e0100000000000000000000000000006fffffffffffffffffffffffffffffffff90921691909102179055565b60405160005b82811a1561215a5760010161214a565b80825260208201838152600082820152505060408101604052919050565b600054610100900460ff1661220f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610aed565b6109003361153e565b803573ffffffffffffffffffffffffffffffffffffffff8116811461223c57600080fd5b919050565b60006020828403121561225357600080fd5b61225c82612218565b9392505050565b803563ffffffff8116811461223c57600080fd5b6000806040838503121561228a57600080fd5b61229383612263565b91506122a160208401612263565b90509250929050565b60005b838110156122c55781810151838201526020016122ad565b838111156111555750506000910152565b600081518084526122ee8160208601602086016122aa565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061225c60208301846122d6565b6000806040838503121561234657600080fd5b50508035926020909101359150565b803567ffffffffffffffff8116811461223c57600080fd5b60006020828403121561237f57600080fd5b61225c82612355565b60006020828403121561239a57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160c0810167ffffffffffffffff811182821017156123f3576123f36123a1565b60405290565b60ff811681146107a257600080fd5b600060e0828403121561241a57600080fd5b60405160e0810181811067ffffffffffffffff8211171561243d5761243d6123a1565b60405290508061244c83612218565b815261245a60208401612218565b602082015261246b60408401612218565b604082015261247c60608401612218565b606082015261248d60808401612218565b608082015261249e60a08401612218565b60a08201526124af60c08401612218565b60c08201525092915050565b6000806000806000806000806000898b036102808112156124db57600080fd5b6124e48b612218565b99506124f260208c01612263565b985061250060408c01612263565b975060608b0135965061251560808c01612355565b955061252360a08c01612218565b945060c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff408201121561255557600080fd5b5061255e6123d0565b61256a60c08c01612263565b815260e08b013561257a816123f9565b60208201526101008b013561258e816123f9565b60408201526125a06101208c01612263565b60608201526125b26101408c01612263565b60808201526101608b01356fffffffffffffffffffffffffffffffff811681146125db57600080fd5b60a082015292506125ef6101808b01612218565b91506125ff8b6101a08c01612408565b90509295985092959850929598565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561264f5761264f61260e565b500390565b600067ffffffffffffffff8083168185168083038211156126775761267761260e565b01949350505050565b60006020828403121561269257600080fd5b815161225c816123f9565b6000602082840312156126af57600080fd5b815167ffffffffffffffff808211156126c757600080fd5b818401915084601f8301126126db57600080fd5b8151818111156126ed576126ed6123a1565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715612733576127336123a1565b8160405282815287602084870101111561274c57600080fd5b61275d8360208301602088016122aa565b979650505050505050565b600063ffffffff8083168185168083038211156126775761267761260e565b600063ffffffff808416806127c5577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b92169190910492915050565b600063ffffffff808316818516818304811182151516156127f4576127f461260e565b0294935050505056fea164736f6c634300080f000a"; bytes internal constant l1StandardBridgeCode = - hex"6080604052600436106101845760003560e01c80637f46ddb2116100d65780639a2ac6d51161007f578063c0c53b8b11610059578063c0c53b8b14610529578063c89701a214610549578063e11013dd1461057657600080fd5b80639a2ac6d5146104e3578063a9f9e675146104f6578063b1a1a8821461051657600080fd5b80638f601f66116100b05780638f601f661461047257806391c49bf814610407578063927ede2d146104b857600080fd5b80637f46ddb214610407578063838b252014610432578063870876231461045257600080fd5b806335e80ab31161013857806354fd4d501161011257806354fd4d501461036c57806358a997f6146103c25780635c975abb146103e257600080fd5b806335e80ab3146102f25780633cb747bf1461031f578063540abf731461034c57600080fd5b80631532ec34116101695780631532ec34146102755780631635f5fd1461028857806333d7e2bd1461029b57600080fd5b80630166a07a1461024257806309fc88431461026257600080fd5b3661023d57333b1561021d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084015b60405180910390fd5b61023b333362030d40604051806020016040528060008152506105a5565b005b600080fd5b34801561024e57600080fd5b5061023b61025d366004612991565b6105b8565b61023b610270366004612a42565b6109d2565b61023b610283366004612a95565b610aa9565b61023b610296366004612a95565b610abd565b3480156102a757600080fd5b506033546102c89073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156102fe57600080fd5b506032546102c89073ffffffffffffffffffffffffffffffffffffffff1681565b34801561032b57600080fd5b506003546102c89073ffffffffffffffffffffffffffffffffffffffff1681565b34801561035857600080fd5b5061023b610367366004612b08565b61101b565b34801561037857600080fd5b506103b56040518060400160405280600581526020017f322e322e3000000000000000000000000000000000000000000000000000000081525081565b6040516102e99190612bf5565b3480156103ce57600080fd5b5061023b6103dd366004612c08565b611060565b3480156103ee57600080fd5b506103f7611134565b60405190151581526020016102e9565b34801561041357600080fd5b5060045473ffffffffffffffffffffffffffffffffffffffff166102c8565b34801561043e57600080fd5b5061023b61044d366004612b08565b6111cd565b34801561045e57600080fd5b5061023b61046d366004612c08565b611212565b34801561047e57600080fd5b506104aa61048d366004612c8b565b600260209081526000928352604080842090915290825290205481565b6040519081526020016102e9565b3480156104c457600080fd5b5060035473ffffffffffffffffffffffffffffffffffffffff166102c8565b61023b6104f1366004612cc4565b6112e6565b34801561050257600080fd5b5061023b610511366004612991565b611328565b61023b610524366004612a42565b611337565b34801561053557600080fd5b5061023b610544366004612d27565b611408565b34801561055557600080fd5b506004546102c89073ffffffffffffffffffffffffffffffffffffffff1681565b61023b610584366004612cc4565b611607565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6105b2848434858561164a565b50505050565b60035473ffffffffffffffffffffffffffffffffffffffff163314801561068b575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa15801561064f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106739190612d72565b73ffffffffffffffffffffffffffffffffffffffff16145b61073d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a401610214565b610745611134565b156107ac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616e646172644272696467653a20706175736564000000000000000000006044820152606401610214565b6107b5876118a9565b15610903576107c4878761190b565b610876576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a401610214565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b1580156108e657600080fd5b505af11580156108fa573d6000803e3d6000fd5b50505050610985565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054610941908490612dbe565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c1683529390529190912091909155610985908585611a2b565b6109c9878787878787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611aff92505050565b50505050505050565b333b15610a61576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610214565b610aa43333348686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061164a92505050565b505050565b610ab68585858585610abd565b5050505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610b90575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa158015610b54573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b789190612d72565b73ffffffffffffffffffffffffffffffffffffffff16145b610c42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a401610214565b610c4a611134565b15610cb1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616e646172644272696467653a20706175736564000000000000000000006044820152606401610214565b610cb9611b8d565b15610d46576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e0000000000000000006064820152608401610214565b823414610dd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e742072657175697265640000000000006064820152608401610214565b3073ffffffffffffffffffffffffffffffffffffffff851603610e7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c6600000000000000000000000000000000000000000000000000000000006064820152608401610214565b60035473ffffffffffffffffffffffffffffffffffffffff90811690851603610f25576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e6765720000000000000000000000000000000000000000000000006064820152608401610214565b610f6785858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611bcc92505050565b6000610f84855a8660405180602001604052806000815250611c3f565b905080611013576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c656400000000000000000000000000000000000000000000000000000000006064820152608401610214565b505050505050565b6109c987873388888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611c5792505050565b333b156110ef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610214565b61101386863333888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061201092505050565b603254604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa1580156111a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111c89190612dd5565b905090565b6109c987873388888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061201092505050565b333b156112a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610214565b61101386863333888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611c5792505050565b6105b233858585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506105a592505050565b6109c9878787878787876105b8565b333b156113c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610214565b610aa433338585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506105a592505050565b600054610100900460ff16158080156114285750600054600160ff909116105b806114425750303b158015611442575060005460ff166001145b6114ce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610214565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561152c57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6032805473ffffffffffffffffffffffffffffffffffffffff8086167fffffffffffffffffffffffff000000000000000000000000000000000000000092831617909255603380549285169290911691909117905561159f8473420000000000000000000000000000000000001061201f565b80156105b257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150505050565b6105b23385348686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061164a92505050565b611652611b8d565b156116df576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e0000000000000000006064820152608401610214565b82341461176e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c756500006064820152608401610214565b61177a85858584612109565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9287929116907f1635f5fd00000000000000000000000000000000000000000000000000000000906117dd908b908b9086908a90602401612df7565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b909216825261187092918890600401612e40565b6000604051808303818588803b15801561188957600080fd5b505af115801561189d573d6000803e3d6000fd5b50505050505050505050565b60006118d5827f1d1d8b630000000000000000000000000000000000000000000000000000000061217c565b806119055750611905827fec4fc8e30000000000000000000000000000000000000000000000000000000061217c565b92915050565b6000611937837f1d1d8b630000000000000000000000000000000000000000000000000000000061217c565b156119e0578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015611987573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ab9190612d72565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050611905565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611987573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052610aa49084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915261219f565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f3ceee06c1e37648fcbb6ed52e17b3e1f275a1f8c7b22a84b2b84732431e046b3868686604051611b7793929190612e85565b60405180910390a46110138686868686866122ab565b600080611b98612333565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2ac69ee804d9a7a0984249f508dfab7cb2534b465b6ce1580f99a38ba9c5e6318484604051611c2b929190612ec3565b60405180910390a36105b2848484846123d0565b6000806000835160208501868989f195945050505050565b3415611ce5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5374616e646172644272696467653a2063616e6e6f742073656e642076616c7560448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610214565b611cee876118a9565b15611e3c57611cfd878761190b565b611daf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a401610214565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b158015611e1f57600080fd5b505af1158015611e33573d6000803e3d6000fd5b50505050611ed0565b611e5e73ffffffffffffffffffffffffffffffffffffffff881686308661243d565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054611e9c908490612edc565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b611ede87878787878661249b565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9216907f0166a07a0000000000000000000000000000000000000000000000000000000090611f42908b908d908c908c908c908b90602401612ef4565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b9092168252611fd592918790600401612e40565b600060405180830381600087803b158015611fef57600080fd5b505af1158015612003573d6000803e3d6000fd5b5050505050505050505050565b6109c987878787878787611c57565b600054610100900460ff166120b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610214565b6003805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560048054929093169116179055565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f35d79ab81f2b2017e19afb5c5571778877782d7a8786f5907f93b0f4702f4f238484604051612168929190612ec3565b60405180910390a36105b284848484612529565b600061218783612588565b8015612198575061219883836125ec565b9392505050565b6000612201826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166126bb9092919063ffffffff16565b805190915015610aa4578080602001905181019061221f9190612dd5565b610aa4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610214565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd86868660405161232393929190612e85565b60405180910390a4505050505050565b603354604080517f4397dfef0000000000000000000000000000000000000000000000000000000081528151600093849373ffffffffffffffffffffffffffffffffffffffff90911692634397dfef92600480830193928290030181865afa1580156123a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123c79190612f4f565b90939092509050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d848460405161242f929190612ec3565b60405180910390a350505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526105b29085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611a7d565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f718594027abd4eaed59f95162563e0cc6d0e8d5b86b1c7be8b1b0ac3343d039686868660405161251393929190612e85565b60405180910390a46110138686868686866126d2565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af5848460405161242f929190612ec3565b60006125b4827f01ffc9a7000000000000000000000000000000000000000000000000000000006125ec565b801561190557506125e5827fffffffff000000000000000000000000000000000000000000000000000000006125ec565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d915060005190508280156126a4575060208210155b80156126b05750600081115b979650505050505050565b60606126ca848460008561274a565b949350505050565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf86868660405161232393929190612e85565b6060824710156127dc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610214565b73ffffffffffffffffffffffffffffffffffffffff85163b61285a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610214565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516128839190612f84565b60006040518083038185875af1925050503d80600081146128c0576040519150601f19603f3d011682016040523d82523d6000602084013e6128c5565b606091505b50915091506126b0828286606083156128df575081612198565b8251156128ef5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102149190612bf5565b73ffffffffffffffffffffffffffffffffffffffff8116811461294557600080fd5b50565b60008083601f84011261295a57600080fd5b50813567ffffffffffffffff81111561297257600080fd5b60208301915083602082850101111561298a57600080fd5b9250929050565b600080600080600080600060c0888a0312156129ac57600080fd5b87356129b781612923565b965060208801356129c781612923565b955060408801356129d781612923565b945060608801356129e781612923565b93506080880135925060a088013567ffffffffffffffff811115612a0a57600080fd5b612a168a828b01612948565b989b979a50959850939692959293505050565b803563ffffffff81168114612a3d57600080fd5b919050565b600080600060408486031215612a5757600080fd5b612a6084612a29565b9250602084013567ffffffffffffffff811115612a7c57600080fd5b612a8886828701612948565b9497909650939450505050565b600080600080600060808688031215612aad57600080fd5b8535612ab881612923565b94506020860135612ac881612923565b935060408601359250606086013567ffffffffffffffff811115612aeb57600080fd5b612af788828901612948565b969995985093965092949392505050565b600080600080600080600060c0888a031215612b2357600080fd5b8735612b2e81612923565b96506020880135612b3e81612923565b95506040880135612b4e81612923565b945060608801359350612b6360808901612a29565b925060a088013567ffffffffffffffff811115612a0a57600080fd5b60005b83811015612b9a578181015183820152602001612b82565b838111156105b25750506000910152565b60008151808452612bc3816020860160208601612b7f565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006121986020830184612bab565b60008060008060008060a08789031215612c2157600080fd5b8635612c2c81612923565b95506020870135612c3c81612923565b945060408701359350612c5160608801612a29565b9250608087013567ffffffffffffffff811115612c6d57600080fd5b612c7989828a01612948565b979a9699509497509295939492505050565b60008060408385031215612c9e57600080fd5b8235612ca981612923565b91506020830135612cb981612923565b809150509250929050565b60008060008060608587031215612cda57600080fd5b8435612ce581612923565b9350612cf360208601612a29565b9250604085013567ffffffffffffffff811115612d0f57600080fd5b612d1b87828801612948565b95989497509550505050565b600080600060608486031215612d3c57600080fd5b8335612d4781612923565b92506020840135612d5781612923565b91506040840135612d6781612923565b809150509250925092565b600060208284031215612d8457600080fd5b815161219881612923565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015612dd057612dd0612d8f565b500390565b600060208284031215612de757600080fd5b8151801515811461219857600080fd5b600073ffffffffffffffffffffffffffffffffffffffff808716835280861660208401525083604083015260806060830152612e366080830184612bab565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff84168152606060208201526000612e6f6060830185612bab565b905063ffffffff83166040830152949350505050565b73ffffffffffffffffffffffffffffffffffffffff84168152826020820152606060408201526000612eba6060830184612bab565b95945050505050565b8281526040602082015260006126ca6040830184612bab565b60008219821115612eef57612eef612d8f565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a0830152612f4360c0830184612bab565b98975050505050505050565b60008060408385031215612f6257600080fd5b8251612f6d81612923565b602084015190925060ff81168114612cb957600080fd5b60008251612f96818460208701612b7f565b919091019291505056fea164736f6c634300080f000a"; + hex"6080604052600436106101845760003560e01c80637f46ddb2116100d65780639a2ac6d51161007f578063c0c53b8b11610059578063c0c53b8b14610529578063c89701a214610549578063e11013dd1461057657600080fd5b80639a2ac6d5146104e3578063a9f9e675146104f6578063b1a1a8821461051657600080fd5b80638f601f66116100b05780638f601f661461047257806391c49bf814610407578063927ede2d146104b857600080fd5b80637f46ddb214610407578063838b252014610432578063870876231461045257600080fd5b806335e80ab31161013857806354fd4d501161011257806354fd4d501461036c57806358a997f6146103c25780635c975abb146103e257600080fd5b806335e80ab3146102f25780633cb747bf1461031f578063540abf731461034c57600080fd5b80631532ec34116101695780631532ec34146102755780631635f5fd1461028857806333d7e2bd1461029b57600080fd5b80630166a07a1461024257806309fc88431461026257600080fd5b3661023d57333b1561021d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084015b60405180910390fd5b61023b333362030d40604051806020016040528060008152506105a5565b005b600080fd5b34801561024e57600080fd5b5061023b61025d366004612991565b6105b8565b61023b610270366004612a42565b6109d2565b61023b610283366004612a95565b610aa9565b61023b610296366004612a95565b610abd565b3480156102a757600080fd5b506033546102c89073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156102fe57600080fd5b506032546102c89073ffffffffffffffffffffffffffffffffffffffff1681565b34801561032b57600080fd5b506003546102c89073ffffffffffffffffffffffffffffffffffffffff1681565b34801561035857600080fd5b5061023b610367366004612b08565b61101b565b34801561037857600080fd5b506103b56040518060400160405280600c81526020017f322e322e312d626574612e31000000000000000000000000000000000000000081525081565b6040516102e99190612bf5565b3480156103ce57600080fd5b5061023b6103dd366004612c08565b611060565b3480156103ee57600080fd5b506103f7611134565b60405190151581526020016102e9565b34801561041357600080fd5b5060045473ffffffffffffffffffffffffffffffffffffffff166102c8565b34801561043e57600080fd5b5061023b61044d366004612b08565b6111cd565b34801561045e57600080fd5b5061023b61046d366004612c08565b611212565b34801561047e57600080fd5b506104aa61048d366004612c8b565b600260209081526000928352604080842090915290825290205481565b6040519081526020016102e9565b3480156104c457600080fd5b5060035473ffffffffffffffffffffffffffffffffffffffff166102c8565b61023b6104f1366004612cc4565b6112e6565b34801561050257600080fd5b5061023b610511366004612991565b611328565b61023b610524366004612a42565b611337565b34801561053557600080fd5b5061023b610544366004612d27565b611408565b34801561055557600080fd5b506004546102c89073ffffffffffffffffffffffffffffffffffffffff1681565b61023b610584366004612cc4565b611607565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6105b2848434858561164a565b50505050565b60035473ffffffffffffffffffffffffffffffffffffffff163314801561068b575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa15801561064f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106739190612d72565b73ffffffffffffffffffffffffffffffffffffffff16145b61073d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a401610214565b610745611134565b156107ac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616e646172644272696467653a20706175736564000000000000000000006044820152606401610214565b6107b5876118a9565b15610903576107c4878761190b565b610876576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a401610214565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b1580156108e657600080fd5b505af11580156108fa573d6000803e3d6000fd5b50505050610985565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054610941908490612dbe565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c1683529390529190912091909155610985908585611a2b565b6109c9878787878787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611aff92505050565b50505050505050565b333b15610a61576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610214565b610aa43333348686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061164a92505050565b505050565b610ab68585858585610abd565b5050505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610b90575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa158015610b54573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b789190612d72565b73ffffffffffffffffffffffffffffffffffffffff16145b610c42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a401610214565b610c4a611134565b15610cb1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616e646172644272696467653a20706175736564000000000000000000006044820152606401610214565b610cb9611b8d565b15610d46576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e0000000000000000006064820152608401610214565b823414610dd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e742072657175697265640000000000006064820152608401610214565b3073ffffffffffffffffffffffffffffffffffffffff851603610e7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c6600000000000000000000000000000000000000000000000000000000006064820152608401610214565b60035473ffffffffffffffffffffffffffffffffffffffff90811690851603610f25576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e6765720000000000000000000000000000000000000000000000006064820152608401610214565b610f6785858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611bcc92505050565b6000610f84855a8660405180602001604052806000815250611c3f565b905080611013576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c656400000000000000000000000000000000000000000000000000000000006064820152608401610214565b505050505050565b6109c987873388888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611c5792505050565b333b156110ef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610214565b61101386863333888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061201092505050565b603254604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa1580156111a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111c89190612dd5565b905090565b6109c987873388888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061201092505050565b333b156112a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610214565b61101386863333888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611c5792505050565b6105b233858585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506105a592505050565b6109c9878787878787876105b8565b333b156113c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610214565b610aa433338585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506105a592505050565b600054610100900460ff16158080156114285750600054600160ff909116105b806114425750303b158015611442575060005460ff166001145b6114ce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610214565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561152c57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6032805473ffffffffffffffffffffffffffffffffffffffff8086167fffffffffffffffffffffffff000000000000000000000000000000000000000092831617909255603380549285169290911691909117905561159f8473420000000000000000000000000000000000001061201f565b80156105b257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150505050565b6105b23385348686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061164a92505050565b611652611b8d565b156116df576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e0000000000000000006064820152608401610214565b82341461176e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c756500006064820152608401610214565b61177a85858584612109565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9287929116907f1635f5fd00000000000000000000000000000000000000000000000000000000906117dd908b908b9086908a90602401612df7565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b909216825261187092918890600401612e40565b6000604051808303818588803b15801561188957600080fd5b505af115801561189d573d6000803e3d6000fd5b50505050505050505050565b60006118d5827f1d1d8b630000000000000000000000000000000000000000000000000000000061217c565b806119055750611905827fec4fc8e30000000000000000000000000000000000000000000000000000000061217c565b92915050565b6000611937837f1d1d8b630000000000000000000000000000000000000000000000000000000061217c565b156119e0578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015611987573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ab9190612d72565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050611905565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611987573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052610aa49084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915261219f565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f3ceee06c1e37648fcbb6ed52e17b3e1f275a1f8c7b22a84b2b84732431e046b3868686604051611b7793929190612e85565b60405180910390a46110138686868686866122ab565b600080611b98612333565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2ac69ee804d9a7a0984249f508dfab7cb2534b465b6ce1580f99a38ba9c5e6318484604051611c2b929190612ec3565b60405180910390a36105b2848484846123d0565b6000806000835160208501868989f195945050505050565b3415611ce5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5374616e646172644272696467653a2063616e6e6f742073656e642076616c7560448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610214565b611cee876118a9565b15611e3c57611cfd878761190b565b611daf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a401610214565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b158015611e1f57600080fd5b505af1158015611e33573d6000803e3d6000fd5b50505050611ed0565b611e5e73ffffffffffffffffffffffffffffffffffffffff881686308661243d565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054611e9c908490612edc565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b611ede87878787878661249b565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9216907f0166a07a0000000000000000000000000000000000000000000000000000000090611f42908b908d908c908c908c908b90602401612ef4565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b9092168252611fd592918790600401612e40565b600060405180830381600087803b158015611fef57600080fd5b505af1158015612003573d6000803e3d6000fd5b5050505050505050505050565b6109c987878787878787611c57565b600054610100900460ff166120b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610214565b6003805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560048054929093169116179055565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f35d79ab81f2b2017e19afb5c5571778877782d7a8786f5907f93b0f4702f4f238484604051612168929190612ec3565b60405180910390a36105b284848484612529565b600061218783612588565b8015612198575061219883836125ec565b9392505050565b6000612201826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166126bb9092919063ffffffff16565b805190915015610aa4578080602001905181019061221f9190612dd5565b610aa4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610214565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd86868660405161232393929190612e85565b60405180910390a4505050505050565b603354604080517f4397dfef0000000000000000000000000000000000000000000000000000000081528151600093849373ffffffffffffffffffffffffffffffffffffffff90911692634397dfef92600480830193928290030181865afa1580156123a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123c79190612f4f565b90939092509050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d848460405161242f929190612ec3565b60405180910390a350505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526105b29085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611a7d565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f718594027abd4eaed59f95162563e0cc6d0e8d5b86b1c7be8b1b0ac3343d039686868660405161251393929190612e85565b60405180910390a46110138686868686866126d2565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af5848460405161242f929190612ec3565b60006125b4827f01ffc9a7000000000000000000000000000000000000000000000000000000006125ec565b801561190557506125e5827fffffffff000000000000000000000000000000000000000000000000000000006125ec565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d915060005190508280156126a4575060208210155b80156126b05750600081115b979650505050505050565b60606126ca848460008561274a565b949350505050565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf86868660405161232393929190612e85565b6060824710156127dc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610214565b73ffffffffffffffffffffffffffffffffffffffff85163b61285a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610214565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516128839190612f84565b60006040518083038185875af1925050503d80600081146128c0576040519150601f19603f3d011682016040523d82523d6000602084013e6128c5565b606091505b50915091506126b0828286606083156128df575081612198565b8251156128ef5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102149190612bf5565b73ffffffffffffffffffffffffffffffffffffffff8116811461294557600080fd5b50565b60008083601f84011261295a57600080fd5b50813567ffffffffffffffff81111561297257600080fd5b60208301915083602082850101111561298a57600080fd5b9250929050565b600080600080600080600060c0888a0312156129ac57600080fd5b87356129b781612923565b965060208801356129c781612923565b955060408801356129d781612923565b945060608801356129e781612923565b93506080880135925060a088013567ffffffffffffffff811115612a0a57600080fd5b612a168a828b01612948565b989b979a50959850939692959293505050565b803563ffffffff81168114612a3d57600080fd5b919050565b600080600060408486031215612a5757600080fd5b612a6084612a29565b9250602084013567ffffffffffffffff811115612a7c57600080fd5b612a8886828701612948565b9497909650939450505050565b600080600080600060808688031215612aad57600080fd5b8535612ab881612923565b94506020860135612ac881612923565b935060408601359250606086013567ffffffffffffffff811115612aeb57600080fd5b612af788828901612948565b969995985093965092949392505050565b600080600080600080600060c0888a031215612b2357600080fd5b8735612b2e81612923565b96506020880135612b3e81612923565b95506040880135612b4e81612923565b945060608801359350612b6360808901612a29565b925060a088013567ffffffffffffffff811115612a0a57600080fd5b60005b83811015612b9a578181015183820152602001612b82565b838111156105b25750506000910152565b60008151808452612bc3816020860160208601612b7f565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006121986020830184612bab565b60008060008060008060a08789031215612c2157600080fd5b8635612c2c81612923565b95506020870135612c3c81612923565b945060408701359350612c5160608801612a29565b9250608087013567ffffffffffffffff811115612c6d57600080fd5b612c7989828a01612948565b979a9699509497509295939492505050565b60008060408385031215612c9e57600080fd5b8235612ca981612923565b91506020830135612cb981612923565b809150509250929050565b60008060008060608587031215612cda57600080fd5b8435612ce581612923565b9350612cf360208601612a29565b9250604085013567ffffffffffffffff811115612d0f57600080fd5b612d1b87828801612948565b95989497509550505050565b600080600060608486031215612d3c57600080fd5b8335612d4781612923565b92506020840135612d5781612923565b91506040840135612d6781612923565b809150509250925092565b600060208284031215612d8457600080fd5b815161219881612923565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015612dd057612dd0612d8f565b500390565b600060208284031215612de757600080fd5b8151801515811461219857600080fd5b600073ffffffffffffffffffffffffffffffffffffffff808716835280861660208401525083604083015260806060830152612e366080830184612bab565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff84168152606060208201526000612e6f6060830185612bab565b905063ffffffff83166040830152949350505050565b73ffffffffffffffffffffffffffffffffffffffff84168152826020820152606060408201526000612eba6060830184612bab565b95945050505050565b8281526040602082015260006126ca6040830184612bab565b60008219821115612eef57612eef612d8f565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a0830152612f4360c0830184612bab565b98975050505050505050565b60008060408385031215612f6257600080fd5b8251612f6d81612923565b602084015190925060ff81168114612cb957600080fd5b60008251612f96818460208701612b7f565b919091019291505056fea164736f6c634300080f000a"; bytes internal constant l1ERC721BridgeCode = - hex"608060405234801561001057600080fd5b50600436106100d45760003560e01c80635d93a3fc11610081578063927ede2d1161005b578063927ede2d14610231578063aa5574521461024f578063c89701a21461026257600080fd5b80635d93a3fc146101cc578063761f4493146102005780637f46ddb21461021357600080fd5b8063485cc955116100b2578063485cc9551461015857806354fd4d501461016b5780635c975abb146101b457600080fd5b806335e80ab3146100d95780633687011a146101235780633cb747bf14610138575b600080fd5b6032546100f99073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b610136610131366004610fe1565b610282565b005b6001546100f99073ffffffffffffffffffffffffffffffffffffffff1681565b610136610166366004611064565b61032e565b6101a76040518060400160405280600c81526020017f322e312e312b626574612e31000000000000000000000000000000000000000081525081565b60405161011a9190611108565b6101bc610518565b604051901515815260200161011a565b6101bc6101da366004611122565b603160209081526000938452604080852082529284528284209052825290205460ff1681565b61013661020e366004611163565b6105b1565b60025473ffffffffffffffffffffffffffffffffffffffff166100f9565b60015473ffffffffffffffffffffffffffffffffffffffff166100f9565b61013661025d3660046111fb565b610a58565b6002546100f99073ffffffffffffffffffffffffffffffffffffffff1681565b333b15610316576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4552433732314272696467653a206163636f756e74206973206e6f742065787460448201527f65726e616c6c79206f776e65640000000000000000000000000000000000000060648201526084015b60405180910390fd5b6103268686333388888888610b30565b505050505050565b600054610100900460ff161580801561034e5750600054600160ff909116105b806103685750303b158015610368575060005460ff166001145b6103f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161030d565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561045257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84161790556104b083734200000000000000000000000000000000000014610e70565b801561051357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b603254604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa158015610588573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ac9190611272565b905090565b60015473ffffffffffffffffffffffffffffffffffffffff16331480156106865750600254600154604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9384169390921691636e296e45916004808201926020929091908290030181865afa15801561064a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061066e9190611294565b73ffffffffffffffffffffffffffffffffffffffff16145b610712576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4552433732314272696467653a2066756e6374696f6e2063616e206f6e6c792060448201527f62652063616c6c65642066726f6d20746865206f746865722062726964676500606482015260840161030d565b61071a610518565b15610781576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4c314552433732314272696467653a2070617573656400000000000000000000604482015260640161030d565b3073ffffffffffffffffffffffffffffffffffffffff881603610826576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4c314552433732314272696467653a206c6f63616c20746f6b656e2063616e6e60448201527f6f742062652073656c6600000000000000000000000000000000000000000000606482015260840161030d565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152603160209081526040808320938a1683529281528282208683529052205460ff1615156001146108f5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4c314552433732314272696467653a20546f6b656e204944206973206e6f742060448201527f657363726f77656420696e20746865204c312042726964676500000000000000606482015260840161030d565b73ffffffffffffffffffffffffffffffffffffffff87811660008181526031602090815260408083208b8616845282528083208884529091529081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517f42842e0e000000000000000000000000000000000000000000000000000000008152306004820152918616602483015260448201859052906342842e0e90606401600060405180830381600087803b1580156109b557600080fd5b505af11580156109c9573d6000803e3d6000fd5b505050508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167f1f39bf6707b5d608453e0ae4c067b562bcc4c85c0f562ef5d2c774d2e7f131ac87878787604051610a4794939291906112fa565b60405180910390a450505050505050565b73ffffffffffffffffffffffffffffffffffffffff8516610afb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4552433732314272696467653a206e667420726563697069656e742063616e6e60448201527f6f74206265206164647265737328302900000000000000000000000000000000606482015260840161030d565b610b0b8787338888888888610b30565b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b73ffffffffffffffffffffffffffffffffffffffff8716610bd3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f4c314552433732314272696467653a2072656d6f746520746f6b656e2063616e60448201527f6e6f742062652061646472657373283029000000000000000000000000000000606482015260840161030d565b600063761f449360e01b888a8989898888604051602401610bfa979695949392919061133a565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000959095169490941790935273ffffffffffffffffffffffffffffffffffffffff8c81166000818152603186528381208e8416825286528381208b82529095529382902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905590517f23b872dd000000000000000000000000000000000000000000000000000000008152908a166004820152306024820152604481018890529092506323b872dd90606401600060405180830381600087803b158015610d3a57600080fd5b505af1158015610d4e573d6000803e3d6000fd5b50506001546002546040517f3dbb202b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9283169450633dbb202b9350610db1929091169085908990600401611397565b600060405180830381600087803b158015610dcb57600080fd5b505af1158015610ddf573d6000803e3d6000fd5b505050508673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff167fb7460e2a880f256ebef3406116ff3eee0cee51ebccdc2a40698f87ebb2e9c1a589898888604051610e5d94939291906112fa565b60405180910390a4505050505050505050565b600054610100900460ff16610f07576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161030d565b6001805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560028054929093169116179055565b73ffffffffffffffffffffffffffffffffffffffff81168114610f7c57600080fd5b50565b803563ffffffff81168114610f9357600080fd5b919050565b60008083601f840112610faa57600080fd5b50813567ffffffffffffffff811115610fc257600080fd5b602083019150836020828501011115610fda57600080fd5b9250929050565b60008060008060008060a08789031215610ffa57600080fd5b863561100581610f5a565b9550602087013561101581610f5a565b94506040870135935061102a60608801610f7f565b9250608087013567ffffffffffffffff81111561104657600080fd5b61105289828a01610f98565b979a9699509497509295939492505050565b6000806040838503121561107757600080fd5b823561108281610f5a565b9150602083013561109281610f5a565b809150509250929050565b6000815180845260005b818110156110c3576020818501810151868301820152016110a7565b818111156110d5576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061111b602083018461109d565b9392505050565b60008060006060848603121561113757600080fd5b833561114281610f5a565b9250602084013561115281610f5a565b929592945050506040919091013590565b600080600080600080600060c0888a03121561117e57600080fd5b873561118981610f5a565b9650602088013561119981610f5a565b955060408801356111a981610f5a565b945060608801356111b981610f5a565b93506080880135925060a088013567ffffffffffffffff8111156111dc57600080fd5b6111e88a828b01610f98565b989b979a50959850939692959293505050565b600080600080600080600060c0888a03121561121657600080fd5b873561122181610f5a565b9650602088013561123181610f5a565b9550604088013561124181610f5a565b94506060880135935061125660808901610f7f565b925060a088013567ffffffffffffffff8111156111dc57600080fd5b60006020828403121561128457600080fd5b8151801515811461111b57600080fd5b6000602082840312156112a657600080fd5b815161111b81610f5a565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff851681528360208201526060604082015260006113306060830184866112b1565b9695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff808a1683528089166020840152808816604084015280871660608401525084608083015260c060a083015261138a60c0830184866112b1565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006113c6606083018561109d565b905063ffffffff8316604083015294935050505056fea164736f6c634300080f000a"; + hex"608060405234801561001057600080fd5b50600436106100d45760003560e01c80635d93a3fc11610081578063927ede2d1161005b578063927ede2d14610231578063aa5574521461024f578063c89701a21461026257600080fd5b80635d93a3fc146101cc578063761f4493146102005780637f46ddb21461021357600080fd5b8063485cc955116100b2578063485cc9551461015857806354fd4d501461016b5780635c975abb146101b457600080fd5b806335e80ab3146100d95780633687011a146101235780633cb747bf14610138575b600080fd5b6032546100f99073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b610136610131366004610fe1565b610282565b005b6001546100f99073ffffffffffffffffffffffffffffffffffffffff1681565b610136610166366004611064565b61032e565b6101a76040518060400160405280600c81526020017f322e312e312d626574612e32000000000000000000000000000000000000000081525081565b60405161011a9190611108565b6101bc610518565b604051901515815260200161011a565b6101bc6101da366004611122565b603160209081526000938452604080852082529284528284209052825290205460ff1681565b61013661020e366004611163565b6105b1565b60025473ffffffffffffffffffffffffffffffffffffffff166100f9565b60015473ffffffffffffffffffffffffffffffffffffffff166100f9565b61013661025d3660046111fb565b610a58565b6002546100f99073ffffffffffffffffffffffffffffffffffffffff1681565b333b15610316576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4552433732314272696467653a206163636f756e74206973206e6f742065787460448201527f65726e616c6c79206f776e65640000000000000000000000000000000000000060648201526084015b60405180910390fd5b6103268686333388888888610b30565b505050505050565b600054610100900460ff161580801561034e5750600054600160ff909116105b806103685750303b158015610368575060005460ff166001145b6103f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161030d565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561045257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84161790556104b083734200000000000000000000000000000000000014610e70565b801561051357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b603254604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa158015610588573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ac9190611272565b905090565b60015473ffffffffffffffffffffffffffffffffffffffff16331480156106865750600254600154604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9384169390921691636e296e45916004808201926020929091908290030181865afa15801561064a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061066e9190611294565b73ffffffffffffffffffffffffffffffffffffffff16145b610712576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4552433732314272696467653a2066756e6374696f6e2063616e206f6e6c792060448201527f62652063616c6c65642066726f6d20746865206f746865722062726964676500606482015260840161030d565b61071a610518565b15610781576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4c314552433732314272696467653a2070617573656400000000000000000000604482015260640161030d565b3073ffffffffffffffffffffffffffffffffffffffff881603610826576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4c314552433732314272696467653a206c6f63616c20746f6b656e2063616e6e60448201527f6f742062652073656c6600000000000000000000000000000000000000000000606482015260840161030d565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152603160209081526040808320938a1683529281528282208683529052205460ff1615156001146108f5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4c314552433732314272696467653a20546f6b656e204944206973206e6f742060448201527f657363726f77656420696e20746865204c312042726964676500000000000000606482015260840161030d565b73ffffffffffffffffffffffffffffffffffffffff87811660008181526031602090815260408083208b8616845282528083208884529091529081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517f42842e0e000000000000000000000000000000000000000000000000000000008152306004820152918616602483015260448201859052906342842e0e90606401600060405180830381600087803b1580156109b557600080fd5b505af11580156109c9573d6000803e3d6000fd5b505050508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167f1f39bf6707b5d608453e0ae4c067b562bcc4c85c0f562ef5d2c774d2e7f131ac87878787604051610a4794939291906112fa565b60405180910390a450505050505050565b73ffffffffffffffffffffffffffffffffffffffff8516610afb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4552433732314272696467653a206e667420726563697069656e742063616e6e60448201527f6f74206265206164647265737328302900000000000000000000000000000000606482015260840161030d565b610b0b8787338888888888610b30565b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b73ffffffffffffffffffffffffffffffffffffffff8716610bd3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f4c314552433732314272696467653a2072656d6f746520746f6b656e2063616e60448201527f6e6f742062652061646472657373283029000000000000000000000000000000606482015260840161030d565b600063761f449360e01b888a8989898888604051602401610bfa979695949392919061133a565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000959095169490941790935273ffffffffffffffffffffffffffffffffffffffff8c81166000818152603186528381208e8416825286528381208b82529095529382902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905590517f23b872dd000000000000000000000000000000000000000000000000000000008152908a166004820152306024820152604481018890529092506323b872dd90606401600060405180830381600087803b158015610d3a57600080fd5b505af1158015610d4e573d6000803e3d6000fd5b50506001546002546040517f3dbb202b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9283169450633dbb202b9350610db1929091169085908990600401611397565b600060405180830381600087803b158015610dcb57600080fd5b505af1158015610ddf573d6000803e3d6000fd5b505050508673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff167fb7460e2a880f256ebef3406116ff3eee0cee51ebccdc2a40698f87ebb2e9c1a589898888604051610e5d94939291906112fa565b60405180910390a4505050505050505050565b600054610100900460ff16610f07576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161030d565b6001805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560028054929093169116179055565b73ffffffffffffffffffffffffffffffffffffffff81168114610f7c57600080fd5b50565b803563ffffffff81168114610f9357600080fd5b919050565b60008083601f840112610faa57600080fd5b50813567ffffffffffffffff811115610fc257600080fd5b602083019150836020828501011115610fda57600080fd5b9250929050565b60008060008060008060a08789031215610ffa57600080fd5b863561100581610f5a565b9550602087013561101581610f5a565b94506040870135935061102a60608801610f7f565b9250608087013567ffffffffffffffff81111561104657600080fd5b61105289828a01610f98565b979a9699509497509295939492505050565b6000806040838503121561107757600080fd5b823561108281610f5a565b9150602083013561109281610f5a565b809150509250929050565b6000815180845260005b818110156110c3576020818501810151868301820152016110a7565b818111156110d5576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061111b602083018461109d565b9392505050565b60008060006060848603121561113757600080fd5b833561114281610f5a565b9250602084013561115281610f5a565b929592945050506040919091013590565b600080600080600080600060c0888a03121561117e57600080fd5b873561118981610f5a565b9650602088013561119981610f5a565b955060408801356111a981610f5a565b945060608801356111b981610f5a565b93506080880135925060a088013567ffffffffffffffff8111156111dc57600080fd5b6111e88a828b01610f98565b989b979a50959850939692959293505050565b600080600080600080600060c0888a03121561121657600080fd5b873561122181610f5a565b9650602088013561123181610f5a565b9550604088013561124181610f5a565b94506060880135935061125660808901610f7f565b925060a088013567ffffffffffffffff8111156111dc57600080fd5b60006020828403121561128457600080fd5b8151801515811461111b57600080fd5b6000602082840312156112a657600080fd5b815161111b81610f5a565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff851681528360208201526060604082015260006113306060830184866112b1565b9695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff808a1683528089166020840152808816604084015280871660608401525084608083015260c060a083015261138a60c0830184866112b1565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006113c6606083018561109d565b905063ffffffff8316604083015294935050505056fea164736f6c634300080f000a"; bytes internal constant optimismPortalCode = - hex"6080604052600436106101635760003560e01c80638c3152e9116100c0578063b69ef8a811610074578063cff0ab9611610059578063cff0ab9614610444578063e965084c146104e5578063e9e05c421461057157600080fd5b8063b69ef8a814610401578063c0c53b8b1461042457600080fd5b80639bf62d82116100a55780639bf62d821461036b578063a14238e714610398578063a35d99df146103c857600080fd5b80638c3152e91461031e5780639b5f694a1461033e57600080fd5b806354fd4d50116101175780636dbffb78116100fc5780636dbffb78146102de57806371cfaa3f146102fe5780638b4c40b01461018857600080fd5b806354fd4d501461026d5780635c975abb146102b957600080fd5b806335e80ab31161014857806335e80ab314610206578063452a9320146102385780634870496f1461024d57600080fd5b8063149f2f221461018f57806333d7e2bd146101af57600080fd5b3661018a576101883334620186a060006040518060200160405280600081525061057f565b005b600080fd5b34801561019b57600080fd5b506101886101aa366004614b97565b610624565b3480156101bb57600080fd5b506037546101dc9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561021257600080fd5b506035546101dc90610100900473ffffffffffffffffffffffffffffffffffffffff1681565b34801561024457600080fd5b506101dc610865565b34801561025957600080fd5b50610188610268366004614ccb565b6108fd565b34801561027957600080fd5b50604080518082018252600c81527f322e382e312d626574612e310000000000000000000000000000000000000000602082015290516101fd9190614e1d565b3480156102c557600080fd5b506102ce610eaa565b60405190151581526020016101fd565b3480156102ea57600080fd5b506102ce6102f9366004614e30565b610f3d565b34801561030a57600080fd5b50610188610319366004614e58565b610ff8565b34801561032a57600080fd5b50610188610339366004614e9e565b6111ba565b34801561034a57600080fd5b506036546101dc9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561037757600080fd5b506032546101dc9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156103a457600080fd5b506102ce6103b3366004614e30565b60336020526000908152604090205460ff1681565b3480156103d457600080fd5b506103e86103e3366004614edb565b611c3c565b60405167ffffffffffffffff90911681526020016101fd565b34801561040d57600080fd5b50610416611c55565b6040519081526020016101fd565b34801561043057600080fd5b5061018861043f366004614ef6565b611caf565b34801561045057600080fd5b506001546104ac906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff92831660208501529116908201526060016101fd565b3480156104f157600080fd5b50610543610500366004614e30565b603460205260009081526040902080546001909101546fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041683565b604080519384526fffffffffffffffffffffffffffffffff92831660208501529116908201526060016101fd565b61018861057f366004614f41565b8260005a9050600061058f611f19565b50905073ffffffffffffffffffffffffffffffffffffffff811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee148015906105cb57503415155b15610602576040517ff2365b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610610883489898989611fb6565b5061061b8282612162565b50505050505050565b8260005a90506000610634611f19565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8216016106a6576040517f0eaf3c0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87603d60008282546106b89190614fed565b90915550506040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa15801561072a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061074e9190615005565b905061077273ffffffffffffffffffffffffffffffffffffffff831633308c61242f565b61077c8982614fed565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa1580156107e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061080a9190615005565b14610841576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61084f8a8a8a8a8a8a611fb6565b505061085b8282612162565b5050505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f8919061501e565b905090565b610905610eaa565b1561093c576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff16036109a5576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6036546040517fa25ae5570000000000000000000000000000000000000000000000000000000081526004810186905260009173ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa158015610a15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a39919061505b565b519050610a53610a4e368690038601866150c0565b61250b565b8114610ae6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f7074696d69736d506f7274616c3a20696e76616c6964206f7574707574207260448201527f6f6f742070726f6f66000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000610af187612567565b6000818152603460209081526040918290208251606081018452815481526001909101546fffffffffffffffffffffffffffffffff8082169383018490527001000000000000000000000000000000009091041692810192909252919250901580610c075750805160365460408084015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff909116600482015273ffffffffffffffffffffffffffffffffffffffff9091169063a25ae55790602401606060405180830381865afa158015610bdf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c03919061505b565b5114155b610c93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173682060448201527f68617320616c7265616479206265656e2070726f76656e0000000000000000006064820152608401610add565b60408051602081018490526000918101829052606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201209083018190529250610d5c9101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f0100000000000000000000000000000000000000000000000000000000000000602083015290610d52888a615126565b8a60400135612597565b610de8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a20696e76616c696420776974686472617760448201527f616c20696e636c7573696f6e2070726f6f6600000000000000000000000000006064820152608401610add565b604080516060810182528581526fffffffffffffffffffffffffffffffff42811660208084019182528c831684860190815260008981526034835286812095518655925190518416700100000000000000000000000000000000029316929092176001909301929092558b830151908c0151925173ffffffffffffffffffffffffffffffffffffffff918216939091169186917f67a6208cfcc0801d50f6cbe764733f4fddf66ac0b04442061a8a8c0cb6b63f629190a4505050505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f19573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f891906151aa565b6036546040517fa25ae55700000000000000000000000000000000000000000000000000000000815260048101839052600091610ff29173ffffffffffffffffffffffffffffffffffffffff9091169063a25ae55790602401606060405180830381865afa158015610fb3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fd7919061505b565b602001516fffffffffffffffffffffffffffffffff166125bb565b92915050565b60375473ffffffffffffffffffffffffffffffffffffffff163314611049576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61105562030d40612661565b60405173ffffffffffffffffffffffffffffffffffffffff8516602482015260ff8416604482015260648101839052608481018290526000907342000000000000000000000000000000000000159073deaddeaddeaddeaddeaddeaddeaddeaddead0001907fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32908490819062030d4090829060a401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f71cfaa3f000000000000000000000000000000000000000000000000000000001790529051611172969594939291016151c7565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526111aa91614e1d565b60405180910390a450505050565b565b6111c2610eaa565b156111f9576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60325473ffffffffffffffffffffffffffffffffffffffff1661dead1461124c576040517f9396d15600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061125782612567565b60008181526034602090815260408083208151606081018352815481526001909101546fffffffffffffffffffffffffffffffff80821694830185905270010000000000000000000000000000000090910416918101919091529293509003611342576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206e60448201527f6f74206265656e2070726f76656e2079657400000000000000000000000000006064820152608401610add565b603660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663887862726040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113d39190615005565b81602001516fffffffffffffffffffffffffffffffff16101561149e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604b60248201527f4f7074696d69736d506f7274616c3a207769746864726177616c2074696d657360448201527f74616d70206c657373207468616e204c32204f7261636c65207374617274696e60648201527f672074696d657374616d70000000000000000000000000000000000000000000608482015260a401610add565b6114bd81602001516fffffffffffffffffffffffffffffffff166125bb565b61156f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604560248201527f4f7074696d69736d506f7274616c3a2070726f76656e2077697468647261776160448201527f6c2066696e616c697a6174696f6e20706572696f6420686173206e6f7420656c60648201527f6170736564000000000000000000000000000000000000000000000000000000608482015260a401610add565b60365460408281015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff909116600482015260009173ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa1580156115f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061161a919061505b565b82518151919250146116d4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4f7074696d69736d506f7274616c3a206f757470757420726f6f742070726f7660448201527f656e206973206e6f74207468652073616d652061732063757272656e74206f7560648201527f7470757420726f6f740000000000000000000000000000000000000000000000608482015260a401610add565b6116f381602001516fffffffffffffffffffffffffffffffff166125bb565b6117a5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4f7074696d69736d506f7274616c3a206f75747075742070726f706f73616c2060448201527f66696e616c697a6174696f6e20706572696f6420686173206e6f7420656c617060648201527f7365640000000000000000000000000000000000000000000000000000000000608482015260a401610add565b60008381526033602052604090205460ff1615611844576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206160448201527f6c7265616479206265656e2066696e616c697a656400000000000000000000006064820152608401610add565b6000838152603360209081526040822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558501516032805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff0000000000000000000000000000000000000000909216919091179055806118cf611f19565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8216016119325761192b8660400151876080015188606001518960a001516126c3565b9150611b85565b8073ffffffffffffffffffffffffffffffffffffffff16866040015173ffffffffffffffffffffffffffffffffffffffff160361199b576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606086015115611b5c578560600151603d60008282546119bb919061522c565b90915550506040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015611a2d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a519190615005565b9050611a86876040015188606001518473ffffffffffffffffffffffffffffffffffffffff166127219092919063ffffffff16565b6060870151611a95908261522c565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015611aff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b239190615005565b14611b5a576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60a08601515115611b805761192b8660400151876080015160008960a001516126c3565b600191505b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405185907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b90611be790851515815260200190565b60405180910390a281158015611bfd5750326001145b15611c34576040517feeae4ed300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000611c49826010615243565b610ff290615208615273565b600080611c60611f19565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff821601611ca7574791505090565b5050603d5490565b600054610100900460ff1615808015611ccf5750600054600160ff909116105b80611ce95750303b158015611ce9575060005460ff166001145b611d75576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610add565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015611dd357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603680547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff8781169190911790925560378054909116858316179055603580547fffffffffffffffffffffff0000000000000000000000000000000000000000ff166101008584160217905560325416611e8c57603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790555b611e9461277c565b8015611ef757600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b603754604080517f4397dfef0000000000000000000000000000000000000000000000000000000081528151600093849373ffffffffffffffffffffffffffffffffffffffff90911692634397dfef92600480830193928290030181865afa158015611f89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fad919061529f565b90939092509050565b818015611fd8575073ffffffffffffffffffffffffffffffffffffffff861615155b1561200f576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6120198151611c3c565b67ffffffffffffffff168367ffffffffffffffff161015612066576040517f4929b80800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6201d4c0815111156120a4576040517f73052b0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b333281146120c5575033731111000000000000000000000000000000001111015b600086868686866040516020016120e09594939291906151c7565b604051602081830303815290604052905060008873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32846040516121509190614e1d565b60405180910390a45050505050505050565b600154600090612198907801000000000000000000000000000000000000000000000000900467ffffffffffffffff164361522c565b905060006121a461288f565b90506000816020015160ff16826000015163ffffffff166121c59190615308565b905082156122fc576001546000906121fc908390700100000000000000000000000000000000900467ffffffffffffffff16615370565b90506000836040015160ff168361221391906153e4565b6001546122339084906fffffffffffffffffffffffffffffffff166153e4565b61223d9190615308565b60015490915060009061228e906122679084906fffffffffffffffffffffffffffffffff166154a0565b866060015163ffffffff168760a001516fffffffffffffffffffffffffffffffff16612950565b905060018611156122bd576122ba61226782876040015160ff1660018a6122b5919061522c565b61296f565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b6001805486919060109061232f908490700100000000000000000000000000000000900467ffffffffffffffff16615273565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550816000015163ffffffff16600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff1613156123bc576040517f77ebef4d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001546000906123e8906fffffffffffffffffffffffffffffffff1667ffffffffffffffff8816615514565b905060006123fa48633b9aca006129c4565b6124049083615551565b905060005a612413908861522c565b90508082111561085b5761085b61242a828461522c565b6129db565b60405173ffffffffffffffffffffffffffffffffffffffff80851660248301528316604482015260648101829052611ef79085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612a04565b6000816000015182602001518360400151846060015160405160200161254a949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b80516020808301516040808501516060860151608087015160a0880151935160009761254a979096959101615565565b6000806125a386612b10565b90506125b181868686612b42565b9695505050505050565b603654604080517ff4daa291000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163f4daa2919160048083019260209291908290030181865afa15801561262b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061264f9190615005565b6126599083614fed565b421192915050565b6001805463ffffffff8316919060109061269a908490700100000000000000000000000000000000900467ffffffffffffffff16615273565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555050565b60008060006126d3866000612b72565b905080612709576308c379a06000526020805278185361666543616c6c3a204e6f7420656e6f756768206761736058526064601cfd5b600080855160208701888b5af1979650505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526127779084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401612489565b505050565b600054610100900460ff16612813576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610add565b6001547801000000000000000000000000000000000000000000000000900467ffffffffffffffff166000036111b85760408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b6040805160c08082018352600080835260208301819052828401819052606083018190526080830181905260a083015260375483517fcc731b020000000000000000000000000000000000000000000000000000000081529351929373ffffffffffffffffffffffffffffffffffffffff9091169263cc731b02926004808401939192918290030181865afa15801561292c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f891906155d0565b600061296561295f8585612b90565b83612ba0565b90505b9392505050565b6000670de0b6b3a76400006129b06129878583615308565b61299990670de0b6b3a7640000615370565b6129ab85670de0b6b3a76400006153e4565b612baf565b6129ba90866153e4565b6129659190615308565b6000818310156129d45781612968565b5090919050565b6000805a90505b825a6129ee908361522c565b1015612777576129fd82615673565b91506129e2565b6000612a66826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612be09092919063ffffffff16565b8051909150156127775780806020019051810190612a8491906151aa565b612777576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610add565b60608180519060200120604051602001612b2c91815260200190565b6040516020818303038152906040529050919050565b6000612b6984612b53878686612bef565b8051602091820120825192909101919091201490565b95945050505050565b600080603f83619c4001026040850201603f5a021015949350505050565b6000818312156129d45781612968565b60008183126129d45781612968565b6000612968670de0b6b3a764000083612bc78661366d565b612bd191906153e4565b612bdb9190615308565b6138b1565b60606129658484600085613af0565b60606000845111612c5c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4d65726b6c65547269653a20656d707479206b657900000000000000000000006044820152606401610add565b6000612c6784613c86565b90506000612c7486613d72565b9050600084604051602001612c8b91815260200190565b60405160208183030381529060405290506000805b84518110156135e4576000858281518110612cbd57612cbd6156ab565b602002602001015190508451831115612d58576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4d65726b6c65547269653a206b657920696e646578206578636565647320746f60448201527f74616c206b6579206c656e6774680000000000000000000000000000000000006064820152608401610add565b82600003612e115780518051602091820120604051612da692612d8092910190815260200190565b604051602081830303815290604052858051602091820120825192909101919091201490565b612e0c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4d65726b6c65547269653a20696e76616c696420726f6f7420686173680000006044820152606401610add565b612f68565b805151602011612ec75780518051602091820120604051612e3b92612d8092910190815260200190565b612e0c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d65726b6c65547269653a20696e76616c6964206c6172676520696e7465726e60448201527f616c2068617368000000000000000000000000000000000000000000000000006064820152608401610add565b805184516020808701919091208251919092012014612f68576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4d65726b6c65547269653a20696e76616c696420696e7465726e616c206e6f6460448201527f65206861736800000000000000000000000000000000000000000000000000006064820152608401610add565b612f7460106001614fed565b8160200151510361315057845183036130e857612fae8160200151601081518110612fa157612fa16156ab565b6020026020010151613dd5565b96506000875111613041576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603b60248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286272616e63682900000000006064820152608401610add565b6001865161304f919061522c565b82146130dd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286272616e6368290000000000006064820152608401610add565b505050505050612968565b60008584815181106130fc576130fc6156ab565b602001015160f81c60f81b60f81c9050600082602001518260ff1681518110613127576131276156ab565b6020026020010151905061313a81613e89565b9550613147600186614fed565b945050506135d1565b60028160200151510361354957600061316882613eae565b905060008160008151811061317f5761317f6156ab565b016020015160f81c905060006131966002836156da565b6131a19060026156fc565b905060006131b2848360ff16613ed2565b905060006131c08a89613ed2565b905060006131ce8383613f08565b905080835114613260576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a20706174682072656d61696e646572206d7573742060448201527f736861726520616c6c206e6962626c65732077697468206b65790000000000006064820152608401610add565b60ff851660021480613275575060ff85166003145b15613464578082511461330a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f4d65726b6c65547269653a206b65792072656d61696e646572206d757374206260448201527f65206964656e746963616c20746f20706174682072656d61696e6465720000006064820152608401610add565b6133248760200151600181518110612fa157612fa16156ab565b9c5060008d51116133b7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286c65616629000000000000006064820152608401610add565b60018c516133c5919061522c565b8814613453576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286c6561662900000000000000006064820152608401610add565b505050505050505050505050612968565b60ff85161580613477575060ff85166001145b156134b6576134a38760200151600181518110613496576134966156ab565b6020026020010151613e89565b99506134af818a614fed565b985061353e565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4d65726b6c65547269653a2072656365697665642061206e6f6465207769746860448201527f20616e20756e6b6e6f776e2070726566697800000000000000000000000000006064820152608401610add565b5050505050506135d1565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4d65726b6c65547269653a20726563656976656420616e20756e70617273656160448201527f626c65206e6f64650000000000000000000000000000000000000000000000006064820152608401610add565b50806135dc81615673565b915050612ca0565b506040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4d65726b6c65547269653a2072616e206f7574206f662070726f6f6620656c6560448201527f6d656e74730000000000000000000000000000000000000000000000000000006064820152608401610add565b60008082136136d8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610add565b600060606136e584613fbc565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c182136138e257506000919050565b680755bf798b4a1bf1e58212613954576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4558505f4f564552464c4f5700000000000000000000000000000000000000006044820152606401610add565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b606082471015613b82576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610add565b73ffffffffffffffffffffffffffffffffffffffff85163b613c00576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610add565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051613c29919061571f565b60006040518083038185875af1925050503d8060008114613c66576040519150601f19603f3d011682016040523d82523d6000602084013e613c6b565b606091505b5091509150613c7b828286614092565b979650505050505050565b80516060908067ffffffffffffffff811115613ca457613ca4614a8b565b604051908082528060200260200182016040528015613ce957816020015b6040805180820190915260608082526020820152815260200190600190039081613cc25790505b50915060005b81811015613d6b576040518060400160405280858381518110613d1457613d146156ab565b60200260200101518152602001613d43868481518110613d3657613d366156ab565b60200260200101516140e5565b815250838281518110613d5857613d586156ab565b6020908102919091010152600101613cef565b5050919050565b606080604051905082518060011b603f8101601f1916830160405280835250602084016020830160005b83811015613dca578060011b82018184015160001a8060041c8253600f811660018301535050600101613d9c565b509295945050505050565b60606000806000613de5856140f8565b919450925090506000816001811115613e0057613e0061573b565b14613e37576040517f1ff9b2e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613e418284614fed565b855114613e7a576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612b6985602001518484614596565b60606020826000015110613ea557613ea082613dd5565b610ff2565b610ff28261462a565b6060610ff2613ecd8360200151600081518110612fa157612fa16156ab565b613d72565b606082518210613ef15750604080516020810190915260008152610ff2565b6129688383848651613f03919061522c565b614640565b6000808251845110613f1b578251613f1e565b83515b90505b8082108015613fa55750828281518110613f3d57613f3d6156ab565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916848381518110613f7c57613f7c6156ab565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b15613fb557816001019150613f21565b5092915050565b6000808211614027576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610add565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b606083156140a1575081612968565b8251156140b15782518084602001fd5b816040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610add9190614e1d565b6060610ff26140f383614818565b614885565b6000806000836000015160000361413b576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020840151805160001a607f811161416057600060016000945094509450505061458f565b60b7811161427657600061417560808361522c565b9050808760000151116141b4576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001838101517fff0000000000000000000000000000000000000000000000000000000000000016908214801561422c57507f80000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008216105b15614263576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506001955093506000925061458f915050565b60bf81116143d457600061428b60b78361522c565b9050808760000151116142ca576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff0000000000000000000000000000000000000000000000000000000000000016600081900361432c576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c60378111614374576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61437e8184614fed565b8951116143b7576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6143c2836001614fed565b975095506000945061458f9350505050565b60f781116144395760006143e960c08361522c565b905080876000015111614428576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60019550935084925061458f915050565b600061444660f78361522c565b905080876000015111614485576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff000000000000000000000000000000000000000000000000000000000000001660008190036144e7576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c6037811161452f576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6145398184614fed565b895111614572576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61457d836001614fed565b975095506001945061458f9350505050565b9193909250565b60608167ffffffffffffffff8111156145b1576145b1614a8b565b6040519080825280601f01601f1916602001820160405280156145db576020820181803683370190505b50905081156129685760006145f08486614fed565b90506020820160005b848110156146115782810151828201526020016145f9565b84811115614620576000858301525b5050509392505050565b6060610ff2826020015160008460000151614596565b60608182601f0110156146af576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610add565b82828401101561471b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610add565b81830184511015614788576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401610add565b6060821580156147a7576040519150600082526020820160405261480f565b6040519150601f8416801560200281840101858101878315602002848b0101015b818310156147e05780518352602092830192016147c8565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b60408051808201909152600080825260208201528151600003614867576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50604080518082019091528151815260209182019181019190915290565b60606000806000614895856140f8565b9194509250905060018160018111156148b0576148b061573b565b146148e7576040517f4b9c6abe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84516148f38385614fed565b1461492a576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808252610420820190925290816020015b60408051808201909152600080825260208201528152602001906001900390816149415790505093506000835b8651811015614a2f576000806149b46040518060400160405280858c60000151614998919061522c565b8152602001858c602001516149ad9190614fed565b90526140f8565b5091509150604051806040016040528083836149d09190614fed565b8152602001848b602001516149e59190614fed565b8152508885815181106149fa576149fa6156ab565b6020908102919091010152614a10600185614fed565b9350614a1c8183614fed565b614a269084614fed565b9250505061496e565b50845250919392505050565b73ffffffffffffffffffffffffffffffffffffffff81168114614a5d57600080fd5b50565b803567ffffffffffffffff81168114614a7857600080fd5b919050565b8015158114614a5d57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614b0157614b01614a8b565b604052919050565b600082601f830112614b1a57600080fd5b813567ffffffffffffffff811115614b3457614b34614a8b565b614b6560207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614aba565b818152846020838601011115614b7a57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060008060c08789031215614bb057600080fd5b8635614bbb81614a3b565b95506020870135945060408701359350614bd760608801614a60565b92506080870135614be781614a7d565b915060a087013567ffffffffffffffff811115614c0357600080fd5b614c0f89828a01614b09565b9150509295509295509295565b600060c08284031215614c2e57600080fd5b60405160c0810167ffffffffffffffff8282108183111715614c5257614c52614a8b565b816040528293508435835260208501359150614c6d82614a3b565b81602084015260408501359150614c8382614a3b565b816040840152606085013560608401526080850135608084015260a0850135915080821115614cb157600080fd5b50614cbe85828601614b09565b60a0830152505092915050565b600080600080600085870360e0811215614ce457600080fd5b863567ffffffffffffffff80821115614cfc57600080fd5b614d088a838b01614c1c565b97506020890135965060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc084011215614d4157600080fd5b60408901955060c0890135925080831115614d5b57600080fd5b828901925089601f840112614d6f57600080fd5b8235915080821115614d8057600080fd5b508860208260051b8401011115614d9657600080fd5b959894975092955050506020019190565b60005b83811015614dc2578181015183820152602001614daa565b83811115611ef75750506000910152565b60008151808452614deb816020860160208601614da7565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006129686020830184614dd3565b600060208284031215614e4257600080fd5b5035919050565b60ff81168114614a5d57600080fd5b60008060008060808587031215614e6e57600080fd5b8435614e7981614a3b565b93506020850135614e8981614e49565b93969395505050506040820135916060013590565b600060208284031215614eb057600080fd5b813567ffffffffffffffff811115614ec757600080fd5b614ed384828501614c1c565b949350505050565b600060208284031215614eed57600080fd5b61296882614a60565b600080600060608486031215614f0b57600080fd5b8335614f1681614a3b565b92506020840135614f2681614a3b565b91506040840135614f3681614a3b565b809150509250925092565b600080600080600060a08688031215614f5957600080fd5b8535614f6481614a3b565b945060208601359350614f7960408701614a60565b92506060860135614f8981614a7d565b9150608086013567ffffffffffffffff811115614fa557600080fd5b614fb188828901614b09565b9150509295509295909350565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561500057615000614fbe565b500190565b60006020828403121561501757600080fd5b5051919050565b60006020828403121561503057600080fd5b815161296881614a3b565b80516fffffffffffffffffffffffffffffffff81168114614a7857600080fd5b60006060828403121561506d57600080fd5b6040516060810181811067ffffffffffffffff8211171561509057615090614a8b565b604052825181526150a36020840161503b565b60208201526150b46040840161503b565b60408201529392505050565b6000608082840312156150d257600080fd5b6040516080810181811067ffffffffffffffff821117156150f5576150f5614a8b565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b600067ffffffffffffffff8084111561514157615141614a8b565b8360051b6020615152818301614aba565b86815291850191818101903684111561516a57600080fd5b865b8481101561519e578035868111156151845760008081fd5b61519036828b01614b09565b84525091830191830161516c565b50979650505050505050565b6000602082840312156151bc57600080fd5b815161296881614a7d565b8581528460208201527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b16604082015282151560f81b60488201526000825161521b816049850160208701614da7565b919091016049019695505050505050565b60008282101561523e5761523e614fbe565b500390565b600067ffffffffffffffff8083168185168183048111821515161561526a5761526a614fbe565b02949350505050565b600067ffffffffffffffff80831681851680830382111561529657615296614fbe565b01949350505050565b600080604083850312156152b257600080fd5b82516152bd81614a3b565b60208401519092506152ce81614e49565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082615317576153176152d9565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f80000000000000000000000000000000000000000000000000000000000000008314161561536b5761536b614fbe565b500590565b6000808312837f8000000000000000000000000000000000000000000000000000000000000000018312811516156153aa576153aa614fbe565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0183138116156153de576153de614fbe565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60008413600084138583048511828216161561542557615425614fbe565b7f8000000000000000000000000000000000000000000000000000000000000000600087128682058812818416161561546057615460614fbe565b6000871292508782058712848416161561547c5761547c614fbe565b8785058712818416161561549257615492614fbe565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038413811516156154da576154da614fbe565b827f800000000000000000000000000000000000000000000000000000000000000003841281161561550e5761550e614fbe565b50500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561554c5761554c614fbe565b500290565b600082615560576155606152d9565b500490565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a08301526155b060c0830184614dd3565b98975050505050505050565b805163ffffffff81168114614a7857600080fd5b600060c082840312156155e257600080fd5b60405160c0810181811067ffffffffffffffff8211171561560557615605614a8b565b604052615611836155bc565b8152602083015161562181614e49565b6020820152604083015161563481614e49565b6040820152615645606084016155bc565b6060820152615656608084016155bc565b608082015261566760a0840161503b565b60a08201529392505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036156a4576156a4614fbe565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060ff8316806156ed576156ed6152d9565b8060ff84160691505092915050565b600060ff821660ff84168082101561571657615716614fbe565b90039392505050565b60008251615731818460208701614da7565b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea164736f6c634300080f000a"; + hex"6080604052600436106101635760003560e01c80638c3152e9116100c0578063b69ef8a811610074578063cff0ab9611610059578063cff0ab9614610444578063e965084c146104e5578063e9e05c421461057157600080fd5b8063b69ef8a814610401578063c0c53b8b1461042457600080fd5b80639bf62d82116100a55780639bf62d821461036b578063a14238e714610398578063a35d99df146103c857600080fd5b80638c3152e91461031e5780639b5f694a1461033e57600080fd5b806354fd4d50116101175780636dbffb78116100fc5780636dbffb78146102de57806371cfaa3f146102fe5780638b4c40b01461018857600080fd5b806354fd4d501461026d5780635c975abb146102b957600080fd5b806335e80ab31161014857806335e80ab314610206578063452a9320146102385780634870496f1461024d57600080fd5b8063149f2f221461018f57806333d7e2bd146101af57600080fd5b3661018a576101883334620186a060006040518060200160405280600081525061057f565b005b600080fd5b34801561019b57600080fd5b506101886101aa366004614c13565b610624565b3480156101bb57600080fd5b506037546101dc9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561021257600080fd5b506035546101dc90610100900473ffffffffffffffffffffffffffffffffffffffff1681565b34801561024457600080fd5b506101dc610865565b34801561025957600080fd5b50610188610268366004614d47565b6108fd565b34801561027957600080fd5b50604080518082018252600c81527f322e382e312d626574612e320000000000000000000000000000000000000000602082015290516101fd9190614e99565b3480156102c557600080fd5b506102ce610eaa565b60405190151581526020016101fd565b3480156102ea57600080fd5b506102ce6102f9366004614eac565b610f3d565b34801561030a57600080fd5b50610188610319366004614ed4565b610ff8565b34801561032a57600080fd5b50610188610339366004614f1a565b6111ba565b34801561034a57600080fd5b506036546101dc9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561037757600080fd5b506032546101dc9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156103a457600080fd5b506102ce6103b3366004614eac565b60336020526000908152604090205460ff1681565b3480156103d457600080fd5b506103e86103e3366004614f57565b611c3c565b60405167ffffffffffffffff90911681526020016101fd565b34801561040d57600080fd5b50610416611c55565b6040519081526020016101fd565b34801561043057600080fd5b5061018861043f366004614f72565b611caf565b34801561045057600080fd5b506001546104ac906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff92831660208501529116908201526060016101fd565b3480156104f157600080fd5b50610543610500366004614eac565b603460205260009081526040902080546001909101546fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041683565b604080519384526fffffffffffffffffffffffffffffffff92831660208501529116908201526060016101fd565b61018861057f366004614fbd565b8260005a9050600061058f611f19565b50905073ffffffffffffffffffffffffffffffffffffffff811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee148015906105cb57503415155b15610602576040517ff2365b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610610883489898989611fb6565b5061061b8282612162565b50505050505050565b8260005a90506000610634611f19565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8216016106a6576040517f0eaf3c0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87603d60008282546106b89190615069565b90915550506040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa15801561072a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061074e9190615081565b905061077273ffffffffffffffffffffffffffffffffffffffff831633308c61242f565b61077c8982615069565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa1580156107e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061080a9190615081565b14610841576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61084f8a8a8a8a8a8a611fb6565b505061085b8282612162565b5050505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f8919061509a565b905090565b610905610eaa565b1561093c576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff16036109a5576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6036546040517fa25ae5570000000000000000000000000000000000000000000000000000000081526004810186905260009173ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa158015610a15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a3991906150d7565b519050610a53610a4e3686900386018661513c565b61250b565b8114610ae6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f7074696d69736d506f7274616c3a20696e76616c6964206f7574707574207260448201527f6f6f742070726f6f66000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000610af187612567565b6000818152603460209081526040918290208251606081018452815481526001909101546fffffffffffffffffffffffffffffffff8082169383018490527001000000000000000000000000000000009091041692810192909252919250901580610c075750805160365460408084015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff909116600482015273ffffffffffffffffffffffffffffffffffffffff9091169063a25ae55790602401606060405180830381865afa158015610bdf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c0391906150d7565b5114155b610c93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173682060448201527f68617320616c7265616479206265656e2070726f76656e0000000000000000006064820152608401610add565b60408051602081018490526000918101829052606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201209083018190529250610d5c9101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f0100000000000000000000000000000000000000000000000000000000000000602083015290610d52888a6151a2565b8a60400135612597565b610de8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a20696e76616c696420776974686472617760448201527f616c20696e636c7573696f6e2070726f6f6600000000000000000000000000006064820152608401610add565b604080516060810182528581526fffffffffffffffffffffffffffffffff42811660208084019182528c831684860190815260008981526034835286812095518655925190518416700100000000000000000000000000000000029316929092176001909301929092558b830151908c0151925173ffffffffffffffffffffffffffffffffffffffff918216939091169186917f67a6208cfcc0801d50f6cbe764733f4fddf66ac0b04442061a8a8c0cb6b63f629190a4505050505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f19573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f89190615226565b6036546040517fa25ae55700000000000000000000000000000000000000000000000000000000815260048101839052600091610ff29173ffffffffffffffffffffffffffffffffffffffff9091169063a25ae55790602401606060405180830381865afa158015610fb3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fd791906150d7565b602001516fffffffffffffffffffffffffffffffff166125bb565b92915050565b60375473ffffffffffffffffffffffffffffffffffffffff163314611049576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61105562030d40612661565b60405173ffffffffffffffffffffffffffffffffffffffff8516602482015260ff8416604482015260648101839052608481018290526000907342000000000000000000000000000000000000159073deaddeaddeaddeaddeaddeaddeaddeaddead0001907fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32908490819062030d4090829060a401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f71cfaa3f00000000000000000000000000000000000000000000000000000000179052905161117296959493929101615243565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526111aa91614e99565b60405180910390a450505050565b565b6111c2610eaa565b156111f9576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60325473ffffffffffffffffffffffffffffffffffffffff1661dead1461124c576040517f9396d15600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061125782612567565b60008181526034602090815260408083208151606081018352815481526001909101546fffffffffffffffffffffffffffffffff80821694830185905270010000000000000000000000000000000090910416918101919091529293509003611342576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206e60448201527f6f74206265656e2070726f76656e2079657400000000000000000000000000006064820152608401610add565b603660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663887862726040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113d39190615081565b81602001516fffffffffffffffffffffffffffffffff16101561149e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604b60248201527f4f7074696d69736d506f7274616c3a207769746864726177616c2074696d657360448201527f74616d70206c657373207468616e204c32204f7261636c65207374617274696e60648201527f672074696d657374616d70000000000000000000000000000000000000000000608482015260a401610add565b6114bd81602001516fffffffffffffffffffffffffffffffff166125bb565b61156f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604560248201527f4f7074696d69736d506f7274616c3a2070726f76656e2077697468647261776160448201527f6c2066696e616c697a6174696f6e20706572696f6420686173206e6f7420656c60648201527f6170736564000000000000000000000000000000000000000000000000000000608482015260a401610add565b60365460408281015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff909116600482015260009173ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa1580156115f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061161a91906150d7565b82518151919250146116d4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4f7074696d69736d506f7274616c3a206f757470757420726f6f742070726f7660448201527f656e206973206e6f74207468652073616d652061732063757272656e74206f7560648201527f7470757420726f6f740000000000000000000000000000000000000000000000608482015260a401610add565b6116f381602001516fffffffffffffffffffffffffffffffff166125bb565b6117a5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4f7074696d69736d506f7274616c3a206f75747075742070726f706f73616c2060448201527f66696e616c697a6174696f6e20706572696f6420686173206e6f7420656c617060648201527f7365640000000000000000000000000000000000000000000000000000000000608482015260a401610add565b60008381526033602052604090205460ff1615611844576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206160448201527f6c7265616479206265656e2066696e616c697a656400000000000000000000006064820152608401610add565b6000838152603360209081526040822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558501516032805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff0000000000000000000000000000000000000000909216919091179055806118cf611f19565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8216016119325761192b8660400151876080015188606001518960a001516126c3565b9150611b85565b8073ffffffffffffffffffffffffffffffffffffffff16866040015173ffffffffffffffffffffffffffffffffffffffff160361199b576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606086015115611b5c578560600151603d60008282546119bb91906152a8565b90915550506040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015611a2d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a519190615081565b9050611a86876040015188606001518473ffffffffffffffffffffffffffffffffffffffff166127219092919063ffffffff16565b6060870151611a9590826152a8565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015611aff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b239190615081565b14611b5a576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60a08601515115611b805761192b8660400151876080015160008960a001516126c3565b600191505b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405185907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b90611be790851515815260200190565b60405180910390a281158015611bfd5750326001145b15611c34576040517feeae4ed300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000611c498260106152bf565b610ff2906152086152ef565b600080611c60611f19565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff821601611ca7574791505090565b5050603d5490565b600054610100900460ff1615808015611ccf5750600054600160ff909116105b80611ce95750303b158015611ce9575060005460ff166001145b611d75576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610add565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015611dd357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603680547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff8781169190911790925560378054909116858316179055603580547fffffffffffffffffffffff0000000000000000000000000000000000000000ff166101008584160217905560325416611e8c57603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790555b611e9461277c565b8015611ef757600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b603754604080517f4397dfef0000000000000000000000000000000000000000000000000000000081528151600093849373ffffffffffffffffffffffffffffffffffffffff90911692634397dfef92600480830193928290030181865afa158015611f89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fad919061531b565b90939092509050565b818015611fd8575073ffffffffffffffffffffffffffffffffffffffff861615155b1561200f576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6120198151611c3c565b67ffffffffffffffff168367ffffffffffffffff161015612066576040517f4929b80800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6201d4c0815111156120a4576040517f73052b0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b333281146120c5575033731111000000000000000000000000000000001111015b600086868686866040516020016120e0959493929190615243565b604051602081830303815290604052905060008873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32846040516121509190614e99565b60405180910390a45050505050505050565b600154600090612198907801000000000000000000000000000000000000000000000000900467ffffffffffffffff16436152a8565b905060006121a461288f565b90506000816020015160ff16826000015163ffffffff166121c59190615384565b905082156122fc576001546000906121fc908390700100000000000000000000000000000000900467ffffffffffffffff166153ec565b90506000836040015160ff16836122139190615460565b6001546122339084906fffffffffffffffffffffffffffffffff16615460565b61223d9190615384565b60015490915060009061228e906122679084906fffffffffffffffffffffffffffffffff1661551c565b866060015163ffffffff168760a001516fffffffffffffffffffffffffffffffff166129cc565b905060018611156122bd576122ba61226782876040015160ff1660018a6122b591906152a8565b6129eb565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b6001805486919060109061232f908490700100000000000000000000000000000000900467ffffffffffffffff166152ef565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550816000015163ffffffff16600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff1613156123bc576040517f77ebef4d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001546000906123e8906fffffffffffffffffffffffffffffffff1667ffffffffffffffff8816615590565b905060006123fa48633b9aca00612a40565b61240490836155cd565b905060005a61241390886152a8565b90508082111561085b5761085b61242a82846152a8565b612a57565b60405173ffffffffffffffffffffffffffffffffffffffff80851660248301528316604482015260648101829052611ef79085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612a80565b6000816000015182602001518360400151846060015160405160200161254a949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b80516020808301516040808501516060860151608087015160a0880151935160009761254a9790969591016155e1565b6000806125a386612b8c565b90506125b181868686612bbe565b9695505050505050565b603654604080517ff4daa291000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163f4daa2919160048083019260209291908290030181865afa15801561262b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061264f9190615081565b6126599083615069565b421192915050565b6001805463ffffffff8316919060109061269a908490700100000000000000000000000000000000900467ffffffffffffffff166152ef565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555050565b60008060006126d3866000612bee565b905080612709576308c379a06000526020805278185361666543616c6c3a204e6f7420656e6f756768206761736058526064601cfd5b600080855160208701888b5af1979650505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526127779084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401612489565b505050565b600054610100900460ff16612813576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610add565b6001547801000000000000000000000000000000000000000000000000900467ffffffffffffffff166000036111b85760408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152603754604080517fcc731b02000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163cc731b029160048083019260c09291908290030181865afa158015612931573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612955919061564c565b90506040518060c00160405280826000015163ffffffff168152602001826020015160ff168152602001826040015160ff168152602001826060015163ffffffff168152602001826080015163ffffffff1681526020018260a001516fffffffffffffffffffffffffffffffff1681525091505090565b60006129e16129db8585612c0c565b83612c1c565b90505b9392505050565b6000670de0b6b3a7640000612a2c612a038583615384565b612a1590670de0b6b3a76400006153ec565b612a2785670de0b6b3a7640000615460565b612c2b565b612a369086615460565b6129e19190615384565b600081831015612a5057816129e4565b5090919050565b6000805a90505b825a612a6a90836152a8565b101561277757612a79826156ef565b9150612a5e565b6000612ae2826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612c5c9092919063ffffffff16565b8051909150156127775780806020019051810190612b009190615226565b612777576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610add565b60608180519060200120604051602001612ba891815260200190565b6040516020818303038152906040529050919050565b6000612be584612bcf878686612c6b565b8051602091820120825192909101919091201490565b95945050505050565b600080603f83619c4001026040850201603f5a021015949350505050565b600081831215612a5057816129e4565b6000818312612a5057816129e4565b60006129e4670de0b6b3a764000083612c43866136e9565b612c4d9190615460565b612c579190615384565b61392d565b60606129e18484600085613b6c565b60606000845111612cd8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4d65726b6c65547269653a20656d707479206b657900000000000000000000006044820152606401610add565b6000612ce384613d02565b90506000612cf086613dee565b9050600084604051602001612d0791815260200190565b60405160208183030381529060405290506000805b8451811015613660576000858281518110612d3957612d39615727565b602002602001015190508451831115612dd4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4d65726b6c65547269653a206b657920696e646578206578636565647320746f60448201527f74616c206b6579206c656e6774680000000000000000000000000000000000006064820152608401610add565b82600003612e8d5780518051602091820120604051612e2292612dfc92910190815260200190565b604051602081830303815290604052858051602091820120825192909101919091201490565b612e88576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4d65726b6c65547269653a20696e76616c696420726f6f7420686173680000006044820152606401610add565b612fe4565b805151602011612f435780518051602091820120604051612eb792612dfc92910190815260200190565b612e88576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d65726b6c65547269653a20696e76616c6964206c6172676520696e7465726e60448201527f616c2068617368000000000000000000000000000000000000000000000000006064820152608401610add565b805184516020808701919091208251919092012014612fe4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4d65726b6c65547269653a20696e76616c696420696e7465726e616c206e6f6460448201527f65206861736800000000000000000000000000000000000000000000000000006064820152608401610add565b612ff060106001615069565b816020015151036131cc57845183036131645761302a816020015160108151811061301d5761301d615727565b6020026020010151613e51565b965060008751116130bd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603b60248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286272616e63682900000000006064820152608401610add565b600186516130cb91906152a8565b8214613159576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286272616e6368290000000000006064820152608401610add565b5050505050506129e4565b600085848151811061317857613178615727565b602001015160f81c60f81b60f81c9050600082602001518260ff16815181106131a3576131a3615727565b602002602001015190506131b681613f05565b95506131c3600186615069565b9450505061364d565b6002816020015151036135c55760006131e482613f2a565b90506000816000815181106131fb576131fb615727565b016020015160f81c90506000613212600283615756565b61321d906002615778565b9050600061322e848360ff16613f4e565b9050600061323c8a89613f4e565b9050600061324a8383613f84565b9050808351146132dc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a20706174682072656d61696e646572206d7573742060448201527f736861726520616c6c206e6962626c65732077697468206b65790000000000006064820152608401610add565b60ff8516600214806132f1575060ff85166003145b156134e05780825114613386576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f4d65726b6c65547269653a206b65792072656d61696e646572206d757374206260448201527f65206964656e746963616c20746f20706174682072656d61696e6465720000006064820152608401610add565b6133a0876020015160018151811061301d5761301d615727565b9c5060008d5111613433576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286c65616629000000000000006064820152608401610add565b60018c5161344191906152a8565b88146134cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286c6561662900000000000000006064820152608401610add565b5050505050505050505050506129e4565b60ff851615806134f3575060ff85166001145b156135325761351f876020015160018151811061351257613512615727565b6020026020010151613f05565b995061352b818a615069565b98506135ba565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4d65726b6c65547269653a2072656365697665642061206e6f6465207769746860448201527f20616e20756e6b6e6f776e2070726566697800000000000000000000000000006064820152608401610add565b50505050505061364d565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4d65726b6c65547269653a20726563656976656420616e20756e70617273656160448201527f626c65206e6f64650000000000000000000000000000000000000000000000006064820152608401610add565b5080613658816156ef565b915050612d1c565b506040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4d65726b6c65547269653a2072616e206f7574206f662070726f6f6620656c6560448201527f6d656e74730000000000000000000000000000000000000000000000000000006064820152608401610add565b6000808213613754576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610add565b6000606061376184614038565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c1821361395e57506000919050565b680755bf798b4a1bf1e582126139d0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4558505f4f564552464c4f5700000000000000000000000000000000000000006044820152606401610add565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b606082471015613bfe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610add565b73ffffffffffffffffffffffffffffffffffffffff85163b613c7c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610add565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051613ca5919061579b565b60006040518083038185875af1925050503d8060008114613ce2576040519150601f19603f3d011682016040523d82523d6000602084013e613ce7565b606091505b5091509150613cf782828661410e565b979650505050505050565b80516060908067ffffffffffffffff811115613d2057613d20614b07565b604051908082528060200260200182016040528015613d6557816020015b6040805180820190915260608082526020820152815260200190600190039081613d3e5790505b50915060005b81811015613de7576040518060400160405280858381518110613d9057613d90615727565b60200260200101518152602001613dbf868481518110613db257613db2615727565b6020026020010151614161565b815250838281518110613dd457613dd4615727565b6020908102919091010152600101613d6b565b5050919050565b606080604051905082518060011b603f8101601f1916830160405280835250602084016020830160005b83811015613e46578060011b82018184015160001a8060041c8253600f811660018301535050600101613e18565b509295945050505050565b60606000806000613e6185614174565b919450925090506000816001811115613e7c57613e7c6157b7565b14613eb3576040517f1ff9b2e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613ebd8284615069565b855114613ef6576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612be585602001518484614612565b60606020826000015110613f2157613f1c82613e51565b610ff2565b610ff2826146a6565b6060610ff2613f49836020015160008151811061301d5761301d615727565b613dee565b606082518210613f6d5750604080516020810190915260008152610ff2565b6129e48383848651613f7f91906152a8565b6146bc565b6000808251845110613f97578251613f9a565b83515b90505b80821080156140215750828281518110613fb957613fb9615727565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916848381518110613ff857613ff8615727565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b1561403157816001019150613f9d565b5092915050565b60008082116140a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610add565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b6060831561411d5750816129e4565b82511561412d5782518084602001fd5b816040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610add9190614e99565b6060610ff261416f83614894565b614901565b600080600083600001516000036141b7576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020840151805160001a607f81116141dc57600060016000945094509450505061460b565b60b781116142f25760006141f16080836152a8565b905080876000015111614230576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001838101517fff000000000000000000000000000000000000000000000000000000000000001690821480156142a857507f80000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008216105b156142df576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506001955093506000925061460b915050565b60bf811161445057600061430760b7836152a8565b905080876000015111614346576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff000000000000000000000000000000000000000000000000000000000000001660008190036143a8576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c603781116143f0576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6143fa8184615069565b895111614433576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61443e836001615069565b975095506000945061460b9350505050565b60f781116144b557600061446560c0836152a8565b9050808760000151116144a4576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60019550935084925061460b915050565b60006144c260f7836152a8565b905080876000015111614501576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614563576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c603781116145ab576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6145b58184615069565b8951116145ee576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6145f9836001615069565b975095506001945061460b9350505050565b9193909250565b60608167ffffffffffffffff81111561462d5761462d614b07565b6040519080825280601f01601f191660200182016040528015614657576020820181803683370190505b50905081156129e457600061466c8486615069565b90506020820160005b8481101561468d578281015182820152602001614675565b8481111561469c576000858301525b5050509392505050565b6060610ff2826020015160008460000151614612565b60608182601f01101561472b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610add565b828284011015614797576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610add565b81830184511015614804576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401610add565b606082158015614823576040519150600082526020820160405261488b565b6040519150601f8416801560200281840101858101878315602002848b0101015b8183101561485c578051835260209283019201614844565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b604080518082019091526000808252602082015281516000036148e3576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50604080518082019091528151815260209182019181019190915290565b6060600080600061491185614174565b91945092509050600181600181111561492c5761492c6157b7565b14614963576040517f4b9c6abe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845161496f8385615069565b146149a6576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808252610420820190925290816020015b60408051808201909152600080825260208201528152602001906001900390816149bd5790505093506000835b8651811015614aab57600080614a306040518060400160405280858c60000151614a1491906152a8565b8152602001858c60200151614a299190615069565b9052614174565b509150915060405180604001604052808383614a4c9190615069565b8152602001848b60200151614a619190615069565b815250888581518110614a7657614a76615727565b6020908102919091010152614a8c600185615069565b9350614a988183615069565b614aa29084615069565b925050506149ea565b50845250919392505050565b73ffffffffffffffffffffffffffffffffffffffff81168114614ad957600080fd5b50565b803567ffffffffffffffff81168114614af457600080fd5b919050565b8015158114614ad957600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614b7d57614b7d614b07565b604052919050565b600082601f830112614b9657600080fd5b813567ffffffffffffffff811115614bb057614bb0614b07565b614be160207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614b36565b818152846020838601011115614bf657600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060008060c08789031215614c2c57600080fd5b8635614c3781614ab7565b95506020870135945060408701359350614c5360608801614adc565b92506080870135614c6381614af9565b915060a087013567ffffffffffffffff811115614c7f57600080fd5b614c8b89828a01614b85565b9150509295509295509295565b600060c08284031215614caa57600080fd5b60405160c0810167ffffffffffffffff8282108183111715614cce57614cce614b07565b816040528293508435835260208501359150614ce982614ab7565b81602084015260408501359150614cff82614ab7565b816040840152606085013560608401526080850135608084015260a0850135915080821115614d2d57600080fd5b50614d3a85828601614b85565b60a0830152505092915050565b600080600080600085870360e0811215614d6057600080fd5b863567ffffffffffffffff80821115614d7857600080fd5b614d848a838b01614c98565b97506020890135965060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc084011215614dbd57600080fd5b60408901955060c0890135925080831115614dd757600080fd5b828901925089601f840112614deb57600080fd5b8235915080821115614dfc57600080fd5b508860208260051b8401011115614e1257600080fd5b959894975092955050506020019190565b60005b83811015614e3e578181015183820152602001614e26565b83811115611ef75750506000910152565b60008151808452614e67816020860160208601614e23565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006129e46020830184614e4f565b600060208284031215614ebe57600080fd5b5035919050565b60ff81168114614ad957600080fd5b60008060008060808587031215614eea57600080fd5b8435614ef581614ab7565b93506020850135614f0581614ec5565b93969395505050506040820135916060013590565b600060208284031215614f2c57600080fd5b813567ffffffffffffffff811115614f4357600080fd5b614f4f84828501614c98565b949350505050565b600060208284031215614f6957600080fd5b6129e482614adc565b600080600060608486031215614f8757600080fd5b8335614f9281614ab7565b92506020840135614fa281614ab7565b91506040840135614fb281614ab7565b809150509250925092565b600080600080600060a08688031215614fd557600080fd5b8535614fe081614ab7565b945060208601359350614ff560408701614adc565b9250606086013561500581614af9565b9150608086013567ffffffffffffffff81111561502157600080fd5b61502d88828901614b85565b9150509295509295909350565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561507c5761507c61503a565b500190565b60006020828403121561509357600080fd5b5051919050565b6000602082840312156150ac57600080fd5b81516129e481614ab7565b80516fffffffffffffffffffffffffffffffff81168114614af457600080fd5b6000606082840312156150e957600080fd5b6040516060810181811067ffffffffffffffff8211171561510c5761510c614b07565b6040528251815261511f602084016150b7565b6020820152615130604084016150b7565b60408201529392505050565b60006080828403121561514e57600080fd5b6040516080810181811067ffffffffffffffff8211171561517157615171614b07565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b600067ffffffffffffffff808411156151bd576151bd614b07565b8360051b60206151ce818301614b36565b8681529185019181810190368411156151e657600080fd5b865b8481101561521a578035868111156152005760008081fd5b61520c36828b01614b85565b8452509183019183016151e8565b50979650505050505050565b60006020828403121561523857600080fd5b81516129e481614af9565b8581528460208201527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b16604082015282151560f81b604882015260008251615297816049850160208701614e23565b919091016049019695505050505050565b6000828210156152ba576152ba61503a565b500390565b600067ffffffffffffffff808316818516818304811182151516156152e6576152e661503a565b02949350505050565b600067ffffffffffffffff8083168185168083038211156153125761531261503a565b01949350505050565b6000806040838503121561532e57600080fd5b825161533981614ab7565b602084015190925061534a81614ec5565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261539357615393615355565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f8000000000000000000000000000000000000000000000000000000000000000831416156153e7576153e761503a565b500590565b6000808312837f8000000000000000000000000000000000000000000000000000000000000000018312811516156154265761542661503a565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01831381161561545a5761545a61503a565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000841360008413858304851182821616156154a1576154a161503a565b7f800000000000000000000000000000000000000000000000000000000000000060008712868205881281841616156154dc576154dc61503a565b600087129250878205871284841616156154f8576154f861503a565b8785058712818416161561550e5761550e61503a565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038413811516156155565761555661503a565b827f800000000000000000000000000000000000000000000000000000000000000003841281161561558a5761558a61503a565b50500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156155c8576155c861503a565b500290565b6000826155dc576155dc615355565b500490565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a083015261562c60c0830184614e4f565b98975050505050505050565b805163ffffffff81168114614af457600080fd5b600060c0828403121561565e57600080fd5b60405160c0810181811067ffffffffffffffff8211171561568157615681614b07565b60405261568d83615638565b8152602083015161569d81614ec5565b602082015260408301516156b081614ec5565b60408201526156c160608401615638565b60608201526156d260808401615638565b60808201526156e360a084016150b7565b60a08201529392505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036157205761572061503a565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060ff83168061576957615769615355565b8060ff84160691505092915050565b600060ff821660ff8416808210156157925761579261503a565b90039392505050565b600082516157ad818460208701614e23565b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea164736f6c634300080f000a"; bytes internal constant l2OutputOracleCode = - hex"60806040526004361061018a5760003560e01c806389c44cbb116100d6578063ce5db8d61161007f578063dcec334811610059578063dcec33481461049b578063e1a41bcf146104b0578063f4daa291146104c657600080fd5b8063ce5db8d614610445578063cf8e5cf01461045b578063d1de856c1461047b57600080fd5b8063a25ae557116100b0578063a25ae55714610391578063a8e4fb90146103ed578063bffa7f0f1461041a57600080fd5b806389c44cbb1461034857806393991af3146103685780639aaab6481461037e57600080fd5b806369f16eec1161013857806370872aa51161011257806370872aa5146102fc5780637f00642014610312578063887862721461033257600080fd5b806369f16eec146102a75780636abcf563146102bc5780636b4d98dd146102d157600080fd5b8063529933df11610169578063529933df146101ea578063534db0e2146101ff57806354fd4d501461025157600080fd5b80622134cc1461018f5780631c89c97d146101b35780634599c788146101d5575b600080fd5b34801561019b57600080fd5b506005545b6040519081526020015b60405180910390f35b3480156101bf57600080fd5b506101d36101ce3660046113a2565b6104db565b005b3480156101e157600080fd5b506101a06108b6565b3480156101f657600080fd5b506004546101a0565b34801561020b57600080fd5b5060065461022c9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101aa565b34801561025d57600080fd5b5061029a6040518060400160405280600581526020017f312e382e3000000000000000000000000000000000000000000000000000000081525081565b6040516101aa9190611405565b3480156102b357600080fd5b506101a0610929565b3480156102c857600080fd5b506003546101a0565b3480156102dd57600080fd5b5060065473ffffffffffffffffffffffffffffffffffffffff1661022c565b34801561030857600080fd5b506101a060015481565b34801561031e57600080fd5b506101a061032d366004611478565b61093b565b34801561033e57600080fd5b506101a060025481565b34801561035457600080fd5b506101d3610363366004611478565b610b4f565b34801561037457600080fd5b506101a060055481565b6101d361038c366004611491565b610de9565b34801561039d57600080fd5b506103b16103ac366004611478565b61124a565b60408051825181526020808401516fffffffffffffffffffffffffffffffff9081169183019190915292820151909216908201526060016101aa565b3480156103f957600080fd5b5060075461022c9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561042657600080fd5b5060075473ffffffffffffffffffffffffffffffffffffffff1661022c565b34801561045157600080fd5b506101a060085481565b34801561046757600080fd5b506103b1610476366004611478565b6112de565b34801561048757600080fd5b506101a0610496366004611478565b611316565b3480156104a757600080fd5b506101a0611346565b3480156104bc57600080fd5b506101a060045481565b3480156104d257600080fd5b506008546101a0565b600054610100900460ff16158080156104fb5750600054600160ff909116105b806105155750303b158015610515575060005460ff166001145b6105a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561060457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b60008811610694576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4c324f75747075744f7261636c653a207375626d697373696f6e20696e74657260448201527f76616c206d7573742062652067726561746572207468616e2030000000000000606482015260840161059d565b60008711610724576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4c324f75747075744f7261636c653a204c3220626c6f636b2074696d65206d7560448201527f73742062652067726561746572207468616e2030000000000000000000000000606482015260840161059d565b428511156107db576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526044602482018190527f4c324f75747075744f7261636c653a207374617274696e67204c322074696d65908201527f7374616d70206d757374206265206c657373207468616e2063757272656e742060648201527f74696d6500000000000000000000000000000000000000000000000000000000608482015260a40161059d565b60048890556005879055600186905560028590556007805473ffffffffffffffffffffffffffffffffffffffff8087167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179092556006805492861692909116919091179055600882905580156108ac57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b6003546000901561092057600380546108d1906001906114f2565b815481106108e1576108e1611509565b600091825260209091206002909102016001015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16919050565b6001545b905090565b600354600090610924906001906114f2565b60006109456108b6565b8211156109fa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a2063616e6e6f7420676574206f7574707560448201527f7420666f72206120626c6f636b207468617420686173206e6f74206265656e2060648201527f70726f706f736564000000000000000000000000000000000000000000000000608482015260a40161059d565b600354610aaf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f4c324f75747075744f7261636c653a2063616e6e6f7420676574206f7574707560448201527f74206173206e6f206f7574707574732068617665206265656e2070726f706f7360648201527f6564207965740000000000000000000000000000000000000000000000000000608482015260a40161059d565b6003546000905b80821015610b485760006002610acc8385611538565b610ad69190611550565b90508460038281548110610aec57610aec611509565b600091825260209091206002909102016001015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff161015610b3e57610b37816001611538565b9250610b42565b8091505b50610ab6565b5092915050565b60065473ffffffffffffffffffffffffffffffffffffffff163314610bf6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f4c324f75747075744f7261636c653a206f6e6c7920746865206368616c6c656e60448201527f67657220616464726573732063616e2064656c657465206f7574707574730000606482015260840161059d565b6003548110610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4c324f75747075744f7261636c653a2063616e6e6f742064656c657465206f7560448201527f747075747320616674657220746865206c6174657374206f757470757420696e60648201527f6465780000000000000000000000000000000000000000000000000000000000608482015260a40161059d565b60085460038281548110610cc357610cc3611509565b6000918252602090912060016002909202010154610cf3906fffffffffffffffffffffffffffffffff16426114f2565b10610da6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f4c324f75747075744f7261636c653a2063616e6e6f742064656c657465206f7560448201527f74707574732074686174206861766520616c7265616479206265656e2066696e60648201527f616c697a65640000000000000000000000000000000000000000000000000000608482015260a40161059d565b6000610db160035490565b90508160035581817f4ee37ac2c786ec85e87592d3c5c8a1dd66f8496dda3f125d9ea8ca5f657629b660405160405180910390a35050565b60075473ffffffffffffffffffffffffffffffffffffffff163314610eb6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f4c324f75747075744f7261636c653a206f6e6c79207468652070726f706f736560448201527f7220616464726573732063616e2070726f706f7365206e6577206f757470757460648201527f7300000000000000000000000000000000000000000000000000000000000000608482015260a40161059d565b610ebe611346565b8314610f72576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a20626c6f636b206e756d626572206d757360448201527f7420626520657175616c20746f206e65787420657870656374656420626c6f6360648201527f6b206e756d626572000000000000000000000000000000000000000000000000608482015260a40161059d565b42610f7c84611316565b10611009576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f4c324f75747075744f7261636c653a2063616e6e6f742070726f706f7365204c60448201527f32206f757470757420696e207468652066757475726500000000000000000000606482015260840161059d565b83611096576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4c324f75747075744f7261636c653a204c32206f75747075742070726f706f7360448201527f616c2063616e6e6f7420626520746865207a65726f2068617368000000000000606482015260840161059d565b81156111525781814014611152576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4c324f75747075744f7261636c653a20626c6f636b206861736820646f65732060448201527f6e6f74206d61746368207468652068617368206174207468652065787065637460648201527f6564206865696768740000000000000000000000000000000000000000000000608482015260a40161059d565b8261115c60035490565b857fa7aaf2512769da4e444e3de247be2564225c2e7a8f74cfe528e46e17d24868e24260405161118e91815260200190565b60405180910390a45050604080516060810182529283526fffffffffffffffffffffffffffffffff4281166020850190815292811691840191825260038054600181018255600091909152935160029094027fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b810194909455915190518216700100000000000000000000000000000000029116177fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85c90910155565b60408051606081018252600080825260208201819052918101919091526003828154811061127a5761127a611509565b600091825260209182902060408051606081018252600290930290910180548352600101546fffffffffffffffffffffffffffffffff8082169484019490945270010000000000000000000000000000000090049092169181019190915292915050565b604080516060810182526000808252602082018190529181019190915260036113068361093b565b8154811061127a5761127a611509565b60006005546001548361132991906114f2565b611333919061158b565b6002546113409190611538565b92915050565b60006004546113536108b6565b6109249190611538565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b803573ffffffffffffffffffffffffffffffffffffffff8116811461139d57600080fd5b919050565b600080600080600080600060e0888a0312156113bd57600080fd5b873596506020880135955060408801359450606088013593506113e260808901611379565b92506113f060a08901611379565b915060c0880135905092959891949750929550565b600060208083528351808285015260005b8181101561143257858101830151858201604001528201611416565b81811115611444576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b60006020828403121561148a57600080fd5b5035919050565b600080600080608085870312156114a757600080fd5b5050823594602084013594506040840135936060013592509050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015611504576115046114c3565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000821982111561154b5761154b6114c3565b500190565b600082611586577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156115c3576115c36114c3565b50029056fea164736f6c634300080f000a"; + hex"60806040526004361061018a5760003560e01c806389c44cbb116100d6578063ce5db8d61161007f578063dcec334811610059578063dcec33481461049b578063e1a41bcf146104b0578063f4daa291146104c657600080fd5b8063ce5db8d614610445578063cf8e5cf01461045b578063d1de856c1461047b57600080fd5b8063a25ae557116100b0578063a25ae55714610391578063a8e4fb90146103ed578063bffa7f0f1461041a57600080fd5b806389c44cbb1461034857806393991af3146103685780639aaab6481461037e57600080fd5b806369f16eec1161013857806370872aa51161011257806370872aa5146102fc5780637f00642014610312578063887862721461033257600080fd5b806369f16eec146102a75780636abcf563146102bc5780636b4d98dd146102d157600080fd5b8063529933df11610169578063529933df146101ea578063534db0e2146101ff57806354fd4d501461025157600080fd5b80622134cc1461018f5780631c89c97d146101b35780634599c788146101d5575b600080fd5b34801561019b57600080fd5b506005545b6040519081526020015b60405180910390f35b3480156101bf57600080fd5b506101d36101ce3660046113a2565b6104db565b005b3480156101e157600080fd5b506101a06108b6565b3480156101f657600080fd5b506004546101a0565b34801561020b57600080fd5b5060065461022c9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101aa565b34801561025d57600080fd5b5061029a6040518060400160405280600c81526020017f312e382e312d626574612e31000000000000000000000000000000000000000081525081565b6040516101aa9190611405565b3480156102b357600080fd5b506101a0610929565b3480156102c857600080fd5b506003546101a0565b3480156102dd57600080fd5b5060065473ffffffffffffffffffffffffffffffffffffffff1661022c565b34801561030857600080fd5b506101a060015481565b34801561031e57600080fd5b506101a061032d366004611478565b61093b565b34801561033e57600080fd5b506101a060025481565b34801561035457600080fd5b506101d3610363366004611478565b610b4f565b34801561037457600080fd5b506101a060055481565b6101d361038c366004611491565b610de9565b34801561039d57600080fd5b506103b16103ac366004611478565b61124a565b60408051825181526020808401516fffffffffffffffffffffffffffffffff9081169183019190915292820151909216908201526060016101aa565b3480156103f957600080fd5b5060075461022c9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561042657600080fd5b5060075473ffffffffffffffffffffffffffffffffffffffff1661022c565b34801561045157600080fd5b506101a060085481565b34801561046757600080fd5b506103b1610476366004611478565b6112de565b34801561048757600080fd5b506101a0610496366004611478565b611316565b3480156104a757600080fd5b506101a0611346565b3480156104bc57600080fd5b506101a060045481565b3480156104d257600080fd5b506008546101a0565b600054610100900460ff16158080156104fb5750600054600160ff909116105b806105155750303b158015610515575060005460ff166001145b6105a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561060457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b60008811610694576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4c324f75747075744f7261636c653a207375626d697373696f6e20696e74657260448201527f76616c206d7573742062652067726561746572207468616e2030000000000000606482015260840161059d565b60008711610724576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4c324f75747075744f7261636c653a204c3220626c6f636b2074696d65206d7560448201527f73742062652067726561746572207468616e2030000000000000000000000000606482015260840161059d565b428511156107db576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526044602482018190527f4c324f75747075744f7261636c653a207374617274696e67204c322074696d65908201527f7374616d70206d757374206265206c657373207468616e2063757272656e742060648201527f74696d6500000000000000000000000000000000000000000000000000000000608482015260a40161059d565b60048890556005879055600186905560028590556007805473ffffffffffffffffffffffffffffffffffffffff8087167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179092556006805492861692909116919091179055600882905580156108ac57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b6003546000901561092057600380546108d1906001906114f2565b815481106108e1576108e1611509565b600091825260209091206002909102016001015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16919050565b6001545b905090565b600354600090610924906001906114f2565b60006109456108b6565b8211156109fa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a2063616e6e6f7420676574206f7574707560448201527f7420666f72206120626c6f636b207468617420686173206e6f74206265656e2060648201527f70726f706f736564000000000000000000000000000000000000000000000000608482015260a40161059d565b600354610aaf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f4c324f75747075744f7261636c653a2063616e6e6f7420676574206f7574707560448201527f74206173206e6f206f7574707574732068617665206265656e2070726f706f7360648201527f6564207965740000000000000000000000000000000000000000000000000000608482015260a40161059d565b6003546000905b80821015610b485760006002610acc8385611538565b610ad69190611550565b90508460038281548110610aec57610aec611509565b600091825260209091206002909102016001015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff161015610b3e57610b37816001611538565b9250610b42565b8091505b50610ab6565b5092915050565b60065473ffffffffffffffffffffffffffffffffffffffff163314610bf6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f4c324f75747075744f7261636c653a206f6e6c7920746865206368616c6c656e60448201527f67657220616464726573732063616e2064656c657465206f7574707574730000606482015260840161059d565b6003548110610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4c324f75747075744f7261636c653a2063616e6e6f742064656c657465206f7560448201527f747075747320616674657220746865206c6174657374206f757470757420696e60648201527f6465780000000000000000000000000000000000000000000000000000000000608482015260a40161059d565b60085460038281548110610cc357610cc3611509565b6000918252602090912060016002909202010154610cf3906fffffffffffffffffffffffffffffffff16426114f2565b10610da6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f4c324f75747075744f7261636c653a2063616e6e6f742064656c657465206f7560448201527f74707574732074686174206861766520616c7265616479206265656e2066696e60648201527f616c697a65640000000000000000000000000000000000000000000000000000608482015260a40161059d565b6000610db160035490565b90508160035581817f4ee37ac2c786ec85e87592d3c5c8a1dd66f8496dda3f125d9ea8ca5f657629b660405160405180910390a35050565b60075473ffffffffffffffffffffffffffffffffffffffff163314610eb6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f4c324f75747075744f7261636c653a206f6e6c79207468652070726f706f736560448201527f7220616464726573732063616e2070726f706f7365206e6577206f757470757460648201527f7300000000000000000000000000000000000000000000000000000000000000608482015260a40161059d565b610ebe611346565b8314610f72576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a20626c6f636b206e756d626572206d757360448201527f7420626520657175616c20746f206e65787420657870656374656420626c6f6360648201527f6b206e756d626572000000000000000000000000000000000000000000000000608482015260a40161059d565b42610f7c84611316565b10611009576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f4c324f75747075744f7261636c653a2063616e6e6f742070726f706f7365204c60448201527f32206f757470757420696e207468652066757475726500000000000000000000606482015260840161059d565b83611096576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4c324f75747075744f7261636c653a204c32206f75747075742070726f706f7360448201527f616c2063616e6e6f7420626520746865207a65726f2068617368000000000000606482015260840161059d565b81156111525781814014611152576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4c324f75747075744f7261636c653a20626c6f636b206861736820646f65732060448201527f6e6f74206d61746368207468652068617368206174207468652065787065637460648201527f6564206865696768740000000000000000000000000000000000000000000000608482015260a40161059d565b8261115c60035490565b857fa7aaf2512769da4e444e3de247be2564225c2e7a8f74cfe528e46e17d24868e24260405161118e91815260200190565b60405180910390a45050604080516060810182529283526fffffffffffffffffffffffffffffffff4281166020850190815292811691840191825260038054600181018255600091909152935160029094027fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b810194909455915190518216700100000000000000000000000000000000029116177fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85c90910155565b60408051606081018252600080825260208201819052918101919091526003828154811061127a5761127a611509565b600091825260209182902060408051606081018252600290930290910180548352600101546fffffffffffffffffffffffffffffffff8082169484019490945270010000000000000000000000000000000090049092169181019190915292915050565b604080516060810182526000808252602082018190529181019190915260036113068361093b565b8154811061127a5761127a611509565b60006005546001548361132991906114f2565b611333919061158b565b6002546113409190611538565b92915050565b60006004546113536108b6565b6109249190611538565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b803573ffffffffffffffffffffffffffffffffffffffff8116811461139d57600080fd5b919050565b600080600080600080600060e0888a0312156113bd57600080fd5b873596506020880135955060408801359450606088013593506113e260808901611379565b92506113f060a08901611379565b915060c0880135905092959891949750929550565b600060208083528351808285015260005b8181101561143257858101830151858201604001528201611416565b81811115611444576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b60006020828403121561148a57600080fd5b5035919050565b600080600080608085870312156114a757600080fd5b5050823594602084013594506040840135936060013592509050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015611504576115046114c3565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000821982111561154b5761154b6114c3565b500190565b600082611586577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156115c3576115c36114c3565b50029056fea164736f6c634300080f000a"; bytes internal constant optimismPortal2Code = - hex"6080604052600436106101d15760003560e01c80637fc48504116100f7578063a35d99df11610095578063bf653a5c11610064578063bf653a5c14610697578063cff0ab96146106ca578063e9e05c421461076b578063f2b4e6171461077e57600080fd5b8063a35d99df1461059b578063a3860f48146105bb578063b69ef8a8146105db578063bb2c727e146105f057600080fd5b80638e819e54116100d15780638e819e54146104eb578063952b27971461050b5780639bf62d821461053e578063a14238e71461056b57600080fd5b80637fc48504146104ab5780638b4c40b0146101f65780638c3152e9146104cb57600080fd5b80634870496f1161016f5780635c975abb1161013e5780635c975abb1461043657806371c1566e1461044b57806371cfaa3f1461046b5780637d6be8dc1461048b57600080fd5b80634870496f1461034d5780634fd0434c1461036d578063513747ab146103af57806354fd4d50146103ea57600080fd5b80633c9f397c116101ab5780633c9f397c146102a657806343ca1c50146102d8578063452a9320146102f857806345884d321461030d57600080fd5b8063149f2f22146101fd57806333d7e2bd1461021d57806335e80ab31461027457600080fd5b366101f8576101f63334620186a06000604051806020016040528060008152506107ab565b005b600080fd5b34801561020957600080fd5b506101f6610218366004614fe6565b610850565b34801561022957600080fd5b5060375461024a9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561028057600080fd5b5060355461024a90610100900473ffffffffffffffffffffffffffffffffffffffff1681565b3480156102b257600080fd5b50603b546102c39063ffffffff1681565b60405163ffffffff909116815260200161026b565b3480156102e457600080fd5b506101f66102f336600461511c565b610a91565b34801561030457600080fd5b5061024a610f31565b34801561031957600080fd5b5061033d61032836600461516e565b603a6020526000908152604090205460ff1681565b604051901515815260200161026b565b34801561035957600080fd5b506101f661036836600461518b565b610fc9565b34801561037957600080fd5b50603b5461039690640100000000900467ffffffffffffffff1681565b60405167ffffffffffffffff909116815260200161026b565b3480156103bb57600080fd5b506103dc6103ca366004615267565b6000908152603c602052604090205490565b60405190815260200161026b565b3480156103f657600080fd5b50604080518082018252600d81527f332e31312e302d626574612e32000000000000000000000000000000000000006020820152905161026b91906152f6565b34801561044257600080fd5b5061033d611531565b34801561045757600080fd5b506101f6610466366004615309565b6115c4565b34801561047757600080fd5b506101f661048636600461533d565b611c7f565b34801561049757600080fd5b506101f66104a636600461516e565b611e3f565b3480156104b757600080fd5b506101f66104c6366004615395565b611f22565b3480156104d757600080fd5b506101f66104e63660046153b2565b61200e565b3480156104f757600080fd5b506101f66105063660046153ef565b61205a565b34801561051757600080fd5b507f00000000000000000000000000000000000000000000000000000000000000066103dc565b34801561054a57600080fd5b5060325461024a9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561057757600080fd5b5061033d610586366004615267565b60336020526000908152604090205460ff1681565b3480156105a757600080fd5b506103966105b636600461544b565b61230f565b3480156105c757600080fd5b5061024a6105d6366004615468565b61232e565b3480156105e757600080fd5b506103dc612373565b3480156105fc57600080fd5b5061066261060b366004615309565b603960209081526000928352604080842090915290825290205473ffffffffffffffffffffffffffffffffffffffff81169074010000000000000000000000000000000000000000900467ffffffffffffffff1682565b6040805173ffffffffffffffffffffffffffffffffffffffff909316835267ffffffffffffffff90911660208301520161026b565b3480156106a357600080fd5b507f000000000000000000000000000000000000000000000000000000000000000c6103dc565b3480156106d657600080fd5b50600154610732906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff928316602085015291169082015260600161026b565b6101f661077936600461548a565b6107ab565b34801561078a57600080fd5b5060385461024a9073ffffffffffffffffffffffffffffffffffffffff1681565b8260005a905060006107bb6123e9565b50905073ffffffffffffffffffffffffffffffffffffffff811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee148015906107f757503415155b1561082e576040517ff2365b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61083c883489898989612486565b506108478282612632565b50505050505050565b8260005a905060006108606123e9565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8216016108d2576040517f0eaf3c0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87603d60008282546108e49190615538565b90915550506040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610956573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097a9190615550565b905061099e73ffffffffffffffffffffffffffffffffffffffff831633308c6128ff565b6109a88982615538565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015610a12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a369190615550565b14610a6d576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a7b8a8a8a8a8a8a612486565b5050610a878282612632565b5050505050505050565b610a99611531565b15610ad0576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60325473ffffffffffffffffffffffffffffffffffffffff1661dead14610b23576040517f9396d15600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610b2e836129e1565b9050610b3a81836115c4565b6000818152603360209081526040822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558401516032805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff000000000000000000000000000000000000000090921691909117905580610bc56123e9565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff821601610c2857610c218560400151866080015187606001518860a00151612a2e565b9150610e7b565b8073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff1603610c91576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606085015115610e52578460600151603d6000828254610cb19190615569565b90915550506040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610d23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d479190615550565b9050610d7c866040015187606001518473ffffffffffffffffffffffffffffffffffffffff16612a8c9092919063ffffffff16565b6060860151610d8b9082615569565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015610df5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e199190615550565b14610e50576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60a08501515115610e7657610c218560400151866080015160008860a00151612a2e565b600191505b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405183907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b90610edd90851515815260200190565b60405180910390a281158015610ef35750326001145b15610f2a576040517feeae4ed300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa158015610fa0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc49190615580565b905090565b610fd1611531565b15611008576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff1603611071576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6038546040517fbb8aa1fc00000000000000000000000000000000000000000000000000000000815260048101869052600091829173ffffffffffffffffffffffffffffffffffffffff9091169063bb8aa1fc90602401606060405180830381865afa1580156110e5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611109919061559d565b925050915060008173ffffffffffffffffffffffffffffffffffffffff1663bcef3b556040518163ffffffff1660e01b8152600401602060405180830381865afa15801561115b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061117f9190615550565b603b5490915063ffffffff8481169116146111c6576040517f27a10cc200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111dd6111d8368890038801886155ea565b612ae7565b8114611215576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611220896129e1565b905060018373ffffffffffffffffffffffffffffffffffffffff1663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa15801561126f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611293919061567f565b60028111156112a4576112a4615650565b036112db576040517fd357347400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051602081018390526000918101829052606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012090830181905292506113a49101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f010000000000000000000000000000000000000000000000000000000000000060208301529061139a898b6156a0565b8b60400135612b26565b15156000036113df576040517fb05e92fa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051808201825273ffffffffffffffffffffffffffffffffffffffff808716825267ffffffffffffffff4281166020808501918252600088815260398252868120338252825286812095518654935190941674010000000000000000000000000000000000000000027fffffffff0000000000000000000000000000000000000000000000000000000090931693851693909317919091179093558d840151928e01519351928216939091169185917f67a6208cfcc0801d50f6cbe764733f4fddf66ac0b04442061a8a8c0cb6b63f6291a4604051339083907f798f9f13695f8f045aa5f80ed8efebb695f3c7fe65da381969f2f28bf3c60b9790600090a3506000908152603c602090815260408220805460018101825590835291200180547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790555050505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115a0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc49190615724565b600082815260396020908152604080832073ffffffffffffffffffffffffffffffffffffffff85811685529083528184208251808401845290549182168082527401000000000000000000000000000000000000000090920467ffffffffffffffff1681850152818552603a90935292205490919060ff1615611673576040517f09550c7700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b816020015167ffffffffffffffff166000036116bb576040517f94efd49b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061173c8273ffffffffffffffffffffffffffffffffffffffff1663cf09e0d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561170b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061172f9190615741565b67ffffffffffffffff1690565b90508067ffffffffffffffff16836020015167ffffffffffffffff1611611810576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604e60248201527f4f7074696d69736d506f7274616c3a207769746864726177616c2074696d657360448201527f74616d70206c657373207468616e20646973707574652067616d65206372656160648201527f74696f6e2074696d657374616d70000000000000000000000000000000000000608482015260a4015b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000c836020015167ffffffffffffffff164261184b9190615569565b116118d8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a2070726f76656e2077697468647261776160448201527f6c20686173206e6f74206d6174757265642079657400000000000000000000006064820152608401611807565b60028273ffffffffffffffffffffffffffffffffffffffff1663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611925573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611949919061567f565b600281111561195a5761195a615650565b14611991576040517fa080a3c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603b5463ffffffff1663ffffffff16611a1b8373ffffffffffffffffffffffffffffffffffffffff1663bbdc02db6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119ee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a12919061575e565b63ffffffff1690565b63ffffffff1614611a58576040517f27a10cc200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603b5467ffffffffffffffff64010000000090910481169082161015611b26576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604b60248201527f4f7074696d69736d506f7274616c3a20646973707574652067616d652063726560448201527f61746564206265666f7265207265737065637465642067616d6520747970652060648201527f7761732075706461746564000000000000000000000000000000000000000000608482015260a401611807565b7f0000000000000000000000000000000000000000000000000000000000000006611b958373ffffffffffffffffffffffffffffffffffffffff166319effeb46040518163ffffffff1660e01b8152600401602060405180830381865afa15801561170b573d6000803e3d6000fd5b611ba99067ffffffffffffffff1642615569565b11611c36576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4f7074696d69736d506f7274616c3a206f75747075742070726f706f73616c2060448201527f696e206169722d676170000000000000000000000000000000000000000000006064820152608401611807565b60008581526033602052604090205460ff1615610f2a576040517f475a253500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60375473ffffffffffffffffffffffffffffffffffffffff163314611cd0576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611cdc62030d40612b4a565b60405173ffffffffffffffffffffffffffffffffffffffff8516602482015260ff8416604482015260648101839052608481018290526000907342000000000000000000000000000000000000159073deaddeaddeaddeaddeaddeaddeaddeaddead0001907fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32908490819062030d4090829060a401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f71cfaa3f000000000000000000000000000000000000000000000000000000001790529051611df99695949392910161577b565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815290829052611e31916152f6565b60405180910390a450505050565b611e47610f31565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611eab576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81166000818152603a602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055517f192c289026d59a41a27f5aea08f3969b57931b0589202d14f4368cded95d3cda9190a250565b611f2a610f31565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611f8e576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603b805463ffffffff83167fffffffffffffffffffffffffffffffffffffffff00000000000000000000000090911681176401000000004267ffffffffffffffff90811682029290921793849055604051930416917f049fe9dd413cdf037cce27011cc1790c753118272f3630e6e8bdfa5e8208176090600090a350565b565b612016611531565b1561204d576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6120578133610a91565b50565b600054610100900460ff161580801561207a5750600054600160ff909116105b806120945750303b158015612094575060005460ff166001145b612120576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401611807565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561217e57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603880547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff8881169190911790925560378054909116868316179055603580547fffffffffffffffffffffff0000000000000000000000000000000000000000ff16610100868416021790556032541661229e576032805461dead7fffffffffffffffffffffffff0000000000000000000000000000000000000000909116179055603b80547fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166401000000004267ffffffffffffffff16027fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000161763ffffffff84161790555b6122a6612bac565b8015610f2a57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050565b600061231c8260106157e0565b61232890615208615810565b92915050565b603c602052816000526040600020818154811061234a57600080fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff169150829050565b60008061237e6123e9565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8216016123c5574791505090565b5050603d5490565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b603754604080517f4397dfef0000000000000000000000000000000000000000000000000000000081528151600093849373ffffffffffffffffffffffffffffffffffffffff90911692634397dfef92600480830193928290030181865afa158015612459573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061247d919061583c565b90939092509050565b8180156124a8575073ffffffffffffffffffffffffffffffffffffffff861615155b156124df576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6124e9815161230f565b67ffffffffffffffff168367ffffffffffffffff161015612536576040517f4929b80800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6201d4c081511115612574576040517f73052b0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b33328114612595575033731111000000000000000000000000000000001111015b600086868686866040516020016125b095949392919061577b565b604051602081830303815290604052905060008873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c328460405161262091906152f6565b60405180910390a45050505050505050565b600154600090612668907801000000000000000000000000000000000000000000000000900467ffffffffffffffff1643615569565b90506000612674612cbf565b90506000816020015160ff16826000015163ffffffff16612695919061589a565b905082156127cc576001546000906126cc908390700100000000000000000000000000000000900467ffffffffffffffff16615902565b90506000836040015160ff16836126e39190615976565b6001546127039084906fffffffffffffffffffffffffffffffff16615976565b61270d919061589a565b60015490915060009061275e906127379084906fffffffffffffffffffffffffffffffff16615a32565b866060015163ffffffff168760a001516fffffffffffffffffffffffffffffffff16612d80565b9050600186111561278d5761278a61273782876040015160ff1660018a6127859190615569565b612d9f565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b600180548691906010906127ff908490700100000000000000000000000000000000900467ffffffffffffffff16615810565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550816000015163ffffffff16600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff16131561288c576040517f77ebef4d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001546000906128b8906fffffffffffffffffffffffffffffffff1667ffffffffffffffff8816615aa6565b905060006128ca48633b9aca00612df4565b6128d49083615ae3565b905060005a6128e39088615569565b905080821115610a8757610a876128fa8284615569565b612e0b565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526129db9085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612e34565b50505050565b80516020808301516040808501516060860151608087015160a08801519351600097612a11979096959101615af7565b604051602081830303815290604052805190602001209050919050565b6000806000612a3e866000612f40565b905080612a74576308c379a06000526020805278185361666543616c6c3a204e6f7420656e6f756768206761736058526064601cfd5b600080855160208701888b5af1979650505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052612ae29084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401612959565b505050565b60008160000151826020015183604001518460600151604051602001612a11949392919093845260208401929092526040830152606082015260800190565b600080612b3286612f5e565b9050612b4081868686612f90565b9695505050505050565b6001805463ffffffff83169190601090612b83908490700100000000000000000000000000000000900467ffffffffffffffff16615810565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555050565b600054610100900460ff16612c43576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401611807565b6001547801000000000000000000000000000000000000000000000000900467ffffffffffffffff1660000361200c5760408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b6040805160c08082018352600080835260208301819052828401819052606083018190526080830181905260a083015260375483517fcc731b020000000000000000000000000000000000000000000000000000000081529351929373ffffffffffffffffffffffffffffffffffffffff9091169263cc731b02926004808401939192918290030181865afa158015612d5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc49190615b4e565b6000612d95612d8f8585612fc0565b83612fd0565b90505b9392505050565b6000670de0b6b3a7640000612de0612db7858361589a565b612dc990670de0b6b3a7640000615902565b612ddb85670de0b6b3a7640000615976565b612fdf565b612dea9086615976565b612d95919061589a565b600081831015612e045781612d98565b5090919050565b6000805a90505b825a612e1e9083615569565b1015612ae257612e2d82615bf0565b9150612e12565b6000612e96826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166130109092919063ffffffff16565b805190915015612ae25780806020019051810190612eb49190615724565b612ae2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401611807565b600080603f83619c4001026040850201603f5a021015949350505050565b60608180519060200120604051602001612f7a91815260200190565b6040516020818303038152906040529050919050565b6000612fb784612fa187868661301f565b8051602091820120825192909101919091201490565b95945050505050565b600081831215612e045781612d98565b6000818312612e045781612d98565b6000612d98670de0b6b3a764000083612ff786613a9d565b6130019190615976565b61300b919061589a565b613ce1565b6060612d958484600085613f20565b6060600084511161308c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4d65726b6c65547269653a20656d707479206b657900000000000000000000006044820152606401611807565b6000613097846140b6565b905060006130a4866141a2565b90506000846040516020016130bb91815260200190565b60405160208183030381529060405290506000805b8451811015613a145760008582815181106130ed576130ed615c28565b602002602001015190508451831115613188576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4d65726b6c65547269653a206b657920696e646578206578636565647320746f60448201527f74616c206b6579206c656e6774680000000000000000000000000000000000006064820152608401611807565b8260000361324157805180516020918201206040516131d6926131b092910190815260200190565b604051602081830303815290604052858051602091820120825192909101919091201490565b61323c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4d65726b6c65547269653a20696e76616c696420726f6f7420686173680000006044820152606401611807565b613398565b8051516020116132f7578051805160209182012060405161326b926131b092910190815260200190565b61323c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d65726b6c65547269653a20696e76616c6964206c6172676520696e7465726e60448201527f616c2068617368000000000000000000000000000000000000000000000000006064820152608401611807565b805184516020808701919091208251919092012014613398576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4d65726b6c65547269653a20696e76616c696420696e7465726e616c206e6f6460448201527f65206861736800000000000000000000000000000000000000000000000000006064820152608401611807565b6133a460106001615538565b816020015151036135805784518303613518576133de81602001516010815181106133d1576133d1615c28565b6020026020010151614205565b96506000875111613471576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603b60248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286272616e63682900000000006064820152608401611807565b6001865161347f9190615569565b821461350d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286272616e6368290000000000006064820152608401611807565b505050505050612d98565b600085848151811061352c5761352c615c28565b602001015160f81c60f81b60f81c9050600082602001518260ff168151811061355757613557615c28565b6020026020010151905061356a816142b9565b9550613577600186615538565b94505050613a01565b600281602001515103613979576000613598826142de565b90506000816000815181106135af576135af615c28565b016020015160f81c905060006135c6600283615c57565b6135d1906002615c79565b905060006135e2848360ff16614302565b905060006135f08a89614302565b905060006135fe8383614338565b905080835114613690576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a20706174682072656d61696e646572206d7573742060448201527f736861726520616c6c206e6962626c65732077697468206b65790000000000006064820152608401611807565b60ff8516600214806136a5575060ff85166003145b15613894578082511461373a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f4d65726b6c65547269653a206b65792072656d61696e646572206d757374206260448201527f65206964656e746963616c20746f20706174682072656d61696e6465720000006064820152608401611807565b61375487602001516001815181106133d1576133d1615c28565b9c5060008d51116137e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286c65616629000000000000006064820152608401611807565b60018c516137f59190615569565b8814613883576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286c6561662900000000000000006064820152608401611807565b505050505050505050505050612d98565b60ff851615806138a7575060ff85166001145b156138e6576138d387602001516001815181106138c6576138c6615c28565b60200260200101516142b9565b99506138df818a615538565b985061396e565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4d65726b6c65547269653a2072656365697665642061206e6f6465207769746860448201527f20616e20756e6b6e6f776e2070726566697800000000000000000000000000006064820152608401611807565b505050505050613a01565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4d65726b6c65547269653a20726563656976656420616e20756e70617273656160448201527f626c65206e6f64650000000000000000000000000000000000000000000000006064820152608401611807565b5080613a0c81615bf0565b9150506130d0565b506040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4d65726b6c65547269653a2072616e206f7574206f662070726f6f6620656c6560448201527f6d656e74730000000000000000000000000000000000000000000000000000006064820152608401611807565b6000808213613b08576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401611807565b60006060613b15846143ec565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c18213613d1257506000919050565b680755bf798b4a1bf1e58212613d84576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4558505f4f564552464c4f5700000000000000000000000000000000000000006044820152606401611807565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b606082471015613fb2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401611807565b73ffffffffffffffffffffffffffffffffffffffff85163b614030576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401611807565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516140599190615c9c565b60006040518083038185875af1925050503d8060008114614096576040519150601f19603f3d011682016040523d82523d6000602084013e61409b565b606091505b50915091506140ab8282866144c2565b979650505050505050565b80516060908067ffffffffffffffff8111156140d4576140d4614eb1565b60405190808252806020026020018201604052801561411957816020015b60408051808201909152606080825260208201528152602001906001900390816140f25790505b50915060005b8181101561419b57604051806040016040528085838151811061414457614144615c28565b6020026020010151815260200161417386848151811061416657614166615c28565b6020026020010151614515565b81525083828151811061418857614188615c28565b602090810291909101015260010161411f565b5050919050565b606080604051905082518060011b603f8101601f1916830160405280835250602084016020830160005b838110156141fa578060011b82018184015160001a8060041c8253600f8116600183015350506001016141cc565b509295945050505050565b6060600080600061421585614528565b91945092509050600081600181111561423057614230615650565b14614267576040517f1ff9b2e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6142718284615538565b8551146142aa576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612fb7856020015184846149c6565b606060208260000151106142d5576142d082614205565b612328565b61232882614a5a565b60606123286142fd83602001516000815181106133d1576133d1615c28565b6141a2565b6060825182106143215750604080516020810190915260008152612328565b612d9883838486516143339190615569565b614a70565b600080825184511061434b57825161434e565b83515b90505b80821080156143d5575082828151811061436d5761436d615c28565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168483815181106143ac576143ac615c28565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b156143e557816001019150614351565b5092915050565b6000808211614457576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401611807565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b606083156144d1575081612d98565b8251156144e15782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161180791906152f6565b606061232861452383614c48565b614cb5565b6000806000836000015160000361456b576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020840151805160001a607f81116145905760006001600094509450945050506149bf565b60b781116146a65760006145a5608083615569565b9050808760000151116145e4576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001838101517fff0000000000000000000000000000000000000000000000000000000000000016908214801561465c57507f80000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008216105b15614693576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50600195509350600092506149bf915050565b60bf81116148045760006146bb60b783615569565b9050808760000151116146fa576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff0000000000000000000000000000000000000000000000000000000000000016600081900361475c576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c603781116147a4576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6147ae8184615538565b8951116147e7576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6147f2836001615538565b97509550600094506149bf9350505050565b60f7811161486957600061481960c083615569565b905080876000015111614858576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001955093508492506149bf915050565b600061487660f783615569565b9050808760000151116148b5576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614917576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c6037811161495f576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6149698184615538565b8951116149a2576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6149ad836001615538565b97509550600194506149bf9350505050565b9193909250565b60608167ffffffffffffffff8111156149e1576149e1614eb1565b6040519080825280601f01601f191660200182016040528015614a0b576020820181803683370190505b5090508115612d98576000614a208486615538565b90506020820160005b84811015614a41578281015182820152602001614a29565b84811115614a50576000858301525b5050509392505050565b60606123288260200151600084600001516149c6565b60608182601f011015614adf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401611807565b828284011015614b4b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401611807565b81830184511015614bb8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401611807565b606082158015614bd75760405191506000825260208201604052614c3f565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015614c10578051835260209283019201614bf8565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b60408051808201909152600080825260208201528151600003614c97576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50604080518082019091528151815260209182019181019190915290565b60606000806000614cc585614528565b919450925090506001816001811115614ce057614ce0615650565b14614d17576040517f4b9c6abe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8451614d238385615538565b14614d5a576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808252610420820190925290816020015b6040805180820190915260008082526020820152815260200190600190039081614d715790505093506000835b8651811015614e5f57600080614de46040518060400160405280858c60000151614dc89190615569565b8152602001858c60200151614ddd9190615538565b9052614528565b509150915060405180604001604052808383614e009190615538565b8152602001848b60200151614e159190615538565b815250888581518110614e2a57614e2a615c28565b6020908102919091010152614e40600185615538565b9350614e4c8183615538565b614e569084615538565b92505050614d9e565b50845250919392505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461205757600080fd5b67ffffffffffffffff8116811461205757600080fd5b801515811461205757600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160c0810167ffffffffffffffff81118282101715614f0357614f03614eb1565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614f5057614f50614eb1565b604052919050565b600082601f830112614f6957600080fd5b813567ffffffffffffffff811115614f8357614f83614eb1565b614fb460207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614f09565b818152846020838601011115614fc957600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060008060c08789031215614fff57600080fd5b863561500a81614e6b565b95506020870135945060408701359350606087013561502881614e8d565b9250608087013561503881614ea3565b915060a087013567ffffffffffffffff81111561505457600080fd5b61506089828a01614f58565b9150509295509295509295565b600060c0828403121561507f57600080fd5b60405160c0810167ffffffffffffffff82821081831117156150a3576150a3614eb1565b8160405282935084358352602085013591506150be82614e6b565b816020840152604085013591506150d482614e6b565b816040840152606085013560608401526080850135608084015260a085013591508082111561510257600080fd5b5061510f85828601614f58565b60a0830152505092915050565b6000806040838503121561512f57600080fd5b823567ffffffffffffffff81111561514657600080fd5b6151528582860161506d565b925050602083013561516381614e6b565b809150509250929050565b60006020828403121561518057600080fd5b8135612d9881614e6b565b600080600080600085870360e08112156151a457600080fd5b863567ffffffffffffffff808211156151bc57600080fd5b6151c88a838b0161506d565b97506020890135965060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08401121561520157600080fd5b60408901955060c089013592508083111561521b57600080fd5b828901925089601f84011261522f57600080fd5b823591508082111561524057600080fd5b508860208260051b840101111561525657600080fd5b959894975092955050506020019190565b60006020828403121561527957600080fd5b5035919050565b60005b8381101561529b578181015183820152602001615283565b838111156129db5750506000910152565b600081518084526152c4816020860160208601615280565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000612d9860208301846152ac565b6000806040838503121561531c57600080fd5b82359150602083013561516381614e6b565b60ff8116811461205757600080fd5b6000806000806080858703121561535357600080fd5b843561535e81614e6b565b9350602085013561536e8161532e565b93969395505050506040820135916060013590565b63ffffffff8116811461205757600080fd5b6000602082840312156153a757600080fd5b8135612d9881615383565b6000602082840312156153c457600080fd5b813567ffffffffffffffff8111156153db57600080fd5b6153e78482850161506d565b949350505050565b6000806000806080858703121561540557600080fd5b843561541081614e6b565b9350602085013561542081614e6b565b9250604085013561543081614e6b565b9150606085013561544081615383565b939692955090935050565b60006020828403121561545d57600080fd5b8135612d9881614e8d565b6000806040838503121561547b57600080fd5b50508035926020909101359150565b600080600080600060a086880312156154a257600080fd5b85356154ad81614e6b565b94506020860135935060408601356154c481614e8d565b925060608601356154d481614ea3565b9150608086013567ffffffffffffffff8111156154f057600080fd5b6154fc88828901614f58565b9150509295509295909350565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561554b5761554b615509565b500190565b60006020828403121561556257600080fd5b5051919050565b60008282101561557b5761557b615509565b500390565b60006020828403121561559257600080fd5b8151612d9881614e6b565b6000806000606084860312156155b257600080fd5b83516155bd81615383565b60208501519093506155ce81614e8d565b60408501519092506155df81614e6b565b809150509250925092565b6000608082840312156155fc57600080fd5b6040516080810181811067ffffffffffffffff8211171561561f5761561f614eb1565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60006020828403121561569157600080fd5b815160038110612d9857600080fd5b600067ffffffffffffffff808411156156bb576156bb614eb1565b8360051b60206156cc818301614f09565b8681529185019181810190368411156156e457600080fd5b865b84811015615718578035868111156156fe5760008081fd5b61570a36828b01614f58565b8452509183019183016156e6565b50979650505050505050565b60006020828403121561573657600080fd5b8151612d9881614ea3565b60006020828403121561575357600080fd5b8151612d9881614e8d565b60006020828403121561577057600080fd5b8151612d9881615383565b8581528460208201527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b16604082015282151560f81b6048820152600082516157cf816049850160208701615280565b919091016049019695505050505050565b600067ffffffffffffffff8083168185168183048111821515161561580757615807615509565b02949350505050565b600067ffffffffffffffff80831681851680830382111561583357615833615509565b01949350505050565b6000806040838503121561584f57600080fd5b825161585a81614e6b565b60208401519092506151638161532e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826158a9576158a961586b565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f8000000000000000000000000000000000000000000000000000000000000000831416156158fd576158fd615509565b500590565b6000808312837f80000000000000000000000000000000000000000000000000000000000000000183128115161561593c5761593c615509565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01831381161561597057615970615509565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000841360008413858304851182821616156159b7576159b7615509565b7f800000000000000000000000000000000000000000000000000000000000000060008712868205881281841616156159f2576159f2615509565b60008712925087820587128484161615615a0e57615a0e615509565b87850587128184161615615a2457615a24615509565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03841381151615615a6c57615a6c615509565b827f8000000000000000000000000000000000000000000000000000000000000000038412811615615aa057615aa0615509565b50500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615ade57615ade615509565b500290565b600082615af257615af261586b565b500490565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a0830152615b4260c08301846152ac565b98975050505050505050565b600060c08284031215615b6057600080fd5b615b68614ee0565b8251615b7381615383565b81526020830151615b838161532e565b60208201526040830151615b968161532e565b60408201526060830151615ba981615383565b60608201526080830151615bbc81615383565b608082015260a08301516fffffffffffffffffffffffffffffffff81168114615be457600080fd5b60a08201529392505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203615c2157615c21615509565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060ff831680615c6a57615c6a61586b565b8060ff84160691505092915050565b600060ff821660ff841680821015615c9357615c93615509565b90039392505050565b60008251615cae818460208701615280565b919091019291505056fea164736f6c634300080f000a"; + hex"6080604052600436106101d15760003560e01c80637fc48504116100f7578063a35d99df11610095578063bf653a5c11610064578063bf653a5c14610697578063cff0ab96146106ca578063e9e05c421461076b578063f2b4e6171461077e57600080fd5b8063a35d99df1461059b578063a3860f48146105bb578063b69ef8a8146105db578063bb2c727e146105f057600080fd5b80638e819e54116100d15780638e819e54146104eb578063952b27971461050b5780639bf62d821461053e578063a14238e71461056b57600080fd5b80637fc48504146104ab5780638b4c40b0146101f65780638c3152e9146104cb57600080fd5b80634870496f1161016f5780635c975abb1161013e5780635c975abb1461043657806371c1566e1461044b57806371cfaa3f1461046b5780637d6be8dc1461048b57600080fd5b80634870496f1461034d5780634fd0434c1461036d578063513747ab146103af57806354fd4d50146103ea57600080fd5b80633c9f397c116101ab5780633c9f397c146102a657806343ca1c50146102d8578063452a9320146102f857806345884d321461030d57600080fd5b8063149f2f22146101fd57806333d7e2bd1461021d57806335e80ab31461027457600080fd5b366101f8576101f63334620186a06000604051806020016040528060008152506107ab565b005b600080fd5b34801561020957600080fd5b506101f6610218366004614feb565b610850565b34801561022957600080fd5b5060375461024a9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561028057600080fd5b5060355461024a90610100900473ffffffffffffffffffffffffffffffffffffffff1681565b3480156102b257600080fd5b50603b546102c39063ffffffff1681565b60405163ffffffff909116815260200161026b565b3480156102e457600080fd5b506101f66102f3366004615121565b610a91565b34801561030457600080fd5b5061024a610f31565b34801561031957600080fd5b5061033d610328366004615173565b603a6020526000908152604090205460ff1681565b604051901515815260200161026b565b34801561035957600080fd5b506101f6610368366004615190565b610fc9565b34801561037957600080fd5b50603b5461039690640100000000900467ffffffffffffffff1681565b60405167ffffffffffffffff909116815260200161026b565b3480156103bb57600080fd5b506103dc6103ca36600461526c565b6000908152603c602052604090205490565b60405190815260200161026b565b3480156103f657600080fd5b50604080518082018252600d81527f332e31312e302d626574612e33000000000000000000000000000000000000006020820152905161026b91906152fb565b34801561044257600080fd5b5061033d611531565b34801561045757600080fd5b506101f661046636600461530e565b6115c4565b34801561047757600080fd5b506101f6610486366004615342565b611c7f565b34801561049757600080fd5b506101f66104a6366004615173565b611e3f565b3480156104b757600080fd5b506101f66104c636600461539a565b611f22565b3480156104d757600080fd5b506101f66104e63660046153b7565b61200e565b3480156104f757600080fd5b506101f66105063660046153f4565b61205a565b34801561051757600080fd5b507f00000000000000000000000000000000000000000000000000000000000000066103dc565b34801561054a57600080fd5b5060325461024a9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561057757600080fd5b5061033d61058636600461526c565b60336020526000908152604090205460ff1681565b3480156105a757600080fd5b506103966105b6366004615450565b61230f565b3480156105c757600080fd5b5061024a6105d636600461546d565b61232e565b3480156105e757600080fd5b506103dc612373565b3480156105fc57600080fd5b5061066261060b36600461530e565b603960209081526000928352604080842090915290825290205473ffffffffffffffffffffffffffffffffffffffff81169074010000000000000000000000000000000000000000900467ffffffffffffffff1682565b6040805173ffffffffffffffffffffffffffffffffffffffff909316835267ffffffffffffffff90911660208301520161026b565b3480156106a357600080fd5b507f000000000000000000000000000000000000000000000000000000000000000c6103dc565b3480156106d657600080fd5b50600154610732906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff928316602085015291169082015260600161026b565b6101f661077936600461548f565b6107ab565b34801561078a57600080fd5b5060385461024a9073ffffffffffffffffffffffffffffffffffffffff1681565b8260005a905060006107bb6123e9565b50905073ffffffffffffffffffffffffffffffffffffffff811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee148015906107f757503415155b1561082e576040517ff2365b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61083c883489898989612486565b506108478282612632565b50505050505050565b8260005a905060006108606123e9565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8216016108d2576040517f0eaf3c0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87603d60008282546108e4919061553d565b90915550506040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610956573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097a9190615555565b905061099e73ffffffffffffffffffffffffffffffffffffffff831633308c6128ff565b6109a8898261553d565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015610a12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a369190615555565b14610a6d576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a7b8a8a8a8a8a8a612486565b5050610a878282612632565b5050505050505050565b610a99611531565b15610ad0576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60325473ffffffffffffffffffffffffffffffffffffffff1661dead14610b23576040517f9396d15600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610b2e836129e1565b9050610b3a81836115c4565b6000818152603360209081526040822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558401516032805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff000000000000000000000000000000000000000090921691909117905580610bc56123e9565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff821601610c2857610c218560400151866080015187606001518860a00151612a2e565b9150610e7b565b8073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff1603610c91576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606085015115610e52578460600151603d6000828254610cb1919061556e565b90915550506040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610d23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d479190615555565b9050610d7c866040015187606001518473ffffffffffffffffffffffffffffffffffffffff16612a8c9092919063ffffffff16565b6060860151610d8b908261556e565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015610df5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e199190615555565b14610e50576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60a08501515115610e7657610c218560400151866080015160008860a00151612a2e565b600191505b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405183907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b90610edd90851515815260200190565b60405180910390a281158015610ef35750326001145b15610f2a576040517feeae4ed300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa158015610fa0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc49190615585565b905090565b610fd1611531565b15611008576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff1603611071576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6038546040517fbb8aa1fc00000000000000000000000000000000000000000000000000000000815260048101869052600091829173ffffffffffffffffffffffffffffffffffffffff9091169063bb8aa1fc90602401606060405180830381865afa1580156110e5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061110991906155a2565b925050915060008173ffffffffffffffffffffffffffffffffffffffff1663bcef3b556040518163ffffffff1660e01b8152600401602060405180830381865afa15801561115b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061117f9190615555565b603b5490915063ffffffff8481169116146111c6576040517f27a10cc200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111dd6111d8368890038801886155ef565b612ae7565b8114611215576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611220896129e1565b905060018373ffffffffffffffffffffffffffffffffffffffff1663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa15801561126f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112939190615684565b60028111156112a4576112a4615655565b036112db576040517fd357347400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051602081018390526000918101829052606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012090830181905292506113a49101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f010000000000000000000000000000000000000000000000000000000000000060208301529061139a898b6156a5565b8b60400135612b26565b15156000036113df576040517fb05e92fa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051808201825273ffffffffffffffffffffffffffffffffffffffff808716825267ffffffffffffffff4281166020808501918252600088815260398252868120338252825286812095518654935190941674010000000000000000000000000000000000000000027fffffffff0000000000000000000000000000000000000000000000000000000090931693851693909317919091179093558d840151928e01519351928216939091169185917f67a6208cfcc0801d50f6cbe764733f4fddf66ac0b04442061a8a8c0cb6b63f6291a4604051339083907f798f9f13695f8f045aa5f80ed8efebb695f3c7fe65da381969f2f28bf3c60b9790600090a3506000908152603c602090815260408220805460018101825590835291200180547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790555050505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115a0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc49190615729565b600082815260396020908152604080832073ffffffffffffffffffffffffffffffffffffffff85811685529083528184208251808401845290549182168082527401000000000000000000000000000000000000000090920467ffffffffffffffff1681850152818552603a90935292205490919060ff1615611673576040517f09550c7700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b816020015167ffffffffffffffff166000036116bb576040517f94efd49b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061173c8273ffffffffffffffffffffffffffffffffffffffff1663cf09e0d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561170b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061172f9190615746565b67ffffffffffffffff1690565b90508067ffffffffffffffff16836020015167ffffffffffffffff1611611810576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604e60248201527f4f7074696d69736d506f7274616c3a207769746864726177616c2074696d657360448201527f74616d70206c657373207468616e20646973707574652067616d65206372656160648201527f74696f6e2074696d657374616d70000000000000000000000000000000000000608482015260a4015b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000c836020015167ffffffffffffffff164261184b919061556e565b116118d8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a2070726f76656e2077697468647261776160448201527f6c20686173206e6f74206d6174757265642079657400000000000000000000006064820152608401611807565b60028273ffffffffffffffffffffffffffffffffffffffff1663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611925573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119499190615684565b600281111561195a5761195a615655565b14611991576040517fa080a3c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603b5463ffffffff1663ffffffff16611a1b8373ffffffffffffffffffffffffffffffffffffffff1663bbdc02db6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119ee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a129190615763565b63ffffffff1690565b63ffffffff1614611a58576040517f27a10cc200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603b5467ffffffffffffffff64010000000090910481169082161015611b26576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604b60248201527f4f7074696d69736d506f7274616c3a20646973707574652067616d652063726560448201527f61746564206265666f7265207265737065637465642067616d6520747970652060648201527f7761732075706461746564000000000000000000000000000000000000000000608482015260a401611807565b7f0000000000000000000000000000000000000000000000000000000000000006611b958373ffffffffffffffffffffffffffffffffffffffff166319effeb46040518163ffffffff1660e01b8152600401602060405180830381865afa15801561170b573d6000803e3d6000fd5b611ba99067ffffffffffffffff164261556e565b11611c36576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4f7074696d69736d506f7274616c3a206f75747075742070726f706f73616c2060448201527f696e206169722d676170000000000000000000000000000000000000000000006064820152608401611807565b60008581526033602052604090205460ff1615610f2a576040517f475a253500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60375473ffffffffffffffffffffffffffffffffffffffff163314611cd0576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611cdc62030d40612b4a565b60405173ffffffffffffffffffffffffffffffffffffffff8516602482015260ff8416604482015260648101839052608481018290526000907342000000000000000000000000000000000000159073deaddeaddeaddeaddeaddeaddeaddeaddead0001907fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32908490819062030d4090829060a401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f71cfaa3f000000000000000000000000000000000000000000000000000000001790529051611df996959493929101615780565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815290829052611e31916152fb565b60405180910390a450505050565b611e47610f31565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611eab576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81166000818152603a602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055517f192c289026d59a41a27f5aea08f3969b57931b0589202d14f4368cded95d3cda9190a250565b611f2a610f31565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611f8e576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603b805463ffffffff83167fffffffffffffffffffffffffffffffffffffffff00000000000000000000000090911681176401000000004267ffffffffffffffff90811682029290921793849055604051930416917f049fe9dd413cdf037cce27011cc1790c753118272f3630e6e8bdfa5e8208176090600090a350565b565b612016611531565b1561204d576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6120578133610a91565b50565b600054610100900460ff161580801561207a5750600054600160ff909116105b806120945750303b158015612094575060005460ff166001145b612120576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401611807565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561217e57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603880547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff8881169190911790925560378054909116868316179055603580547fffffffffffffffffffffff0000000000000000000000000000000000000000ff16610100868416021790556032541661229e576032805461dead7fffffffffffffffffffffffff0000000000000000000000000000000000000000909116179055603b80547fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166401000000004267ffffffffffffffff16027fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000161763ffffffff84161790555b6122a6612bac565b8015610f2a57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050565b600061231c8260106157e5565b61232890615208615815565b92915050565b603c602052816000526040600020818154811061234a57600080fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff169150829050565b60008061237e6123e9565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8216016123c5574791505090565b5050603d5490565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b603754604080517f4397dfef0000000000000000000000000000000000000000000000000000000081528151600093849373ffffffffffffffffffffffffffffffffffffffff90911692634397dfef92600480830193928290030181865afa158015612459573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061247d9190615841565b90939092509050565b8180156124a8575073ffffffffffffffffffffffffffffffffffffffff861615155b156124df576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6124e9815161230f565b67ffffffffffffffff168367ffffffffffffffff161015612536576040517f4929b80800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6201d4c081511115612574576040517f73052b0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b33328114612595575033731111000000000000000000000000000000001111015b600086868686866040516020016125b0959493929190615780565b604051602081830303815290604052905060008873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c328460405161262091906152fb565b60405180910390a45050505050505050565b600154600090612668907801000000000000000000000000000000000000000000000000900467ffffffffffffffff164361556e565b90506000612674612cbf565b90506000816020015160ff16826000015163ffffffff16612695919061589f565b905082156127cc576001546000906126cc908390700100000000000000000000000000000000900467ffffffffffffffff16615907565b90506000836040015160ff16836126e3919061597b565b6001546127039084906fffffffffffffffffffffffffffffffff1661597b565b61270d919061589f565b60015490915060009061275e906127379084906fffffffffffffffffffffffffffffffff16615a37565b866060015163ffffffff168760a001516fffffffffffffffffffffffffffffffff16612d85565b9050600186111561278d5761278a61273782876040015160ff1660018a612785919061556e565b612da4565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b600180548691906010906127ff908490700100000000000000000000000000000000900467ffffffffffffffff16615815565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550816000015163ffffffff16600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff16131561288c576040517f77ebef4d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001546000906128b8906fffffffffffffffffffffffffffffffff1667ffffffffffffffff8816615aab565b905060006128ca48633b9aca00612df9565b6128d49083615ae8565b905060005a6128e3908861556e565b905080821115610a8757610a876128fa828461556e565b612e10565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526129db9085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612e39565b50505050565b80516020808301516040808501516060860151608087015160a08801519351600097612a11979096959101615afc565b604051602081830303815290604052805190602001209050919050565b6000806000612a3e866000612f45565b905080612a74576308c379a06000526020805278185361666543616c6c3a204e6f7420656e6f756768206761736058526064601cfd5b600080855160208701888b5af1979650505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052612ae29084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401612959565b505050565b60008160000151826020015183604001518460600151604051602001612a11949392919093845260208401929092526040830152606082015260800190565b600080612b3286612f63565b9050612b4081868686612f95565b9695505050505050565b6001805463ffffffff83169190601090612b83908490700100000000000000000000000000000000900467ffffffffffffffff16615815565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555050565b600054610100900460ff16612c43576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401611807565b6001547801000000000000000000000000000000000000000000000000900467ffffffffffffffff1660000361200c5760408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152603754604080517fcc731b02000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163cc731b029160048083019260c09291908290030181865afa158015612d61573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123289190615b53565b6000612d9a612d948585612fc5565b83612fd5565b90505b9392505050565b6000670de0b6b3a7640000612de5612dbc858361589f565b612dce90670de0b6b3a7640000615907565b612de085670de0b6b3a764000061597b565b612fe4565b612def908661597b565b612d9a919061589f565b600081831015612e095781612d9d565b5090919050565b6000805a90505b825a612e23908361556e565b1015612ae257612e3282615bf5565b9150612e17565b6000612e9b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166130159092919063ffffffff16565b805190915015612ae25780806020019051810190612eb99190615729565b612ae2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401611807565b600080603f83619c4001026040850201603f5a021015949350505050565b60608180519060200120604051602001612f7f91815260200190565b6040516020818303038152906040529050919050565b6000612fbc84612fa6878686613024565b8051602091820120825192909101919091201490565b95945050505050565b600081831215612e095781612d9d565b6000818312612e095781612d9d565b6000612d9d670de0b6b3a764000083612ffc86613aa2565b613006919061597b565b613010919061589f565b613ce6565b6060612d9a8484600085613f25565b60606000845111613091576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4d65726b6c65547269653a20656d707479206b657900000000000000000000006044820152606401611807565b600061309c846140bb565b905060006130a9866141a7565b90506000846040516020016130c091815260200190565b60405160208183030381529060405290506000805b8451811015613a195760008582815181106130f2576130f2615c2d565b60200260200101519050845183111561318d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4d65726b6c65547269653a206b657920696e646578206578636565647320746f60448201527f74616c206b6579206c656e6774680000000000000000000000000000000000006064820152608401611807565b8260000361324657805180516020918201206040516131db926131b592910190815260200190565b604051602081830303815290604052858051602091820120825192909101919091201490565b613241576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4d65726b6c65547269653a20696e76616c696420726f6f7420686173680000006044820152606401611807565b61339d565b8051516020116132fc5780518051602091820120604051613270926131b592910190815260200190565b613241576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d65726b6c65547269653a20696e76616c6964206c6172676520696e7465726e60448201527f616c2068617368000000000000000000000000000000000000000000000000006064820152608401611807565b80518451602080870191909120825191909201201461339d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4d65726b6c65547269653a20696e76616c696420696e7465726e616c206e6f6460448201527f65206861736800000000000000000000000000000000000000000000000000006064820152608401611807565b6133a96010600161553d565b81602001515103613585578451830361351d576133e381602001516010815181106133d6576133d6615c2d565b602002602001015161420a565b96506000875111613476576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603b60248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286272616e63682900000000006064820152608401611807565b60018651613484919061556e565b8214613512576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286272616e6368290000000000006064820152608401611807565b505050505050612d9d565b600085848151811061353157613531615c2d565b602001015160f81c60f81b60f81c9050600082602001518260ff168151811061355c5761355c615c2d565b6020026020010151905061356f816142be565b955061357c60018661553d565b94505050613a06565b60028160200151510361397e57600061359d826142e3565b90506000816000815181106135b4576135b4615c2d565b016020015160f81c905060006135cb600283615c5c565b6135d6906002615c7e565b905060006135e7848360ff16614307565b905060006135f58a89614307565b90506000613603838361433d565b905080835114613695576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a20706174682072656d61696e646572206d7573742060448201527f736861726520616c6c206e6962626c65732077697468206b65790000000000006064820152608401611807565b60ff8516600214806136aa575060ff85166003145b15613899578082511461373f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f4d65726b6c65547269653a206b65792072656d61696e646572206d757374206260448201527f65206964656e746963616c20746f20706174682072656d61696e6465720000006064820152608401611807565b61375987602001516001815181106133d6576133d6615c2d565b9c5060008d51116137ec576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286c65616629000000000000006064820152608401611807565b60018c516137fa919061556e565b8814613888576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286c6561662900000000000000006064820152608401611807565b505050505050505050505050612d9d565b60ff851615806138ac575060ff85166001145b156138eb576138d887602001516001815181106138cb576138cb615c2d565b60200260200101516142be565b99506138e4818a61553d565b9850613973565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4d65726b6c65547269653a2072656365697665642061206e6f6465207769746860448201527f20616e20756e6b6e6f776e2070726566697800000000000000000000000000006064820152608401611807565b505050505050613a06565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4d65726b6c65547269653a20726563656976656420616e20756e70617273656160448201527f626c65206e6f64650000000000000000000000000000000000000000000000006064820152608401611807565b5080613a1181615bf5565b9150506130d5565b506040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4d65726b6c65547269653a2072616e206f7574206f662070726f6f6620656c6560448201527f6d656e74730000000000000000000000000000000000000000000000000000006064820152608401611807565b6000808213613b0d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401611807565b60006060613b1a846143f1565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c18213613d1757506000919050565b680755bf798b4a1bf1e58212613d89576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4558505f4f564552464c4f5700000000000000000000000000000000000000006044820152606401611807565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b606082471015613fb7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401611807565b73ffffffffffffffffffffffffffffffffffffffff85163b614035576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401611807565b6000808673ffffffffffffffffffffffffffffffffffffffff16858760405161405e9190615ca1565b60006040518083038185875af1925050503d806000811461409b576040519150601f19603f3d011682016040523d82523d6000602084013e6140a0565b606091505b50915091506140b08282866144c7565b979650505050505050565b80516060908067ffffffffffffffff8111156140d9576140d9614eb6565b60405190808252806020026020018201604052801561411e57816020015b60408051808201909152606080825260208201528152602001906001900390816140f75790505b50915060005b818110156141a057604051806040016040528085838151811061414957614149615c2d565b6020026020010151815260200161417886848151811061416b5761416b615c2d565b602002602001015161451a565b81525083828151811061418d5761418d615c2d565b6020908102919091010152600101614124565b5050919050565b606080604051905082518060011b603f8101601f1916830160405280835250602084016020830160005b838110156141ff578060011b82018184015160001a8060041c8253600f8116600183015350506001016141d1565b509295945050505050565b6060600080600061421a8561452d565b91945092509050600081600181111561423557614235615655565b1461426c576040517f1ff9b2e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614276828461553d565b8551146142af576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612fbc856020015184846149cb565b606060208260000151106142da576142d58261420a565b612328565b61232882614a5f565b606061232861430283602001516000815181106133d6576133d6615c2d565b6141a7565b6060825182106143265750604080516020810190915260008152612328565b612d9d8383848651614338919061556e565b614a75565b6000808251845110614350578251614353565b83515b90505b80821080156143da575082828151811061437257614372615c2d565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168483815181106143b1576143b1615c2d565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b156143ea57816001019150614356565b5092915050565b600080821161445c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401611807565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b606083156144d6575081612d9d565b8251156144e65782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161180791906152fb565b606061232861452883614c4d565b614cba565b60008060008360000151600003614570576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020840151805160001a607f81116145955760006001600094509450945050506149c4565b60b781116146ab5760006145aa60808361556e565b9050808760000151116145e9576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001838101517fff0000000000000000000000000000000000000000000000000000000000000016908214801561466157507f80000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008216105b15614698576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50600195509350600092506149c4915050565b60bf81116148095760006146c060b78361556e565b9050808760000151116146ff576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614761576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c603781116147a9576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6147b3818461553d565b8951116147ec576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6147f783600161553d565b97509550600094506149c49350505050565b60f7811161486e57600061481e60c08361556e565b90508087600001511161485d576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001955093508492506149c4915050565b600061487b60f78361556e565b9050808760000151116148ba576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff0000000000000000000000000000000000000000000000000000000000000016600081900361491c576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c60378111614964576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61496e818461553d565b8951116149a7576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6149b283600161553d565b97509550600194506149c49350505050565b9193909250565b60608167ffffffffffffffff8111156149e6576149e6614eb6565b6040519080825280601f01601f191660200182016040528015614a10576020820181803683370190505b5090508115612d9d576000614a25848661553d565b90506020820160005b84811015614a46578281015182820152602001614a2e565b84811115614a55576000858301525b5050509392505050565b60606123288260200151600084600001516149cb565b60608182601f011015614ae4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401611807565b828284011015614b50576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401611807565b81830184511015614bbd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401611807565b606082158015614bdc5760405191506000825260208201604052614c44565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015614c15578051835260209283019201614bfd565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b60408051808201909152600080825260208201528151600003614c9c576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50604080518082019091528151815260209182019181019190915290565b60606000806000614cca8561452d565b919450925090506001816001811115614ce557614ce5615655565b14614d1c576040517f4b9c6abe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8451614d28838561553d565b14614d5f576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808252610420820190925290816020015b6040805180820190915260008082526020820152815260200190600190039081614d765790505093506000835b8651811015614e6457600080614de96040518060400160405280858c60000151614dcd919061556e565b8152602001858c60200151614de2919061553d565b905261452d565b509150915060405180604001604052808383614e05919061553d565b8152602001848b60200151614e1a919061553d565b815250888581518110614e2f57614e2f615c2d565b6020908102919091010152614e4560018561553d565b9350614e51818361553d565b614e5b908461553d565b92505050614da3565b50845250919392505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461205757600080fd5b67ffffffffffffffff8116811461205757600080fd5b801515811461205757600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160c0810167ffffffffffffffff81118282101715614f0857614f08614eb6565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614f5557614f55614eb6565b604052919050565b600082601f830112614f6e57600080fd5b813567ffffffffffffffff811115614f8857614f88614eb6565b614fb960207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614f0e565b818152846020838601011115614fce57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060008060c0878903121561500457600080fd5b863561500f81614e70565b95506020870135945060408701359350606087013561502d81614e92565b9250608087013561503d81614ea8565b915060a087013567ffffffffffffffff81111561505957600080fd5b61506589828a01614f5d565b9150509295509295509295565b600060c0828403121561508457600080fd5b60405160c0810167ffffffffffffffff82821081831117156150a8576150a8614eb6565b8160405282935084358352602085013591506150c382614e70565b816020840152604085013591506150d982614e70565b816040840152606085013560608401526080850135608084015260a085013591508082111561510757600080fd5b5061511485828601614f5d565b60a0830152505092915050565b6000806040838503121561513457600080fd5b823567ffffffffffffffff81111561514b57600080fd5b61515785828601615072565b925050602083013561516881614e70565b809150509250929050565b60006020828403121561518557600080fd5b8135612d9d81614e70565b600080600080600085870360e08112156151a957600080fd5b863567ffffffffffffffff808211156151c157600080fd5b6151cd8a838b01615072565b97506020890135965060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08401121561520657600080fd5b60408901955060c089013592508083111561522057600080fd5b828901925089601f84011261523457600080fd5b823591508082111561524557600080fd5b508860208260051b840101111561525b57600080fd5b959894975092955050506020019190565b60006020828403121561527e57600080fd5b5035919050565b60005b838110156152a0578181015183820152602001615288565b838111156129db5750506000910152565b600081518084526152c9816020860160208601615285565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000612d9d60208301846152b1565b6000806040838503121561532157600080fd5b82359150602083013561516881614e70565b60ff8116811461205757600080fd5b6000806000806080858703121561535857600080fd5b843561536381614e70565b9350602085013561537381615333565b93969395505050506040820135916060013590565b63ffffffff8116811461205757600080fd5b6000602082840312156153ac57600080fd5b8135612d9d81615388565b6000602082840312156153c957600080fd5b813567ffffffffffffffff8111156153e057600080fd5b6153ec84828501615072565b949350505050565b6000806000806080858703121561540a57600080fd5b843561541581614e70565b9350602085013561542581614e70565b9250604085013561543581614e70565b9150606085013561544581615388565b939692955090935050565b60006020828403121561546257600080fd5b8135612d9d81614e92565b6000806040838503121561548057600080fd5b50508035926020909101359150565b600080600080600060a086880312156154a757600080fd5b85356154b281614e70565b94506020860135935060408601356154c981614e92565b925060608601356154d981614ea8565b9150608086013567ffffffffffffffff8111156154f557600080fd5b61550188828901614f5d565b9150509295509295909350565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156155505761555061550e565b500190565b60006020828403121561556757600080fd5b5051919050565b6000828210156155805761558061550e565b500390565b60006020828403121561559757600080fd5b8151612d9d81614e70565b6000806000606084860312156155b757600080fd5b83516155c281615388565b60208501519093506155d381614e92565b60408501519092506155e481614e70565b809150509250925092565b60006080828403121561560157600080fd5b6040516080810181811067ffffffffffffffff8211171561562457615624614eb6565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60006020828403121561569657600080fd5b815160038110612d9d57600080fd5b600067ffffffffffffffff808411156156c0576156c0614eb6565b8360051b60206156d1818301614f0e565b8681529185019181810190368411156156e957600080fd5b865b8481101561571d578035868111156157035760008081fd5b61570f36828b01614f5d565b8452509183019183016156eb565b50979650505050505050565b60006020828403121561573b57600080fd5b8151612d9d81614ea8565b60006020828403121561575857600080fd5b8151612d9d81614e92565b60006020828403121561577557600080fd5b8151612d9d81615388565b8581528460208201527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b16604082015282151560f81b6048820152600082516157d4816049850160208701615285565b919091016049019695505050505050565b600067ffffffffffffffff8083168185168183048111821515161561580c5761580c61550e565b02949350505050565b600067ffffffffffffffff8083168185168083038211156158385761583861550e565b01949350505050565b6000806040838503121561585457600080fd5b825161585f81614e70565b602084015190925061516881615333565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826158ae576158ae615870565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f8000000000000000000000000000000000000000000000000000000000000000831416156159025761590261550e565b500590565b6000808312837f8000000000000000000000000000000000000000000000000000000000000000018312811516156159415761594161550e565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0183138116156159755761597561550e565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000841360008413858304851182821616156159bc576159bc61550e565b7f800000000000000000000000000000000000000000000000000000000000000060008712868205881281841616156159f7576159f761550e565b60008712925087820587128484161615615a1357615a1361550e565b87850587128184161615615a2957615a2961550e565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03841381151615615a7157615a7161550e565b827f8000000000000000000000000000000000000000000000000000000000000000038412811615615aa557615aa561550e565b50500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615ae357615ae361550e565b500290565b600082615af757615af7615870565b500490565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a0830152615b4760c08301846152b1565b98975050505050505050565b600060c08284031215615b6557600080fd5b615b6d614ee5565b8251615b7881615388565b81526020830151615b8881615333565b60208201526040830151615b9b81615333565b60408201526060830151615bae81615388565b60608201526080830151615bc181615388565b608082015260a08301516fffffffffffffffffffffffffffffffff81168114615be957600080fd5b60a08201529392505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203615c2657615c2661550e565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060ff831680615c6f57615c6f615870565b8060ff84160691505092915050565b600060ff821660ff841680821015615c9857615c9861550e565b90039392505050565b60008251615cb3818460208701615285565b919091019291505056fea164736f6c634300080f000a"; bytes internal constant disputeGameFactoryCode = - hex"6080604052600436106100e85760003560e01c80636593dc6e1161008a57806396cd97201161005957806396cd972014610313578063bb8aa1fc14610333578063c4d66de814610394578063f2fde38b146103b457600080fd5b80636593dc6e14610293578063715018a6146102c057806382ecf2f6146102d55780638da5cb5b146102e857600080fd5b8063254bd683116100c6578063254bd6831461019c5780634d1975b4146101c957806354fd4d50146101e85780635f0150cb1461023e57600080fd5b806314f6b1a3146100ed5780631b685b9e1461010f5780631e3342401461017c575b600080fd5b3480156100f957600080fd5b5061010d6101083660046110c6565b6103d4565b005b34801561011b57600080fd5b5061015261012a3660046110fd565b60656020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561018857600080fd5b5061010d610197366004611118565b61045e565b3480156101a857600080fd5b506101bc6101b7366004611142565b6104aa565b60405161017391906111ef565b3480156101d557600080fd5b506068545b604051908152602001610173565b3480156101f457600080fd5b506102316040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b60405161017391906112ac565b34801561024a57600080fd5b5061025e6102593660046112bf565b6106ee565b6040805173ffffffffffffffffffffffffffffffffffffffff909316835267ffffffffffffffff909116602083015201610173565b34801561029f57600080fd5b506101da6102ae3660046110fd565b60666020526000908152604090205481565b3480156102cc57600080fd5b5061010d610741565b6101526102e33660046112bf565b610755565b3480156102f457600080fd5b5060335473ffffffffffffffffffffffffffffffffffffffff16610152565b34801561031f57600080fd5b506101da61032e3660046112bf565b6109ef565b34801561033f57600080fd5b5061035361034e366004611346565b610a28565b6040805163ffffffff909416845267ffffffffffffffff909216602084015273ffffffffffffffffffffffffffffffffffffffff1690820152606001610173565b3480156103a057600080fd5b5061010d6103af36600461135f565b610a91565b3480156103c057600080fd5b5061010d6103cf36600461135f565b610c2d565b6103dc610d00565b63ffffffff821660008181526065602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8616908117909155905190917fff513d80e2c7fa487608f70a618dfbc0cf415699dc69588c747e8c71566c88de91a35050565b610466610d00565b63ffffffff8216600081815260666020526040808220849055518392917f74d6665c4b26d5596a5aa13d3014e0c06af4d322075a797f87b03cd4c5bc91ca91a35050565b606854606090831015806104bc575081155b6106e7575060408051600583901b8101602001909152825b8381116106e5576000606882815481106104f0576104f061137c565b600091825260209091200154905060e081901c60a082901c67ffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff831663ffffffff891683036106b6576001865101865260008173ffffffffffffffffffffffffffffffffffffffff1663609d33346040518163ffffffff1660e01b8152600401600060405180830381865afa15801561058a573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526105d091908101906113da565b905060008273ffffffffffffffffffffffffffffffffffffffff1663bcef3b556040518163ffffffff1660e01b8152600401602060405180830381865afa15801561061f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064391906114a5565b90506040518060a001604052808881526020018781526020018567ffffffffffffffff168152602001828152602001838152508860018a5161068591906114be565b815181106106955761069561137c565b6020026020010181905250888851106106b3575050505050506106e5565b50505b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90920191506104d49050565b505b9392505050565b60008060006106ff878787876109ef565b60009081526067602052604090205473ffffffffffffffffffffffffffffffffffffffff81169860a09190911c67ffffffffffffffff16975095505050505050565b610749610d00565b6107536000610d81565b565b63ffffffff841660009081526065602052604081205473ffffffffffffffffffffffffffffffffffffffff16806107c5576040517f031c6de400000000000000000000000000000000000000000000000000000000815263ffffffff871660048201526024015b60405180910390fd5b63ffffffff86166000908152606660205260409020543414610813576040517f8620aa1900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006108206001436114be565b40905061088a338783888860405160200161083f9594939291906114fc565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905273ffffffffffffffffffffffffffffffffffffffff841690610df8565b92508273ffffffffffffffffffffffffffffffffffffffff16638129fc1c346040518263ffffffff1660e01b81526004016000604051808303818588803b1580156108d457600080fd5b505af11580156108e8573d6000803e3d6000fd5b505050505060006108fb888888886109ef565b60008181526067602052604090205490915015610947576040517f014f6fe5000000000000000000000000000000000000000000000000000000008152600481018290526024016107bc565b60004260a01b60e08a901b178517600083815260676020526040808220839055606880546001810182559083527fa2153420d844928b4421650203c77babc8b33d7f2e7b450e2966db0c220977530183905551919250899163ffffffff8c169173ffffffffffffffffffffffffffffffffffffffff8916917f5b565efe82411da98814f356d0e7bcb8f0219b8d970307c5afb4a6903a8b2e359190a450505050949350505050565b600084848484604051602001610a089493929190611549565b604051602081830303815290604052805190602001209050949350505050565b600080600080600080610a8160688881548110610a4757610a4761137c565b906000526020600020015460e081901c9160a082901c67ffffffffffffffff169173ffffffffffffffffffffffffffffffffffffffff1690565b9199909850909650945050505050565b600054610100900460ff1615808015610ab15750600054600160ff909116105b80610acb5750303b158015610acb575060005460ff166001145b610b57576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016107bc565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610bb557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610bbd610e06565b610bc682610d81565b8015610c2957600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b610c35610d00565b73ffffffffffffffffffffffffffffffffffffffff8116610cd8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016107bc565b610ce181610d81565b50565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b60335473ffffffffffffffffffffffffffffffffffffffff163314610753576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016107bc565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006106e760008484610ea5565b600054610100900460ff16610e9d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016107bc565b610753610feb565b600060608203516040830351602084035184518060208701018051600283016c5af43d3d93803e606057fd5bf3895289600d8a035278593da1005b363d3d373d3d3d3d610000806062363936013d738160481b1760218a03527f9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff603a8a035272fd6100003d81600a3d39f336602c57343d527f6062820160781b1761ff9e82106059018a03528060f01b8352606c8101604c8a038cf097505086610f715763301164256000526004601cfd5b905285527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08501527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08401527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa09092019190915292915050565b600054610100900460ff16611082576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016107bc565b61075333610d81565b803563ffffffff8116811461109f57600080fd5b919050565b73ffffffffffffffffffffffffffffffffffffffff81168114610ce157600080fd5b600080604083850312156110d957600080fd5b6110e28361108b565b915060208301356110f2816110a4565b809150509250929050565b60006020828403121561110f57600080fd5b6106e78261108b565b6000806040838503121561112b57600080fd5b6111348361108b565b946020939093013593505050565b60008060006060848603121561115757600080fd5b6111608461108b565b95602085013595506040909401359392505050565b60005b83811015611190578181015183820152602001611178565b8381111561119f576000848401525b50505050565b600081518084526111bd816020860160208601611175565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b8381101561129e578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc001855281518051845287810151888501528681015167ffffffffffffffff16878501526060808201519085015260809081015160a09185018290529061128a818601836111a5565b968901969450505090860190600101611216565b509098975050505050505050565b6020815260006106e760208301846111a5565b600080600080606085870312156112d557600080fd5b6112de8561108b565b935060208501359250604085013567ffffffffffffffff8082111561130257600080fd5b818701915087601f83011261131657600080fd5b81358181111561132557600080fd5b88602082850101111561133757600080fd5b95989497505060200194505050565b60006020828403121561135857600080fd5b5035919050565b60006020828403121561137157600080fd5b81356106e7816110a4565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156113ec57600080fd5b815167ffffffffffffffff8082111561140457600080fd5b818401915084601f83011261141857600080fd5b81518181111561142a5761142a6113ab565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611470576114706113ab565b8160405282815287602084870101111561148957600080fd5b61149a836020830160208801611175565b979650505050505050565b6000602082840312156114b757600080fd5b5051919050565b6000828210156114f7577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b500390565b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008660601b1681528460148201528360348201528183605483013760009101605401908152949350505050565b63ffffffff8516815283602082015260606040820152816060820152818360808301376000818301608090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101939250505056fea164736f6c634300080f000a"; + hex"6080604052600436106100e85760003560e01c80636593dc6e1161008a57806396cd97201161005957806396cd972014610313578063bb8aa1fc14610333578063c4d66de814610394578063f2fde38b146103b457600080fd5b80636593dc6e14610293578063715018a6146102c057806382ecf2f6146102d55780638da5cb5b146102e857600080fd5b8063254bd683116100c6578063254bd6831461019c5780634d1975b4146101c957806354fd4d50146101e85780635f0150cb1461023e57600080fd5b806314f6b1a3146100ed5780631b685b9e1461010f5780631e3342401461017c575b600080fd5b3480156100f957600080fd5b5061010d6101083660046110c6565b6103d4565b005b34801561011b57600080fd5b5061015261012a3660046110fd565b60656020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561018857600080fd5b5061010d610197366004611118565b61045e565b3480156101a857600080fd5b506101bc6101b7366004611142565b6104aa565b60405161017391906111ef565b3480156101d557600080fd5b506068545b604051908152602001610173565b3480156101f457600080fd5b506102316040518060400160405280600c81526020017f312e302e312d626574612e31000000000000000000000000000000000000000081525081565b60405161017391906112ac565b34801561024a57600080fd5b5061025e6102593660046112bf565b6106ee565b6040805173ffffffffffffffffffffffffffffffffffffffff909316835267ffffffffffffffff909116602083015201610173565b34801561029f57600080fd5b506101da6102ae3660046110fd565b60666020526000908152604090205481565b3480156102cc57600080fd5b5061010d610741565b6101526102e33660046112bf565b610755565b3480156102f457600080fd5b5060335473ffffffffffffffffffffffffffffffffffffffff16610152565b34801561031f57600080fd5b506101da61032e3660046112bf565b6109ef565b34801561033f57600080fd5b5061035361034e366004611346565b610a28565b6040805163ffffffff909416845267ffffffffffffffff909216602084015273ffffffffffffffffffffffffffffffffffffffff1690820152606001610173565b3480156103a057600080fd5b5061010d6103af36600461135f565b610a91565b3480156103c057600080fd5b5061010d6103cf36600461135f565b610c2d565b6103dc610d00565b63ffffffff821660008181526065602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8616908117909155905190917fff513d80e2c7fa487608f70a618dfbc0cf415699dc69588c747e8c71566c88de91a35050565b610466610d00565b63ffffffff8216600081815260666020526040808220849055518392917f74d6665c4b26d5596a5aa13d3014e0c06af4d322075a797f87b03cd4c5bc91ca91a35050565b606854606090831015806104bc575081155b6106e7575060408051600583901b8101602001909152825b8381116106e5576000606882815481106104f0576104f061137c565b600091825260209091200154905060e081901c60a082901c67ffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff831663ffffffff891683036106b6576001865101865260008173ffffffffffffffffffffffffffffffffffffffff1663609d33346040518163ffffffff1660e01b8152600401600060405180830381865afa15801561058a573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526105d091908101906113da565b905060008273ffffffffffffffffffffffffffffffffffffffff1663bcef3b556040518163ffffffff1660e01b8152600401602060405180830381865afa15801561061f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064391906114a5565b90506040518060a001604052808881526020018781526020018567ffffffffffffffff168152602001828152602001838152508860018a5161068591906114be565b815181106106955761069561137c565b6020026020010181905250888851106106b3575050505050506106e5565b50505b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90920191506104d49050565b505b9392505050565b60008060006106ff878787876109ef565b60009081526067602052604090205473ffffffffffffffffffffffffffffffffffffffff81169860a09190911c67ffffffffffffffff16975095505050505050565b610749610d00565b6107536000610d81565b565b63ffffffff841660009081526065602052604081205473ffffffffffffffffffffffffffffffffffffffff16806107c5576040517f031c6de400000000000000000000000000000000000000000000000000000000815263ffffffff871660048201526024015b60405180910390fd5b63ffffffff86166000908152606660205260409020543414610813576040517f8620aa1900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006108206001436114be565b40905061088a338783888860405160200161083f9594939291906114fc565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905273ffffffffffffffffffffffffffffffffffffffff841690610df8565b92508273ffffffffffffffffffffffffffffffffffffffff16638129fc1c346040518263ffffffff1660e01b81526004016000604051808303818588803b1580156108d457600080fd5b505af11580156108e8573d6000803e3d6000fd5b505050505060006108fb888888886109ef565b60008181526067602052604090205490915015610947576040517f014f6fe5000000000000000000000000000000000000000000000000000000008152600481018290526024016107bc565b60004260a01b60e08a901b178517600083815260676020526040808220839055606880546001810182559083527fa2153420d844928b4421650203c77babc8b33d7f2e7b450e2966db0c220977530183905551919250899163ffffffff8c169173ffffffffffffffffffffffffffffffffffffffff8916917f5b565efe82411da98814f356d0e7bcb8f0219b8d970307c5afb4a6903a8b2e359190a450505050949350505050565b600084848484604051602001610a089493929190611549565b604051602081830303815290604052805190602001209050949350505050565b600080600080600080610a8160688881548110610a4757610a4761137c565b906000526020600020015460e081901c9160a082901c67ffffffffffffffff169173ffffffffffffffffffffffffffffffffffffffff1690565b9199909850909650945050505050565b600054610100900460ff1615808015610ab15750600054600160ff909116105b80610acb5750303b158015610acb575060005460ff166001145b610b57576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016107bc565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610bb557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610bbd610e06565b610bc682610d81565b8015610c2957600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b610c35610d00565b73ffffffffffffffffffffffffffffffffffffffff8116610cd8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016107bc565b610ce181610d81565b50565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b60335473ffffffffffffffffffffffffffffffffffffffff163314610753576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016107bc565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006106e760008484610ea5565b600054610100900460ff16610e9d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016107bc565b610753610feb565b600060608203516040830351602084035184518060208701018051600283016c5af43d3d93803e606057fd5bf3895289600d8a035278593da1005b363d3d373d3d3d3d610000806062363936013d738160481b1760218a03527f9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff603a8a035272fd6100003d81600a3d39f336602c57343d527f6062820160781b1761ff9e82106059018a03528060f01b8352606c8101604c8a038cf097505086610f715763301164256000526004601cfd5b905285527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08501527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08401527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa09092019190915292915050565b600054610100900460ff16611082576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016107bc565b61075333610d81565b803563ffffffff8116811461109f57600080fd5b919050565b73ffffffffffffffffffffffffffffffffffffffff81168114610ce157600080fd5b600080604083850312156110d957600080fd5b6110e28361108b565b915060208301356110f2816110a4565b809150509250929050565b60006020828403121561110f57600080fd5b6106e78261108b565b6000806040838503121561112b57600080fd5b6111348361108b565b946020939093013593505050565b60008060006060848603121561115757600080fd5b6111608461108b565b95602085013595506040909401359392505050565b60005b83811015611190578181015183820152602001611178565b8381111561119f576000848401525b50505050565b600081518084526111bd816020860160208601611175565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b8381101561129e578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc001855281518051845287810151888501528681015167ffffffffffffffff16878501526060808201519085015260809081015160a09185018290529061128a818601836111a5565b968901969450505090860190600101611216565b509098975050505050505050565b6020815260006106e760208301846111a5565b600080600080606085870312156112d557600080fd5b6112de8561108b565b935060208501359250604085013567ffffffffffffffff8082111561130257600080fd5b818701915087601f83011261131657600080fd5b81358181111561132557600080fd5b88602082850101111561133757600080fd5b95989497505060200194505050565b60006020828403121561135857600080fd5b5035919050565b60006020828403121561137157600080fd5b81356106e7816110a4565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156113ec57600080fd5b815167ffffffffffffffff8082111561140457600080fd5b818401915084601f83011261141857600080fd5b81518181111561142a5761142a6113ab565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611470576114706113ab565b8160405282815287602084870101111561148957600080fd5b61149a836020830160208801611175565b979650505050505050565b6000602082840312156114b757600080fd5b5051919050565b6000828210156114f7577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b500390565b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008660601b1681528460148201528360348201528183605483013760009101605401908152949350505050565b63ffffffff8516815283602082015260606040820152816060820152818360808301376000818301608090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101939250505056fea164736f6c634300080f000a"; bytes internal constant delayedWETHCode = - hex"6080604052600436106101845760003560e01c8063715018a6116100d6578063a9059cbb1161007f578063dd62ed3e11610059578063dd62ed3e1461051c578063f2fde38b14610554578063f3fef3a31461057457610193565b8063a9059cbb146104a8578063cd47bde1146104c8578063d0e30db01461019357610193565b80638da5cb5b116100b05780638da5cb5b1461041757806395d89b4114610442578063977a5ec51461048857610193565b8063715018a61461039057806379502c55146103a55780637eee288d146103f757610193565b80632e1a7d4d1161013857806354fd4d501161011257806354fd4d50146102e75780636a42b8f81461033057806370a082311461036357610193565b80632e1a7d4d14610280578063313ce567146102a0578063485cc955146102c757610193565b80630ca35682116101695780630ca356821461022357806318160ddd1461024357806323b872dd1461026057610193565b806306fdde031461019b578063095ea7b3146101f357610193565b3661019357610191610594565b005b610191610594565b3480156101a757600080fd5b5060408051808201909152600d81527f577261707065642045746865720000000000000000000000000000000000000060208201525b6040516101ea91906113fd565b60405180910390f35b3480156101ff57600080fd5b5061021361020e366004611492565b6105ef565b60405190151581526020016101ea565b34801561022f57600080fd5b5061019161023e3660046114be565b610668565b34801561024f57600080fd5b50475b6040519081526020016101ea565b34801561026c57600080fd5b5061021361027b3660046114d7565b6107b9565b34801561028c57600080fd5b5061019161029b3660046114be565b6109d0565b3480156102ac57600080fd5b506102b5601281565b60405160ff90911681526020016101ea565b3480156102d357600080fd5b506101916102e2366004611518565b6109dd565b3480156102f357600080fd5b506101dd6040518060400160405280600a81526020017f312e312e302d72632e310000000000000000000000000000000000000000000081525081565b34801561033c57600080fd5b507f0000000000000000000000000000000000000000000000000000000000093a80610252565b34801561036f57600080fd5b5061025261037e366004611551565b60656020526000908152604090205481565b34801561039c57600080fd5b50610191610bb9565b3480156103b157600080fd5b506068546103d29073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101ea565b34801561040357600080fd5b50610191610412366004611492565b610bcd565b34801561042357600080fd5b5060335473ffffffffffffffffffffffffffffffffffffffff166103d2565b34801561044e57600080fd5b5060408051808201909152600481527f574554480000000000000000000000000000000000000000000000000000000060208201526101dd565b34801561049457600080fd5b506101916104a3366004611492565b610c21565b3480156104b457600080fd5b506102136104c3366004611492565b610d0e565b3480156104d457600080fd5b506105076104e3366004611518565b60676020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016101ea565b34801561052857600080fd5b50610252610537366004611518565b606660209081526000928352604080842090915290825290205481565b34801561056057600080fd5b5061019161056f366004611551565b610d22565b34801561058057600080fd5b5061019161058f366004611492565b610dd6565b33600090815260656020526040812080543492906105b390849061159d565b909155505060405134815233907fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9060200160405180910390a2565b33600081815260666020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906106579086815260200190565b60405180910390a350600192915050565b60335473ffffffffffffffffffffffffffffffffffffffff1633146106ee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f44656c61796564574554483a206e6f74206f776e65720000000000000000000060448201526064015b60405180910390fd5b60004782106106fd57476106ff565b815b604051909150600090339083908381818185875af1925050503d8060008114610744576040519150601f19603f3d011682016040523d82523d6000602084013e610749565b606091505b50509050806107b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f44656c61796564574554483a207265636f766572206661696c6564000000000060448201526064016106e5565b505050565b73ffffffffffffffffffffffffffffffffffffffff83166000908152606560205260408120548211156107eb57600080fd5b73ffffffffffffffffffffffffffffffffffffffff84163314801590610861575073ffffffffffffffffffffffffffffffffffffffff841660009081526066602090815260408083203384529091529020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14155b156108e95773ffffffffffffffffffffffffffffffffffffffff841660009081526066602090815260408083203384529091529020548211156108a357600080fd5b73ffffffffffffffffffffffffffffffffffffffff84166000908152606660209081526040808320338452909152812080548492906108e39084906115b5565b90915550505b73ffffffffffffffffffffffffffffffffffffffff84166000908152606560205260408120805484929061091e9084906115b5565b909155505073ffffffffffffffffffffffffffffffffffffffff83166000908152606560205260408120805484929061095890849061159d565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516109be91815260200190565b60405180910390a35060019392505050565b6109da3382610dd6565b50565b600054610100900460ff16158080156109fd5750600054600160ff909116105b80610a175750303b158015610a17575060005460ff166001145b610aa3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016106e5565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610b0157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610b09611120565b610b12836111bf565b606880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff841617905580156107b457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a1505050565b610bc1611236565b610bcb60006111bf565b565b33600090815260676020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091528120426001820155805490918391839190610c1790849061159d565b9091555050505050565b60335473ffffffffffffffffffffffffffffffffffffffff163314610ca2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f44656c61796564574554483a206e6f74206f776e65720000000000000000000060448201526064016106e5565b73ffffffffffffffffffffffffffffffffffffffff821660008181526066602090815260408083203380855290835292819020859055518481529192917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a35050565b6000610d1b3384846107b9565b9392505050565b610d2a611236565b73ffffffffffffffffffffffffffffffffffffffff8116610dcd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016106e5565b6109da816111bf565b606860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e6791906115cc565b15610ece576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f44656c61796564574554483a20636f6e7472616374206973207061757365640060448201526064016106e5565b33600090815260676020908152604080832073ffffffffffffffffffffffffffffffffffffffff8616845290915290208054821115610f8f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f44656c61796564574554483a20696e73756666696369656e7420756e6c6f636b60448201527f6564207769746864726177616c0000000000000000000000000000000000000060648201526084016106e5565b6000816001015411611022576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f44656c61796564574554483a207769746864726177616c206e6f7420756e6c6f60448201527f636b65640000000000000000000000000000000000000000000000000000000060648201526084016106e5565b427f0000000000000000000000000000000000000000000000000000000000093a808260010154611053919061159d565b11156110e1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f44656c61796564574554483a207769746864726177616c2064656c6179206e6f60448201527f74206d657400000000000000000000000000000000000000000000000000000060648201526084016106e5565b818160000160008282546110f591906115b5565b909155506107b49050826112b7565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b600054610100900460ff166111b7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016106e5565b610bcb61135d565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60335473ffffffffffffffffffffffffffffffffffffffff163314610bcb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106e5565b336000908152606560205260409020548111156112d357600080fd5b33600090815260656020526040812080548392906112f29084906115b5565b9091555050604051339082156108fc029083906000818181858888f19350505050158015611324573d6000803e3d6000fd5b5060405181815233907f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b659060200160405180910390a250565b600054610100900460ff166113f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016106e5565b610bcb336111bf565b600060208083528351808285015260005b8181101561142a5785810183015185820160400152820161140e565b8181111561143c576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b73ffffffffffffffffffffffffffffffffffffffff811681146109da57600080fd5b600080604083850312156114a557600080fd5b82356114b081611470565b946020939093013593505050565b6000602082840312156114d057600080fd5b5035919050565b6000806000606084860312156114ec57600080fd5b83356114f781611470565b9250602084013561150781611470565b929592945050506040919091013590565b6000806040838503121561152b57600080fd5b823561153681611470565b9150602083013561154681611470565b809150509250929050565b60006020828403121561156357600080fd5b8135610d1b81611470565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156115b0576115b061156e565b500190565b6000828210156115c7576115c761156e565b500390565b6000602082840312156115de57600080fd5b81518015158114610d1b57600080fdfea164736f6c634300080f000a"; + hex"6080604052600436106101845760003560e01c8063715018a6116100d6578063a9059cbb1161007f578063dd62ed3e11610059578063dd62ed3e1461051c578063f2fde38b14610554578063f3fef3a31461057457610193565b8063a9059cbb146104a8578063cd47bde1146104c8578063d0e30db01461019357610193565b80638da5cb5b116100b05780638da5cb5b1461041757806395d89b4114610442578063977a5ec51461048857610193565b8063715018a61461039057806379502c55146103a55780637eee288d146103f757610193565b80632e1a7d4d1161013857806354fd4d501161011257806354fd4d50146102e75780636a42b8f81461033057806370a082311461036357610193565b80632e1a7d4d14610280578063313ce567146102a0578063485cc955146102c757610193565b80630ca35682116101695780630ca356821461022357806318160ddd1461024357806323b872dd1461026057610193565b806306fdde031461019b578063095ea7b3146101f357610193565b3661019357610191610594565b005b610191610594565b3480156101a757600080fd5b5060408051808201909152600d81527f577261707065642045746865720000000000000000000000000000000000000060208201525b6040516101ea91906113fd565b60405180910390f35b3480156101ff57600080fd5b5061021361020e366004611492565b6105ef565b60405190151581526020016101ea565b34801561022f57600080fd5b5061019161023e3660046114be565b610668565b34801561024f57600080fd5b50475b6040519081526020016101ea565b34801561026c57600080fd5b5061021361027b3660046114d7565b6107b9565b34801561028c57600080fd5b5061019161029b3660046114be565b6109d0565b3480156102ac57600080fd5b506102b5601281565b60405160ff90911681526020016101ea565b3480156102d357600080fd5b506101916102e2366004611518565b6109dd565b3480156102f357600080fd5b506101dd6040518060400160405280600c81526020017f312e312e312d626574612e32000000000000000000000000000000000000000081525081565b34801561033c57600080fd5b507f0000000000000000000000000000000000000000000000000000000000093a80610252565b34801561036f57600080fd5b5061025261037e366004611551565b60656020526000908152604090205481565b34801561039c57600080fd5b50610191610bb9565b3480156103b157600080fd5b506068546103d29073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101ea565b34801561040357600080fd5b50610191610412366004611492565b610bcd565b34801561042357600080fd5b5060335473ffffffffffffffffffffffffffffffffffffffff166103d2565b34801561044e57600080fd5b5060408051808201909152600481527f574554480000000000000000000000000000000000000000000000000000000060208201526101dd565b34801561049457600080fd5b506101916104a3366004611492565b610c21565b3480156104b457600080fd5b506102136104c3366004611492565b610d0e565b3480156104d457600080fd5b506105076104e3366004611518565b60676020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016101ea565b34801561052857600080fd5b50610252610537366004611518565b606660209081526000928352604080842090915290825290205481565b34801561056057600080fd5b5061019161056f366004611551565b610d22565b34801561058057600080fd5b5061019161058f366004611492565b610dd6565b33600090815260656020526040812080543492906105b390849061159d565b909155505060405134815233907fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9060200160405180910390a2565b33600081815260666020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906106579086815260200190565b60405180910390a350600192915050565b60335473ffffffffffffffffffffffffffffffffffffffff1633146106ee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f44656c61796564574554483a206e6f74206f776e65720000000000000000000060448201526064015b60405180910390fd5b60004782106106fd57476106ff565b815b604051909150600090339083908381818185875af1925050503d8060008114610744576040519150601f19603f3d011682016040523d82523d6000602084013e610749565b606091505b50509050806107b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f44656c61796564574554483a207265636f766572206661696c6564000000000060448201526064016106e5565b505050565b73ffffffffffffffffffffffffffffffffffffffff83166000908152606560205260408120548211156107eb57600080fd5b73ffffffffffffffffffffffffffffffffffffffff84163314801590610861575073ffffffffffffffffffffffffffffffffffffffff841660009081526066602090815260408083203384529091529020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14155b156108e95773ffffffffffffffffffffffffffffffffffffffff841660009081526066602090815260408083203384529091529020548211156108a357600080fd5b73ffffffffffffffffffffffffffffffffffffffff84166000908152606660209081526040808320338452909152812080548492906108e39084906115b5565b90915550505b73ffffffffffffffffffffffffffffffffffffffff84166000908152606560205260408120805484929061091e9084906115b5565b909155505073ffffffffffffffffffffffffffffffffffffffff83166000908152606560205260408120805484929061095890849061159d565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516109be91815260200190565b60405180910390a35060019392505050565b6109da3382610dd6565b50565b600054610100900460ff16158080156109fd5750600054600160ff909116105b80610a175750303b158015610a17575060005460ff166001145b610aa3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016106e5565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610b0157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610b09611120565b610b12836111bf565b606880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff841617905580156107b457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a1505050565b610bc1611236565b610bcb60006111bf565b565b33600090815260676020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091528120426001820155805490918391839190610c1790849061159d565b9091555050505050565b60335473ffffffffffffffffffffffffffffffffffffffff163314610ca2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f44656c61796564574554483a206e6f74206f776e65720000000000000000000060448201526064016106e5565b73ffffffffffffffffffffffffffffffffffffffff821660008181526066602090815260408083203380855290835292819020859055518481529192917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a35050565b6000610d1b3384846107b9565b9392505050565b610d2a611236565b73ffffffffffffffffffffffffffffffffffffffff8116610dcd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016106e5565b6109da816111bf565b606860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e6791906115cc565b15610ece576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f44656c61796564574554483a20636f6e7472616374206973207061757365640060448201526064016106e5565b33600090815260676020908152604080832073ffffffffffffffffffffffffffffffffffffffff8616845290915290208054821115610f8f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f44656c61796564574554483a20696e73756666696369656e7420756e6c6f636b60448201527f6564207769746864726177616c0000000000000000000000000000000000000060648201526084016106e5565b6000816001015411611022576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f44656c61796564574554483a207769746864726177616c206e6f7420756e6c6f60448201527f636b65640000000000000000000000000000000000000000000000000000000060648201526084016106e5565b427f0000000000000000000000000000000000000000000000000000000000093a808260010154611053919061159d565b11156110e1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f44656c61796564574554483a207769746864726177616c2064656c6179206e6f60448201527f74206d657400000000000000000000000000000000000000000000000000000060648201526084016106e5565b818160000160008282546110f591906115b5565b909155506107b49050826112b7565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b600054610100900460ff166111b7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016106e5565b610bcb61135d565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60335473ffffffffffffffffffffffffffffffffffffffff163314610bcb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106e5565b336000908152606560205260409020548111156112d357600080fd5b33600090815260656020526040812080548392906112f29084906115b5565b9091555050604051339082156108fc029083906000818181858888f19350505050158015611324573d6000803e3d6000fd5b5060405181815233907f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b659060200160405180910390a250565b600054610100900460ff166113f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016106e5565b610bcb336111bf565b600060208083528351808285015260005b8181101561142a5785810183015185820160400152820161140e565b8181111561143c576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b73ffffffffffffffffffffffffffffffffffffffff811681146109da57600080fd5b600080604083850312156114a557600080fd5b82356114b081611470565b946020939093013593505050565b6000602082840312156114d057600080fd5b5035919050565b6000806000606084860312156114ec57600080fd5b83356114f781611470565b9250602084013561150781611470565b929592945050506040919091013590565b6000806040838503121561152b57600080fd5b823561153681611470565b9150602083013561154681611470565b809150509250929050565b60006020828403121561156357600080fd5b8135610d1b81611470565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156115b0576115b061156e565b500190565b6000828210156115c7576115c761156e565b500390565b6000602082840312156115de57600080fd5b81518015158114610d1b57600080fdfea164736f6c634300080f000a"; bytes internal constant preimageOracleCode = - hex"6080604052600436106101d85760003560e01c80639d53a64811610102578063ddcd58de11610095578063ec5efcbc11610064578063ec5efcbc14610681578063f3f480d9146106a1578063faf37bc7146106d4578063fef2b4ed146106e757600080fd5b8063ddcd58de146105d4578063e03110e11461060c578063e159261114610641578063ea7139501461066157600080fd5b8063b5e7154c116100d1578063b5e7154c14610555578063d18534b51461056c578063da35c6641461058c578063dd24f9bf146105a157600080fd5b80639d53a6481461048e5780639d7e8769146104dd578063b2e67ba8146104fd578063b4801e611461053557600080fd5b806361238bde1161017a5780637ac54767116101495780637ac54767146103ca5780638542cf50146103ea578063882856ef146104355780638dc4be111461046e57600080fd5b806361238bde1461031e5780636551927b146103565780637051472e1461038e5780637917de1d146103aa57600080fd5b80633909af5c116101b65780633909af5c146102715780634d52b4c91461029357806352f0f3ad146102a857806354fd4d50146102c857600080fd5b8063013cf08b146101dd5780630359a5631461022e5780632055b36b1461025c575b600080fd5b3480156101e957600080fd5b506101fd6101f8366004612e29565b610714565b6040805173ffffffffffffffffffffffffffffffffffffffff90931683526020830191909152015b60405180910390f35b34801561023a57600080fd5b5061024e610249366004612e6b565b610759565b604051908152602001610225565b34801561026857600080fd5b5061024e601081565b34801561027d57600080fd5b5061029161028c366004613073565b610891565b005b34801561029f57600080fd5b5061024e610ae8565b3480156102b457600080fd5b5061024e6102c336600461315f565b610b03565b3480156102d457600080fd5b506103116040518060400160405280600a81526020017f312e312e322d72632e310000000000000000000000000000000000000000000081525081565b60405161022591906131c6565b34801561032a57600080fd5b5061024e610339366004613217565b600160209081526000928352604080842090915290825290205481565b34801561036257600080fd5b5061024e610371366004612e6b565b601560209081526000928352604080842090915290825290205481565b34801561039a57600080fd5b5061024e6703782dace9d9000081565b3480156103b657600080fd5b506102916103c536600461327b565b610bd9565b3480156103d657600080fd5b5061024e6103e5366004612e29565b6110dc565b3480156103f657600080fd5b50610425610405366004613217565b600260209081526000928352604080842090915290825290205460ff1681565b6040519015158152602001610225565b34801561044157600080fd5b50610455610450366004613317565b6110f3565b60405167ffffffffffffffff9091168152602001610225565b34801561047a57600080fd5b5061029161048936600461334a565b61114d565b34801561049a57600080fd5b5061024e6104a9366004612e6b565b73ffffffffffffffffffffffffffffffffffffffff9091166000908152601860209081526040808320938352929052205490565b3480156104e957600080fd5b506102916104f8366004613396565b611248565b34801561050957600080fd5b5061024e610518366004612e6b565b601760209081526000928352604080842090915290825290205481565b34801561054157600080fd5b5061024e610550366004613317565b6113ff565b34801561056157600080fd5b5061024e620186a081565b34801561057857600080fd5b50610291610587366004613073565b611431565b34801561059857600080fd5b5060135461024e565b3480156105ad57600080fd5b507f000000000000000000000000000000000000000000000000000000000000271061024e565b3480156105e057600080fd5b5061024e6105ef366004612e6b565b601660209081526000928352604080842090915290825290205481565b34801561061857600080fd5b5061062c610627366004613217565b611840565b60408051928352602083019190915201610225565b34801561064d57600080fd5b5061029161065c36600461334a565b611931565b34801561066d57600080fd5b5061029161067c366004613422565b611a39565b34801561068d57600080fd5b5061029161069c366004613491565b611b98565b3480156106ad57600080fd5b507f000000000000000000000000000000000000000000000000000000000000007861024e565b6102916106e2366004613519565b611d1e565b3480156106f357600080fd5b5061024e610702366004612e29565b60006020819052908152604090205481565b6013818154811061072457600080fd5b60009182526020909120600290910201805460019091015473ffffffffffffffffffffffffffffffffffffffff909116915082565b73ffffffffffffffffffffffffffffffffffffffff82166000908152601560209081526040808320848452909152812054819061079c9060601c63ffffffff1690565b63ffffffff16905060005b6010811015610889578160011660010361082f5773ffffffffffffffffffffffffffffffffffffffff85166000908152601460209081526040808320878452909152902081601081106107fc576107fc613555565b01546040805160208101929092528101849052606001604051602081830303815290604052805190602001209250610870565b826003826010811061084357610843613555565b01546040805160208101939093528201526060016040516020818303038152906040528051906020012092505b60019190911c9080610881816135b3565b9150506107a7565b505092915050565b600061089d8a8a610759565b90506108c086868360208b01356108bb6108b68d6135eb565b611fea565b61202a565b80156108de57506108de83838360208801356108bb6108b68a6135eb565b610914576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b86604001358860405160200161092a91906136ba565b6040516020818303038152906040528051906020012014610977576040517f1968a90200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83602001358760200135600161098d91906136f8565b146109c4576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a0c886109d28680613710565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061208b92505050565b610a15886121e6565b836040013588604051602001610a2b91906136ba565b6040516020818303038152906040528051906020012003610a78576040517f9843145b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8a1660009081526015602090815260408083208c8452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000166001179055610adc8a8a3361298e565b50505050505050505050565b6001610af660106002613897565b610b0091906138a3565b81565b6000610b0f8686612a47565b9050610b1c8360086136f8565b82101580610b2a5750602083115b15610b61576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000602081815260c085901b82526008959095528251828252600286526040808320858452875280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558484528752808320948352938652838220558181529384905292205592915050565b60608115610bf257610beb8686612af4565b9050610c2c565b85858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050505b3360009081526014602090815260408083208b845290915280822081516102008101928390529160109082845b815481526020019060010190808311610c5957505050505090506000601560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008b81526020019081526020016000205490506000610cda8260601c63ffffffff1690565b63ffffffff169050333214610d1b576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d2b8260801c63ffffffff1690565b63ffffffff16600003610d6a576040517f87138d5c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d748260c01c90565b67ffffffffffffffff1615610db5576040517f475a253500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b898114610dee576040517f60f95d5a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610dfb89898d8886612b6d565b83516020850160888204881415608883061715610e20576307b1daf16000526004601cfd5b60405160c8810160405260005b83811015610ed0578083018051835260208101516020840152604081015160408401526060810151606084015260808101516080840152508460888301526088810460051b8b013560a883015260c882206001860195508560005b610200811015610ec5576001821615610ea55782818b0152610ec5565b8981015160009081526020938452604090209260019290921c9101610e88565b505050608801610e2d565b50505050600160106002610ee49190613897565b610eee91906138a3565b811115610f27576040517f6229572300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f9c610f3a8360401c63ffffffff1690565b610f4a9063ffffffff168a6136f8565b60401b7fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff606084901b167fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff8516171790565b915084156110295777ffffffffffffffffffffffffffffffffffffffffffffffff82164260c01b179150610fd68260801c63ffffffff1690565b63ffffffff16610fec8360401c63ffffffff1690565b63ffffffff1614611029576040517f7b1dafd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360009081526014602090815260408083208e8452909152902061104f90846010612d9f565b503360008181526018602090815260408083208f8452825280832080546001810182559084528284206004820401805460039092166008026101000a67ffffffffffffffff818102199093164390931602919091179055838352601582528083208f8452909152812084905560609190911b81523690601437366014016000a05050505050505050505050565b600381601081106110ec57600080fd5b0154905081565b6018602052826000526040600020602052816000526040600020818154811061111b57600080fd5b906000526020600020906004918282040191900660080292509250509054906101000a900467ffffffffffffffff1681565b60443560008060088301861061116b5763fe2549876000526004601cfd5b60c083901b60805260888386823786600882030151915060206000858360025afa90508061119857600080fd5b50600080517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0400000000000000000000000000000000000000000000000000000000000000178082526002602090815260408084208a8552825280842080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558385528252808420998452988152888320939093558152908190529490942055505050565b600080603087600037602060006030600060025afa806112705763f91129696000526004601cfd5b6000517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f010000000000000000000000000000000000000000000000000000000000000017608081815260a08c905260c08b905260308a60e037603088609083013760008060c083600a5afa9250826112f2576309bde3396000526004601cfd5b602886106113085763fe2549876000526004601cfd5b6000602882015278200000000000000000000000000000000000000000000000008152600881018b905285810151935060308a8237603081019b909b52505060509098207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0500000000000000000000000000000000000000000000000000000000000000176000818152600260209081526040808320868452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845282528083209583529481528482209a909a559081528089529190912096909655505050505050565b6014602052826000526040600020602052816000526040600020816010811061142757600080fd5b0154925083915050565b73ffffffffffffffffffffffffffffffffffffffff891660009081526015602090815260408083208b845290915290205467ffffffffffffffff8116156114a4576040517fc334f06900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6114ae8160c01c90565b67ffffffffffffffff166000036114f1576040517f55d4cbf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000007861151c8260c01c90565b6115309067ffffffffffffffff16426138a3565b11611567576040517f55d4cbf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006115738b8b610759565b905061158c87878360208c01356108bb6108b68e6135eb565b80156115aa57506115aa84848360208901356108bb6108b68b6135eb565b6115e0576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8760400135896040516020016115f691906136ba565b6040516020818303038152906040528051906020012014611643576040517f1968a90200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84602001358860200135600161165991906136f8565b14158061168b575060016116738360601c63ffffffff1690565b61167d91906138ba565b63ffffffff16856020013514155b156116c2576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6116d0896109d28780613710565b6116d9896121e6565b60006116e48a612cc0565b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0200000000000000000000000000000000000000000000000000000000000000179050600061173b8460a01c63ffffffff1690565b67ffffffffffffffff169050600160026000848152602001908152602001600020600083815260200190815260200160002060006101000a81548160ff021916908315150217905550601760008e73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008d8152602001908152602001600020546001600084815260200190815260200160002060008381526020019081526020016000208190555061180d8460801c63ffffffff1690565b600083815260208190526040902063ffffffff9190911690556118318d8d8161298e565b50505050505050505050505050565b6000828152600260209081526040808320848452909152812054819060ff166118c9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f7072652d696d616765206d757374206578697374000000000000000000000000604482015260640160405180910390fd5b50600083815260208181526040909120546118e58160086136f8565b6118f08560206136f8565b1061190e57836119018260086136f8565b61190b91906138a3565b91505b506000938452600160209081526040808620948652939052919092205492909150565b60443560008060088301861061194f5763fe2549876000526004601cfd5b60c083901b6080526088838682378087017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80151908490207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f02000000000000000000000000000000000000000000000000000000000000001760008181526002602090815260408083208b8452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845282528083209a83529981528982209390935590815290819052959095209190915550505050565b60008060008060808860601b81528760c01b6014820152858782601c0137601c860181207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0600000000000000000000000000000000000000000000000000000000000000179350604088026260216001603f5a021015611ac35763dd629f866000526004601cfd5b6000808783601c018c5afa94503d6001019150600882018a10611aee5763fe2549876000526004601cfd5b60c082901b81526008018481533d6000600183013e89017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8015160008481526002602090815260408083208d8452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915587845282528083209c83529b81528b8220929092559384528390529790912096909655505050505050565b6000611ba48686610759565b9050611bbd83838360208801356108bb6108b68a6135eb565b611bf3576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602084013515611c2f576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611c37612ddd565b611c45816109d28780613710565b611c4e816121e6565b846040013581604051602001611c6491906136ba565b6040516020818303038152906040528051906020012003611cb1576040517f9843145b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff87166000908152601560209081526040808320898452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000166001179055611d1587873361298e565b50505050505050565b6703782dace9d90000341015611d60576040517fe92c469f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b333214611d99576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611da48160086138df565b63ffffffff168263ffffffff1610611de8576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000027108163ffffffff161015611e48576040517f7b1dafd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152601560209081526040808320868452909152902054611e738160801c63ffffffff1690565b63ffffffff1615611eb0576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b608082901b7fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff60a085901b167fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff83161717336000818152601560209081526040808320898452825280832094909455835180850185528381528082018981526013805460018101825590855291517f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a090600290930292830180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909216919091179055517f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a0919091015591815260168252828120968152959052909320349055505050565b600081600001518260200151836040015160405160200161200d93929190613907565b604051602081830303815290604052805190602001209050919050565b60008160005b601081101561207e578060051b880135600186831c16600181146120635760008481526020839052604090209350612074565b600082815260208590526040902093505b5050600101612030565b5090931495945050505050565b608881511461209957600080fd5b602081016020830161211a565b8260031b8201518060001a8160011a60081b178160021a60101b8260031a60181b17178160041a60201b8260051a60281b178260061a60301b8360071a60381b1717179050612114816120ff868560059190911b015190565b1867ffffffffffffffff16600586901b840152565b50505050565b612126600083836120a6565b612132600183836120a6565b61213e600283836120a6565b61214a600383836120a6565b612156600483836120a6565b612162600583836120a6565b61216e600683836120a6565b61217a600783836120a6565b612186600883836120a6565b612192600983836120a6565b61219e600a83836120a6565b6121aa600b83836120a6565b6121b6600c83836120a6565b6121c2600d83836120a6565b6121ce600e83836120a6565b6121da600f83836120a6565b612114601083836120a6565b6040805178010000000000008082800000000000808a8000000080008000602082015279808b00000000800000018000000080008081800000000000800991810191909152788a00000000000000880000000080008009000000008000000a60608201527b8000808b800000000000008b8000000000008089800000000000800360808201527f80000000000080028000000000000080000000000000800a800000008000000a60a08201527f800000008000808180000000000080800000000080000001800000008000800860c082015260009060e0016040516020818303038152906040529050602082016020820161286e565b6102808101516101e082015161014083015160a0840151845118189118186102a082015161020083015161016084015160c0850151602086015118189118186102c083015161022084015161018085015160e0860151604087015118189118186102e08401516102408501516101a0860151610100870151606088015118189118186103008501516102608601516101c0870151610120880151608089015118189118188084603f1c6123998660011b67ffffffffffffffff1690565b18188584603f1c6123b48660011b67ffffffffffffffff1690565b18188584603f1c6123cf8660011b67ffffffffffffffff1690565b181895508483603f1c6123ec8560011b67ffffffffffffffff1690565b181894508387603f1c6124098960011b67ffffffffffffffff1690565b60208b01518b51861867ffffffffffffffff168c5291189190911897508118600181901b603f9190911c18935060c08801518118601481901c602c9190911b1867ffffffffffffffff1660208901526101208801518718602c81901c60149190911b1867ffffffffffffffff1660c08901526102c08801518618600381901c603d9190911b1867ffffffffffffffff166101208901526101c08801518718601981901c60279190911b1867ffffffffffffffff166102c08901526102808801518218602e81901c60129190911b1867ffffffffffffffff166101c089015260408801518618600281901c603e9190911b1867ffffffffffffffff166102808901526101808801518618601581901c602b9190911b1867ffffffffffffffff1660408901526101a08801518518602781901c60199190911b1867ffffffffffffffff166101808901526102608801518718603881901c60089190911b1867ffffffffffffffff166101a08901526102e08801518518600881901c60389190911b1867ffffffffffffffff166102608901526101e08801518218601781901c60299190911b1867ffffffffffffffff166102e089015260808801518718602581901c601b9190911b1867ffffffffffffffff166101e08901526103008801518718603281901c600e9190911b1867ffffffffffffffff1660808901526102a08801518118603e81901c60029190911b1867ffffffffffffffff166103008901526101008801518518600981901c60379190911b1867ffffffffffffffff166102a08901526102008801518118601381901c602d9190911b1867ffffffffffffffff1661010089015260a08801518218601c81901c60249190911b1867ffffffffffffffff1661020089015260608801518518602481901c601c9190911b1867ffffffffffffffff1660a08901526102408801518518602b81901c60159190911b1867ffffffffffffffff1660608901526102208801518618603181901c600f9190911b1867ffffffffffffffff166102408901526101608801518118603681901c600a9190911b1867ffffffffffffffff166102208901525060e08701518518603a81901c60069190911b1867ffffffffffffffff166101608801526101408701518118603d81901c60039190911b1867ffffffffffffffff1660e0880152505067ffffffffffffffff81166101408601525b5050505050565b600582811b8201805160018501831b8401805160028701851b8601805160038901871b8801805160048b0190981b8901805167ffffffffffffffff861985168918811690995283198a16861889169096528819861683188816909352841986168818871690528419831684189095169052919391929190611d15565b612808600082612781565b612813600582612781565b61281e600a82612781565b612829600f82612781565b612834601482612781565b50565b612840816122dc565b612849816127fd565b600383901b820151815160c09190911c9061211490821867ffffffffffffffff168352565b61287a60008284612837565b61288660018284612837565b61289260028284612837565b61289e60038284612837565b6128aa60048284612837565b6128b660058284612837565b6128c260068284612837565b6128ce60078284612837565b6128da60088284612837565b6128e660098284612837565b6128f2600a8284612837565b6128fe600b8284612837565b61290a600c8284612837565b612916600d8284612837565b612922600e8284612837565b61292e600f8284612837565b61293a60108284612837565b61294660118284612837565b61295260128284612837565b61295e60138284612837565b61296a60148284612837565b61297660158284612837565b61298260168284612837565b61211460178284612837565b73ffffffffffffffffffffffffffffffffffffffff83811660009081526016602090815260408083208684529091528082208054908390559051909284169083908381818185875af1925050503d8060008114612a07576040519150601f19603f3d011682016040523d82523d6000602084013e612a0c565b606091505b505090508061277a576040517f83e6cc6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f01000000000000000000000000000000000000000000000000000000000000007effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831617612aed818360408051600093845233602052918152606090922091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790565b9392505050565b6060604051905081602082018181018286833760888306808015612b3d5760888290038501848101848103803687375060806001820353506001845160001a1784538652612b54565b608836843760018353608060878401536088850186525b5050505050601f19603f82510116810160405292915050565b6000612b7f8260a01c63ffffffff1690565b67ffffffffffffffff1690506000612b9d8360801c63ffffffff1690565b63ffffffff1690506000612bb78460401c63ffffffff1690565b63ffffffff169050600883108015612bcd575080155b15612c015760c082901b6000908152883560085283513382526017602090815260408084208a855290915290912055612cb6565b60088310158015612c1f575080612c196008856138a3565b93508310155b8015612c335750612c3087826136f8565b83105b15612cb6576000612c4482856138a3565b905087612c528260206136f8565b10158015612c5e575085155b15612c95576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360009081526017602090815260408083208a845290915290209089013590555b5050505050505050565b6000612d43565b66ff00ff00ff00ff8160081c1667ff00ff00ff00ff00612cf18360081b67ffffffffffffffff1690565b1617905065ffff0000ffff8160101c1667ffff0000ffff0000612d1e8360101b67ffffffffffffffff1690565b1617905060008160201c612d3c8360201b67ffffffffffffffff1690565b1792915050565b60808201516020830190612d5b90612cc7565b612cc7565b6040820151612d6990612cc7565b60401b17612d81612d5660018460059190911b015190565b825160809190911b90612d9390612cc7565b60c01b17179392505050565b8260108101928215612dcd579160200282015b82811115612dcd578251825591602001919060010190612db2565b50612dd9929150612df5565b5090565b6040518060200160405280612df0612e0a565b905290565b5b80821115612dd95760008155600101612df6565b6040518061032001604052806019906020820280368337509192915050565b600060208284031215612e3b57600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114612e6657600080fd5b919050565b60008060408385031215612e7e57600080fd5b612e8783612e42565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610320810167ffffffffffffffff81118282101715612ee857612ee8612e95565b60405290565b6040516060810167ffffffffffffffff81118282101715612ee857612ee8612e95565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715612f5857612f58612e95565b604052919050565b803567ffffffffffffffff81168114612e6657600080fd5b6000610320808385031215612f8c57600080fd5b604051602080820182811067ffffffffffffffff82111715612fb057612fb0612e95565b806040525081935085601f860112612fc757600080fd5b612fcf612ec4565b928501928087851115612fe157600080fd5b865b8581101561300157612ff481612f60565b8352918301918301612fe3565b509092525091949350505050565b60006060828403121561302157600080fd5b50919050565b60008083601f84011261303957600080fd5b50813567ffffffffffffffff81111561305157600080fd5b6020830191508360208260051b850101111561306c57600080fd5b9250929050565b60008060008060008060008060006103e08a8c03121561309257600080fd5b61309b8a612e42565b985060208a013597506130b18b60408c01612f78565b96506103608a013567ffffffffffffffff808211156130cf57600080fd5b6130db8d838e0161300f565b97506103808c01359150808211156130f257600080fd5b6130fe8d838e01613027565b90975095506103a08c013591508082111561311857600080fd5b6131248d838e0161300f565b94506103c08c013591508082111561313b57600080fd5b506131488c828d01613027565b915080935050809150509295985092959850929598565b600080600080600060a0868803121561317757600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b60005b838110156131b557818101518382015260200161319d565b838111156121145750506000910152565b60208152600082518060208401526131e581604085016020870161319a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b6000806040838503121561322a57600080fd5b50508035926020909101359150565b60008083601f84011261324b57600080fd5b50813567ffffffffffffffff81111561326357600080fd5b60208301915083602082850101111561306c57600080fd5b600080600080600080600060a0888a03121561329657600080fd5b8735965060208801359550604088013567ffffffffffffffff808211156132bc57600080fd5b6132c88b838c01613239565b909750955060608a01359150808211156132e157600080fd5b506132ee8a828b01613027565b9094509250506080880135801515811461330757600080fd5b8091505092959891949750929550565b60008060006060848603121561332c57600080fd5b61333584612e42565b95602085013595506040909401359392505050565b60008060006040848603121561335f57600080fd5b83359250602084013567ffffffffffffffff81111561337d57600080fd5b61338986828701613239565b9497909650939450505050565b600080600080600080600060a0888a0312156133b157600080fd5b8735965060208801359550604088013567ffffffffffffffff808211156133d757600080fd5b6133e38b838c01613239565b909750955060608a01359150808211156133fc57600080fd5b506134098a828b01613239565b989b979a50959894979596608090950135949350505050565b60008060008060006080868803121561343a57600080fd5b8535945061344a60208701612e42565b935061345860408701612f60565b9250606086013567ffffffffffffffff81111561347457600080fd5b61348088828901613239565b969995985093965092949392505050565b6000806000806000608086880312156134a957600080fd5b6134b286612e42565b945060208601359350604086013567ffffffffffffffff808211156134d657600080fd5b6134e289838a0161300f565b945060608801359150808211156134f857600080fd5b5061348088828901613027565b803563ffffffff81168114612e6657600080fd5b60008060006060848603121561352e57600080fd5b8335925061353e60208501613505565b915061354c60408501613505565b90509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036135e4576135e4613584565b5060010190565b6000606082360312156135fd57600080fd5b613605612eee565b823567ffffffffffffffff8082111561361d57600080fd5b9084019036601f83011261363057600080fd5b813560208282111561364457613644612e95565b613674817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f85011601612f11565b9250818352368183860101111561368a57600080fd5b81818501828501376000918301810191909152908352848101359083015250604092830135928101929092525090565b81516103208201908260005b60198110156136ef57825167ffffffffffffffff168252602092830192909101906001016136c6565b50505092915050565b6000821982111561370b5761370b613584565b500190565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261374557600080fd5b83018035915067ffffffffffffffff82111561376057600080fd5b60200191503681900382131561306c57600080fd5b600181815b808511156137ce57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156137b4576137b4613584565b808516156137c157918102915b93841c939080029061377a565b509250929050565b6000826137e557506001613891565b816137f257506000613891565b816001811461380857600281146138125761382e565b6001915050613891565b60ff84111561382357613823613584565b50506001821b613891565b5060208310610133831016604e8410600b8410161715613851575081810a613891565b61385b8383613775565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561388d5761388d613584565b0290505b92915050565b6000612aed83836137d6565b6000828210156138b5576138b5613584565b500390565b600063ffffffff838116908316818110156138d7576138d7613584565b039392505050565b600063ffffffff8083168185168083038211156138fe576138fe613584565b01949350505050565b6000845161391981846020890161319a565b9190910192835250602082015260400191905056fea164736f6c634300080f000a"; + hex"6080604052600436106101d85760003560e01c80639d53a64811610102578063ddcd58de11610095578063ec5efcbc11610064578063ec5efcbc14610681578063f3f480d9146106a1578063faf37bc7146106d4578063fef2b4ed146106e757600080fd5b8063ddcd58de146105d4578063e03110e11461060c578063e159261114610641578063ea7139501461066157600080fd5b8063b5e7154c116100d1578063b5e7154c14610555578063d18534b51461056c578063da35c6641461058c578063dd24f9bf146105a157600080fd5b80639d53a6481461048e5780639d7e8769146104dd578063b2e67ba8146104fd578063b4801e611461053557600080fd5b806361238bde1161017a5780637ac54767116101495780637ac54767146103ca5780638542cf50146103ea578063882856ef146104355780638dc4be111461046e57600080fd5b806361238bde1461031e5780636551927b146103565780637051472e1461038e5780637917de1d146103aa57600080fd5b80633909af5c116101b65780633909af5c146102715780634d52b4c91461029357806352f0f3ad146102a857806354fd4d50146102c857600080fd5b8063013cf08b146101dd5780630359a5631461022e5780632055b36b1461025c575b600080fd5b3480156101e957600080fd5b506101fd6101f8366004612e29565b610714565b6040805173ffffffffffffffffffffffffffffffffffffffff90931683526020830191909152015b60405180910390f35b34801561023a57600080fd5b5061024e610249366004612e6b565b610759565b604051908152602001610225565b34801561026857600080fd5b5061024e601081565b34801561027d57600080fd5b5061029161028c366004613073565b610891565b005b34801561029f57600080fd5b5061024e610ae8565b3480156102b457600080fd5b5061024e6102c336600461315f565b610b03565b3480156102d457600080fd5b506103116040518060400160405280600c81526020017f312e312e332d626574612e32000000000000000000000000000000000000000081525081565b60405161022591906131c6565b34801561032a57600080fd5b5061024e610339366004613217565b600160209081526000928352604080842090915290825290205481565b34801561036257600080fd5b5061024e610371366004612e6b565b601560209081526000928352604080842090915290825290205481565b34801561039a57600080fd5b5061024e6703782dace9d9000081565b3480156103b657600080fd5b506102916103c536600461327b565b610bd9565b3480156103d657600080fd5b5061024e6103e5366004612e29565b6110dc565b3480156103f657600080fd5b50610425610405366004613217565b600260209081526000928352604080842090915290825290205460ff1681565b6040519015158152602001610225565b34801561044157600080fd5b50610455610450366004613317565b6110f3565b60405167ffffffffffffffff9091168152602001610225565b34801561047a57600080fd5b5061029161048936600461334a565b61114d565b34801561049a57600080fd5b5061024e6104a9366004612e6b565b73ffffffffffffffffffffffffffffffffffffffff9091166000908152601860209081526040808320938352929052205490565b3480156104e957600080fd5b506102916104f8366004613396565b611248565b34801561050957600080fd5b5061024e610518366004612e6b565b601760209081526000928352604080842090915290825290205481565b34801561054157600080fd5b5061024e610550366004613317565b6113ff565b34801561056157600080fd5b5061024e620186a081565b34801561057857600080fd5b50610291610587366004613073565b611431565b34801561059857600080fd5b5060135461024e565b3480156105ad57600080fd5b507f000000000000000000000000000000000000000000000000000000000000271061024e565b3480156105e057600080fd5b5061024e6105ef366004612e6b565b601660209081526000928352604080842090915290825290205481565b34801561061857600080fd5b5061062c610627366004613217565b611840565b60408051928352602083019190915201610225565b34801561064d57600080fd5b5061029161065c36600461334a565b611931565b34801561066d57600080fd5b5061029161067c366004613422565b611a39565b34801561068d57600080fd5b5061029161069c366004613491565b611b98565b3480156106ad57600080fd5b507f000000000000000000000000000000000000000000000000000000000000007861024e565b6102916106e2366004613519565b611d1e565b3480156106f357600080fd5b5061024e610702366004612e29565b60006020819052908152604090205481565b6013818154811061072457600080fd5b60009182526020909120600290910201805460019091015473ffffffffffffffffffffffffffffffffffffffff909116915082565b73ffffffffffffffffffffffffffffffffffffffff82166000908152601560209081526040808320848452909152812054819061079c9060601c63ffffffff1690565b63ffffffff16905060005b6010811015610889578160011660010361082f5773ffffffffffffffffffffffffffffffffffffffff85166000908152601460209081526040808320878452909152902081601081106107fc576107fc613555565b01546040805160208101929092528101849052606001604051602081830303815290604052805190602001209250610870565b826003826010811061084357610843613555565b01546040805160208101939093528201526060016040516020818303038152906040528051906020012092505b60019190911c9080610881816135b3565b9150506107a7565b505092915050565b600061089d8a8a610759565b90506108c086868360208b01356108bb6108b68d6135eb565b611fea565b61202a565b80156108de57506108de83838360208801356108bb6108b68a6135eb565b610914576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b86604001358860405160200161092a91906136ba565b6040516020818303038152906040528051906020012014610977576040517f1968a90200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83602001358760200135600161098d91906136f8565b146109c4576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a0c886109d28680613710565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061208b92505050565b610a15886121e6565b836040013588604051602001610a2b91906136ba565b6040516020818303038152906040528051906020012003610a78576040517f9843145b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8a1660009081526015602090815260408083208c8452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000166001179055610adc8a8a3361298e565b50505050505050505050565b6001610af660106002613897565b610b0091906138a3565b81565b6000610b0f8686612a47565b9050610b1c8360086136f8565b82101580610b2a5750602083115b15610b61576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000602081815260c085901b82526008959095528251828252600286526040808320858452875280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558484528752808320948352938652838220558181529384905292205592915050565b60608115610bf257610beb8686612af4565b9050610c2c565b85858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050505b3360009081526014602090815260408083208b845290915280822081516102008101928390529160109082845b815481526020019060010190808311610c5957505050505090506000601560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008b81526020019081526020016000205490506000610cda8260601c63ffffffff1690565b63ffffffff169050333214610d1b576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d2b8260801c63ffffffff1690565b63ffffffff16600003610d6a576040517f87138d5c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d748260c01c90565b67ffffffffffffffff1615610db5576040517f475a253500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b898114610dee576040517f60f95d5a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610dfb89898d8886612b6d565b83516020850160888204881415608883061715610e20576307b1daf16000526004601cfd5b60405160c8810160405260005b83811015610ed0578083018051835260208101516020840152604081015160408401526060810151606084015260808101516080840152508460888301526088810460051b8b013560a883015260c882206001860195508560005b610200811015610ec5576001821615610ea55782818b0152610ec5565b8981015160009081526020938452604090209260019290921c9101610e88565b505050608801610e2d565b50505050600160106002610ee49190613897565b610eee91906138a3565b811115610f27576040517f6229572300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f9c610f3a8360401c63ffffffff1690565b610f4a9063ffffffff168a6136f8565b60401b7fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff606084901b167fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff8516171790565b915084156110295777ffffffffffffffffffffffffffffffffffffffffffffffff82164260c01b179150610fd68260801c63ffffffff1690565b63ffffffff16610fec8360401c63ffffffff1690565b63ffffffff1614611029576040517f7b1dafd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360009081526014602090815260408083208e8452909152902061104f90846010612d9f565b503360008181526018602090815260408083208f8452825280832080546001810182559084528284206004820401805460039092166008026101000a67ffffffffffffffff818102199093164390931602919091179055838352601582528083208f8452909152812084905560609190911b81523690601437366014016000a05050505050505050505050565b600381601081106110ec57600080fd5b0154905081565b6018602052826000526040600020602052816000526040600020818154811061111b57600080fd5b906000526020600020906004918282040191900660080292509250509054906101000a900467ffffffffffffffff1681565b60443560008060088301861061116b5763fe2549876000526004601cfd5b60c083901b60805260888386823786600882030151915060206000858360025afa90508061119857600080fd5b50600080517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0400000000000000000000000000000000000000000000000000000000000000178082526002602090815260408084208a8552825280842080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558385528252808420998452988152888320939093558152908190529490942055505050565b600080603087600037602060006030600060025afa806112705763f91129696000526004601cfd5b6000517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f010000000000000000000000000000000000000000000000000000000000000017608081815260a08c905260c08b905260308a60e037603088609083013760008060c083600a5afa9250826112f2576309bde3396000526004601cfd5b602886106113085763fe2549876000526004601cfd5b6000602882015278200000000000000000000000000000000000000000000000008152600881018b905285810151935060308a8237603081019b909b52505060509098207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0500000000000000000000000000000000000000000000000000000000000000176000818152600260209081526040808320868452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845282528083209583529481528482209a909a559081528089529190912096909655505050505050565b6014602052826000526040600020602052816000526040600020816010811061142757600080fd5b0154925083915050565b73ffffffffffffffffffffffffffffffffffffffff891660009081526015602090815260408083208b845290915290205467ffffffffffffffff8116156114a4576040517fc334f06900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6114ae8160c01c90565b67ffffffffffffffff166000036114f1576040517f55d4cbf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000007861151c8260c01c90565b6115309067ffffffffffffffff16426138a3565b11611567576040517f55d4cbf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006115738b8b610759565b905061158c87878360208c01356108bb6108b68e6135eb565b80156115aa57506115aa84848360208901356108bb6108b68b6135eb565b6115e0576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8760400135896040516020016115f691906136ba565b6040516020818303038152906040528051906020012014611643576040517f1968a90200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84602001358860200135600161165991906136f8565b14158061168b575060016116738360601c63ffffffff1690565b61167d91906138ba565b63ffffffff16856020013514155b156116c2576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6116d0896109d28780613710565b6116d9896121e6565b60006116e48a612cc0565b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0200000000000000000000000000000000000000000000000000000000000000179050600061173b8460a01c63ffffffff1690565b67ffffffffffffffff169050600160026000848152602001908152602001600020600083815260200190815260200160002060006101000a81548160ff021916908315150217905550601760008e73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008d8152602001908152602001600020546001600084815260200190815260200160002060008381526020019081526020016000208190555061180d8460801c63ffffffff1690565b600083815260208190526040902063ffffffff9190911690556118318d8d8161298e565b50505050505050505050505050565b6000828152600260209081526040808320848452909152812054819060ff166118c9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f7072652d696d616765206d757374206578697374000000000000000000000000604482015260640160405180910390fd5b50600083815260208181526040909120546118e58160086136f8565b6118f08560206136f8565b1061190e57836119018260086136f8565b61190b91906138a3565b91505b506000938452600160209081526040808620948652939052919092205492909150565b60443560008060088301861061194f5763fe2549876000526004601cfd5b60c083901b6080526088838682378087017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80151908490207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f02000000000000000000000000000000000000000000000000000000000000001760008181526002602090815260408083208b8452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845282528083209a83529981528982209390935590815290819052959095209190915550505050565b60008060008060808860601b81528760c01b6014820152858782601c0137601c860181207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0600000000000000000000000000000000000000000000000000000000000000179350604088026260216001603f5a021015611ac35763dd629f866000526004601cfd5b6000808783601c018c5afa94503d6001019150600882018a10611aee5763fe2549876000526004601cfd5b60c082901b81526008018481533d6000600183013e89017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8015160008481526002602090815260408083208d8452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915587845282528083209c83529b81528b8220929092559384528390529790912096909655505050505050565b6000611ba48686610759565b9050611bbd83838360208801356108bb6108b68a6135eb565b611bf3576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602084013515611c2f576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611c37612ddd565b611c45816109d28780613710565b611c4e816121e6565b846040013581604051602001611c6491906136ba565b6040516020818303038152906040528051906020012003611cb1576040517f9843145b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff87166000908152601560209081526040808320898452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000166001179055611d1587873361298e565b50505050505050565b6703782dace9d90000341015611d60576040517fe92c469f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b333214611d99576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611da48160086138df565b63ffffffff168263ffffffff1610611de8576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000027108163ffffffff161015611e48576040517f7b1dafd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152601560209081526040808320868452909152902054611e738160801c63ffffffff1690565b63ffffffff1615611eb0576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b608082901b7fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff60a085901b167fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff83161717336000818152601560209081526040808320898452825280832094909455835180850185528381528082018981526013805460018101825590855291517f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a090600290930292830180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909216919091179055517f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a0919091015591815260168252828120968152959052909320349055505050565b600081600001518260200151836040015160405160200161200d93929190613907565b604051602081830303815290604052805190602001209050919050565b60008160005b601081101561207e578060051b880135600186831c16600181146120635760008481526020839052604090209350612074565b600082815260208590526040902093505b5050600101612030565b5090931495945050505050565b608881511461209957600080fd5b602081016020830161211a565b8260031b8201518060001a8160011a60081b178160021a60101b8260031a60181b17178160041a60201b8260051a60281b178260061a60301b8360071a60381b1717179050612114816120ff868560059190911b015190565b1867ffffffffffffffff16600586901b840152565b50505050565b612126600083836120a6565b612132600183836120a6565b61213e600283836120a6565b61214a600383836120a6565b612156600483836120a6565b612162600583836120a6565b61216e600683836120a6565b61217a600783836120a6565b612186600883836120a6565b612192600983836120a6565b61219e600a83836120a6565b6121aa600b83836120a6565b6121b6600c83836120a6565b6121c2600d83836120a6565b6121ce600e83836120a6565b6121da600f83836120a6565b612114601083836120a6565b6040805178010000000000008082800000000000808a8000000080008000602082015279808b00000000800000018000000080008081800000000000800991810191909152788a00000000000000880000000080008009000000008000000a60608201527b8000808b800000000000008b8000000000008089800000000000800360808201527f80000000000080028000000000000080000000000000800a800000008000000a60a08201527f800000008000808180000000000080800000000080000001800000008000800860c082015260009060e0016040516020818303038152906040529050602082016020820161286e565b6102808101516101e082015161014083015160a0840151845118189118186102a082015161020083015161016084015160c0850151602086015118189118186102c083015161022084015161018085015160e0860151604087015118189118186102e08401516102408501516101a0860151610100870151606088015118189118186103008501516102608601516101c0870151610120880151608089015118189118188084603f1c6123998660011b67ffffffffffffffff1690565b18188584603f1c6123b48660011b67ffffffffffffffff1690565b18188584603f1c6123cf8660011b67ffffffffffffffff1690565b181895508483603f1c6123ec8560011b67ffffffffffffffff1690565b181894508387603f1c6124098960011b67ffffffffffffffff1690565b60208b01518b51861867ffffffffffffffff168c5291189190911897508118600181901b603f9190911c18935060c08801518118601481901c602c9190911b1867ffffffffffffffff1660208901526101208801518718602c81901c60149190911b1867ffffffffffffffff1660c08901526102c08801518618600381901c603d9190911b1867ffffffffffffffff166101208901526101c08801518718601981901c60279190911b1867ffffffffffffffff166102c08901526102808801518218602e81901c60129190911b1867ffffffffffffffff166101c089015260408801518618600281901c603e9190911b1867ffffffffffffffff166102808901526101808801518618601581901c602b9190911b1867ffffffffffffffff1660408901526101a08801518518602781901c60199190911b1867ffffffffffffffff166101808901526102608801518718603881901c60089190911b1867ffffffffffffffff166101a08901526102e08801518518600881901c60389190911b1867ffffffffffffffff166102608901526101e08801518218601781901c60299190911b1867ffffffffffffffff166102e089015260808801518718602581901c601b9190911b1867ffffffffffffffff166101e08901526103008801518718603281901c600e9190911b1867ffffffffffffffff1660808901526102a08801518118603e81901c60029190911b1867ffffffffffffffff166103008901526101008801518518600981901c60379190911b1867ffffffffffffffff166102a08901526102008801518118601381901c602d9190911b1867ffffffffffffffff1661010089015260a08801518218601c81901c60249190911b1867ffffffffffffffff1661020089015260608801518518602481901c601c9190911b1867ffffffffffffffff1660a08901526102408801518518602b81901c60159190911b1867ffffffffffffffff1660608901526102208801518618603181901c600f9190911b1867ffffffffffffffff166102408901526101608801518118603681901c600a9190911b1867ffffffffffffffff166102208901525060e08701518518603a81901c60069190911b1867ffffffffffffffff166101608801526101408701518118603d81901c60039190911b1867ffffffffffffffff1660e0880152505067ffffffffffffffff81166101408601525b5050505050565b600582811b8201805160018501831b8401805160028701851b8601805160038901871b8801805160048b0190981b8901805167ffffffffffffffff861985168918811690995283198a16861889169096528819861683188816909352841986168818871690528419831684189095169052919391929190611d15565b612808600082612781565b612813600582612781565b61281e600a82612781565b612829600f82612781565b612834601482612781565b50565b612840816122dc565b612849816127fd565b600383901b820151815160c09190911c9061211490821867ffffffffffffffff168352565b61287a60008284612837565b61288660018284612837565b61289260028284612837565b61289e60038284612837565b6128aa60048284612837565b6128b660058284612837565b6128c260068284612837565b6128ce60078284612837565b6128da60088284612837565b6128e660098284612837565b6128f2600a8284612837565b6128fe600b8284612837565b61290a600c8284612837565b612916600d8284612837565b612922600e8284612837565b61292e600f8284612837565b61293a60108284612837565b61294660118284612837565b61295260128284612837565b61295e60138284612837565b61296a60148284612837565b61297660158284612837565b61298260168284612837565b61211460178284612837565b73ffffffffffffffffffffffffffffffffffffffff83811660009081526016602090815260408083208684529091528082208054908390559051909284169083908381818185875af1925050503d8060008114612a07576040519150601f19603f3d011682016040523d82523d6000602084013e612a0c565b606091505b505090508061277a576040517f83e6cc6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f01000000000000000000000000000000000000000000000000000000000000007effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831617612aed818360408051600093845233602052918152606090922091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790565b9392505050565b6060604051905081602082018181018286833760888306808015612b3d5760888290038501848101848103803687375060806001820353506001845160001a1784538652612b54565b608836843760018353608060878401536088850186525b5050505050601f19603f82510116810160405292915050565b6000612b7f8260a01c63ffffffff1690565b67ffffffffffffffff1690506000612b9d8360801c63ffffffff1690565b63ffffffff1690506000612bb78460401c63ffffffff1690565b63ffffffff169050600883108015612bcd575080155b15612c015760c082901b6000908152883560085283513382526017602090815260408084208a855290915290912055612cb6565b60088310158015612c1f575080612c196008856138a3565b93508310155b8015612c335750612c3087826136f8565b83105b15612cb6576000612c4482856138a3565b905087612c528260206136f8565b10158015612c5e575085155b15612c95576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360009081526017602090815260408083208a845290915290209089013590555b5050505050505050565b6000612d43565b66ff00ff00ff00ff8160081c1667ff00ff00ff00ff00612cf18360081b67ffffffffffffffff1690565b1617905065ffff0000ffff8160101c1667ffff0000ffff0000612d1e8360101b67ffffffffffffffff1690565b1617905060008160201c612d3c8360201b67ffffffffffffffff1690565b1792915050565b60808201516020830190612d5b90612cc7565b612cc7565b6040820151612d6990612cc7565b60401b17612d81612d5660018460059190911b015190565b825160809190911b90612d9390612cc7565b60c01b17179392505050565b8260108101928215612dcd579160200282015b82811115612dcd578251825591602001919060010190612db2565b50612dd9929150612df5565b5090565b6040518060200160405280612df0612e0a565b905290565b5b80821115612dd95760008155600101612df6565b6040518061032001604052806019906020820280368337509192915050565b600060208284031215612e3b57600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114612e6657600080fd5b919050565b60008060408385031215612e7e57600080fd5b612e8783612e42565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610320810167ffffffffffffffff81118282101715612ee857612ee8612e95565b60405290565b6040516060810167ffffffffffffffff81118282101715612ee857612ee8612e95565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715612f5857612f58612e95565b604052919050565b803567ffffffffffffffff81168114612e6657600080fd5b6000610320808385031215612f8c57600080fd5b604051602080820182811067ffffffffffffffff82111715612fb057612fb0612e95565b806040525081935085601f860112612fc757600080fd5b612fcf612ec4565b928501928087851115612fe157600080fd5b865b8581101561300157612ff481612f60565b8352918301918301612fe3565b509092525091949350505050565b60006060828403121561302157600080fd5b50919050565b60008083601f84011261303957600080fd5b50813567ffffffffffffffff81111561305157600080fd5b6020830191508360208260051b850101111561306c57600080fd5b9250929050565b60008060008060008060008060006103e08a8c03121561309257600080fd5b61309b8a612e42565b985060208a013597506130b18b60408c01612f78565b96506103608a013567ffffffffffffffff808211156130cf57600080fd5b6130db8d838e0161300f565b97506103808c01359150808211156130f257600080fd5b6130fe8d838e01613027565b90975095506103a08c013591508082111561311857600080fd5b6131248d838e0161300f565b94506103c08c013591508082111561313b57600080fd5b506131488c828d01613027565b915080935050809150509295985092959850929598565b600080600080600060a0868803121561317757600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b60005b838110156131b557818101518382015260200161319d565b838111156121145750506000910152565b60208152600082518060208401526131e581604085016020870161319a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b6000806040838503121561322a57600080fd5b50508035926020909101359150565b60008083601f84011261324b57600080fd5b50813567ffffffffffffffff81111561326357600080fd5b60208301915083602082850101111561306c57600080fd5b600080600080600080600060a0888a03121561329657600080fd5b8735965060208801359550604088013567ffffffffffffffff808211156132bc57600080fd5b6132c88b838c01613239565b909750955060608a01359150808211156132e157600080fd5b506132ee8a828b01613027565b9094509250506080880135801515811461330757600080fd5b8091505092959891949750929550565b60008060006060848603121561332c57600080fd5b61333584612e42565b95602085013595506040909401359392505050565b60008060006040848603121561335f57600080fd5b83359250602084013567ffffffffffffffff81111561337d57600080fd5b61338986828701613239565b9497909650939450505050565b600080600080600080600060a0888a0312156133b157600080fd5b8735965060208801359550604088013567ffffffffffffffff808211156133d757600080fd5b6133e38b838c01613239565b909750955060608a01359150808211156133fc57600080fd5b506134098a828b01613239565b989b979a50959894979596608090950135949350505050565b60008060008060006080868803121561343a57600080fd5b8535945061344a60208701612e42565b935061345860408701612f60565b9250606086013567ffffffffffffffff81111561347457600080fd5b61348088828901613239565b969995985093965092949392505050565b6000806000806000608086880312156134a957600080fd5b6134b286612e42565b945060208601359350604086013567ffffffffffffffff808211156134d657600080fd5b6134e289838a0161300f565b945060608801359150808211156134f857600080fd5b5061348088828901613027565b803563ffffffff81168114612e6657600080fd5b60008060006060848603121561352e57600080fd5b8335925061353e60208501613505565b915061354c60408501613505565b90509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036135e4576135e4613584565b5060010190565b6000606082360312156135fd57600080fd5b613605612eee565b823567ffffffffffffffff8082111561361d57600080fd5b9084019036601f83011261363057600080fd5b813560208282111561364457613644612e95565b613674817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f85011601612f11565b9250818352368183860101111561368a57600080fd5b81818501828501376000918301810191909152908352848101359083015250604092830135928101929092525090565b81516103208201908260005b60198110156136ef57825167ffffffffffffffff168252602092830192909101906001016136c6565b50505092915050565b6000821982111561370b5761370b613584565b500190565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261374557600080fd5b83018035915067ffffffffffffffff82111561376057600080fd5b60200191503681900382131561306c57600080fd5b600181815b808511156137ce57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156137b4576137b4613584565b808516156137c157918102915b93841c939080029061377a565b509250929050565b6000826137e557506001613891565b816137f257506000613891565b816001811461380857600281146138125761382e565b6001915050613891565b60ff84111561382357613823613584565b50506001821b613891565b5060208310610133831016604e8410600b8410161715613851575081810a613891565b61385b8383613775565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561388d5761388d613584565b0290505b92915050565b6000612aed83836137d6565b6000828210156138b5576138b5613584565b500390565b600063ffffffff838116908316818110156138d7576138d7613584565b039392505050565b600063ffffffff8083168185168083038211156138fe576138fe613584565b01949350505050565b6000845161391981846020890161319a565b9190910192835250602082015260400191905056fea164736f6c634300080f000a"; bytes internal constant mipsCode = - hex"608060405234801561001057600080fd5b50600436106100415760003560e01c806354fd4d50146100465780637dc0d1d014610098578063e14ced32146100dc575b600080fd5b6100826040518060400160405280600a81526020017f312e312e302d72632e310000000000000000000000000000000000000000000081525081565b60405161008f91906121ee565b60405180910390f35b60405173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000373d916d11cce55b548f7051002e76bcfbd7a85d16815260200161008f565b6100ef6100ea3660046122a3565b6100fd565b60405190815260200161008f565b6000610107612164565b6080811461011457600080fd5b6040516106001461012457600080fd5b6084871461013157600080fd5b6101a4851461013f57600080fd5b8635608052602087013560a052604087013560e090811c60c09081526044890135821c82526048890135821c61010052604c890135821c610120526050890135821c61014052605489013590911c61016052605888013560f890811c610180526059890135901c6101a0819052605a89013590911c6101c05260628801906101e09060018111156101f5576040517f0136cc76000000000000000000000000000000000000000000000000000000008152600481fd5b506020810181511461020657600080fd5b60200160005b602081101561023057823560e01c825260049092019160209091019060010161020c565b5050508061012001511561024e576102466103a6565b91505061039d565b6101408101805160010167ffffffffffffffff16905260006101a49050600080600061028385606001518660000151866104f7565b9250925092508163ffffffff1660001480156102a557508063ffffffff16600c145b156102bf576102b387610521565b9550505050505061039d565b6000610339866040805160808101825260008082526020820181905291810182905260608101919091526040518060800160405280836060015163ffffffff168152602001836080015163ffffffff1681526020018360a0015163ffffffff1681526020018360c0015163ffffffff168152509050919050565b6101608701518751919250610356918391906105248888886108f9565b8652805163ffffffff9081166060808901919091526020830151821660808901526040830151821660a08901528201511660c08701526103946103a6565b96505050505050505b95945050505050565b60408051608051815260a051602082015260dc519181019190915260fc51604482015261011c51604882015261013c51604c82015261015c51605082015261017c5160548201526101805161019f5160588301526101a0516101bf5160598401526101d851605a8401526000926102009290916062830191906001811115610453576040517f0136cc76000000000000000000000000000000000000000000000000000000008152600481fd5b60005b602081101561047a57601c8601518452602090950194600490930192600101610456565b506000835283830384a060009450806001811461049a57600395506104c2565b8280156104b257600181146104bb57600296506104c0565b600096506104c0565b600196505b505b50505081900390207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1660f89190911b17919050565b6000806000610507858786610cdf565b925050603f601a83901c8116915082165b93509350939050565b600061052b612164565b608090506000806000806105628561016001516040810151608082015160a083015160c084015160e0909401519294919390929091565b509350935093509350600080610ffa63ffffffff168663ffffffff16036105a75761059285858960e00151610d93565b63ffffffff1660e08a01529092509050610808565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03363ffffffff8716016105e05763400000009150610808565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefe863ffffffff8716016106165760019150610808565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffef6a63ffffffff87160161066a57600161012088015260ff851661010088015261065d6103a6565b9998505050505050505050565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff05d63ffffffff8716016107665760006040518061012001604052808763ffffffff1681526020018663ffffffff1681526020018563ffffffff16815260200189602001518152602001896040015163ffffffff1681526020018b81526020017f000000000000000000000000373d916d11cce55b548f7051002e76bcfbd7a85d73ffffffffffffffffffffffffffffffffffffffff1681526020016107386101a4600160ff16610380020190565b81528951602090910152905061074d81610e27565b8b5263ffffffff1660408b015290935091506108089050565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff05c63ffffffff8716016107cb57602087015160408801516107b1918791879187916105248d5161109f565b63ffffffff1660408b015260208a01529092509050610808565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff02963ffffffff871601610808576108028585611195565b90925090505b6000610882886040805160808101825260008082526020820181905291810182905260608101919091526040518060800160405280836060015163ffffffff168152602001836080015163ffffffff1681526020018360a0015163ffffffff1681526020018360c0015163ffffffff168152509050919050565b61016089015163ffffffff85811660408084019190915285821660e0909301929092526020830180518083168086526004909101831682526060808e01919091529051821660808d015291830151811660a08c0152908201511660c08a015290506108eb6103a6565b9a9950505050505050505050565b84600263ffffffff8416148061091557508263ffffffff166003145b156109675760006002856303ffffff1663ffffffff16901b896020015163f00000001617905061096189898663ffffffff1660021461095557601f610958565b60005b60ff168461124a565b50610cd4565b600080601f601087901c8116908a90601589901c166020811061098c5761098c612317565b602002015192508063ffffffff871615806109ad57508663ffffffff16601c145b156109df578a8263ffffffff16602081106109ca576109ca612317565b6020020151925050601f600b88901c16610a96565b60208763ffffffff161015610a41578663ffffffff16600c1480610a0957508663ffffffff16600d145b80610a1a57508663ffffffff16600e145b15610a2b578761ffff169250610a96565b610a3a8861ffff166010611322565b9250610a96565b60288763ffffffff16101580610a5d57508663ffffffff166022145b80610a6e57508663ffffffff166026145b15610a96578a8263ffffffff1660208110610a8b57610a8b612317565b602002015192508190505b60048763ffffffff1610158015610ab3575060088763ffffffff16105b80610ac457508663ffffffff166001145b15610ae057610ad78c8c898b8689611395565b50505050610cd4565b63ffffffff6000602089831610610b4557610b008a61ffff166010611322565b9095019463fffffffc8616610b168d828e610cdf565b915060288a63ffffffff1610158015610b3657508963ffffffff16603014155b15610b4357809250600093505b505b6000610b558b8b8b8a8a87611583565b63ffffffff1690508963ffffffff166000148015610b7a575060088963ffffffff1610155b8015610b8c5750601c8963ffffffff16105b15610c54578863ffffffff1660081480610bac57508863ffffffff166009145b15610bdf57610bd38f8f8b63ffffffff16600814610bca5786610bcd565b60005b8a61124a565b50505050505050610cd4565b8863ffffffff16600a03610c0157610bd38f8f868a63ffffffff8b1615611ca0565b8863ffffffff16600b03610c2457610bd38f8f868a63ffffffff8b161515611ca0565b60108963ffffffff1610158015610c415750601c8963ffffffff16105b15610c5457610bd38f8f8b8a8a89611d70565b8963ffffffff166038148015610c6f575063ffffffff851615155b15610c9f5760018e8663ffffffff1660208110610c8e57610c8e612317565b63ffffffff90921660209290920201525b8263ffffffff1663ffffffff14610cbe57610cbb838d83612029565b97505b610ccc8f8f86846001611ca0565b505050505050505b979650505050505050565b6000610cea826120cb565b6003831615610cf857600080fd5b6020820191358360051c8160005b601b811015610d5e5760208601953583821c6001168015610d2e5760018114610d4357610d54565b60008481526020839052604090209350610d54565b600082815260208590526040902093505b5050600101610d06565b50868114610d7457630badf00d60005260206000fd5b5050601f93909316601c0360031b9290921c63ffffffff169392505050565b6000808284610fff811615610dad57610fff811661100003015b8663ffffffff16600003610e195784935090810190636000000063ffffffff83161180610de557508463ffffffff168263ffffffff16105b80610dfb57508563ffffffff168163ffffffff16105b15610e14575063ffffffff925060169150839050610518565b610e1d565b8693505b5093509350939050565b6101008101516080820151825160009283929163ffffffff161561109857845163ffffffff167ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb01611052576000610e93866101000151876020015163fffffffc168860e00151610cdf565b606087015190915060001a600103610f1557610f0f86606001518760a0015160408051600093845233602052918152606090922091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790565b60608701525b6000808760c0015173ffffffffffffffffffffffffffffffffffffffff1663e03110e189606001518a608001516040518363ffffffff1660e01b8152600401610f6e92919091825263ffffffff16602082015260400190565b6040805180830381865afa158015610f8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fae9190612346565b60208a015160408b01519294509092509060038216600481900384811015610fd4578094505b5083821015610fe1578193505b8460088502610100031c9450846008828660040303021b9450600180600883600403021b036001806008878560040303021b0391508119811690508581198816179650505061103f8a6020015163fffffffc168b60e0015187612029565b9298505050938601939250611098915050565b845163ffffffff167ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd0161108c5784604001519350611098565b63ffffffff9350600992505b9193509193565b600080858563ffffffff8b16600114806110bf575063ffffffff8b166002145b806110d0575063ffffffff8b166004145b156110dd57889350611187565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa63ffffffff8c160161117b57600061111d868c63fffffffc1689610cdf565b90508860038c166004038b81101561113357809b505b8b965086900360089081029290921c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600193880293841b0116911b17915060009050611187565b63ffffffff9350600992505b975097509750979350505050565b60008063ffffffff83166003036112385763ffffffff841615806111bf575063ffffffff84166005145b806111d0575063ffffffff84166003145b156111de5760009150611243565b63ffffffff8416600114806111f9575063ffffffff84166002145b8061120a575063ffffffff84166006145b8061121b575063ffffffff84166004145b156112295760019150611243565b5063ffffffff90506009611243565b5063ffffffff905060165b9250929050565b836000015160040163ffffffff16846020015163ffffffff16146112cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6a756d7020696e2064656c617920736c6f74000000000000000000000000000060448201526064015b60405180910390fd5b835160208501805163ffffffff908116875283811690915283161561131b5780600801848463ffffffff166020811061130a5761130a612317565b63ffffffff90921660209290920201525b5050505050565b600063ffffffff8381167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80850183169190911c821615159160016020869003821681901b830191861691821b92911b018261137f576000611381565b815b90861663ffffffff16179250505092915050565b6000866000015160040163ffffffff16876020015163ffffffff1614611417576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f6272616e636820696e2064656c617920736c6f7400000000000000000000000060448201526064016112c6565b8463ffffffff166004148061143257508463ffffffff166005145b156114a9576000868463ffffffff166020811061145157611451612317565b602002015190508063ffffffff168363ffffffff1614801561147957508563ffffffff166004145b806114a157508063ffffffff168363ffffffff16141580156114a157508563ffffffff166005145b915050611526565b8463ffffffff166006036114c65760008260030b13159050611526565b8463ffffffff166007036114e25760008260030b139050611526565b8463ffffffff1660010361152657601f601085901c16600081900361150b5760008360030b1291505b8063ffffffff166001036115245760008360030b121591505b505b8651602088015163ffffffff168852811561156757600261154c8661ffff166010611322565b63ffffffff90811690911b8201600401166020890152611579565b60208801805160040163ffffffff1690525b5050505050505050565b600063ffffffff861615806115b0575060088663ffffffff16101580156115b05750600f8663ffffffff16105b156119b05785600881146115f357600981146115fc57600a811461160557600b811461160e57600c811461161757600d811461162057600e81146116295761162e565b6020955061162e565b6021955061162e565b602a955061162e565b602b955061162e565b6024955061162e565b6025955061162e565b602695505b508463ffffffff16600003611653575063ffffffff8216601f600688901c161b611c96565b8463ffffffff16600203611677575063ffffffff8216601f600688901c161c611c96565b8463ffffffff166003036116ab57601f600688901c166116a363ffffffff8516821c6020839003611322565b915050611c96565b8463ffffffff166004036116cb575063ffffffff8216601f84161b611c96565b8463ffffffff166006036116eb575063ffffffff8216601f84161c611c96565b8463ffffffff1660070361171357601f84166116a363ffffffff8516821c6020839003611322565b8463ffffffff16600803611728575082611c96565b8463ffffffff1660090361173d575082611c96565b8463ffffffff16600a03611752575082611c96565b8463ffffffff16600b03611767575082611c96565b8463ffffffff16600c0361177c575082611c96565b8463ffffffff16600f03611791575082611c96565b8463ffffffff166010036117a6575082611c96565b8463ffffffff166011036117bb575082611c96565b8463ffffffff166012036117d0575082611c96565b8463ffffffff166013036117e5575082611c96565b8463ffffffff166018036117fa575082611c96565b8463ffffffff1660190361180f575082611c96565b8463ffffffff16601a03611824575082611c96565b8463ffffffff16601b03611839575082611c96565b8463ffffffff166020036118505750828201611c96565b8463ffffffff166021036118675750828201611c96565b8463ffffffff1660220361187e5750818303611c96565b8463ffffffff166023036118955750818303611c96565b8463ffffffff166024036118ac5750828216611c96565b8463ffffffff166025036118c35750828217611c96565b8463ffffffff166026036118da5750828218611c96565b8463ffffffff166027036118f2575082821719611c96565b8463ffffffff16602a03611921578260030b8460030b12611914576000611917565b60015b60ff169050611c96565b8463ffffffff16602b03611949578263ffffffff168463ffffffff1610611914576000611917565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f696e76616c696420696e737472756374696f6e0000000000000000000000000060448201526064016112c6565b611949565b8563ffffffff16601c03611a30578463ffffffff166002036119d55750828202611c96565b8463ffffffff16602014806119f057508463ffffffff166021145b156119ab578463ffffffff16602003611a07579219925b60005b6380000000851615611a29576401fffffffe600195861b169401611a0a565b9050611c96565b8563ffffffff16600f03611a51575065ffffffff0000601083901b16611c96565b8563ffffffff16602003611a8557611a298460031660080260180363ffffffff168363ffffffff16901c60ff166008611322565b8563ffffffff16602103611aba57611a298460021660080260100363ffffffff168363ffffffff16901c61ffff166010611322565b8563ffffffff16602203611ae8575063ffffffff60086003851602811681811b198416918316901b17611c96565b8563ffffffff16602303611afd575080611c96565b8563ffffffff16602403611b2e578360031660080260180363ffffffff168263ffffffff16901c60ff169050611c96565b8563ffffffff16602503611b60578360021660080260100363ffffffff168263ffffffff16901c61ffff169050611c96565b8563ffffffff16602603611b91575063ffffffff60086003851602601803811681811c198416918316901c17611c96565b8563ffffffff16602803611bc6575060ff63ffffffff60086003861602601803811682811b9091188316918416901b17611c96565b8563ffffffff16602903611bfc575061ffff63ffffffff60086002861602601003811682811b9091188316918416901b17611c96565b8563ffffffff16602a03611c2a575063ffffffff60086003851602811681811c198316918416901c17611c96565b8563ffffffff16602b03611c3f575081611c96565b8563ffffffff16602e03611c70575063ffffffff60086003851602601803811681811b198316918416901b17611c96565b8563ffffffff16603003611c85575080611c96565b8563ffffffff166038036119495750815b9695505050505050565b60208363ffffffff1610611d10576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f76616c696420726567697374657200000000000000000000000000000000000060448201526064016112c6565b63ffffffff831615801590611d225750805b15611d515781848463ffffffff1660208110611d4057611d40612317565b63ffffffff90921660209290920201525b5050505060208101805163ffffffff8082169093526004019091169052565b60008463ffffffff16601003611d8b57506060860151611fd1565b8463ffffffff16601103611daa5763ffffffff84166060880152611fd1565b8463ffffffff16601203611dc357506040860151611fd1565b8463ffffffff16601303611de25763ffffffff84166040880152611fd1565b8463ffffffff16601803611e165763ffffffff600385810b9085900b02602081901c821660608a0152166040880152611fd1565b8463ffffffff16601903611e475763ffffffff84811681851602602081901c821660608a0152166040880152611fd1565b8463ffffffff16601a03611f0a578260030b600003611ec2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d4950533a206469766973696f6e206279207a65726f0000000000000000000060448201526064016112c6565b8260030b8460030b81611ed757611ed761236a565b0763ffffffff166060880152600383810b9085900b81611ef957611ef961236a565b0563ffffffff166040880152611fd1565b8463ffffffff16601b03611fd1578263ffffffff16600003611f88576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d4950533a206469766973696f6e206279207a65726f0000000000000000000060448201526064016112c6565b8263ffffffff168463ffffffff1681611fa357611fa361236a565b0663ffffffff908116606089015283811690851681611fc457611fc461236a565b0463ffffffff1660408801525b63ffffffff8216156120075780868363ffffffff1660208110611ff657611ff6612317565b63ffffffff90921660209290920201525b50505060208401805163ffffffff808216909652600401909416909352505050565b6000612034836120cb565b600384161561204257600080fd5b6020830192601f8516601c0360031b83811b913563ffffffff90911b1916178460051c60005b601b8110156120c05760208601953582821c600116801561209057600181146120a5576120b6565b600085815260208390526040902094506120b6565b600082815260208690526040902094505b5050600101612068565b509095945050505050565b366103808201811015612160576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f636865636b207468617420746865726520697320656e6f7567682063616c6c6460448201527f617461000000000000000000000000000000000000000000000000000000000060648201526084016112c6565b5050565b6040805161018081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081018290526101008101829052610120810182905261014081019190915261016081016121ca6121cf565b905290565b6040518061040001604052806020906020820280368337509192915050565b600060208083528351808285015260005b8181101561221b578581018301518582016040015282016121ff565b8181111561222d576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b60008083601f84011261227357600080fd5b50813567ffffffffffffffff81111561228b57600080fd5b60208301915083602082850101111561124357600080fd5b6000806000806000606086880312156122bb57600080fd5b853567ffffffffffffffff808211156122d357600080fd5b6122df89838a01612261565b909750955060208801359150808211156122f857600080fd5b5061230588828901612261565b96999598509660400135949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000806040838503121561235957600080fd5b505080516020909101519092909150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fdfea164736f6c634300080f000a"; + hex"608060405234801561001057600080fd5b50600436106100415760003560e01c806354fd4d50146100465780637dc0d1d014610098578063e14ced32146100dc575b600080fd5b6100826040518060400160405280600c81526020017f312e312e312d626574612e33000000000000000000000000000000000000000081525081565b60405161008f9190612237565b60405180910390f35b60405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000007a9eab4ce99d157aee7a02e95b366e972a2d5b0b16815260200161008f565b6100ef6100ea3660046122ec565b6100fd565b60405190815260200161008f565b60006101076121ad565b6080811461011457600080fd5b6040516106001461012457600080fd5b6084871461013157600080fd5b6101a4851461013f57600080fd5b8635608052602087013560a052604087013560e090811c60c09081526044890135821c82526048890135821c61010052604c890135821c610120526050890135821c61014052605489013590911c61016052605888013560f890811c610180526059890135901c6101a0819052605a89013590911c6101c05260628801906101e09060018111156101f5576040517f0136cc76000000000000000000000000000000000000000000000000000000008152600481fd5b506020810181511461020657600080fd5b60200160005b602081101561023057823560e01c825260049092019160209091019060010161020c565b5050508061012001511561024e576102466103a6565b91505061039d565b6101408101805160010167ffffffffffffffff16905260006101a49050600080600061028385606001518660000151866104f7565b9250925092508163ffffffff1660001480156102a557508063ffffffff16600c145b156102bf576102b387610521565b9550505050505061039d565b6000610339866040805160808101825260008082526020820181905291810182905260608101919091526040518060800160405280836060015163ffffffff168152602001836080015163ffffffff1681526020018360a0015163ffffffff1681526020018360c0015163ffffffff168152509050919050565b6101608701518751919250610356918391906105248888886108f9565b8652805163ffffffff9081166060808901919091526020830151821660808901526040830151821660a08901528201511660c08701526103946103a6565b96505050505050505b95945050505050565b60408051608051815260a051602082015260dc519181019190915260fc51604482015261011c51604882015261013c51604c82015261015c51605082015261017c5160548201526101805161019f5160588301526101a0516101bf5160598401526101d851605a8401526000926102009290916062830191906001811115610453576040517f0136cc76000000000000000000000000000000000000000000000000000000008152600481fd5b60005b602081101561047a57601c8601518452602090950194600490930192600101610456565b506000835283830384a060009450806001811461049a57600395506104c2565b8280156104b257600181146104bb57600296506104c0565b600096506104c0565b600196505b505b50505081900390207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1660f89190911b17919050565b6000806000610507858786610cdf565b925050603f601a83901c8116915082165b93509350939050565b600061052b6121ad565b608090506000806000806105628561016001516040810151608082015160a083015160c084015160e0909401519294919390929091565b509350935093509350600080610ffa63ffffffff168663ffffffff16036105a75761059285858960e00151610d31565b63ffffffff1660e08a01529092509050610808565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03363ffffffff8716016105e05763400000009150610808565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefe863ffffffff8716016106165760019150610808565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffef6a63ffffffff87160161066a57600161012088015260ff851661010088015261065d6103a6565b9998505050505050505050565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff05d63ffffffff8716016107665760006040518061012001604052808763ffffffff1681526020018663ffffffff1681526020018563ffffffff16815260200189602001518152602001896040015163ffffffff1681526020018b81526020017f0000000000000000000000007a9eab4ce99d157aee7a02e95b366e972a2d5b0b73ffffffffffffffffffffffffffffffffffffffff1681526020016107386101a4600160ff16610380020190565b81528951602090910152905061074d81610dc5565b8b5263ffffffff1660408b015290935091506108089050565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff05c63ffffffff8716016107cb57602087015160408801516107b1918791879187916105248d5161103d565b63ffffffff1660408b015260208a01529092509050610808565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff02963ffffffff871601610808576108028585611133565b90925090505b6000610882886040805160808101825260008082526020820181905291810182905260608101919091526040518060800160405280836060015163ffffffff168152602001836080015163ffffffff1681526020018360a0015163ffffffff1681526020018360c0015163ffffffff168152509050919050565b61016089015163ffffffff85811660408084019190915285821660e0909301929092526020830180518083168086526004909101831682526060808e01919091529051821660808d015291830151811660a08c0152908201511660c08a015290506108eb6103a6565b9a9950505050505050505050565b84600263ffffffff8416148061091557508263ffffffff166003145b156109675760006002856303ffffff1663ffffffff16901b896020015163f00000001617905061096189898663ffffffff1660021461095557601f610958565b60005b60ff16846111e8565b50610cd4565b600080601f601087901c8116908a90601589901c166020811061098c5761098c612360565b602002015192508063ffffffff871615806109ad57508663ffffffff16601c145b156109df578a8263ffffffff16602081106109ca576109ca612360565b6020020151925050601f600b88901c16610a96565b60208763ffffffff161015610a41578663ffffffff16600c1480610a0957508663ffffffff16600d145b80610a1a57508663ffffffff16600e145b15610a2b578761ffff169250610a96565b610a3a8861ffff1660106112c0565b9250610a96565b60288763ffffffff16101580610a5d57508663ffffffff166022145b80610a6e57508663ffffffff166026145b15610a96578a8263ffffffff1660208110610a8b57610a8b612360565b602002015192508190505b60048763ffffffff1610158015610ab3575060088763ffffffff16105b80610ac457508663ffffffff166001145b15610ae057610ad78c8c898b8689611333565b50505050610cd4565b63ffffffff6000602089831610610b4557610b008a61ffff1660106112c0565b9095019463fffffffc8616610b168d828e610cdf565b915060288a63ffffffff1610158015610b3657508963ffffffff16603014155b15610b4357809250600093505b505b6000610b558b8b8b8a8a87611521565b63ffffffff1690508963ffffffff166000148015610b7a575060088963ffffffff1610155b8015610b8c5750601c8963ffffffff16105b15610c54578863ffffffff1660081480610bac57508863ffffffff166009145b15610bdf57610bd38f8f8b63ffffffff16600814610bca5786610bcd565b60005b8a6111e8565b50505050505050610cd4565b8863ffffffff16600a03610c0157610bd38f8f868a63ffffffff8b1615611c3e565b8863ffffffff16600b03610c2457610bd38f8f868a63ffffffff8b161515611c3e565b60108963ffffffff1610158015610c415750601c8963ffffffff16105b15610c5457610bd38f8f8b8a8a89611d0e565b8963ffffffff166038148015610c6f575063ffffffff851615155b15610c9f5760018e8663ffffffff1660208110610c8e57610c8e612360565b63ffffffff90921660209290920201525b8263ffffffff1663ffffffff14610cbe57610cbb838d83611fc7565b97505b610ccc8f8f86846001611c3e565b505050505050505b979650505050505050565b600080610ced858585612069565b909250905080610d29576040517f8e77b2b700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b509392505050565b6000808284610fff811615610d4b57610fff811661100003015b8663ffffffff16600003610db75784935090810190636000000063ffffffff83161180610d8357508463ffffffff168263ffffffff16105b80610d9957508563ffffffff168163ffffffff16105b15610db2575063ffffffff925060169150839050610518565b610dbb565b8693505b5093509350939050565b6101008101516080820151825160009283929163ffffffff161561103657845163ffffffff167ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb01610ff0576000610e31866101000151876020015163fffffffc168860e00151610cdf565b606087015190915060001a600103610eb357610ead86606001518760a0015160408051600093845233602052918152606090922091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790565b60608701525b6000808760c0015173ffffffffffffffffffffffffffffffffffffffff1663e03110e189606001518a608001516040518363ffffffff1660e01b8152600401610f0c92919091825263ffffffff16602082015260400190565b6040805180830381865afa158015610f28573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4c919061238f565b60208a015160408b01519294509092509060038216600481900384811015610f72578094505b5083821015610f7f578193505b8460088502610100031c9450846008828660040303021b9450600180600883600403021b036001806008878560040303021b03915081198116905085811988161796505050610fdd8a6020015163fffffffc168b60e0015187611fc7565b9298505050938601939250611036915050565b845163ffffffff167ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd0161102a5784604001519350611036565b63ffffffff9350600992505b9193509193565b600080858563ffffffff8b166001148061105d575063ffffffff8b166002145b8061106e575063ffffffff8b166004145b1561107b57889350611125565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa63ffffffff8c16016111195760006110bb868c63fffffffc1689610cdf565b90508860038c166004038b8110156110d157809b505b8b965086900360089081029290921c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600193880293841b0116911b17915060009050611125565b63ffffffff9350600992505b975097509750979350505050565b60008063ffffffff83166003036111d65763ffffffff8416158061115d575063ffffffff84166005145b8061116e575063ffffffff84166003145b1561117c57600091506111e1565b63ffffffff841660011480611197575063ffffffff84166002145b806111a8575063ffffffff84166006145b806111b9575063ffffffff84166004145b156111c757600191506111e1565b5063ffffffff905060096111e1565b5063ffffffff905060165b9250929050565b836000015160040163ffffffff16846020015163ffffffff161461126d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6a756d7020696e2064656c617920736c6f74000000000000000000000000000060448201526064015b60405180910390fd5b835160208501805163ffffffff90811687528381169091528316156112b95780600801848463ffffffff16602081106112a8576112a8612360565b63ffffffff90921660209290920201525b5050505050565b600063ffffffff8381167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80850183169190911c821615159160016020869003821681901b830191861691821b92911b018261131d57600061131f565b815b90861663ffffffff16179250505092915050565b6000866000015160040163ffffffff16876020015163ffffffff16146113b5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f6272616e636820696e2064656c617920736c6f740000000000000000000000006044820152606401611264565b8463ffffffff16600414806113d057508463ffffffff166005145b15611447576000868463ffffffff16602081106113ef576113ef612360565b602002015190508063ffffffff168363ffffffff1614801561141757508563ffffffff166004145b8061143f57508063ffffffff168363ffffffff161415801561143f57508563ffffffff166005145b9150506114c4565b8463ffffffff166006036114645760008260030b131590506114c4565b8463ffffffff166007036114805760008260030b1390506114c4565b8463ffffffff166001036114c457601f601085901c1660008190036114a95760008360030b1291505b8063ffffffff166001036114c25760008360030b121591505b505b8651602088015163ffffffff16885281156115055760026114ea8661ffff1660106112c0565b63ffffffff90811690911b8201600401166020890152611517565b60208801805160040163ffffffff1690525b5050505050505050565b600063ffffffff8616158061154e575060088663ffffffff161015801561154e5750600f8663ffffffff16105b1561194e578560088114611591576009811461159a57600a81146115a357600b81146115ac57600c81146115b557600d81146115be57600e81146115c7576115cc565b602095506115cc565b602195506115cc565b602a95506115cc565b602b95506115cc565b602495506115cc565b602595506115cc565b602695505b508463ffffffff166000036115f1575063ffffffff8216601f600688901c161b611c34565b8463ffffffff16600203611615575063ffffffff8216601f600688901c161c611c34565b8463ffffffff1660030361164957601f600688901c1661164163ffffffff8516821c60208390036112c0565b915050611c34565b8463ffffffff16600403611669575063ffffffff8216601f84161b611c34565b8463ffffffff16600603611689575063ffffffff8216601f84161c611c34565b8463ffffffff166007036116b157601f841661164163ffffffff8516821c60208390036112c0565b8463ffffffff166008036116c6575082611c34565b8463ffffffff166009036116db575082611c34565b8463ffffffff16600a036116f0575082611c34565b8463ffffffff16600b03611705575082611c34565b8463ffffffff16600c0361171a575082611c34565b8463ffffffff16600f0361172f575082611c34565b8463ffffffff16601003611744575082611c34565b8463ffffffff16601103611759575082611c34565b8463ffffffff1660120361176e575082611c34565b8463ffffffff16601303611783575082611c34565b8463ffffffff16601803611798575082611c34565b8463ffffffff166019036117ad575082611c34565b8463ffffffff16601a036117c2575082611c34565b8463ffffffff16601b036117d7575082611c34565b8463ffffffff166020036117ee5750828201611c34565b8463ffffffff166021036118055750828201611c34565b8463ffffffff1660220361181c5750818303611c34565b8463ffffffff166023036118335750818303611c34565b8463ffffffff1660240361184a5750828216611c34565b8463ffffffff166025036118615750828217611c34565b8463ffffffff166026036118785750828218611c34565b8463ffffffff16602703611890575082821719611c34565b8463ffffffff16602a036118bf578260030b8460030b126118b25760006118b5565b60015b60ff169050611c34565b8463ffffffff16602b036118e7578263ffffffff168463ffffffff16106118b25760006118b5565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f696e76616c696420696e737472756374696f6e000000000000000000000000006044820152606401611264565b6118e7565b8563ffffffff16601c036119ce578463ffffffff166002036119735750828202611c34565b8463ffffffff166020148061198e57508463ffffffff166021145b15611949578463ffffffff166020036119a5579219925b60005b63800000008516156119c7576401fffffffe600195861b1694016119a8565b9050611c34565b8563ffffffff16600f036119ef575065ffffffff0000601083901b16611c34565b8563ffffffff16602003611a23576119c78460031660080260180363ffffffff168363ffffffff16901c60ff1660086112c0565b8563ffffffff16602103611a58576119c78460021660080260100363ffffffff168363ffffffff16901c61ffff1660106112c0565b8563ffffffff16602203611a86575063ffffffff60086003851602811681811b198416918316901b17611c34565b8563ffffffff16602303611a9b575080611c34565b8563ffffffff16602403611acc578360031660080260180363ffffffff168263ffffffff16901c60ff169050611c34565b8563ffffffff16602503611afe578360021660080260100363ffffffff168263ffffffff16901c61ffff169050611c34565b8563ffffffff16602603611b2f575063ffffffff60086003851602601803811681811c198416918316901c17611c34565b8563ffffffff16602803611b64575060ff63ffffffff60086003861602601803811682811b9091188316918416901b17611c34565b8563ffffffff16602903611b9a575061ffff63ffffffff60086002861602601003811682811b9091188316918416901b17611c34565b8563ffffffff16602a03611bc8575063ffffffff60086003851602811681811c198316918416901c17611c34565b8563ffffffff16602b03611bdd575081611c34565b8563ffffffff16602e03611c0e575063ffffffff60086003851602601803811681811b198316918416901b17611c34565b8563ffffffff16603003611c23575080611c34565b8563ffffffff166038036118e75750815b9695505050505050565b60208363ffffffff1610611cae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f76616c69642072656769737465720000000000000000000000000000000000006044820152606401611264565b63ffffffff831615801590611cc05750805b15611cef5781848463ffffffff1660208110611cde57611cde612360565b63ffffffff90921660209290920201525b5050505060208101805163ffffffff8082169093526004019091169052565b60008463ffffffff16601003611d2957506060860151611f6f565b8463ffffffff16601103611d485763ffffffff84166060880152611f6f565b8463ffffffff16601203611d6157506040860151611f6f565b8463ffffffff16601303611d805763ffffffff84166040880152611f6f565b8463ffffffff16601803611db45763ffffffff600385810b9085900b02602081901c821660608a0152166040880152611f6f565b8463ffffffff16601903611de55763ffffffff84811681851602602081901c821660608a0152166040880152611f6f565b8463ffffffff16601a03611ea8578260030b600003611e60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d4950533a206469766973696f6e206279207a65726f000000000000000000006044820152606401611264565b8260030b8460030b81611e7557611e756123b3565b0763ffffffff166060880152600383810b9085900b81611e9757611e976123b3565b0563ffffffff166040880152611f6f565b8463ffffffff16601b03611f6f578263ffffffff16600003611f26576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d4950533a206469766973696f6e206279207a65726f000000000000000000006044820152606401611264565b8263ffffffff168463ffffffff1681611f4157611f416123b3565b0663ffffffff908116606089015283811690851681611f6257611f626123b3565b0463ffffffff1660408801525b63ffffffff821615611fa55780868363ffffffff1660208110611f9457611f94612360565b63ffffffff90921660209290920201525b50505060208401805163ffffffff808216909652600401909416909352505050565b6000611fd283612114565b6003841615611fe057600080fd5b6020830192601f8516601c0360031b83811b913563ffffffff90911b1916178460051c60005b601b81101561205e5760208601953582821c600116801561202e576001811461204357612054565b60008581526020839052604090209450612054565b600082815260208690526040902094505b5050600101612006565b509095945050505050565b60008061207583612114565b600384161561208357600080fd5b6020830192358460051c8160005b601b8110156120e95760208701963583821c60011680156120b957600181146120ce576120df565b600084815260208390526040902093506120df565b600082815260208590526040902093505b5050600101612091565b508714925050811561210b57601f8516601c0360031b81901c63ffffffff1692505b50935093915050565b3661038082018110156121a9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f636865636b207468617420746865726520697320656e6f7567682063616c6c6460448201527f61746100000000000000000000000000000000000000000000000000000000006064820152608401611264565b5050565b6040805161018081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101919091526101608101612213612218565b905290565b6040518061040001604052806020906020820280368337509192915050565b600060208083528351808285015260005b8181101561226457858101830151858201604001528201612248565b81811115612276576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b60008083601f8401126122bc57600080fd5b50813567ffffffffffffffff8111156122d457600080fd5b6020830191508360208285010111156111e157600080fd5b60008060008060006060868803121561230457600080fd5b853567ffffffffffffffff8082111561231c57600080fd5b61232889838a016122aa565b9097509550602088013591508082111561234157600080fd5b5061234e888289016122aa565b96999598509660400135949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600080604083850312156123a257600080fd5b505080516020909101519092909150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fdfea164736f6c634300080f000a"; bytes internal constant anchorStateRegistryCode = - hex"608060405234801561001057600080fd5b506004361061007d5760003560e01c80635e05fbd01161005b5780635e05fbd01461012a5780637258a8071461013d578063838c2d1e14610179578063f2b4e6171461018157600080fd5b806317cf21a91461008257806335e80ab31461009757806354fd4d50146100e1575b600080fd5b610095610090366004610b4c565b6101a7565b005b6002546100b79073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b61011d6040518060400160405280600a81526020017f322e302e302d72632e310000000000000000000000000000000000000000000081525081565b6040516100d89190610bea565b610095610138366004610cc6565b61061c565b61016461014b366004610df0565b6001602081905260009182526040909120805491015482565b604080519283526020830191909152016100d8565b610095610853565b7f0000000000000000000000005207cfa0166e8de0fcdfd78b4d17b68587be306d6100b7565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa158015610214573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102389190610e0d565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461029c576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060008373ffffffffffffffffffffffffffffffffffffffff1663fa24f7436040518163ffffffff1660e01b8152600401600060405180830381865afa1580156102ec573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526103329190810190610e2a565b92509250925060007f0000000000000000000000005207cfa0166e8de0fcdfd78b4d17b68587be306d73ffffffffffffffffffffffffffffffffffffffff16635f0150cb8585856040518463ffffffff1660e01b815260040161039793929190610efb565b6040805180830381865afa1580156103b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103d79190610f29565b5090508473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461043f576040517f6b0f689100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60028573ffffffffffffffffffffffffffffffffffffffff1663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa15801561048c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104b09190610f9f565b60028111156104c1576104c1610f70565b146104f8576040517f8f8af25f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052806105788773ffffffffffffffffffffffffffffffffffffffff1663bcef3b556040518163ffffffff1660e01b8152600401602060405180830381865afa158015610551573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105759190610fc0565b90565b81526020018673ffffffffffffffffffffffffffffffffffffffff16638b85902b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ec9190610fc0565b905263ffffffff909416600090815260016020818152604090922086518155959091015194019390935550505050565b600054610100900460ff161580801561063c5750600054600160ff909116105b806106565750303b158015610656575060005460ff166001145b6106e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561074457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b60005b83518110156107aa57600084828151811061076457610764610fd9565b60209081029190910181015180820151905163ffffffff1660009081526001808452604090912082518155919092015191015550806107a281611008565b915050610747565b50600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8416179055801561084e57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b600033905060008060008373ffffffffffffffffffffffffffffffffffffffff1663fa24f7436040518163ffffffff1660e01b8152600401600060405180830381865afa1580156108a8573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526108ee9190810190610e2a565b92509250925060007f0000000000000000000000005207cfa0166e8de0fcdfd78b4d17b68587be306d73ffffffffffffffffffffffffffffffffffffffff16635f0150cb8585856040518463ffffffff1660e01b815260040161095393929190610efb565b6040805180830381865afa15801561096f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109939190610f29565b5090508473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146109fb576040517f6b0f689100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160008563ffffffff1663ffffffff168152602001908152602001600020600101548573ffffffffffffffffffffffffffffffffffffffff16638b85902b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8d9190610fc0565b11610a99575050505050565b60028573ffffffffffffffffffffffffffffffffffffffff1663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ae6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b0a9190610f9f565b6002811115610b1b57610b1b610f70565b146104f8575050505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610b4957600080fd5b50565b600060208284031215610b5e57600080fd5b8135610b6981610b27565b9392505050565b60005b83811015610b8b578181015183820152602001610b73565b83811115610b9a576000848401525b50505050565b60008151808452610bb8816020860160208601610b70565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610b696020830184610ba0565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715610c4f57610c4f610bfd565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610c9c57610c9c610bfd565b604052919050565b63ffffffff81168114610b4957600080fd5b8035610cc181610b27565b919050565b6000806040808486031215610cda57600080fd5b833567ffffffffffffffff80821115610cf257600080fd5b818601915086601f830112610d0657600080fd5b8135602082821115610d1a57610d1a610bfd565b610d28818360051b01610c55565b8281528181019350606092830285018201928a841115610d4757600080fd5b948201945b83861015610dd457858b0381811215610d655760008081fd5b610d6d610c2c565b8735610d7881610ca4565b81527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08201891315610daa5760008081fd5b610db2610c2c565b8886013581528989013586820152818601528652509485019493820193610d4c565b509650610de2888201610cb6565b955050505050509250929050565b600060208284031215610e0257600080fd5b8135610b6981610ca4565b600060208284031215610e1f57600080fd5b8151610b6981610b27565b600080600060608486031215610e3f57600080fd5b8351610e4a81610ca4565b60208501516040860151919450925067ffffffffffffffff80821115610e6f57600080fd5b818601915086601f830112610e8357600080fd5b815181811115610e9557610e95610bfd565b610ec660207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601610c55565b9150808252876020828501011115610edd57600080fd5b610eee816020840160208601610b70565b5080925050509250925092565b63ffffffff84168152826020820152606060408201526000610f206060830184610ba0565b95945050505050565b60008060408385031215610f3c57600080fd5b8251610f4781610b27565b602084015190925067ffffffffffffffff81168114610f6557600080fd5b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600060208284031215610fb157600080fd5b815160038110610b6957600080fd5b600060208284031215610fd257600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611060577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b506001019056fea164736f6c634300080f000a"; + hex"608060405234801561001057600080fd5b506004361061007d5760003560e01c80635e05fbd01161005b5780635e05fbd01461012a5780637258a8071461013d578063838c2d1e14610179578063f2b4e6171461018157600080fd5b806317cf21a91461008257806335e80ab31461009757806354fd4d50146100e1575b600080fd5b610095610090366004610b4c565b6101a7565b005b6002546100b79073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b61011d6040518060400160405280600c81526020017f322e302e312d626574612e32000000000000000000000000000000000000000081525081565b6040516100d89190610bea565b610095610138366004610cc6565b61061c565b61016461014b366004610df0565b6001602081905260009182526040909120805491015482565b604080519283526020830191909152016100d8565b610095610853565b7f0000000000000000000000005207cfa0166e8de0fcdfd78b4d17b68587be306d6100b7565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa158015610214573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102389190610e0d565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461029c576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060008373ffffffffffffffffffffffffffffffffffffffff1663fa24f7436040518163ffffffff1660e01b8152600401600060405180830381865afa1580156102ec573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526103329190810190610e2a565b92509250925060007f0000000000000000000000005207cfa0166e8de0fcdfd78b4d17b68587be306d73ffffffffffffffffffffffffffffffffffffffff16635f0150cb8585856040518463ffffffff1660e01b815260040161039793929190610efb565b6040805180830381865afa1580156103b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103d79190610f29565b5090508473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461043f576040517f6b0f689100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60028573ffffffffffffffffffffffffffffffffffffffff1663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa15801561048c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104b09190610f9f565b60028111156104c1576104c1610f70565b146104f8576040517f8f8af25f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052806105788773ffffffffffffffffffffffffffffffffffffffff1663bcef3b556040518163ffffffff1660e01b8152600401602060405180830381865afa158015610551573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105759190610fc0565b90565b81526020018673ffffffffffffffffffffffffffffffffffffffff16638b85902b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ec9190610fc0565b905263ffffffff909416600090815260016020818152604090922086518155959091015194019390935550505050565b600054610100900460ff161580801561063c5750600054600160ff909116105b806106565750303b158015610656575060005460ff166001145b6106e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561074457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b60005b83518110156107aa57600084828151811061076457610764610fd9565b60209081029190910181015180820151905163ffffffff1660009081526001808452604090912082518155919092015191015550806107a281611008565b915050610747565b50600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8416179055801561084e57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b600033905060008060008373ffffffffffffffffffffffffffffffffffffffff1663fa24f7436040518163ffffffff1660e01b8152600401600060405180830381865afa1580156108a8573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526108ee9190810190610e2a565b92509250925060007f0000000000000000000000005207cfa0166e8de0fcdfd78b4d17b68587be306d73ffffffffffffffffffffffffffffffffffffffff16635f0150cb8585856040518463ffffffff1660e01b815260040161095393929190610efb565b6040805180830381865afa15801561096f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109939190610f29565b5090508473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146109fb576040517f6b0f689100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160008563ffffffff1663ffffffff168152602001908152602001600020600101548573ffffffffffffffffffffffffffffffffffffffff16638b85902b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8d9190610fc0565b11610a99575050505050565b60028573ffffffffffffffffffffffffffffffffffffffff1663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ae6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b0a9190610f9f565b6002811115610b1b57610b1b610f70565b146104f8575050505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610b4957600080fd5b50565b600060208284031215610b5e57600080fd5b8135610b6981610b27565b9392505050565b60005b83811015610b8b578181015183820152602001610b73565b83811115610b9a576000848401525b50505050565b60008151808452610bb8816020860160208601610b70565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610b696020830184610ba0565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715610c4f57610c4f610bfd565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610c9c57610c9c610bfd565b604052919050565b63ffffffff81168114610b4957600080fd5b8035610cc181610b27565b919050565b6000806040808486031215610cda57600080fd5b833567ffffffffffffffff80821115610cf257600080fd5b818601915086601f830112610d0657600080fd5b8135602082821115610d1a57610d1a610bfd565b610d28818360051b01610c55565b8281528181019350606092830285018201928a841115610d4757600080fd5b948201945b83861015610dd457858b0381811215610d655760008081fd5b610d6d610c2c565b8735610d7881610ca4565b81527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08201891315610daa5760008081fd5b610db2610c2c565b8886013581528989013586820152818601528652509485019493820193610d4c565b509650610de2888201610cb6565b955050505050509250929050565b600060208284031215610e0257600080fd5b8135610b6981610ca4565b600060208284031215610e1f57600080fd5b8151610b6981610b27565b600080600060608486031215610e3f57600080fd5b8351610e4a81610ca4565b60208501516040860151919450925067ffffffffffffffff80821115610e6f57600080fd5b818601915086601f830112610e8357600080fd5b815181811115610e9557610e95610bfd565b610ec660207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601610c55565b9150808252876020828501011115610edd57600080fd5b610eee816020840160208601610b70565b5080925050509250925092565b63ffffffff84168152826020820152606060408201526000610f206060830184610ba0565b95945050505050565b60008060408385031215610f3c57600080fd5b8251610f4781610b27565b602084015190925067ffffffffffffffff81168114610f6557600080fd5b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600060208284031215610fb157600080fd5b815160038110610b6957600080fd5b600060208284031215610fd257600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611060577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b506001019056fea164736f6c634300080f000a"; bytes internal constant acc33Code = - hex"6080604052600436106102f25760003560e01c806370872aa51161018f578063c6f0308c116100e1578063ec5e63081161008a578063fa24f74311610064578063fa24f74314610b18578063fa315aa914610b3c578063fe2bbeb214610b6f57600080fd5b8063ec5e630814610a95578063eff0f59214610ac8578063f8f43ff614610af857600080fd5b8063d6ae3cd5116100bb578063d6ae3cd514610a0f578063d8cc1a3c14610a42578063dabd396d14610a6257600080fd5b8063c6f0308c14610937578063cf09e0d0146109c1578063d5d44d80146109e257600080fd5b80638d450a9511610143578063bcef3b551161011d578063bcef3b55146108b7578063bd8da956146108f7578063c395e1ca1461091757600080fd5b80638d450a9514610777578063a445ece6146107aa578063bbdc02db1461087657600080fd5b80638129fc1c116101745780638129fc1c1461071a5780638980e0cc146107225780638b85902b1461073757600080fd5b806370872aa5146106f25780637b0f0adc1461070757600080fd5b80633fc8cef3116102485780635c0cba33116101fc5780636361506d116101d65780636361506d1461066c5780636b6716c0146106ac5780636f034409146106df57600080fd5b80635c0cba3314610604578063609d33341461063757806360e274641461064c57600080fd5b806354fd4d501161022d57806354fd4d501461055e57806357da950e146105b45780635a5fa2d9146105e457600080fd5b80633fc8cef314610518578063472777c61461054b57600080fd5b80632810e1d6116102aa57806337b1b2291161028457806337b1b229146104655780633a768463146104a55780633e3ac912146104d857600080fd5b80632810e1d6146103de5780632ad69aeb146103f357806330dbe5701461041357600080fd5b806319effeb4116102db57806319effeb414610339578063200d2ed21461038457806325fc2ace146103bf57600080fd5b806301935130146102f757806303c2924d14610319575b600080fd5b34801561030357600080fd5b506103176103123660046154e2565b610b9f565b005b34801561032557600080fd5b5061031761033436600461553d565b610ec0565b34801561034557600080fd5b506000546103669068010000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020015b60405180910390f35b34801561039057600080fd5b506000546103b290700100000000000000000000000000000000900460ff1681565b60405161037b919061558e565b3480156103cb57600080fd5b506008545b60405190815260200161037b565b3480156103ea57600080fd5b506103b2611566565b3480156103ff57600080fd5b506103d061040e36600461553d565b61180b565b34801561041f57600080fd5b506001546104409073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161037b565b34801561047157600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90033560601c610440565b3480156104b157600080fd5b507f000000000000000000000000444e09fe6d839273316a87002ab0efbea6fe7806610440565b3480156104e457600080fd5b50600054610508907201000000000000000000000000000000000000900460ff1681565b604051901515815260200161037b565b34801561052457600080fd5b507f000000000000000000000000ef179756ea6525afade217ca5ab0b1b5cfe0fd92610440565b6103176105593660046155cf565b611841565b34801561056a57600080fd5b506105a76040518060400160405280600a81526020017f312e332e302d72632e310000000000000000000000000000000000000000000081525081565b60405161037b9190615666565b3480156105c057600080fd5b506008546009546105cf919082565b6040805192835260208301919091520161037b565b3480156105f057600080fd5b506103d06105ff366004615679565b611853565b34801561061057600080fd5b507f000000000000000000000000970670459734a83899773a0fd45941b5afc1200e610440565b34801561064357600080fd5b506105a761188d565b34801561065857600080fd5b506103176106673660046156b7565b61189b565b34801561067857600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003603401356103d0565b3480156106b857600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610366565b6103176106ed3660046156e9565b611a42565b3480156106fe57600080fd5b506009546103d0565b6103176107153660046155cf565b61251b565b610317612528565b34801561072e57600080fd5b506002546103d0565b34801561074357600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401356103d0565b34801561078357600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006103d0565b3480156107b657600080fd5b506108226107c5366004615679565b6007602052600090815260409020805460019091015460ff821691610100810463ffffffff1691650100000000009091046fffffffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff1684565b60408051941515855263ffffffff90931660208501526fffffffffffffffffffffffffffffffff9091169183019190915273ffffffffffffffffffffffffffffffffffffffff16606082015260800161037b565b34801561088257600080fd5b5060405163ffffffff7f000000000000000000000000000000000000000000000000000000000000000016815260200161037b565b3480156108c357600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003601401356103d0565b34801561090357600080fd5b50610366610912366004615679565b612a81565b34801561092357600080fd5b506103d0610932366004615728565b612c60565b34801561094357600080fd5b50610957610952366004615679565b612e43565b6040805163ffffffff909816885273ffffffffffffffffffffffffffffffffffffffff968716602089015295909416948601949094526fffffffffffffffffffffffffffffffff9182166060860152608085015291821660a08401521660c082015260e00161037b565b3480156109cd57600080fd5b506000546103669067ffffffffffffffff1681565b3480156109ee57600080fd5b506103d06109fd3660046156b7565b60036020526000908152604090205481565b348015610a1b57600080fd5b507f00000000000000000000000000000000000000000000000000000000000003856103d0565b348015610a4e57600080fd5b50610317610a5d36600461575a565b612eda565b348015610a6e57600080fd5b507f00000000000000000000000000000000000000000000000000000000000004b0610366565b348015610aa157600080fd5b507f00000000000000000000000000000000000000000000000000000000000000046103d0565b348015610ad457600080fd5b50610508610ae3366004615679565b60046020526000908152604090205460ff1681565b348015610b0457600080fd5b50610317610b133660046155cf565b613509565b348015610b2457600080fd5b50610b2d6139c6565b60405161037b939291906157e4565b348015610b4857600080fd5b507f00000000000000000000000000000000000000000000000000000000000000086103d0565b348015610b7b57600080fd5b50610508610b8a366004615679565b60066020526000908152604090205460ff1681565b60008054700100000000000000000000000000000000900460ff166002811115610bcb57610bcb61555f565b14610c02576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000547201000000000000000000000000000000000000900460ff1615610c55576040517f0ea2e75200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610c8c367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013590565b90565b610ca3610c9e36869003860186615838565b613a41565b14610cda576040517f9cc00b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82606001358282604051610cef9291906158c5565b604051809103902014610d2e576040517fd81d583b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610d77610d7284848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613a9d92505050565b613b0a565b90506000610d9e82600881518110610d9157610d916158d5565b6020026020010151613cc0565b9050602081511115610ddc576040517fd81d583b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602081810151825190910360031b1c367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401358103610e51576040517fb8ed883000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050600180547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790555050600080547fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff1672010000000000000000000000000000000000001790555050565b60008054700100000000000000000000000000000000900460ff166002811115610eec57610eec61555f565b14610f23576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028381548110610f3857610f386158d5565b906000526020600020906005020190506000610f5384612a81565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b081169082161015610fbc576040517ff2440b5300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008481526006602052604090205460ff1615611005576040517ff1a9458100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600084815260056020526040902080548015801561102257508515155b156110bd578354640100000000900473ffffffffffffffffffffffffffffffffffffffff16600081156110555781611071565b600186015473ffffffffffffffffffffffffffffffffffffffff165b905061107d8187613d74565b50505060009485525050600660205250506040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b6000868152600760209081526040918290208251608081018452815460ff81161515808352610100820463ffffffff16948301949094526501000000000090046fffffffffffffffffffffffffffffffff16938101939093526001015473ffffffffffffffffffffffffffffffffffffffff166060830152611160576fffffffffffffffffffffffffffffffff6040820152600181526000869003611160578195505b600086826020015163ffffffff166111789190615933565b90506000838211611189578161118b565b835b602084015190915063ffffffff165b818110156112d75760008682815481106111b6576111b66158d5565b6000918252602080832090910154808352600690915260409091205490915060ff1661120e576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028281548110611223576112236158d5565b600091825260209091206005909102018054909150640100000000900473ffffffffffffffffffffffffffffffffffffffff161580156112805750600481015460408701516fffffffffffffffffffffffffffffffff9182169116115b156112c257600181015473ffffffffffffffffffffffffffffffffffffffff16606087015260048101546fffffffffffffffffffffffffffffffff1660408701525b505080806112cf9061594b565b91505061119a565b5063ffffffff818116602085810191825260008c81526007909152604090819020865181549351928801517fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009094169015157fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ff161761010092909416918202939093177fffffffffffffffffffffff00000000000000000000000000000000ffffffffff16650100000000006fffffffffffffffffffffffffffffffff909316929092029190911782556060850151600190920180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9093169290921790915584900361155b57606083015160008a815260066020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558915801561145757506000547201000000000000000000000000000000000000900460ff165b156114cc5760015473ffffffffffffffffffffffffffffffffffffffff1661147f818a613d74565b885473ffffffffffffffffffffffffffffffffffffffff909116640100000000027fffffffffffffffff0000000000000000000000000000000000000000ffffffff909116178855611559565b61151373ffffffffffffffffffffffffffffffffffffffff8216156114f1578161150d565b600189015473ffffffffffffffffffffffffffffffffffffffff165b89613d74565b87547fffffffffffffffff0000000000000000000000000000000000000000ffffffff1664010000000073ffffffffffffffffffffffffffffffffffffffff8316021788555b505b505050505050505050565b600080600054700100000000000000000000000000000000900460ff1660028111156115945761159461555f565b146115cb576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000805260066020527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f85460ff1661162f576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600260008154811061165b5761165b6158d5565b6000918252602090912060059091020154640100000000900473ffffffffffffffffffffffffffffffffffffffff1614611696576001611699565b60025b6000805467ffffffffffffffff421668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff82168117835592935083927fffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffff000000000000000000ffffffffffffffff9091161770010000000000000000000000000000000083600281111561174a5761174a61555f565b02179055600281111561175f5761175f61555f565b6040517f5e186f09b9c93491f14e277eea7faa5de6a2d4bda75a79af7a3684fbfb42da6090600090a27f000000000000000000000000970670459734a83899773a0fd45941b5afc1200e73ffffffffffffffffffffffffffffffffffffffff1663838c2d1e6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156117f057600080fd5b505af1158015611804573d6000803e3d6000fd5b5050505090565b6005602052816000526040600020818154811061182757600080fd5b90600052602060002001600091509150505481565b905090565b61184e8383836001611a42565b505050565b6000818152600760209081526040808320600590925282208054825461188490610100900463ffffffff1682615983565b95945050505050565b606061183c60546020613e75565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260036020526040812080549082905590819003611900576040517f17bfe5f700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517ff3fef3a300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152602482018390527f000000000000000000000000ef179756ea6525afade217ca5ab0b1b5cfe0fd92169063f3fef3a390604401600060405180830381600087803b15801561199057600080fd5b505af11580156119a4573d6000803e3d6000fd5b5050505060008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114611a02576040519150601f19603f3d011682016040523d82523d6000602084013e611a07565b606091505b505090508061184e576040517f83e6cc6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008054700100000000000000000000000000000000900460ff166002811115611a6e57611a6e61555f565b14611aa5576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028481548110611aba57611aba6158d5565b60009182526020918290206040805160e0810182526005909302909101805463ffffffff8116845273ffffffffffffffffffffffffffffffffffffffff64010000000090910481169484019490945260018101549093169082015260028201546fffffffffffffffffffffffffffffffff908116606083015260038301546080830181905260049093015480821660a084015270010000000000000000000000000000000090041660c082015291508514611ba1576040517f3014033200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60a0810151600083156fffffffffffffffffffffffffffffffff83161760011b90506000611c61826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169050861580611c9c5750611c997f00000000000000000000000000000000000000000000000000000000000000046002615933565b81145b8015611ca6575084155b15611cdd576040517fa42637bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000547201000000000000000000000000000000000000900460ff168015611d03575086155b15611d3a576040517f0ea2e75200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000008811115611d94576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611dbf7f00000000000000000000000000000000000000000000000000000000000000046001615933565b8103611dd157611dd186888588613ec7565b34611ddb83612c60565b14611e12576040517f8620aa1900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611e1d88612a81565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b0811690821603611e85576040517f3381d11400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611eb260017f0000000000000000000000000000000000000000000000000000000000000008615983565b8303611ff0577f000000000000000000000000444e09fe6d839273316a87002ab0efbea6fe780673ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f47919061599a565b73ffffffffffffffffffffffffffffffffffffffff1663f3f480d96040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f91573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fb591906159b7565b611fe9907f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff166159d0565b9050612083565b61201b60017f0000000000000000000000000000000000000000000000000000000000000004615983565b830361205657611fe97f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1660026159fc565b507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff165b6120b7817f00000000000000000000000000000000000000000000000000000000000004b067ffffffffffffffff16615a2c565b67ffffffffffffffff166120d28367ffffffffffffffff1690565b67ffffffffffffffff16111561211957612116817f00000000000000000000000000000000000000000000000000000000000004b067ffffffffffffffff16615a2c565b91505b6000604083901b421760008a8152608087901b6fffffffffffffffffffffffffffffffff8d1617602052604081209192509060008181526004602052604090205490915060ff1615612197576040517f80497e3b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60016004600083815260200190815260200160002060006101000a81548160ff02191690831515021790555060026040518060e001604052808d63ffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020013373ffffffffffffffffffffffffffffffffffffffff168152602001346fffffffffffffffffffffffffffffffff1681526020018c8152602001886fffffffffffffffffffffffffffffffff168152602001846fffffffffffffffffffffffffffffffff16815250908060018154018082558091505060019003906000526020600020906005020160009091909190915060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060608201518160020160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055506080820151816003015560a08201518160040160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555060c08201518160040160106101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055505050600560008c8152602001908152602001600020600160028054905061242d9190615983565b81546001810183556000928352602083200155604080517fd0e30db0000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ef179756ea6525afade217ca5ab0b1b5cfe0fd92169263d0e30db09234926004808301939282900301818588803b1580156124c557600080fd5b505af11580156124d9573d6000803e3d6000fd5b50506040513393508d92508e91507f9b3245740ec3b155098a55be84957a4da13eaf7f14a8bc6f53126c0b9350f2be90600090a4505050505050505050505050565b61184e8383836000611a42565b60005471010000000000000000000000000000000000900460ff161561257a576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f7258a80700000000000000000000000000000000000000000000000000000000815263ffffffff7f0000000000000000000000000000000000000000000000000000000000000000166004820152600090819073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000970670459734a83899773a0fd45941b5afc1200e1690637258a807906024016040805180830381865afa15801561262e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126529190615a55565b90925090508161268e576040517f6a6bc3b200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518082019091528281526020018190526008829055600981905536607a146126c157639824bdab6000526004601cfd5b80367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401351161275b576040517ff40239db000000000000000000000000000000000000000000000000000000008152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013560048201526024015b60405180910390fd5b6040805160e08101825263ffffffff8082526000602083018181527ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe369081013560f01c90038035606090811c868801908152346fffffffffffffffffffffffffffffffff81811693890193845260149094013560808901908152600160a08a0181815242871660c08c019081526002805493840181558a529a5160059092027f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace81018054995173ffffffffffffffffffffffffffffffffffffffff908116640100000000027fffffffffffffffff000000000000000000000000000000000000000000000000909b1694909c16939093179890981790915592517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5acf87018054918a167fffffffffffffffffffffffff000000000000000000000000000000000000000090921691909117905592517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad0860180549186167fffffffffffffffffffffffffffffffff0000000000000000000000000000000090921691909117905591517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad185015551955182167001000000000000000000000000000000000295909116949094177f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad29091015580547fffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffff167101000000000000000000000000000000000017815583517fd0e30db000000000000000000000000000000000000000000000000000000000815293517f000000000000000000000000ef179756ea6525afade217ca5ab0b1b5cfe0fd929092169363d0e30db093926004828101939282900301818588803b158015612a3057600080fd5b505af1158015612a44573d6000803e3d6000fd5b5050600080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000164267ffffffffffffffff161790555050505050565b600080600054700100000000000000000000000000000000900460ff166002811115612aaf57612aaf61555f565b14612ae6576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028381548110612afb57612afb6158d5565b600091825260208220600590910201805490925063ffffffff90811614612b6a57815460028054909163ffffffff16908110612b3957612b396158d5565b906000526020600020906005020160040160109054906101000a90046fffffffffffffffffffffffffffffffff1690505b6004820154600090612ba290700100000000000000000000000000000000900467ffffffffffffffff165b67ffffffffffffffff1690565b612bb69067ffffffffffffffff1642615983565b612bd5612b95846fffffffffffffffffffffffffffffffff1660401c90565b67ffffffffffffffff16612be99190615933565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b01667ffffffffffffffff168167ffffffffffffffff1611612c365780611884565b7f00000000000000000000000000000000000000000000000000000000000004b095945050505050565b600080612cff836fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690507f0000000000000000000000000000000000000000000000000000000000000008811115612d5e576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b642e90edd00062061a806311e1a3006000612d798383615aa8565b9050670de0b6b3a76400006000612db0827f0000000000000000000000000000000000000000000000000000000000000008615abc565b90506000612dce612dc9670de0b6b3a764000086615abc565b614078565b90506000612ddc84846142d3565b90506000612dea8383614322565b90506000612df782614350565b90506000612e1682612e11670de0b6b3a76400008f615abc565b614538565b90506000612e248b83614322565b9050612e30818d615abc565b9f9e505050505050505050505050505050565b60028181548110612e5357600080fd5b60009182526020909120600590910201805460018201546002830154600384015460049094015463ffffffff8416955064010000000090930473ffffffffffffffffffffffffffffffffffffffff908116949216926fffffffffffffffffffffffffffffffff91821692918082169170010000000000000000000000000000000090041687565b60008054700100000000000000000000000000000000900460ff166002811115612f0657612f0661555f565b14612f3d576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028781548110612f5257612f526158d5565b6000918252602082206005919091020160048101549092506fffffffffffffffffffffffffffffffff16908715821760011b9050612fb17f00000000000000000000000000000000000000000000000000000000000000086001615933565b61304d826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1614613087576040517f5f53dd9800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080891561317e576130da7f00000000000000000000000000000000000000000000000000000000000000047f0000000000000000000000000000000000000000000000000000000000000008615983565b6001901b6130f9846fffffffffffffffffffffffffffffffff16614569565b6fffffffffffffffffffffffffffffffff166131159190615af9565b156131525761314961313a60016fffffffffffffffffffffffffffffffff8716615b0d565b865463ffffffff166000614608565b60030154613174565b7f00000000000000000000000000000000000000000000000000000000000000005b91508490506131a8565b600385015491506131a561313a6fffffffffffffffffffffffffffffffff86166001615b36565b90505b600882901b60088a8a6040516131bf9291906158c5565b6040518091039020901b14613200576040517f696550ff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061320b8c6146ec565b9050600061321a836003015490565b6040517fe14ced320000000000000000000000000000000000000000000000000000000081527f000000000000000000000000444e09fe6d839273316a87002ab0efbea6fe780673ffffffffffffffffffffffffffffffffffffffff169063e14ced3290613294908f908f908f908f908a90600401615baa565b6020604051808303816000875af11580156132b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132d791906159b7565b600485015491149150600090600290613382906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b61341e896fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b6134289190615be4565b6134329190615c07565b60ff161590508115158103613473576040517ffb4e40dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8754640100000000900473ffffffffffffffffffffffffffffffffffffffff16156134ca576040517f9071e6af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505085547fffffffffffffffff0000000000000000000000000000000000000000ffffffff163364010000000002179095555050505050505050505050565b60008054700100000000000000000000000000000000900460ff1660028111156135355761353561555f565b1461356c576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060008061357b8661471b565b9350935093509350600061359185858585614b24565b905060007f000000000000000000000000444e09fe6d839273316a87002ab0efbea6fe780673ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015613600573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613624919061599a565b90506001890361371c5773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a84613680367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036034013590565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815260048101939093526024830191909152604482015260206064820152608481018a905260a4015b6020604051808303816000875af11580156136f2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061371691906159b7565b5061155b565b600289036137485773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a8489613680565b600389036137745773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a8487613680565b600489036138fb5760006137ba6fffffffffffffffffffffffffffffffff85167f0000000000000000000000000000000000000000000000000000000000000004614bde565b6009546137c79190615933565b6137d2906001615933565b9050367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360540135811061383b57367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036054013561383d565b805b905073ffffffffffffffffffffffffffffffffffffffff82166352f0f3ad8b8560405160e084901b7fffffffff000000000000000000000000000000000000000000000000000000001681526004810192909252602482015260c084901b604482015260086064820152608481018b905260a4016020604051808303816000875af11580156138d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138f491906159b7565b505061155b565b60058903613994576040517f52f0f3ad000000000000000000000000000000000000000000000000000000008152600481018a9052602481018390527f000000000000000000000000000000000000000000000000000000000000038560c01b6044820152600860648201526084810188905273ffffffffffffffffffffffffffffffffffffffff8216906352f0f3ad9060a4016136d3565b6040517fff137e6500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000000367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003601401356060613a1f61188d565b9050909192565b600081831015613a365781613a38565b825b90505b92915050565b60008160000151826020015183604001518460600151604051602001613a80949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b60408051808201909152600080825260208201528151600003613aec576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50604080518082019091528151815260209182019181019190915290565b60606000806000613b1a85614c8c565b919450925090506001816001811115613b3557613b3561555f565b14613b6c576040517f4b9c6abe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8451613b788385615933565b14613baf576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808252610420820190925290816020015b6040805180820190915260008082526020820152815260200190600190039081613bc65790505093506000835b8651811015613cb457600080613c396040518060400160405280858c60000151613c1d9190615983565b8152602001858c60200151613c329190615933565b9052614c8c565b509150915060405180604001604052808383613c559190615933565b8152602001848b60200151613c6a9190615933565b815250888581518110613c7f57613c7f6158d5565b6020908102919091010152613c95600185615933565b9350613ca18183615933565b613cab9084615933565b92505050613bf3565b50845250919392505050565b60606000806000613cd085614c8c565b919450925090506000816001811115613ceb57613ceb61555f565b14613d22576040517f1ff9b2e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613d2c8284615933565b855114613d65576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6118848560200151848461512a565b600281015473ffffffffffffffffffffffffffffffffffffffff8316600090815260036020526040812080546fffffffffffffffffffffffffffffffff90931692839290613dc3908490615933565b90915550506040517f7eee288d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018390527f000000000000000000000000ef179756ea6525afade217ca5ab0b1b5cfe0fd921690637eee288d90604401600060405180830381600087803b158015613e5857600080fd5b505af1158015613e6c573d6000803e3d6000fd5b50505050505050565b604051818152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90038284820160208401378260208301016000815260208101604052505092915050565b6000613ee66fffffffffffffffffffffffffffffffff84166001615b36565b90506000613ef682866001614608565b9050600086901a8380613fe25750613f2f60027f0000000000000000000000000000000000000000000000000000000000000004615af9565b6004830154600290613fd3906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b613fdd9190615c07565b60ff16145b1561403a5760ff811660011480613ffc575060ff81166002145b614035576040517ff40239db00000000000000000000000000000000000000000000000000000000815260048101889052602401612752565b613e6c565b60ff811615613e6c576040517ff40239db00000000000000000000000000000000000000000000000000000000815260048101889052602401612752565b6fffffffffffffffffffffffffffffffff811160071b81811c67ffffffffffffffff1060061b1781811c63ffffffff1060051b1781811c61ffff1060041b1781811c60ff1060031b17600082136140d757631615e6386000526004601cfd5b7ff8f9f9faf9fdfafbf9fdfcfdfafbfcfef9fafdfafcfcfbfefafafcfbffffffff6f8421084210842108cc6318c6db6d54be83831c1c601f161a1890811b609f90811c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506029190037d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b302017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d90565b60007812725dd1d243aba0e75fe645cc4873f9e65afe688c928e1f218311670de0b6b3a76400000215820261431057637c5f487d6000526004601cfd5b50670de0b6b3a7640000919091020490565b6000816000190483118202156143405763bac65e5b6000526004601cfd5b50670de0b6b3a764000091020490565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdc0d0570925a462d7821361437e57919050565b680755bf798b4a1bf1e5821261439c5763a37bfec96000526004601cfd5b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b6000613a38670de0b6b3a76400008361455086614078565b61455a9190615c29565b6145649190615ce5565b614350565b6000806145f6837e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b600160ff919091161b90920392915050565b600080826146515761464c6fffffffffffffffffffffffffffffffff86167f00000000000000000000000000000000000000000000000000000000000000046151bf565b61466c565b61466c856fffffffffffffffffffffffffffffffff1661534b565b905060028481548110614681576146816158d5565b906000526020600020906005020191505b60048201546fffffffffffffffffffffffffffffffff8281169116146146e457815460028054909163ffffffff169081106146cf576146cf6158d5565b90600052602060002090600502019150614692565b509392505050565b60008060008060006146fd8661471b565b935093509350935061471184848484614b24565b9695505050505050565b600080600080600085905060006002828154811061473b5761473b6158d5565b600091825260209091206004600590920201908101549091507f000000000000000000000000000000000000000000000000000000000000000490614812906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff161161484c576040517fb34b5c2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000815b60048301547f000000000000000000000000000000000000000000000000000000000000000490614913906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff16925082111561498857825463ffffffff166149527f00000000000000000000000000000000000000000000000000000000000000046001615933565b830361495c578391505b6002818154811061496f5761496f6158d5565b9060005260206000209060050201935080945050614850565b600481810154908401546fffffffffffffffffffffffffffffffff91821691166000816fffffffffffffffffffffffffffffffff166149f16149dc856fffffffffffffffffffffffffffffffff1660011c90565b6fffffffffffffffffffffffffffffffff1690565b6fffffffffffffffffffffffffffffffff161490508015614ac0576000614a29836fffffffffffffffffffffffffffffffff16614569565b6fffffffffffffffffffffffffffffffff161115614a94576000614a6b614a6360016fffffffffffffffffffffffffffffffff8616615b0d565b896001614608565b6003810154600490910154909c506fffffffffffffffffffffffffffffffff169a50614a9a9050565b6008549a505b600386015460048701549099506fffffffffffffffffffffffffffffffff169750614b16565b6000614ae2614a636fffffffffffffffffffffffffffffffff85166001615b36565b6003808901546004808b015492840154930154909e506fffffffffffffffffffffffffffffffff9182169d50919b50169850505b505050505050509193509193565b60006fffffffffffffffffffffffffffffffff841615614b915760408051602081018790526fffffffffffffffffffffffffffffffff8087169282019290925260608101859052908316608082015260a00160405160208183030381529060405280519060200120611884565b8282604051602001614bbf9291909182526fffffffffffffffffffffffffffffffff16602082015260400190565b6040516020818303038152906040528051906020012095945050505050565b600080614c6b847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690508083036001841b600180831b0386831b17039250505092915050565b60008060008360000151600003614ccf576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020840151805160001a607f8111614cf4576000600160009450945094505050615123565b60b78111614e0a576000614d09608083615983565b905080876000015111614d48576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001838101517fff00000000000000000000000000000000000000000000000000000000000000169082148015614dc057507f80000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008216105b15614df7576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5060019550935060009250615123915050565b60bf8111614f68576000614e1f60b783615983565b905080876000015111614e5e576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614ec0576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c60378111614f08576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614f128184615933565b895111614f4b576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614f56836001615933565b97509550600094506151239350505050565b60f78111614fcd576000614f7d60c083615983565b905080876000015111614fbc576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600195509350849250615123915050565b6000614fda60f783615983565b905080876000015111615019576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff0000000000000000000000000000000000000000000000000000000000000016600081900361507b576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c603781116150c3576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6150cd8184615933565b895111615106576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b615111836001615933565b97509550600194506151239350505050565b9193909250565b60608167ffffffffffffffff81111561514557615145615809565b6040519080825280601f01601f19166020018201604052801561516f576020820181803683370190505b50905081156151b85760006151848486615933565b90506020820160005b848110156151a557828101518282015260200161518d565b848111156151b4576000858301525b5050505b9392505050565b60008161525e846fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff16116152745763b34b5c226000526004601cfd5b61527d8361534b565b90508161531c826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1611613a3b57613a38615332836001615933565b6fffffffffffffffffffffffffffffffff8316906153f0565b600081196001830116816153df827e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169390931c8015179392505050565b60008061547d847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169050808303600180821b0385821b179250505092915050565b60008083601f8401126154ab57600080fd5b50813567ffffffffffffffff8111156154c357600080fd5b6020830191508360208285010111156154db57600080fd5b9250929050565b600080600083850360a08112156154f857600080fd5b608081121561550657600080fd5b50839250608084013567ffffffffffffffff81111561552457600080fd5b61553086828701615499565b9497909650939450505050565b6000806040838503121561555057600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60208101600383106155c9577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b6000806000606084860312156155e457600080fd5b505081359360208301359350604090920135919050565b6000815180845260005b8181101561562157602081850181015186830182015201615605565b81811115615633576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000613a3860208301846155fb565b60006020828403121561568b57600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff811681146156b457600080fd5b50565b6000602082840312156156c957600080fd5b81356151b881615692565b803580151581146156e457600080fd5b919050565b600080600080608085870312156156ff57600080fd5b84359350602085013592506040850135915061571d606086016156d4565b905092959194509250565b60006020828403121561573a57600080fd5b81356fffffffffffffffffffffffffffffffff811681146151b857600080fd5b6000806000806000806080878903121561577357600080fd5b86359550615783602088016156d4565b9450604087013567ffffffffffffffff808211156157a057600080fd5b6157ac8a838b01615499565b909650945060608901359150808211156157c557600080fd5b506157d289828a01615499565b979a9699509497509295939492505050565b63ffffffff8416815282602082015260606040820152600061188460608301846155fb565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006080828403121561584a57600080fd5b6040516080810181811067ffffffffffffffff82111715615894577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561594657615946615904565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361597c5761597c615904565b5060010190565b60008282101561599557615995615904565b500390565b6000602082840312156159ac57600080fd5b81516151b881615692565b6000602082840312156159c957600080fd5b5051919050565b600067ffffffffffffffff8083168185168083038211156159f3576159f3615904565b01949350505050565b600067ffffffffffffffff80831681851681830481118215151615615a2357615a23615904565b02949350505050565b600067ffffffffffffffff83811690831681811015615a4d57615a4d615904565b039392505050565b60008060408385031215615a6857600080fd5b505080516020909101519092909150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082615ab757615ab7615a79565b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615af457615af4615904565b500290565b600082615b0857615b08615a79565b500690565b60006fffffffffffffffffffffffffffffffff83811690831681811015615a4d57615a4d615904565b60006fffffffffffffffffffffffffffffffff8083168185168083038211156159f3576159f3615904565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b606081526000615bbe606083018789615b61565b8281036020840152615bd1818688615b61565b9150508260408301529695505050505050565b600060ff821660ff841680821015615bfe57615bfe615904565b90039392505050565b600060ff831680615c1a57615c1a615a79565b8060ff84160691505092915050565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600084136000841385830485118282161615615c6a57615c6a615904565b7f80000000000000000000000000000000000000000000000000000000000000006000871286820588128184161615615ca557615ca5615904565b60008712925087820587128484161615615cc157615cc1615904565b87850587128184161615615cd757615cd7615904565b505050929093029392505050565b600082615cf457615cf4615a79565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f800000000000000000000000000000000000000000000000000000000000000083141615615d4857615d48615904565b50059056fea164736f6c634300080f000a"; + hex"6080604052600436106102f25760003560e01c806370872aa51161018f578063c6f0308c116100e1578063ec5e63081161008a578063fa24f74311610064578063fa24f74314610b18578063fa315aa914610b3c578063fe2bbeb214610b6f57600080fd5b8063ec5e630814610a95578063eff0f59214610ac8578063f8f43ff614610af857600080fd5b8063d6ae3cd5116100bb578063d6ae3cd514610a0f578063d8cc1a3c14610a42578063dabd396d14610a6257600080fd5b8063c6f0308c14610937578063cf09e0d0146109c1578063d5d44d80146109e257600080fd5b80638d450a9511610143578063bcef3b551161011d578063bcef3b55146108b7578063bd8da956146108f7578063c395e1ca1461091757600080fd5b80638d450a9514610777578063a445ece6146107aa578063bbdc02db1461087657600080fd5b80638129fc1c116101745780638129fc1c1461071a5780638980e0cc146107225780638b85902b1461073757600080fd5b806370872aa5146106f25780637b0f0adc1461070757600080fd5b80633fc8cef3116102485780635c0cba33116101fc5780636361506d116101d65780636361506d1461066c5780636b6716c0146106ac5780636f034409146106df57600080fd5b80635c0cba3314610604578063609d33341461063757806360e274641461064c57600080fd5b806354fd4d501161022d57806354fd4d501461055e57806357da950e146105b45780635a5fa2d9146105e457600080fd5b80633fc8cef314610518578063472777c61461054b57600080fd5b80632810e1d6116102aa57806337b1b2291161028457806337b1b229146104655780633a768463146104a55780633e3ac912146104d857600080fd5b80632810e1d6146103de5780632ad69aeb146103f357806330dbe5701461041357600080fd5b806319effeb4116102db57806319effeb414610339578063200d2ed21461038457806325fc2ace146103bf57600080fd5b806301935130146102f757806303c2924d14610319575b600080fd5b34801561030357600080fd5b506103176103123660046154e2565b610b9f565b005b34801561032557600080fd5b5061031761033436600461553d565b610ec0565b34801561034557600080fd5b506000546103669068010000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020015b60405180910390f35b34801561039057600080fd5b506000546103b290700100000000000000000000000000000000900460ff1681565b60405161037b919061558e565b3480156103cb57600080fd5b506008545b60405190815260200161037b565b3480156103ea57600080fd5b506103b2611566565b3480156103ff57600080fd5b506103d061040e36600461553d565b61180b565b34801561041f57600080fd5b506001546104409073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161037b565b34801561047157600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90033560601c610440565b3480156104b157600080fd5b507f000000000000000000000000180cbe2ebb9f37d3a3c542ddc2546fd160555a73610440565b3480156104e457600080fd5b50600054610508907201000000000000000000000000000000000000900460ff1681565b604051901515815260200161037b565b34801561052457600080fd5b507f000000000000000000000000ef179756ea6525afade217ca5ab0b1b5cfe0fd92610440565b6103176105593660046155cf565b611841565b34801561056a57600080fd5b506105a76040518060400160405280600c81526020017f312e332e312d626574612e32000000000000000000000000000000000000000081525081565b60405161037b9190615666565b3480156105c057600080fd5b506008546009546105cf919082565b6040805192835260208301919091520161037b565b3480156105f057600080fd5b506103d06105ff366004615679565b611853565b34801561061057600080fd5b507f000000000000000000000000970670459734a83899773a0fd45941b5afc1200e610440565b34801561064357600080fd5b506105a761188d565b34801561065857600080fd5b506103176106673660046156b7565b61189b565b34801561067857600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003603401356103d0565b3480156106b857600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610366565b6103176106ed3660046156e9565b611a42565b3480156106fe57600080fd5b506009546103d0565b6103176107153660046155cf565b61251b565b610317612528565b34801561072e57600080fd5b506002546103d0565b34801561074357600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401356103d0565b34801561078357600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006103d0565b3480156107b657600080fd5b506108226107c5366004615679565b6007602052600090815260409020805460019091015460ff821691610100810463ffffffff1691650100000000009091046fffffffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff1684565b60408051941515855263ffffffff90931660208501526fffffffffffffffffffffffffffffffff9091169183019190915273ffffffffffffffffffffffffffffffffffffffff16606082015260800161037b565b34801561088257600080fd5b5060405163ffffffff7f000000000000000000000000000000000000000000000000000000000000000016815260200161037b565b3480156108c357600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003601401356103d0565b34801561090357600080fd5b50610366610912366004615679565b612a81565b34801561092357600080fd5b506103d0610932366004615728565b612c60565b34801561094357600080fd5b50610957610952366004615679565b612e43565b6040805163ffffffff909816885273ffffffffffffffffffffffffffffffffffffffff968716602089015295909416948601949094526fffffffffffffffffffffffffffffffff9182166060860152608085015291821660a08401521660c082015260e00161037b565b3480156109cd57600080fd5b506000546103669067ffffffffffffffff1681565b3480156109ee57600080fd5b506103d06109fd3660046156b7565b60036020526000908152604090205481565b348015610a1b57600080fd5b507f00000000000000000000000000000000000000000000000000000000000003856103d0565b348015610a4e57600080fd5b50610317610a5d36600461575a565b612eda565b348015610a6e57600080fd5b507f00000000000000000000000000000000000000000000000000000000000004b0610366565b348015610aa157600080fd5b507f00000000000000000000000000000000000000000000000000000000000000046103d0565b348015610ad457600080fd5b50610508610ae3366004615679565b60046020526000908152604090205460ff1681565b348015610b0457600080fd5b50610317610b133660046155cf565b613509565b348015610b2457600080fd5b50610b2d6139c6565b60405161037b939291906157e4565b348015610b4857600080fd5b507f00000000000000000000000000000000000000000000000000000000000000086103d0565b348015610b7b57600080fd5b50610508610b8a366004615679565b60066020526000908152604090205460ff1681565b60008054700100000000000000000000000000000000900460ff166002811115610bcb57610bcb61555f565b14610c02576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000547201000000000000000000000000000000000000900460ff1615610c55576040517f0ea2e75200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610c8c367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013590565b90565b610ca3610c9e36869003860186615838565b613a41565b14610cda576040517f9cc00b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82606001358282604051610cef9291906158c5565b604051809103902014610d2e576040517fd81d583b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610d77610d7284848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613a9d92505050565b613b0a565b90506000610d9e82600881518110610d9157610d916158d5565b6020026020010151613cc0565b9050602081511115610ddc576040517fd81d583b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602081810151825190910360031b1c367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401358103610e51576040517fb8ed883000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050600180547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790555050600080547fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff1672010000000000000000000000000000000000001790555050565b60008054700100000000000000000000000000000000900460ff166002811115610eec57610eec61555f565b14610f23576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028381548110610f3857610f386158d5565b906000526020600020906005020190506000610f5384612a81565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b081169082161015610fbc576040517ff2440b5300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008481526006602052604090205460ff1615611005576040517ff1a9458100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600084815260056020526040902080548015801561102257508515155b156110bd578354640100000000900473ffffffffffffffffffffffffffffffffffffffff16600081156110555781611071565b600186015473ffffffffffffffffffffffffffffffffffffffff165b905061107d8187613d74565b50505060009485525050600660205250506040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b6000868152600760209081526040918290208251608081018452815460ff81161515808352610100820463ffffffff16948301949094526501000000000090046fffffffffffffffffffffffffffffffff16938101939093526001015473ffffffffffffffffffffffffffffffffffffffff166060830152611160576fffffffffffffffffffffffffffffffff6040820152600181526000869003611160578195505b600086826020015163ffffffff166111789190615933565b90506000838211611189578161118b565b835b602084015190915063ffffffff165b818110156112d75760008682815481106111b6576111b66158d5565b6000918252602080832090910154808352600690915260409091205490915060ff1661120e576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028281548110611223576112236158d5565b600091825260209091206005909102018054909150640100000000900473ffffffffffffffffffffffffffffffffffffffff161580156112805750600481015460408701516fffffffffffffffffffffffffffffffff9182169116115b156112c257600181015473ffffffffffffffffffffffffffffffffffffffff16606087015260048101546fffffffffffffffffffffffffffffffff1660408701525b505080806112cf9061594b565b91505061119a565b5063ffffffff818116602085810191825260008c81526007909152604090819020865181549351928801517fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009094169015157fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ff161761010092909416918202939093177fffffffffffffffffffffff00000000000000000000000000000000ffffffffff16650100000000006fffffffffffffffffffffffffffffffff909316929092029190911782556060850151600190920180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9093169290921790915584900361155b57606083015160008a815260066020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558915801561145757506000547201000000000000000000000000000000000000900460ff165b156114cc5760015473ffffffffffffffffffffffffffffffffffffffff1661147f818a613d74565b885473ffffffffffffffffffffffffffffffffffffffff909116640100000000027fffffffffffffffff0000000000000000000000000000000000000000ffffffff909116178855611559565b61151373ffffffffffffffffffffffffffffffffffffffff8216156114f1578161150d565b600189015473ffffffffffffffffffffffffffffffffffffffff165b89613d74565b87547fffffffffffffffff0000000000000000000000000000000000000000ffffffff1664010000000073ffffffffffffffffffffffffffffffffffffffff8316021788555b505b505050505050505050565b600080600054700100000000000000000000000000000000900460ff1660028111156115945761159461555f565b146115cb576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000805260066020527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f85460ff1661162f576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600260008154811061165b5761165b6158d5565b6000918252602090912060059091020154640100000000900473ffffffffffffffffffffffffffffffffffffffff1614611696576001611699565b60025b6000805467ffffffffffffffff421668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff82168117835592935083927fffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffff000000000000000000ffffffffffffffff9091161770010000000000000000000000000000000083600281111561174a5761174a61555f565b02179055600281111561175f5761175f61555f565b6040517f5e186f09b9c93491f14e277eea7faa5de6a2d4bda75a79af7a3684fbfb42da6090600090a27f000000000000000000000000970670459734a83899773a0fd45941b5afc1200e73ffffffffffffffffffffffffffffffffffffffff1663838c2d1e6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156117f057600080fd5b505af1158015611804573d6000803e3d6000fd5b5050505090565b6005602052816000526040600020818154811061182757600080fd5b90600052602060002001600091509150505481565b905090565b61184e8383836001611a42565b505050565b6000818152600760209081526040808320600590925282208054825461188490610100900463ffffffff1682615983565b95945050505050565b606061183c60546020613e75565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260036020526040812080549082905590819003611900576040517f17bfe5f700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517ff3fef3a300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152602482018390527f000000000000000000000000ef179756ea6525afade217ca5ab0b1b5cfe0fd92169063f3fef3a390604401600060405180830381600087803b15801561199057600080fd5b505af11580156119a4573d6000803e3d6000fd5b5050505060008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114611a02576040519150601f19603f3d011682016040523d82523d6000602084013e611a07565b606091505b505090508061184e576040517f83e6cc6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008054700100000000000000000000000000000000900460ff166002811115611a6e57611a6e61555f565b14611aa5576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028481548110611aba57611aba6158d5565b60009182526020918290206040805160e0810182526005909302909101805463ffffffff8116845273ffffffffffffffffffffffffffffffffffffffff64010000000090910481169484019490945260018101549093169082015260028201546fffffffffffffffffffffffffffffffff908116606083015260038301546080830181905260049093015480821660a084015270010000000000000000000000000000000090041660c082015291508514611ba1576040517f3014033200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60a0810151600083156fffffffffffffffffffffffffffffffff83161760011b90506000611c61826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169050861580611c9c5750611c997f00000000000000000000000000000000000000000000000000000000000000046002615933565b81145b8015611ca6575084155b15611cdd576040517fa42637bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000547201000000000000000000000000000000000000900460ff168015611d03575086155b15611d3a576040517f0ea2e75200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000008811115611d94576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611dbf7f00000000000000000000000000000000000000000000000000000000000000046001615933565b8103611dd157611dd186888588613ec7565b34611ddb83612c60565b14611e12576040517f8620aa1900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611e1d88612a81565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b0811690821603611e85576040517f3381d11400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611eb260017f0000000000000000000000000000000000000000000000000000000000000008615983565b8303611ff0577f000000000000000000000000180cbe2ebb9f37d3a3c542ddc2546fd160555a7373ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f47919061599a565b73ffffffffffffffffffffffffffffffffffffffff1663f3f480d96040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f91573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fb591906159b7565b611fe9907f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff166159d0565b9050612083565b61201b60017f0000000000000000000000000000000000000000000000000000000000000004615983565b830361205657611fe97f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1660026159fc565b507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff165b6120b7817f00000000000000000000000000000000000000000000000000000000000004b067ffffffffffffffff16615a2c565b67ffffffffffffffff166120d28367ffffffffffffffff1690565b67ffffffffffffffff16111561211957612116817f00000000000000000000000000000000000000000000000000000000000004b067ffffffffffffffff16615a2c565b91505b6000604083901b421760008a8152608087901b6fffffffffffffffffffffffffffffffff8d1617602052604081209192509060008181526004602052604090205490915060ff1615612197576040517f80497e3b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60016004600083815260200190815260200160002060006101000a81548160ff02191690831515021790555060026040518060e001604052808d63ffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020013373ffffffffffffffffffffffffffffffffffffffff168152602001346fffffffffffffffffffffffffffffffff1681526020018c8152602001886fffffffffffffffffffffffffffffffff168152602001846fffffffffffffffffffffffffffffffff16815250908060018154018082558091505060019003906000526020600020906005020160009091909190915060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060608201518160020160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055506080820151816003015560a08201518160040160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555060c08201518160040160106101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055505050600560008c8152602001908152602001600020600160028054905061242d9190615983565b81546001810183556000928352602083200155604080517fd0e30db0000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ef179756ea6525afade217ca5ab0b1b5cfe0fd92169263d0e30db09234926004808301939282900301818588803b1580156124c557600080fd5b505af11580156124d9573d6000803e3d6000fd5b50506040513393508d92508e91507f9b3245740ec3b155098a55be84957a4da13eaf7f14a8bc6f53126c0b9350f2be90600090a4505050505050505050505050565b61184e8383836000611a42565b60005471010000000000000000000000000000000000900460ff161561257a576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f7258a80700000000000000000000000000000000000000000000000000000000815263ffffffff7f0000000000000000000000000000000000000000000000000000000000000000166004820152600090819073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000970670459734a83899773a0fd45941b5afc1200e1690637258a807906024016040805180830381865afa15801561262e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126529190615a55565b90925090508161268e576040517f6a6bc3b200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518082019091528281526020018190526008829055600981905536607a146126c157639824bdab6000526004601cfd5b80367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401351161275b576040517ff40239db000000000000000000000000000000000000000000000000000000008152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013560048201526024015b60405180910390fd5b6040805160e08101825263ffffffff8082526000602083018181527ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe369081013560f01c90038035606090811c868801908152346fffffffffffffffffffffffffffffffff81811693890193845260149094013560808901908152600160a08a0181815242871660c08c019081526002805493840181558a529a5160059092027f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace81018054995173ffffffffffffffffffffffffffffffffffffffff908116640100000000027fffffffffffffffff000000000000000000000000000000000000000000000000909b1694909c16939093179890981790915592517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5acf87018054918a167fffffffffffffffffffffffff000000000000000000000000000000000000000090921691909117905592517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad0860180549186167fffffffffffffffffffffffffffffffff0000000000000000000000000000000090921691909117905591517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad185015551955182167001000000000000000000000000000000000295909116949094177f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad29091015580547fffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffff167101000000000000000000000000000000000017815583517fd0e30db000000000000000000000000000000000000000000000000000000000815293517f000000000000000000000000ef179756ea6525afade217ca5ab0b1b5cfe0fd929092169363d0e30db093926004828101939282900301818588803b158015612a3057600080fd5b505af1158015612a44573d6000803e3d6000fd5b5050600080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000164267ffffffffffffffff161790555050505050565b600080600054700100000000000000000000000000000000900460ff166002811115612aaf57612aaf61555f565b14612ae6576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028381548110612afb57612afb6158d5565b600091825260208220600590910201805490925063ffffffff90811614612b6a57815460028054909163ffffffff16908110612b3957612b396158d5565b906000526020600020906005020160040160109054906101000a90046fffffffffffffffffffffffffffffffff1690505b6004820154600090612ba290700100000000000000000000000000000000900467ffffffffffffffff165b67ffffffffffffffff1690565b612bb69067ffffffffffffffff1642615983565b612bd5612b95846fffffffffffffffffffffffffffffffff1660401c90565b67ffffffffffffffff16612be99190615933565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b01667ffffffffffffffff168167ffffffffffffffff1611612c365780611884565b7f00000000000000000000000000000000000000000000000000000000000004b095945050505050565b600080612cff836fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690507f0000000000000000000000000000000000000000000000000000000000000008811115612d5e576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b642e90edd00062061a806311e1a3006000612d798383615aa8565b9050670de0b6b3a76400006000612db0827f0000000000000000000000000000000000000000000000000000000000000008615abc565b90506000612dce612dc9670de0b6b3a764000086615abc565b614078565b90506000612ddc84846142d3565b90506000612dea8383614322565b90506000612df782614350565b90506000612e1682612e11670de0b6b3a76400008f615abc565b614538565b90506000612e248b83614322565b9050612e30818d615abc565b9f9e505050505050505050505050505050565b60028181548110612e5357600080fd5b60009182526020909120600590910201805460018201546002830154600384015460049094015463ffffffff8416955064010000000090930473ffffffffffffffffffffffffffffffffffffffff908116949216926fffffffffffffffffffffffffffffffff91821692918082169170010000000000000000000000000000000090041687565b60008054700100000000000000000000000000000000900460ff166002811115612f0657612f0661555f565b14612f3d576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028781548110612f5257612f526158d5565b6000918252602082206005919091020160048101549092506fffffffffffffffffffffffffffffffff16908715821760011b9050612fb17f00000000000000000000000000000000000000000000000000000000000000086001615933565b61304d826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1614613087576040517f5f53dd9800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080891561317e576130da7f00000000000000000000000000000000000000000000000000000000000000047f0000000000000000000000000000000000000000000000000000000000000008615983565b6001901b6130f9846fffffffffffffffffffffffffffffffff16614569565b6fffffffffffffffffffffffffffffffff166131159190615af9565b156131525761314961313a60016fffffffffffffffffffffffffffffffff8716615b0d565b865463ffffffff166000614608565b60030154613174565b7f00000000000000000000000000000000000000000000000000000000000000005b91508490506131a8565b600385015491506131a561313a6fffffffffffffffffffffffffffffffff86166001615b36565b90505b600882901b60088a8a6040516131bf9291906158c5565b6040518091039020901b14613200576040517f696550ff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061320b8c6146ec565b9050600061321a836003015490565b6040517fe14ced320000000000000000000000000000000000000000000000000000000081527f000000000000000000000000180cbe2ebb9f37d3a3c542ddc2546fd160555a7373ffffffffffffffffffffffffffffffffffffffff169063e14ced3290613294908f908f908f908f908a90600401615baa565b6020604051808303816000875af11580156132b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132d791906159b7565b600485015491149150600090600290613382906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b61341e896fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b6134289190615be4565b6134329190615c07565b60ff161590508115158103613473576040517ffb4e40dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8754640100000000900473ffffffffffffffffffffffffffffffffffffffff16156134ca576040517f9071e6af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505085547fffffffffffffffff0000000000000000000000000000000000000000ffffffff163364010000000002179095555050505050505050505050565b60008054700100000000000000000000000000000000900460ff1660028111156135355761353561555f565b1461356c576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060008061357b8661471b565b9350935093509350600061359185858585614b24565b905060007f000000000000000000000000180cbe2ebb9f37d3a3c542ddc2546fd160555a7373ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015613600573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613624919061599a565b90506001890361371c5773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a84613680367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036034013590565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815260048101939093526024830191909152604482015260206064820152608481018a905260a4015b6020604051808303816000875af11580156136f2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061371691906159b7565b5061155b565b600289036137485773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a8489613680565b600389036137745773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a8487613680565b600489036138fb5760006137ba6fffffffffffffffffffffffffffffffff85167f0000000000000000000000000000000000000000000000000000000000000004614bde565b6009546137c79190615933565b6137d2906001615933565b9050367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360540135811061383b57367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036054013561383d565b805b905073ffffffffffffffffffffffffffffffffffffffff82166352f0f3ad8b8560405160e084901b7fffffffff000000000000000000000000000000000000000000000000000000001681526004810192909252602482015260c084901b604482015260086064820152608481018b905260a4016020604051808303816000875af11580156138d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138f491906159b7565b505061155b565b60058903613994576040517f52f0f3ad000000000000000000000000000000000000000000000000000000008152600481018a9052602481018390527f000000000000000000000000000000000000000000000000000000000000038560c01b6044820152600860648201526084810188905273ffffffffffffffffffffffffffffffffffffffff8216906352f0f3ad9060a4016136d3565b6040517fff137e6500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000000367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003601401356060613a1f61188d565b9050909192565b600081831015613a365781613a38565b825b90505b92915050565b60008160000151826020015183604001518460600151604051602001613a80949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b60408051808201909152600080825260208201528151600003613aec576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50604080518082019091528151815260209182019181019190915290565b60606000806000613b1a85614c8c565b919450925090506001816001811115613b3557613b3561555f565b14613b6c576040517f4b9c6abe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8451613b788385615933565b14613baf576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808252610420820190925290816020015b6040805180820190915260008082526020820152815260200190600190039081613bc65790505093506000835b8651811015613cb457600080613c396040518060400160405280858c60000151613c1d9190615983565b8152602001858c60200151613c329190615933565b9052614c8c565b509150915060405180604001604052808383613c559190615933565b8152602001848b60200151613c6a9190615933565b815250888581518110613c7f57613c7f6158d5565b6020908102919091010152613c95600185615933565b9350613ca18183615933565b613cab9084615933565b92505050613bf3565b50845250919392505050565b60606000806000613cd085614c8c565b919450925090506000816001811115613ceb57613ceb61555f565b14613d22576040517f1ff9b2e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613d2c8284615933565b855114613d65576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6118848560200151848461512a565b600281015473ffffffffffffffffffffffffffffffffffffffff8316600090815260036020526040812080546fffffffffffffffffffffffffffffffff90931692839290613dc3908490615933565b90915550506040517f7eee288d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018390527f000000000000000000000000ef179756ea6525afade217ca5ab0b1b5cfe0fd921690637eee288d90604401600060405180830381600087803b158015613e5857600080fd5b505af1158015613e6c573d6000803e3d6000fd5b50505050505050565b604051818152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90038284820160208401378260208301016000815260208101604052505092915050565b6000613ee66fffffffffffffffffffffffffffffffff84166001615b36565b90506000613ef682866001614608565b9050600086901a8380613fe25750613f2f60027f0000000000000000000000000000000000000000000000000000000000000004615af9565b6004830154600290613fd3906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b613fdd9190615c07565b60ff16145b1561403a5760ff811660011480613ffc575060ff81166002145b614035576040517ff40239db00000000000000000000000000000000000000000000000000000000815260048101889052602401612752565b613e6c565b60ff811615613e6c576040517ff40239db00000000000000000000000000000000000000000000000000000000815260048101889052602401612752565b6fffffffffffffffffffffffffffffffff811160071b81811c67ffffffffffffffff1060061b1781811c63ffffffff1060051b1781811c61ffff1060041b1781811c60ff1060031b17600082136140d757631615e6386000526004601cfd5b7ff8f9f9faf9fdfafbf9fdfcfdfafbfcfef9fafdfafcfcfbfefafafcfbffffffff6f8421084210842108cc6318c6db6d54be83831c1c601f161a1890811b609f90811c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506029190037d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b302017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d90565b60007812725dd1d243aba0e75fe645cc4873f9e65afe688c928e1f218311670de0b6b3a76400000215820261431057637c5f487d6000526004601cfd5b50670de0b6b3a7640000919091020490565b6000816000190483118202156143405763bac65e5b6000526004601cfd5b50670de0b6b3a764000091020490565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdc0d0570925a462d7821361437e57919050565b680755bf798b4a1bf1e5821261439c5763a37bfec96000526004601cfd5b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b6000613a38670de0b6b3a76400008361455086614078565b61455a9190615c29565b6145649190615ce5565b614350565b6000806145f6837e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b600160ff919091161b90920392915050565b600080826146515761464c6fffffffffffffffffffffffffffffffff86167f00000000000000000000000000000000000000000000000000000000000000046151bf565b61466c565b61466c856fffffffffffffffffffffffffffffffff1661534b565b905060028481548110614681576146816158d5565b906000526020600020906005020191505b60048201546fffffffffffffffffffffffffffffffff8281169116146146e457815460028054909163ffffffff169081106146cf576146cf6158d5565b90600052602060002090600502019150614692565b509392505050565b60008060008060006146fd8661471b565b935093509350935061471184848484614b24565b9695505050505050565b600080600080600085905060006002828154811061473b5761473b6158d5565b600091825260209091206004600590920201908101549091507f000000000000000000000000000000000000000000000000000000000000000490614812906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff161161484c576040517fb34b5c2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000815b60048301547f000000000000000000000000000000000000000000000000000000000000000490614913906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff16925082111561498857825463ffffffff166149527f00000000000000000000000000000000000000000000000000000000000000046001615933565b830361495c578391505b6002818154811061496f5761496f6158d5565b9060005260206000209060050201935080945050614850565b600481810154908401546fffffffffffffffffffffffffffffffff91821691166000816fffffffffffffffffffffffffffffffff166149f16149dc856fffffffffffffffffffffffffffffffff1660011c90565b6fffffffffffffffffffffffffffffffff1690565b6fffffffffffffffffffffffffffffffff161490508015614ac0576000614a29836fffffffffffffffffffffffffffffffff16614569565b6fffffffffffffffffffffffffffffffff161115614a94576000614a6b614a6360016fffffffffffffffffffffffffffffffff8616615b0d565b896001614608565b6003810154600490910154909c506fffffffffffffffffffffffffffffffff169a50614a9a9050565b6008549a505b600386015460048701549099506fffffffffffffffffffffffffffffffff169750614b16565b6000614ae2614a636fffffffffffffffffffffffffffffffff85166001615b36565b6003808901546004808b015492840154930154909e506fffffffffffffffffffffffffffffffff9182169d50919b50169850505b505050505050509193509193565b60006fffffffffffffffffffffffffffffffff841615614b915760408051602081018790526fffffffffffffffffffffffffffffffff8087169282019290925260608101859052908316608082015260a00160405160208183030381529060405280519060200120611884565b8282604051602001614bbf9291909182526fffffffffffffffffffffffffffffffff16602082015260400190565b6040516020818303038152906040528051906020012095945050505050565b600080614c6b847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690508083036001841b600180831b0386831b17039250505092915050565b60008060008360000151600003614ccf576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020840151805160001a607f8111614cf4576000600160009450945094505050615123565b60b78111614e0a576000614d09608083615983565b905080876000015111614d48576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001838101517fff00000000000000000000000000000000000000000000000000000000000000169082148015614dc057507f80000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008216105b15614df7576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5060019550935060009250615123915050565b60bf8111614f68576000614e1f60b783615983565b905080876000015111614e5e576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614ec0576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c60378111614f08576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614f128184615933565b895111614f4b576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614f56836001615933565b97509550600094506151239350505050565b60f78111614fcd576000614f7d60c083615983565b905080876000015111614fbc576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600195509350849250615123915050565b6000614fda60f783615983565b905080876000015111615019576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff0000000000000000000000000000000000000000000000000000000000000016600081900361507b576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c603781116150c3576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6150cd8184615933565b895111615106576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b615111836001615933565b97509550600194506151239350505050565b9193909250565b60608167ffffffffffffffff81111561514557615145615809565b6040519080825280601f01601f19166020018201604052801561516f576020820181803683370190505b50905081156151b85760006151848486615933565b90506020820160005b848110156151a557828101518282015260200161518d565b848111156151b4576000858301525b5050505b9392505050565b60008161525e846fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff16116152745763b34b5c226000526004601cfd5b61527d8361534b565b90508161531c826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1611613a3b57613a38615332836001615933565b6fffffffffffffffffffffffffffffffff8316906153f0565b600081196001830116816153df827e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169390931c8015179392505050565b60008061547d847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169050808303600180821b0385821b179250505092915050565b60008083601f8401126154ab57600080fd5b50813567ffffffffffffffff8111156154c357600080fd5b6020830191508360208285010111156154db57600080fd5b9250929050565b600080600083850360a08112156154f857600080fd5b608081121561550657600080fd5b50839250608084013567ffffffffffffffff81111561552457600080fd5b61553086828701615499565b9497909650939450505050565b6000806040838503121561555057600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60208101600383106155c9577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b6000806000606084860312156155e457600080fd5b505081359360208301359350604090920135919050565b6000815180845260005b8181101561562157602081850181015186830182015201615605565b81811115615633576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000613a3860208301846155fb565b60006020828403121561568b57600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff811681146156b457600080fd5b50565b6000602082840312156156c957600080fd5b81356151b881615692565b803580151581146156e457600080fd5b919050565b600080600080608085870312156156ff57600080fd5b84359350602085013592506040850135915061571d606086016156d4565b905092959194509250565b60006020828403121561573a57600080fd5b81356fffffffffffffffffffffffffffffffff811681146151b857600080fd5b6000806000806000806080878903121561577357600080fd5b86359550615783602088016156d4565b9450604087013567ffffffffffffffff808211156157a057600080fd5b6157ac8a838b01615499565b909650945060608901359150808211156157c557600080fd5b506157d289828a01615499565b979a9699509497509295939492505050565b63ffffffff8416815282602082015260606040820152600061188460608301846155fb565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006080828403121561584a57600080fd5b6040516080810181811067ffffffffffffffff82111715615894577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561594657615946615904565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361597c5761597c615904565b5060010190565b60008282101561599557615995615904565b500390565b6000602082840312156159ac57600080fd5b81516151b881615692565b6000602082840312156159c957600080fd5b5051919050565b600067ffffffffffffffff8083168185168083038211156159f3576159f3615904565b01949350505050565b600067ffffffffffffffff80831681851681830481118215151615615a2357615a23615904565b02949350505050565b600067ffffffffffffffff83811690831681811015615a4d57615a4d615904565b039392505050565b60008060408385031215615a6857600080fd5b505080516020909101519092909150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082615ab757615ab7615a79565b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615af457615af4615904565b500290565b600082615b0857615b08615a79565b500690565b60006fffffffffffffffffffffffffffffffff83811690831681811015615a4d57615a4d615904565b60006fffffffffffffffffffffffffffffffff8083168185168083038211156159f3576159f3615904565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b606081526000615bbe606083018789615b61565b8281036020840152615bd1818688615b61565b9150508260408301529695505050505050565b600060ff821660ff841680821015615bfe57615bfe615904565b90039392505050565b600060ff831680615c1a57615c1a615a79565b8060ff84160691505092915050565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600084136000841385830485118282161615615c6a57615c6a615904565b7f80000000000000000000000000000000000000000000000000000000000000006000871286820588128184161615615ca557615ca5615904565b60008712925087820587128484161615615cc157615cc1615904565b87850587128184161615615cd757615cd7615904565b505050929093029392505050565b600082615cf457615cf4615a79565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f800000000000000000000000000000000000000000000000000000000000000083141615615d4857615d48615904565b50059056fea164736f6c634300080f000a"; bytes internal constant acc34Code = - hex"6080604052600436106103085760003560e01c806370872aa51161019a578063c6f0308c116100e1578063ec5e63081161008a578063fa24f74311610064578063fa24f74314610b94578063fa315aa914610bb8578063fe2bbeb214610beb57600080fd5b8063ec5e630814610b11578063eff0f59214610b44578063f8f43ff614610b7457600080fd5b8063d6ae3cd5116100bb578063d6ae3cd514610a8b578063d8cc1a3c14610abe578063dabd396d14610ade57600080fd5b8063c6f0308c146109b3578063cf09e0d014610a3d578063d5d44d8014610a5e57600080fd5b8063a445ece611610143578063bcef3b551161011d578063bcef3b5514610933578063bd8da95614610973578063c395e1ca1461099357600080fd5b8063a445ece6146107f3578063a8e4fb90146108bf578063bbdc02db146108f257600080fd5b80638980e0cc116101745780638980e0cc1461076b5780638b85902b146107805780638d450a95146107c057600080fd5b806370872aa51461073b5780637b0f0adc146107505780638129fc1c1461076357600080fd5b80633fc8cef31161025e5780635c0cba33116102075780636361506d116101e15780636361506d146106b55780636b6716c0146106f55780636f0344091461072857600080fd5b80635c0cba331461064d578063609d33341461068057806360e274641461069557600080fd5b806354fd4d501161023857806354fd4d50146105a757806357da950e146105fd5780635a5fa2d91461062d57600080fd5b80633fc8cef31461052e578063472777c614610561578063534db0e21461057457600080fd5b80632810e1d6116102c057806337b1b2291161029a57806337b1b2291461047b5780633a768463146104bb5780633e3ac912146104ee57600080fd5b80632810e1d6146103f45780632ad69aeb1461040957806330dbe5701461042957600080fd5b806319effeb4116102f157806319effeb41461034f578063200d2ed21461039a57806325fc2ace146103d557600080fd5b8063019351301461030d57806303c2924d1461032f575b600080fd5b34801561031957600080fd5b5061032d61032836600461575d565b610c1b565b005b34801561033b57600080fd5b5061032d61034a3660046157b8565b610f3c565b34801561035b57600080fd5b5060005461037c9068010000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020015b60405180910390f35b3480156103a657600080fd5b506000546103c890700100000000000000000000000000000000900460ff1681565b6040516103919190615809565b3480156103e157600080fd5b506008545b604051908152602001610391565b34801561040057600080fd5b506103c86115e2565b34801561041557600080fd5b506103e66104243660046157b8565b611887565b34801561043557600080fd5b506001546104569073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610391565b34801561048757600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90033560601c610456565b3480156104c757600080fd5b507f000000000000000000000000444e09fe6d839273316a87002ab0efbea6fe7806610456565b3480156104fa57600080fd5b5060005461051e907201000000000000000000000000000000000000900460ff1681565b6040519015158152602001610391565b34801561053a57600080fd5b507f000000000000000000000000d6eaf4c146261653ee059077b78ed088add54309610456565b61032d61056f36600461584a565b6118bd565b34801561058057600080fd5b507f0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b63610456565b3480156105b357600080fd5b506105f06040518060400160405280600a81526020017f312e332e302d72632e310000000000000000000000000000000000000000000081525081565b60405161039191906158e1565b34801561060957600080fd5b50600854600954610618919082565b60408051928352602083019190915201610391565b34801561063957600080fd5b506103e66106483660046158f4565b6118cf565b34801561065957600080fd5b507f000000000000000000000000970670459734a83899773a0fd45941b5afc1200e610456565b34801561068c57600080fd5b506105f0611909565b3480156106a157600080fd5b5061032d6106b0366004615932565b611917565b3480156106c157600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003603401356103e6565b34801561070157600080fd5b507f000000000000000000000000000000000000000000000000000000000000000061037c565b61032d610736366004615964565b611abe565b34801561074757600080fd5b506009546103e6565b61032d61075e36600461584a565b611b7f565b61032d611b8c565b34801561077757600080fd5b506002546103e6565b34801561078c57600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401356103e6565b3480156107cc57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006103e6565b3480156107ff57600080fd5b5061086b61080e3660046158f4565b6007602052600090815260409020805460019091015460ff821691610100810463ffffffff1691650100000000009091046fffffffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff1684565b60408051941515855263ffffffff90931660208501526fffffffffffffffffffffffffffffffff9091169183019190915273ffffffffffffffffffffffffffffffffffffffff166060820152608001610391565b3480156108cb57600080fd5b507f00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8610456565b3480156108fe57600080fd5b5060405163ffffffff7f0000000000000000000000000000000000000000000000000000000000000001168152602001610391565b34801561093f57600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003601401356103e6565b34801561097f57600080fd5b5061037c61098e3660046158f4565b611c05565b34801561099f57600080fd5b506103e66109ae3660046159a3565b611de4565b3480156109bf57600080fd5b506109d36109ce3660046158f4565b611fc7565b6040805163ffffffff909816885273ffffffffffffffffffffffffffffffffffffffff968716602089015295909416948601949094526fffffffffffffffffffffffffffffffff9182166060860152608085015291821660a08401521660c082015260e001610391565b348015610a4957600080fd5b5060005461037c9067ffffffffffffffff1681565b348015610a6a57600080fd5b506103e6610a79366004615932565b60036020526000908152604090205481565b348015610a9757600080fd5b507f00000000000000000000000000000000000000000000000000000000000003856103e6565b348015610aca57600080fd5b5061032d610ad93660046159d5565b61205e565b348015610aea57600080fd5b507f00000000000000000000000000000000000000000000000000000000000004b061037c565b348015610b1d57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000046103e6565b348015610b5057600080fd5b5061051e610b5f3660046158f4565b60046020526000908152604090205460ff1681565b348015610b8057600080fd5b5061032d610b8f36600461584a565b612123565b348015610ba057600080fd5b50610ba96125e0565b60405161039193929190615a5f565b348015610bc457600080fd5b507f00000000000000000000000000000000000000000000000000000000000000086103e6565b348015610bf757600080fd5b5061051e610c063660046158f4565b60066020526000908152604090205460ff1681565b60008054700100000000000000000000000000000000900460ff166002811115610c4757610c476157da565b14610c7e576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000547201000000000000000000000000000000000000900460ff1615610cd1576040517f0ea2e75200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d08367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013590565b90565b610d1f610d1a36869003860186615ab3565b61265b565b14610d56576040517f9cc00b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82606001358282604051610d6b929190615b40565b604051809103902014610daa576040517fd81d583b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610df3610dee84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506126b792505050565b612724565b90506000610e1a82600881518110610e0d57610e0d615b50565b60200260200101516128da565b9050602081511115610e58576040517fd81d583b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602081810151825190910360031b1c367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401358103610ecd576040517fb8ed883000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050600180547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790555050600080547fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff1672010000000000000000000000000000000000001790555050565b60008054700100000000000000000000000000000000900460ff166002811115610f6857610f686157da565b14610f9f576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028381548110610fb457610fb4615b50565b906000526020600020906005020190506000610fcf84611c05565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b081169082161015611038576040517ff2440b5300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008481526006602052604090205460ff1615611081576040517ff1a9458100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600084815260056020526040902080548015801561109e57508515155b15611139578354640100000000900473ffffffffffffffffffffffffffffffffffffffff16600081156110d157816110ed565b600186015473ffffffffffffffffffffffffffffffffffffffff165b90506110f9818761298e565b50505060009485525050600660205250506040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b6000868152600760209081526040918290208251608081018452815460ff81161515808352610100820463ffffffff16948301949094526501000000000090046fffffffffffffffffffffffffffffffff16938101939093526001015473ffffffffffffffffffffffffffffffffffffffff1660608301526111dc576fffffffffffffffffffffffffffffffff60408201526001815260008690036111dc578195505b600086826020015163ffffffff166111f49190615bae565b905060008382116112055781611207565b835b602084015190915063ffffffff165b8181101561135357600086828154811061123257611232615b50565b6000918252602080832090910154808352600690915260409091205490915060ff1661128a576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006002828154811061129f5761129f615b50565b600091825260209091206005909102018054909150640100000000900473ffffffffffffffffffffffffffffffffffffffff161580156112fc5750600481015460408701516fffffffffffffffffffffffffffffffff9182169116115b1561133e57600181015473ffffffffffffffffffffffffffffffffffffffff16606087015260048101546fffffffffffffffffffffffffffffffff1660408701525b5050808061134b90615bc6565b915050611216565b5063ffffffff818116602085810191825260008c81526007909152604090819020865181549351928801517fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009094169015157fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ff161761010092909416918202939093177fffffffffffffffffffffff00000000000000000000000000000000ffffffffff16650100000000006fffffffffffffffffffffffffffffffff909316929092029190911782556060850151600190920180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909316929092179091558490036115d757606083015160008a815260066020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055891580156114d357506000547201000000000000000000000000000000000000900460ff165b156115485760015473ffffffffffffffffffffffffffffffffffffffff166114fb818a61298e565b885473ffffffffffffffffffffffffffffffffffffffff909116640100000000027fffffffffffffffff0000000000000000000000000000000000000000ffffffff9091161788556115d5565b61158f73ffffffffffffffffffffffffffffffffffffffff82161561156d5781611589565b600189015473ffffffffffffffffffffffffffffffffffffffff165b8961298e565b87547fffffffffffffffff0000000000000000000000000000000000000000ffffffff1664010000000073ffffffffffffffffffffffffffffffffffffffff8316021788555b505b505050505050505050565b600080600054700100000000000000000000000000000000900460ff166002811115611610576116106157da565b14611647576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000805260066020527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f85460ff166116ab576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660026000815481106116d7576116d7615b50565b6000918252602090912060059091020154640100000000900473ffffffffffffffffffffffffffffffffffffffff1614611712576001611715565b60025b6000805467ffffffffffffffff421668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff82168117835592935083927fffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffff000000000000000000ffffffffffffffff909116177001000000000000000000000000000000008360028111156117c6576117c66157da565b0217905560028111156117db576117db6157da565b6040517f5e186f09b9c93491f14e277eea7faa5de6a2d4bda75a79af7a3684fbfb42da6090600090a27f000000000000000000000000970670459734a83899773a0fd45941b5afc1200e73ffffffffffffffffffffffffffffffffffffffff1663838c2d1e6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561186c57600080fd5b505af1158015611880573d6000803e3d6000fd5b5050505090565b600560205281600052604060002081815481106118a357600080fd5b90600052602060002001600091509150505481565b905090565b6118ca8383836001611abe565b505050565b6000818152600760209081526040808320600590925282208054825461190090610100900463ffffffff1682615bfe565b95945050505050565b60606118b860546020612a8f565b73ffffffffffffffffffffffffffffffffffffffff811660009081526003602052604081208054908290559081900361197c576040517f17bfe5f700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517ff3fef3a300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152602482018390527f000000000000000000000000d6eaf4c146261653ee059077b78ed088add54309169063f3fef3a390604401600060405180830381600087803b158015611a0c57600080fd5b505af1158015611a20573d6000803e3d6000fd5b5050505060008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114611a7e576040519150601f19603f3d011682016040523d82523d6000602084013e611a83565b606091505b50509050806118ca576040517f83e6cc6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8161480611b3757503373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b6316145b611b6d576040517fd386ef3e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611b7984848484612ae1565b50505050565b6118ca8383836000611abe565b3273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c81614611bfb576040517fd386ef3e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611c036135ba565b565b600080600054700100000000000000000000000000000000900460ff166002811115611c3357611c336157da565b14611c6a576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028381548110611c7f57611c7f615b50565b600091825260208220600590910201805490925063ffffffff90811614611cee57815460028054909163ffffffff16908110611cbd57611cbd615b50565b906000526020600020906005020160040160109054906101000a90046fffffffffffffffffffffffffffffffff1690505b6004820154600090611d2690700100000000000000000000000000000000900467ffffffffffffffff165b67ffffffffffffffff1690565b611d3a9067ffffffffffffffff1642615bfe565b611d59611d19846fffffffffffffffffffffffffffffffff1660401c90565b67ffffffffffffffff16611d6d9190615bae565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b01667ffffffffffffffff168167ffffffffffffffff1611611dba5780611900565b7f00000000000000000000000000000000000000000000000000000000000004b095945050505050565b600080611e83836fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690507f0000000000000000000000000000000000000000000000000000000000000008811115611ee2576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b642e90edd00062061a806311e1a3006000611efd8383615c44565b9050670de0b6b3a76400006000611f34827f0000000000000000000000000000000000000000000000000000000000000008615c58565b90506000611f52611f4d670de0b6b3a764000086615c58565b613b13565b90506000611f608484613d6e565b90506000611f6e8383613dbd565b90506000611f7b82613deb565b90506000611f9a82611f95670de0b6b3a76400008f615c58565b613fd3565b90506000611fa88b83613dbd565b9050611fb4818d615c58565b9f9e505050505050505050505050505050565b60028181548110611fd757600080fd5b60009182526020909120600590910201805460018201546002830154600384015460049094015463ffffffff8416955064010000000090930473ffffffffffffffffffffffffffffffffffffffff908116949216926fffffffffffffffffffffffffffffffff91821692918082169170010000000000000000000000000000000090041687565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c81614806120d757503373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b6316145b61210d576040517fd386ef3e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61211b868686868686614004565b505050505050565b60008054700100000000000000000000000000000000900460ff16600281111561214f5761214f6157da565b14612186576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060008061219586614633565b935093509350935060006121ab85858585614a3c565b905060007f000000000000000000000000444e09fe6d839273316a87002ab0efbea6fe780673ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561221a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061223e9190615c95565b9050600189036123365773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a8461229a367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036034013590565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815260048101939093526024830191909152604482015260206064820152608481018a905260a4015b6020604051808303816000875af115801561230c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123309190615cb2565b506115d7565b600289036123625773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a848961229a565b6003890361238e5773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a848761229a565b600489036125155760006123d46fffffffffffffffffffffffffffffffff85167f0000000000000000000000000000000000000000000000000000000000000004614af6565b6009546123e19190615bae565b6123ec906001615bae565b9050367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360540135811061245557367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360540135612457565b805b905073ffffffffffffffffffffffffffffffffffffffff82166352f0f3ad8b8560405160e084901b7fffffffff000000000000000000000000000000000000000000000000000000001681526004810192909252602482015260c084901b604482015260086064820152608481018b905260a4016020604051808303816000875af11580156124ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061250e9190615cb2565b50506115d7565b600589036125ae576040517f52f0f3ad000000000000000000000000000000000000000000000000000000008152600481018a9052602481018390527f000000000000000000000000000000000000000000000000000000000000038560c01b6044820152600860648201526084810188905273ffffffffffffffffffffffffffffffffffffffff8216906352f0f3ad9060a4016122ed565b6040517fff137e6500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000001367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003601401356060612639611909565b9050909192565b6000818310156126505781612652565b825b90505b92915050565b6000816000015182602001518360400151846060015160405160200161269a949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b60408051808201909152600080825260208201528151600003612706576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50604080518082019091528151815260209182019181019190915290565b6060600080600061273485614ba4565b91945092509050600181600181111561274f5761274f6157da565b14612786576040517f4b9c6abe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84516127928385615bae565b146127c9576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808252610420820190925290816020015b60408051808201909152600080825260208201528152602001906001900390816127e05790505093506000835b86518110156128ce576000806128536040518060400160405280858c600001516128379190615bfe565b8152602001858c6020015161284c9190615bae565b9052614ba4565b50915091506040518060400160405280838361286f9190615bae565b8152602001848b602001516128849190615bae565b81525088858151811061289957612899615b50565b60209081029190910101526128af600185615bae565b93506128bb8183615bae565b6128c59084615bae565b9250505061280d565b50845250919392505050565b606060008060006128ea85614ba4565b919450925090506000816001811115612905576129056157da565b1461293c576040517f1ff9b2e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6129468284615bae565b85511461297f576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61190085602001518484615042565b600281015473ffffffffffffffffffffffffffffffffffffffff8316600090815260036020526040812080546fffffffffffffffffffffffffffffffff909316928392906129dd908490615bae565b90915550506040517f7eee288d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018390527f000000000000000000000000d6eaf4c146261653ee059077b78ed088add543091690637eee288d90604401600060405180830381600087803b158015612a7257600080fd5b505af1158015612a86573d6000803e3d6000fd5b50505050505050565b604051818152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90038284820160208401378260208301016000815260208101604052505092915050565b60008054700100000000000000000000000000000000900460ff166002811115612b0d57612b0d6157da565b14612b44576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028481548110612b5957612b59615b50565b60009182526020918290206040805160e0810182526005909302909101805463ffffffff8116845273ffffffffffffffffffffffffffffffffffffffff64010000000090910481169484019490945260018101549093169082015260028201546fffffffffffffffffffffffffffffffff908116606083015260038301546080830181905260049093015480821660a084015270010000000000000000000000000000000090041660c082015291508514612c40576040517f3014033200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60a0810151600083156fffffffffffffffffffffffffffffffff83161760011b90506000612d00826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169050861580612d3b5750612d387f00000000000000000000000000000000000000000000000000000000000000046002615bae565b81145b8015612d45575084155b15612d7c576040517fa42637bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000547201000000000000000000000000000000000000900460ff168015612da2575086155b15612dd9576040517f0ea2e75200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000008811115612e33576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612e5e7f00000000000000000000000000000000000000000000000000000000000000046001615bae565b8103612e7057612e70868885886150d7565b34612e7a83611de4565b14612eb1576040517f8620aa1900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612ebc88611c05565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b0811690821603612f24576040517f3381d11400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612f5160017f0000000000000000000000000000000000000000000000000000000000000008615bfe565b830361308f577f000000000000000000000000444e09fe6d839273316a87002ab0efbea6fe780673ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015612fc2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fe69190615c95565b73ffffffffffffffffffffffffffffffffffffffff1663f3f480d96040518163ffffffff1660e01b8152600401602060405180830381865afa158015613030573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130549190615cb2565b613088907f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff16615ccb565b9050613122565b6130ba60017f0000000000000000000000000000000000000000000000000000000000000004615bfe565b83036130f5576130887f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff166002615cf7565b507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff165b613156817f00000000000000000000000000000000000000000000000000000000000004b067ffffffffffffffff16615d27565b67ffffffffffffffff166131718367ffffffffffffffff1690565b67ffffffffffffffff1611156131b8576131b5817f00000000000000000000000000000000000000000000000000000000000004b067ffffffffffffffff16615d27565b91505b6000604083901b421760008a8152608087901b6fffffffffffffffffffffffffffffffff8d1617602052604081209192509060008181526004602052604090205490915060ff1615613236576040517f80497e3b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60016004600083815260200190815260200160002060006101000a81548160ff02191690831515021790555060026040518060e001604052808d63ffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020013373ffffffffffffffffffffffffffffffffffffffff168152602001346fffffffffffffffffffffffffffffffff1681526020018c8152602001886fffffffffffffffffffffffffffffffff168152602001846fffffffffffffffffffffffffffffffff16815250908060018154018082558091505060019003906000526020600020906005020160009091909190915060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060608201518160020160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055506080820151816003015560a08201518160040160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555060c08201518160040160106101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055505050600560008c815260200190815260200160002060016002805490506134cc9190615bfe565b81546001810183556000928352602083200155604080517fd0e30db0000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000d6eaf4c146261653ee059077b78ed088add54309169263d0e30db09234926004808301939282900301818588803b15801561356457600080fd5b505af1158015613578573d6000803e3d6000fd5b50506040513393508d92508e91507f9b3245740ec3b155098a55be84957a4da13eaf7f14a8bc6f53126c0b9350f2be90600090a4505050505050505050505050565b60005471010000000000000000000000000000000000900460ff161561360c576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f7258a80700000000000000000000000000000000000000000000000000000000815263ffffffff7f0000000000000000000000000000000000000000000000000000000000000001166004820152600090819073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000970670459734a83899773a0fd45941b5afc1200e1690637258a807906024016040805180830381865afa1580156136c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136e49190615d50565b909250905081613720576040517f6a6bc3b200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518082019091528281526020018190526008829055600981905536607a1461375357639824bdab6000526004601cfd5b80367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360540135116137ed576040517ff40239db000000000000000000000000000000000000000000000000000000008152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013560048201526024015b60405180910390fd5b6040805160e08101825263ffffffff8082526000602083018181527ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe369081013560f01c90038035606090811c868801908152346fffffffffffffffffffffffffffffffff81811693890193845260149094013560808901908152600160a08a0181815242871660c08c019081526002805493840181558a529a5160059092027f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace81018054995173ffffffffffffffffffffffffffffffffffffffff908116640100000000027fffffffffffffffff000000000000000000000000000000000000000000000000909b1694909c16939093179890981790915592517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5acf87018054918a167fffffffffffffffffffffffff000000000000000000000000000000000000000090921691909117905592517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad0860180549186167fffffffffffffffffffffffffffffffff0000000000000000000000000000000090921691909117905591517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad185015551955182167001000000000000000000000000000000000295909116949094177f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad29091015580547fffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffff167101000000000000000000000000000000000017815583517fd0e30db000000000000000000000000000000000000000000000000000000000815293517f000000000000000000000000d6eaf4c146261653ee059077b78ed088add543099092169363d0e30db093926004828101939282900301818588803b158015613ac257600080fd5b505af1158015613ad6573d6000803e3d6000fd5b5050600080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000164267ffffffffffffffff161790555050505050565b6fffffffffffffffffffffffffffffffff811160071b81811c67ffffffffffffffff1060061b1781811c63ffffffff1060051b1781811c61ffff1060041b1781811c60ff1060031b1760008213613b7257631615e6386000526004601cfd5b7ff8f9f9faf9fdfafbf9fdfcfdfafbfcfef9fafdfafcfcfbfefafafcfbffffffff6f8421084210842108cc6318c6db6d54be83831c1c601f161a1890811b609f90811c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506029190037d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b302017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d90565b60007812725dd1d243aba0e75fe645cc4873f9e65afe688c928e1f218311670de0b6b3a764000002158202613dab57637c5f487d6000526004601cfd5b50670de0b6b3a7640000919091020490565b600081600019048311820215613ddb5763bac65e5b6000526004601cfd5b50670de0b6b3a764000091020490565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdc0d0570925a462d78213613e1957919050565b680755bf798b4a1bf1e58212613e375763a37bfec96000526004601cfd5b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b6000612652670de0b6b3a764000083613feb86613b13565b613ff59190615d74565b613fff9190615e30565b613deb565b60008054700100000000000000000000000000000000900460ff166002811115614030576140306157da565b14614067576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006002878154811061407c5761407c615b50565b6000918252602082206005919091020160048101549092506fffffffffffffffffffffffffffffffff16908715821760011b90506140db7f00000000000000000000000000000000000000000000000000000000000000086001615bae565b614177826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff16146141b1576040517f5f53dd9800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008089156142a8576142047f00000000000000000000000000000000000000000000000000000000000000047f0000000000000000000000000000000000000000000000000000000000000008615bfe565b6001901b614223846fffffffffffffffffffffffffffffffff16615288565b6fffffffffffffffffffffffffffffffff1661423f9190615e98565b1561427c5761427361426460016fffffffffffffffffffffffffffffffff8716615eac565b865463ffffffff166000615327565b6003015461429e565b7f00000000000000000000000000000000000000000000000000000000000000005b91508490506142d2565b600385015491506142cf6142646fffffffffffffffffffffffffffffffff86166001615ed5565b90505b600882901b60088a8a6040516142e9929190615b40565b6040518091039020901b1461432a576040517f696550ff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006143358c61540b565b90506000614344836003015490565b6040517fe14ced320000000000000000000000000000000000000000000000000000000081527f000000000000000000000000444e09fe6d839273316a87002ab0efbea6fe780673ffffffffffffffffffffffffffffffffffffffff169063e14ced32906143be908f908f908f908f908a90600401615f49565b6020604051808303816000875af11580156143dd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144019190615cb2565b6004850154911491506000906002906144ac906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b614548896fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b6145529190615f83565b61455c9190615fa6565b60ff16159050811515810361459d576040517ffb4e40dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8754640100000000900473ffffffffffffffffffffffffffffffffffffffff16156145f4576040517f9071e6af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505085547fffffffffffffffff0000000000000000000000000000000000000000ffffffff163364010000000002179095555050505050505050505050565b600080600080600085905060006002828154811061465357614653615b50565b600091825260209091206004600590920201908101549091507f00000000000000000000000000000000000000000000000000000000000000049061472a906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1611614764576040517fb34b5c2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000815b60048301547f00000000000000000000000000000000000000000000000000000000000000049061482b906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1692508211156148a057825463ffffffff1661486a7f00000000000000000000000000000000000000000000000000000000000000046001615bae565b8303614874578391505b6002818154811061488757614887615b50565b9060005260206000209060050201935080945050614768565b600481810154908401546fffffffffffffffffffffffffffffffff91821691166000816fffffffffffffffffffffffffffffffff166149096148f4856fffffffffffffffffffffffffffffffff1660011c90565b6fffffffffffffffffffffffffffffffff1690565b6fffffffffffffffffffffffffffffffff1614905080156149d8576000614941836fffffffffffffffffffffffffffffffff16615288565b6fffffffffffffffffffffffffffffffff1611156149ac57600061498361497b60016fffffffffffffffffffffffffffffffff8616615eac565b896001615327565b6003810154600490910154909c506fffffffffffffffffffffffffffffffff169a506149b29050565b6008549a505b600386015460048701549099506fffffffffffffffffffffffffffffffff169750614a2e565b60006149fa61497b6fffffffffffffffffffffffffffffffff85166001615ed5565b6003808901546004808b015492840154930154909e506fffffffffffffffffffffffffffffffff9182169d50919b50169850505b505050505050509193509193565b60006fffffffffffffffffffffffffffffffff841615614aa95760408051602081018790526fffffffffffffffffffffffffffffffff8087169282019290925260608101859052908316608082015260a00160405160208183030381529060405280519060200120611900565b8282604051602001614ad79291909182526fffffffffffffffffffffffffffffffff16602082015260400190565b6040516020818303038152906040528051906020012095945050505050565b600080614b83847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690508083036001841b600180831b0386831b17039250505092915050565b60008060008360000151600003614be7576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020840151805160001a607f8111614c0c57600060016000945094509450505061503b565b60b78111614d22576000614c21608083615bfe565b905080876000015111614c60576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001838101517fff00000000000000000000000000000000000000000000000000000000000000169082148015614cd857507f80000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008216105b15614d0f576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506001955093506000925061503b915050565b60bf8111614e80576000614d3760b783615bfe565b905080876000015111614d76576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614dd8576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c60378111614e20576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614e2a8184615bae565b895111614e63576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614e6e836001615bae565b975095506000945061503b9350505050565b60f78111614ee5576000614e9560c083615bfe565b905080876000015111614ed4576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60019550935084925061503b915050565b6000614ef260f783615bfe565b905080876000015111614f31576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614f93576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c60378111614fdb576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614fe58184615bae565b89511161501e576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b615029836001615bae565b975095506001945061503b9350505050565b9193909250565b60608167ffffffffffffffff81111561505d5761505d615a84565b6040519080825280601f01601f191660200182016040528015615087576020820181803683370190505b50905081156150d057600061509c8486615bae565b90506020820160005b848110156150bd5782810151828201526020016150a5565b848111156150cc576000858301525b5050505b9392505050565b60006150f66fffffffffffffffffffffffffffffffff84166001615ed5565b9050600061510682866001615327565b9050600086901a83806151f2575061513f60027f0000000000000000000000000000000000000000000000000000000000000004615e98565b60048301546002906151e3906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b6151ed9190615fa6565b60ff16145b1561524a5760ff81166001148061520c575060ff81166002145b615245576040517ff40239db000000000000000000000000000000000000000000000000000000008152600481018890526024016137e4565b612a86565b60ff811615612a86576040517ff40239db000000000000000000000000000000000000000000000000000000008152600481018890526024016137e4565b600080615315837e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b600160ff919091161b90920392915050565b600080826153705761536b6fffffffffffffffffffffffffffffffff86167f000000000000000000000000000000000000000000000000000000000000000461543a565b61538b565b61538b856fffffffffffffffffffffffffffffffff166155c6565b9050600284815481106153a0576153a0615b50565b906000526020600020906005020191505b60048201546fffffffffffffffffffffffffffffffff82811691161461540357815460028054909163ffffffff169081106153ee576153ee615b50565b906000526020600020906005020191506153b1565b509392505050565b600080600080600061541c86614633565b935093509350935061543084848484614a3c565b9695505050505050565b6000816154d9846fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff16116154ef5763b34b5c226000526004601cfd5b6154f8836155c6565b905081615597826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1611612655576126526155ad836001615bae565b6fffffffffffffffffffffffffffffffff83169061566b565b6000811960018301168161565a827e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169390931c8015179392505050565b6000806156f8847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169050808303600180821b0385821b179250505092915050565b60008083601f84011261572657600080fd5b50813567ffffffffffffffff81111561573e57600080fd5b60208301915083602082850101111561575657600080fd5b9250929050565b600080600083850360a081121561577357600080fd5b608081121561578157600080fd5b50839250608084013567ffffffffffffffff81111561579f57600080fd5b6157ab86828701615714565b9497909650939450505050565b600080604083850312156157cb57600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6020810160038310615844577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b60008060006060848603121561585f57600080fd5b505081359360208301359350604090920135919050565b6000815180845260005b8181101561589c57602081850181015186830182015201615880565b818111156158ae576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006126526020830184615876565b60006020828403121561590657600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff8116811461592f57600080fd5b50565b60006020828403121561594457600080fd5b81356150d08161590d565b8035801515811461595f57600080fd5b919050565b6000806000806080858703121561597a57600080fd5b8435935060208501359250604085013591506159986060860161594f565b905092959194509250565b6000602082840312156159b557600080fd5b81356fffffffffffffffffffffffffffffffff811681146150d057600080fd5b600080600080600080608087890312156159ee57600080fd5b863595506159fe6020880161594f565b9450604087013567ffffffffffffffff80821115615a1b57600080fd5b615a278a838b01615714565b90965094506060890135915080821115615a4057600080fd5b50615a4d89828a01615714565b979a9699509497509295939492505050565b63ffffffff841681528260208201526060604082015260006119006060830184615876565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600060808284031215615ac557600080fd5b6040516080810181811067ffffffffffffffff82111715615b0f577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115615bc157615bc1615b7f565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203615bf757615bf7615b7f565b5060010190565b600082821015615c1057615c10615b7f565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082615c5357615c53615c15565b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615c9057615c90615b7f565b500290565b600060208284031215615ca757600080fd5b81516150d08161590d565b600060208284031215615cc457600080fd5b5051919050565b600067ffffffffffffffff808316818516808303821115615cee57615cee615b7f565b01949350505050565b600067ffffffffffffffff80831681851681830481118215151615615d1e57615d1e615b7f565b02949350505050565b600067ffffffffffffffff83811690831681811015615d4857615d48615b7f565b039392505050565b60008060408385031215615d6357600080fd5b505080516020909101519092909150565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600084136000841385830485118282161615615db557615db5615b7f565b7f80000000000000000000000000000000000000000000000000000000000000006000871286820588128184161615615df057615df0615b7f565b60008712925087820587128484161615615e0c57615e0c615b7f565b87850587128184161615615e2257615e22615b7f565b505050929093029392505050565b600082615e3f57615e3f615c15565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f800000000000000000000000000000000000000000000000000000000000000083141615615e9357615e93615b7f565b500590565b600082615ea757615ea7615c15565b500690565b60006fffffffffffffffffffffffffffffffff83811690831681811015615d4857615d48615b7f565b60006fffffffffffffffffffffffffffffffff808316818516808303821115615cee57615cee615b7f565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b606081526000615f5d606083018789615f00565b8281036020840152615f70818688615f00565b9150508260408301529695505050505050565b600060ff821660ff841680821015615f9d57615f9d615b7f565b90039392505050565b600060ff831680615fb957615fb9615c15565b8060ff8416069150509291505056fea164736f6c634300080f000a"; + hex"6080604052600436106103085760003560e01c806370872aa51161019a578063c6f0308c116100e1578063ec5e63081161008a578063fa24f74311610064578063fa24f74314610b94578063fa315aa914610bb8578063fe2bbeb214610beb57600080fd5b8063ec5e630814610b11578063eff0f59214610b44578063f8f43ff614610b7457600080fd5b8063d6ae3cd5116100bb578063d6ae3cd514610a8b578063d8cc1a3c14610abe578063dabd396d14610ade57600080fd5b8063c6f0308c146109b3578063cf09e0d014610a3d578063d5d44d8014610a5e57600080fd5b8063a445ece611610143578063bcef3b551161011d578063bcef3b5514610933578063bd8da95614610973578063c395e1ca1461099357600080fd5b8063a445ece6146107f3578063a8e4fb90146108bf578063bbdc02db146108f257600080fd5b80638980e0cc116101745780638980e0cc1461076b5780638b85902b146107805780638d450a95146107c057600080fd5b806370872aa51461073b5780637b0f0adc146107505780638129fc1c1461076357600080fd5b80633fc8cef31161025e5780635c0cba33116102075780636361506d116101e15780636361506d146106b55780636b6716c0146106f55780636f0344091461072857600080fd5b80635c0cba331461064d578063609d33341461068057806360e274641461069557600080fd5b806354fd4d501161023857806354fd4d50146105a757806357da950e146105fd5780635a5fa2d91461062d57600080fd5b80633fc8cef31461052e578063472777c614610561578063534db0e21461057457600080fd5b80632810e1d6116102c057806337b1b2291161029a57806337b1b2291461047b5780633a768463146104bb5780633e3ac912146104ee57600080fd5b80632810e1d6146103f45780632ad69aeb1461040957806330dbe5701461042957600080fd5b806319effeb4116102f157806319effeb41461034f578063200d2ed21461039a57806325fc2ace146103d557600080fd5b8063019351301461030d57806303c2924d1461032f575b600080fd5b34801561031957600080fd5b5061032d61032836600461575d565b610c1b565b005b34801561033b57600080fd5b5061032d61034a3660046157b8565b610f3c565b34801561035b57600080fd5b5060005461037c9068010000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020015b60405180910390f35b3480156103a657600080fd5b506000546103c890700100000000000000000000000000000000900460ff1681565b6040516103919190615809565b3480156103e157600080fd5b506008545b604051908152602001610391565b34801561040057600080fd5b506103c86115e2565b34801561041557600080fd5b506103e66104243660046157b8565b611887565b34801561043557600080fd5b506001546104569073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610391565b34801561048757600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90033560601c610456565b3480156104c757600080fd5b507f000000000000000000000000180cbe2ebb9f37d3a3c542ddc2546fd160555a73610456565b3480156104fa57600080fd5b5060005461051e907201000000000000000000000000000000000000900460ff1681565b6040519015158152602001610391565b34801561053a57600080fd5b507f000000000000000000000000d6eaf4c146261653ee059077b78ed088add54309610456565b61032d61056f36600461584a565b6118bd565b34801561058057600080fd5b507f0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b63610456565b3480156105b357600080fd5b506105f06040518060400160405280600c81526020017f312e332e312d626574612e32000000000000000000000000000000000000000081525081565b60405161039191906158e1565b34801561060957600080fd5b50600854600954610618919082565b60408051928352602083019190915201610391565b34801561063957600080fd5b506103e66106483660046158f4565b6118cf565b34801561065957600080fd5b507f000000000000000000000000970670459734a83899773a0fd45941b5afc1200e610456565b34801561068c57600080fd5b506105f0611909565b3480156106a157600080fd5b5061032d6106b0366004615932565b611917565b3480156106c157600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003603401356103e6565b34801561070157600080fd5b507f000000000000000000000000000000000000000000000000000000000000000061037c565b61032d610736366004615964565b611abe565b34801561074757600080fd5b506009546103e6565b61032d61075e36600461584a565b611b7f565b61032d611b8c565b34801561077757600080fd5b506002546103e6565b34801561078c57600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401356103e6565b3480156107cc57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006103e6565b3480156107ff57600080fd5b5061086b61080e3660046158f4565b6007602052600090815260409020805460019091015460ff821691610100810463ffffffff1691650100000000009091046fffffffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff1684565b60408051941515855263ffffffff90931660208501526fffffffffffffffffffffffffffffffff9091169183019190915273ffffffffffffffffffffffffffffffffffffffff166060820152608001610391565b3480156108cb57600080fd5b507f00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8610456565b3480156108fe57600080fd5b5060405163ffffffff7f0000000000000000000000000000000000000000000000000000000000000001168152602001610391565b34801561093f57600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003601401356103e6565b34801561097f57600080fd5b5061037c61098e3660046158f4565b611c05565b34801561099f57600080fd5b506103e66109ae3660046159a3565b611de4565b3480156109bf57600080fd5b506109d36109ce3660046158f4565b611fc7565b6040805163ffffffff909816885273ffffffffffffffffffffffffffffffffffffffff968716602089015295909416948601949094526fffffffffffffffffffffffffffffffff9182166060860152608085015291821660a08401521660c082015260e001610391565b348015610a4957600080fd5b5060005461037c9067ffffffffffffffff1681565b348015610a6a57600080fd5b506103e6610a79366004615932565b60036020526000908152604090205481565b348015610a9757600080fd5b507f00000000000000000000000000000000000000000000000000000000000003856103e6565b348015610aca57600080fd5b5061032d610ad93660046159d5565b61205e565b348015610aea57600080fd5b507f00000000000000000000000000000000000000000000000000000000000004b061037c565b348015610b1d57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000046103e6565b348015610b5057600080fd5b5061051e610b5f3660046158f4565b60046020526000908152604090205460ff1681565b348015610b8057600080fd5b5061032d610b8f36600461584a565b612123565b348015610ba057600080fd5b50610ba96125e0565b60405161039193929190615a5f565b348015610bc457600080fd5b507f00000000000000000000000000000000000000000000000000000000000000086103e6565b348015610bf757600080fd5b5061051e610c063660046158f4565b60066020526000908152604090205460ff1681565b60008054700100000000000000000000000000000000900460ff166002811115610c4757610c476157da565b14610c7e576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000547201000000000000000000000000000000000000900460ff1615610cd1576040517f0ea2e75200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d08367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013590565b90565b610d1f610d1a36869003860186615ab3565b61265b565b14610d56576040517f9cc00b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82606001358282604051610d6b929190615b40565b604051809103902014610daa576040517fd81d583b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610df3610dee84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506126b792505050565b612724565b90506000610e1a82600881518110610e0d57610e0d615b50565b60200260200101516128da565b9050602081511115610e58576040517fd81d583b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602081810151825190910360031b1c367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401358103610ecd576040517fb8ed883000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050600180547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790555050600080547fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff1672010000000000000000000000000000000000001790555050565b60008054700100000000000000000000000000000000900460ff166002811115610f6857610f686157da565b14610f9f576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028381548110610fb457610fb4615b50565b906000526020600020906005020190506000610fcf84611c05565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b081169082161015611038576040517ff2440b5300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008481526006602052604090205460ff1615611081576040517ff1a9458100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600084815260056020526040902080548015801561109e57508515155b15611139578354640100000000900473ffffffffffffffffffffffffffffffffffffffff16600081156110d157816110ed565b600186015473ffffffffffffffffffffffffffffffffffffffff165b90506110f9818761298e565b50505060009485525050600660205250506040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b6000868152600760209081526040918290208251608081018452815460ff81161515808352610100820463ffffffff16948301949094526501000000000090046fffffffffffffffffffffffffffffffff16938101939093526001015473ffffffffffffffffffffffffffffffffffffffff1660608301526111dc576fffffffffffffffffffffffffffffffff60408201526001815260008690036111dc578195505b600086826020015163ffffffff166111f49190615bae565b905060008382116112055781611207565b835b602084015190915063ffffffff165b8181101561135357600086828154811061123257611232615b50565b6000918252602080832090910154808352600690915260409091205490915060ff1661128a576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006002828154811061129f5761129f615b50565b600091825260209091206005909102018054909150640100000000900473ffffffffffffffffffffffffffffffffffffffff161580156112fc5750600481015460408701516fffffffffffffffffffffffffffffffff9182169116115b1561133e57600181015473ffffffffffffffffffffffffffffffffffffffff16606087015260048101546fffffffffffffffffffffffffffffffff1660408701525b5050808061134b90615bc6565b915050611216565b5063ffffffff818116602085810191825260008c81526007909152604090819020865181549351928801517fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009094169015157fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ff161761010092909416918202939093177fffffffffffffffffffffff00000000000000000000000000000000ffffffffff16650100000000006fffffffffffffffffffffffffffffffff909316929092029190911782556060850151600190920180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909316929092179091558490036115d757606083015160008a815260066020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055891580156114d357506000547201000000000000000000000000000000000000900460ff165b156115485760015473ffffffffffffffffffffffffffffffffffffffff166114fb818a61298e565b885473ffffffffffffffffffffffffffffffffffffffff909116640100000000027fffffffffffffffff0000000000000000000000000000000000000000ffffffff9091161788556115d5565b61158f73ffffffffffffffffffffffffffffffffffffffff82161561156d5781611589565b600189015473ffffffffffffffffffffffffffffffffffffffff165b8961298e565b87547fffffffffffffffff0000000000000000000000000000000000000000ffffffff1664010000000073ffffffffffffffffffffffffffffffffffffffff8316021788555b505b505050505050505050565b600080600054700100000000000000000000000000000000900460ff166002811115611610576116106157da565b14611647576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000805260066020527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f85460ff166116ab576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660026000815481106116d7576116d7615b50565b6000918252602090912060059091020154640100000000900473ffffffffffffffffffffffffffffffffffffffff1614611712576001611715565b60025b6000805467ffffffffffffffff421668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff82168117835592935083927fffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffff000000000000000000ffffffffffffffff909116177001000000000000000000000000000000008360028111156117c6576117c66157da565b0217905560028111156117db576117db6157da565b6040517f5e186f09b9c93491f14e277eea7faa5de6a2d4bda75a79af7a3684fbfb42da6090600090a27f000000000000000000000000970670459734a83899773a0fd45941b5afc1200e73ffffffffffffffffffffffffffffffffffffffff1663838c2d1e6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561186c57600080fd5b505af1158015611880573d6000803e3d6000fd5b5050505090565b600560205281600052604060002081815481106118a357600080fd5b90600052602060002001600091509150505481565b905090565b6118ca8383836001611abe565b505050565b6000818152600760209081526040808320600590925282208054825461190090610100900463ffffffff1682615bfe565b95945050505050565b60606118b860546020612a8f565b73ffffffffffffffffffffffffffffffffffffffff811660009081526003602052604081208054908290559081900361197c576040517f17bfe5f700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517ff3fef3a300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152602482018390527f000000000000000000000000d6eaf4c146261653ee059077b78ed088add54309169063f3fef3a390604401600060405180830381600087803b158015611a0c57600080fd5b505af1158015611a20573d6000803e3d6000fd5b5050505060008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114611a7e576040519150601f19603f3d011682016040523d82523d6000602084013e611a83565b606091505b50509050806118ca576040517f83e6cc6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8161480611b3757503373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b6316145b611b6d576040517fd386ef3e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611b7984848484612ae1565b50505050565b6118ca8383836000611abe565b3273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c81614611bfb576040517fd386ef3e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611c036135ba565b565b600080600054700100000000000000000000000000000000900460ff166002811115611c3357611c336157da565b14611c6a576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028381548110611c7f57611c7f615b50565b600091825260208220600590910201805490925063ffffffff90811614611cee57815460028054909163ffffffff16908110611cbd57611cbd615b50565b906000526020600020906005020160040160109054906101000a90046fffffffffffffffffffffffffffffffff1690505b6004820154600090611d2690700100000000000000000000000000000000900467ffffffffffffffff165b67ffffffffffffffff1690565b611d3a9067ffffffffffffffff1642615bfe565b611d59611d19846fffffffffffffffffffffffffffffffff1660401c90565b67ffffffffffffffff16611d6d9190615bae565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b01667ffffffffffffffff168167ffffffffffffffff1611611dba5780611900565b7f00000000000000000000000000000000000000000000000000000000000004b095945050505050565b600080611e83836fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690507f0000000000000000000000000000000000000000000000000000000000000008811115611ee2576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b642e90edd00062061a806311e1a3006000611efd8383615c44565b9050670de0b6b3a76400006000611f34827f0000000000000000000000000000000000000000000000000000000000000008615c58565b90506000611f52611f4d670de0b6b3a764000086615c58565b613b13565b90506000611f608484613d6e565b90506000611f6e8383613dbd565b90506000611f7b82613deb565b90506000611f9a82611f95670de0b6b3a76400008f615c58565b613fd3565b90506000611fa88b83613dbd565b9050611fb4818d615c58565b9f9e505050505050505050505050505050565b60028181548110611fd757600080fd5b60009182526020909120600590910201805460018201546002830154600384015460049094015463ffffffff8416955064010000000090930473ffffffffffffffffffffffffffffffffffffffff908116949216926fffffffffffffffffffffffffffffffff91821692918082169170010000000000000000000000000000000090041687565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c81614806120d757503373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b6316145b61210d576040517fd386ef3e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61211b868686868686614004565b505050505050565b60008054700100000000000000000000000000000000900460ff16600281111561214f5761214f6157da565b14612186576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060008061219586614633565b935093509350935060006121ab85858585614a3c565b905060007f000000000000000000000000180cbe2ebb9f37d3a3c542ddc2546fd160555a7373ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561221a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061223e9190615c95565b9050600189036123365773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a8461229a367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036034013590565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815260048101939093526024830191909152604482015260206064820152608481018a905260a4015b6020604051808303816000875af115801561230c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123309190615cb2565b506115d7565b600289036123625773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a848961229a565b6003890361238e5773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a848761229a565b600489036125155760006123d46fffffffffffffffffffffffffffffffff85167f0000000000000000000000000000000000000000000000000000000000000004614af6565b6009546123e19190615bae565b6123ec906001615bae565b9050367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360540135811061245557367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360540135612457565b805b905073ffffffffffffffffffffffffffffffffffffffff82166352f0f3ad8b8560405160e084901b7fffffffff000000000000000000000000000000000000000000000000000000001681526004810192909252602482015260c084901b604482015260086064820152608481018b905260a4016020604051808303816000875af11580156124ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061250e9190615cb2565b50506115d7565b600589036125ae576040517f52f0f3ad000000000000000000000000000000000000000000000000000000008152600481018a9052602481018390527f000000000000000000000000000000000000000000000000000000000000038560c01b6044820152600860648201526084810188905273ffffffffffffffffffffffffffffffffffffffff8216906352f0f3ad9060a4016122ed565b6040517fff137e6500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000001367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003601401356060612639611909565b9050909192565b6000818310156126505781612652565b825b90505b92915050565b6000816000015182602001518360400151846060015160405160200161269a949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b60408051808201909152600080825260208201528151600003612706576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50604080518082019091528151815260209182019181019190915290565b6060600080600061273485614ba4565b91945092509050600181600181111561274f5761274f6157da565b14612786576040517f4b9c6abe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84516127928385615bae565b146127c9576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808252610420820190925290816020015b60408051808201909152600080825260208201528152602001906001900390816127e05790505093506000835b86518110156128ce576000806128536040518060400160405280858c600001516128379190615bfe565b8152602001858c6020015161284c9190615bae565b9052614ba4565b50915091506040518060400160405280838361286f9190615bae565b8152602001848b602001516128849190615bae565b81525088858151811061289957612899615b50565b60209081029190910101526128af600185615bae565b93506128bb8183615bae565b6128c59084615bae565b9250505061280d565b50845250919392505050565b606060008060006128ea85614ba4565b919450925090506000816001811115612905576129056157da565b1461293c576040517f1ff9b2e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6129468284615bae565b85511461297f576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61190085602001518484615042565b600281015473ffffffffffffffffffffffffffffffffffffffff8316600090815260036020526040812080546fffffffffffffffffffffffffffffffff909316928392906129dd908490615bae565b90915550506040517f7eee288d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018390527f000000000000000000000000d6eaf4c146261653ee059077b78ed088add543091690637eee288d90604401600060405180830381600087803b158015612a7257600080fd5b505af1158015612a86573d6000803e3d6000fd5b50505050505050565b604051818152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90038284820160208401378260208301016000815260208101604052505092915050565b60008054700100000000000000000000000000000000900460ff166002811115612b0d57612b0d6157da565b14612b44576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028481548110612b5957612b59615b50565b60009182526020918290206040805160e0810182526005909302909101805463ffffffff8116845273ffffffffffffffffffffffffffffffffffffffff64010000000090910481169484019490945260018101549093169082015260028201546fffffffffffffffffffffffffffffffff908116606083015260038301546080830181905260049093015480821660a084015270010000000000000000000000000000000090041660c082015291508514612c40576040517f3014033200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60a0810151600083156fffffffffffffffffffffffffffffffff83161760011b90506000612d00826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169050861580612d3b5750612d387f00000000000000000000000000000000000000000000000000000000000000046002615bae565b81145b8015612d45575084155b15612d7c576040517fa42637bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000547201000000000000000000000000000000000000900460ff168015612da2575086155b15612dd9576040517f0ea2e75200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000008811115612e33576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612e5e7f00000000000000000000000000000000000000000000000000000000000000046001615bae565b8103612e7057612e70868885886150d7565b34612e7a83611de4565b14612eb1576040517f8620aa1900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612ebc88611c05565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b0811690821603612f24576040517f3381d11400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612f5160017f0000000000000000000000000000000000000000000000000000000000000008615bfe565b830361308f577f000000000000000000000000180cbe2ebb9f37d3a3c542ddc2546fd160555a7373ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015612fc2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fe69190615c95565b73ffffffffffffffffffffffffffffffffffffffff1663f3f480d96040518163ffffffff1660e01b8152600401602060405180830381865afa158015613030573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130549190615cb2565b613088907f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff16615ccb565b9050613122565b6130ba60017f0000000000000000000000000000000000000000000000000000000000000004615bfe565b83036130f5576130887f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff166002615cf7565b507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff165b613156817f00000000000000000000000000000000000000000000000000000000000004b067ffffffffffffffff16615d27565b67ffffffffffffffff166131718367ffffffffffffffff1690565b67ffffffffffffffff1611156131b8576131b5817f00000000000000000000000000000000000000000000000000000000000004b067ffffffffffffffff16615d27565b91505b6000604083901b421760008a8152608087901b6fffffffffffffffffffffffffffffffff8d1617602052604081209192509060008181526004602052604090205490915060ff1615613236576040517f80497e3b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60016004600083815260200190815260200160002060006101000a81548160ff02191690831515021790555060026040518060e001604052808d63ffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020013373ffffffffffffffffffffffffffffffffffffffff168152602001346fffffffffffffffffffffffffffffffff1681526020018c8152602001886fffffffffffffffffffffffffffffffff168152602001846fffffffffffffffffffffffffffffffff16815250908060018154018082558091505060019003906000526020600020906005020160009091909190915060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060608201518160020160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055506080820151816003015560a08201518160040160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555060c08201518160040160106101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055505050600560008c815260200190815260200160002060016002805490506134cc9190615bfe565b81546001810183556000928352602083200155604080517fd0e30db0000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000d6eaf4c146261653ee059077b78ed088add54309169263d0e30db09234926004808301939282900301818588803b15801561356457600080fd5b505af1158015613578573d6000803e3d6000fd5b50506040513393508d92508e91507f9b3245740ec3b155098a55be84957a4da13eaf7f14a8bc6f53126c0b9350f2be90600090a4505050505050505050505050565b60005471010000000000000000000000000000000000900460ff161561360c576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f7258a80700000000000000000000000000000000000000000000000000000000815263ffffffff7f0000000000000000000000000000000000000000000000000000000000000001166004820152600090819073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000970670459734a83899773a0fd45941b5afc1200e1690637258a807906024016040805180830381865afa1580156136c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136e49190615d50565b909250905081613720576040517f6a6bc3b200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518082019091528281526020018190526008829055600981905536607a1461375357639824bdab6000526004601cfd5b80367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360540135116137ed576040517ff40239db000000000000000000000000000000000000000000000000000000008152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013560048201526024015b60405180910390fd5b6040805160e08101825263ffffffff8082526000602083018181527ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe369081013560f01c90038035606090811c868801908152346fffffffffffffffffffffffffffffffff81811693890193845260149094013560808901908152600160a08a0181815242871660c08c019081526002805493840181558a529a5160059092027f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace81018054995173ffffffffffffffffffffffffffffffffffffffff908116640100000000027fffffffffffffffff000000000000000000000000000000000000000000000000909b1694909c16939093179890981790915592517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5acf87018054918a167fffffffffffffffffffffffff000000000000000000000000000000000000000090921691909117905592517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad0860180549186167fffffffffffffffffffffffffffffffff0000000000000000000000000000000090921691909117905591517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad185015551955182167001000000000000000000000000000000000295909116949094177f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad29091015580547fffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffff167101000000000000000000000000000000000017815583517fd0e30db000000000000000000000000000000000000000000000000000000000815293517f000000000000000000000000d6eaf4c146261653ee059077b78ed088add543099092169363d0e30db093926004828101939282900301818588803b158015613ac257600080fd5b505af1158015613ad6573d6000803e3d6000fd5b5050600080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000164267ffffffffffffffff161790555050505050565b6fffffffffffffffffffffffffffffffff811160071b81811c67ffffffffffffffff1060061b1781811c63ffffffff1060051b1781811c61ffff1060041b1781811c60ff1060031b1760008213613b7257631615e6386000526004601cfd5b7ff8f9f9faf9fdfafbf9fdfcfdfafbfcfef9fafdfafcfcfbfefafafcfbffffffff6f8421084210842108cc6318c6db6d54be83831c1c601f161a1890811b609f90811c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506029190037d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b302017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d90565b60007812725dd1d243aba0e75fe645cc4873f9e65afe688c928e1f218311670de0b6b3a764000002158202613dab57637c5f487d6000526004601cfd5b50670de0b6b3a7640000919091020490565b600081600019048311820215613ddb5763bac65e5b6000526004601cfd5b50670de0b6b3a764000091020490565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdc0d0570925a462d78213613e1957919050565b680755bf798b4a1bf1e58212613e375763a37bfec96000526004601cfd5b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b6000612652670de0b6b3a764000083613feb86613b13565b613ff59190615d74565b613fff9190615e30565b613deb565b60008054700100000000000000000000000000000000900460ff166002811115614030576140306157da565b14614067576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006002878154811061407c5761407c615b50565b6000918252602082206005919091020160048101549092506fffffffffffffffffffffffffffffffff16908715821760011b90506140db7f00000000000000000000000000000000000000000000000000000000000000086001615bae565b614177826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff16146141b1576040517f5f53dd9800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008089156142a8576142047f00000000000000000000000000000000000000000000000000000000000000047f0000000000000000000000000000000000000000000000000000000000000008615bfe565b6001901b614223846fffffffffffffffffffffffffffffffff16615288565b6fffffffffffffffffffffffffffffffff1661423f9190615e98565b1561427c5761427361426460016fffffffffffffffffffffffffffffffff8716615eac565b865463ffffffff166000615327565b6003015461429e565b7f00000000000000000000000000000000000000000000000000000000000000005b91508490506142d2565b600385015491506142cf6142646fffffffffffffffffffffffffffffffff86166001615ed5565b90505b600882901b60088a8a6040516142e9929190615b40565b6040518091039020901b1461432a576040517f696550ff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006143358c61540b565b90506000614344836003015490565b6040517fe14ced320000000000000000000000000000000000000000000000000000000081527f000000000000000000000000180cbe2ebb9f37d3a3c542ddc2546fd160555a7373ffffffffffffffffffffffffffffffffffffffff169063e14ced32906143be908f908f908f908f908a90600401615f49565b6020604051808303816000875af11580156143dd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144019190615cb2565b6004850154911491506000906002906144ac906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b614548896fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b6145529190615f83565b61455c9190615fa6565b60ff16159050811515810361459d576040517ffb4e40dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8754640100000000900473ffffffffffffffffffffffffffffffffffffffff16156145f4576040517f9071e6af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505085547fffffffffffffffff0000000000000000000000000000000000000000ffffffff163364010000000002179095555050505050505050505050565b600080600080600085905060006002828154811061465357614653615b50565b600091825260209091206004600590920201908101549091507f00000000000000000000000000000000000000000000000000000000000000049061472a906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1611614764576040517fb34b5c2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000815b60048301547f00000000000000000000000000000000000000000000000000000000000000049061482b906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1692508211156148a057825463ffffffff1661486a7f00000000000000000000000000000000000000000000000000000000000000046001615bae565b8303614874578391505b6002818154811061488757614887615b50565b9060005260206000209060050201935080945050614768565b600481810154908401546fffffffffffffffffffffffffffffffff91821691166000816fffffffffffffffffffffffffffffffff166149096148f4856fffffffffffffffffffffffffffffffff1660011c90565b6fffffffffffffffffffffffffffffffff1690565b6fffffffffffffffffffffffffffffffff1614905080156149d8576000614941836fffffffffffffffffffffffffffffffff16615288565b6fffffffffffffffffffffffffffffffff1611156149ac57600061498361497b60016fffffffffffffffffffffffffffffffff8616615eac565b896001615327565b6003810154600490910154909c506fffffffffffffffffffffffffffffffff169a506149b29050565b6008549a505b600386015460048701549099506fffffffffffffffffffffffffffffffff169750614a2e565b60006149fa61497b6fffffffffffffffffffffffffffffffff85166001615ed5565b6003808901546004808b015492840154930154909e506fffffffffffffffffffffffffffffffff9182169d50919b50169850505b505050505050509193509193565b60006fffffffffffffffffffffffffffffffff841615614aa95760408051602081018790526fffffffffffffffffffffffffffffffff8087169282019290925260608101859052908316608082015260a00160405160208183030381529060405280519060200120611900565b8282604051602001614ad79291909182526fffffffffffffffffffffffffffffffff16602082015260400190565b6040516020818303038152906040528051906020012095945050505050565b600080614b83847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690508083036001841b600180831b0386831b17039250505092915050565b60008060008360000151600003614be7576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020840151805160001a607f8111614c0c57600060016000945094509450505061503b565b60b78111614d22576000614c21608083615bfe565b905080876000015111614c60576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001838101517fff00000000000000000000000000000000000000000000000000000000000000169082148015614cd857507f80000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008216105b15614d0f576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506001955093506000925061503b915050565b60bf8111614e80576000614d3760b783615bfe565b905080876000015111614d76576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614dd8576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c60378111614e20576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614e2a8184615bae565b895111614e63576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614e6e836001615bae565b975095506000945061503b9350505050565b60f78111614ee5576000614e9560c083615bfe565b905080876000015111614ed4576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60019550935084925061503b915050565b6000614ef260f783615bfe565b905080876000015111614f31576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614f93576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c60378111614fdb576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614fe58184615bae565b89511161501e576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b615029836001615bae565b975095506001945061503b9350505050565b9193909250565b60608167ffffffffffffffff81111561505d5761505d615a84565b6040519080825280601f01601f191660200182016040528015615087576020820181803683370190505b50905081156150d057600061509c8486615bae565b90506020820160005b848110156150bd5782810151828201526020016150a5565b848111156150cc576000858301525b5050505b9392505050565b60006150f66fffffffffffffffffffffffffffffffff84166001615ed5565b9050600061510682866001615327565b9050600086901a83806151f2575061513f60027f0000000000000000000000000000000000000000000000000000000000000004615e98565b60048301546002906151e3906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b6151ed9190615fa6565b60ff16145b1561524a5760ff81166001148061520c575060ff81166002145b615245576040517ff40239db000000000000000000000000000000000000000000000000000000008152600481018890526024016137e4565b612a86565b60ff811615612a86576040517ff40239db000000000000000000000000000000000000000000000000000000008152600481018890526024016137e4565b600080615315837e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b600160ff919091161b90920392915050565b600080826153705761536b6fffffffffffffffffffffffffffffffff86167f000000000000000000000000000000000000000000000000000000000000000461543a565b61538b565b61538b856fffffffffffffffffffffffffffffffff166155c6565b9050600284815481106153a0576153a0615b50565b906000526020600020906005020191505b60048201546fffffffffffffffffffffffffffffffff82811691161461540357815460028054909163ffffffff169081106153ee576153ee615b50565b906000526020600020906005020191506153b1565b509392505050565b600080600080600061541c86614633565b935093509350935061543084848484614a3c565b9695505050505050565b6000816154d9846fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff16116154ef5763b34b5c226000526004601cfd5b6154f8836155c6565b905081615597826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1611612655576126526155ad836001615bae565b6fffffffffffffffffffffffffffffffff83169061566b565b6000811960018301168161565a827e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169390931c8015179392505050565b6000806156f8847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169050808303600180821b0385821b179250505092915050565b60008083601f84011261572657600080fd5b50813567ffffffffffffffff81111561573e57600080fd5b60208301915083602082850101111561575657600080fd5b9250929050565b600080600083850360a081121561577357600080fd5b608081121561578157600080fd5b50839250608084013567ffffffffffffffff81111561579f57600080fd5b6157ab86828701615714565b9497909650939450505050565b600080604083850312156157cb57600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6020810160038310615844577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b60008060006060848603121561585f57600080fd5b505081359360208301359350604090920135919050565b6000815180845260005b8181101561589c57602081850181015186830182015201615880565b818111156158ae576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006126526020830184615876565b60006020828403121561590657600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff8116811461592f57600080fd5b50565b60006020828403121561594457600080fd5b81356150d08161590d565b8035801515811461595f57600080fd5b919050565b6000806000806080858703121561597a57600080fd5b8435935060208501359250604085013591506159986060860161594f565b905092959194509250565b6000602082840312156159b557600080fd5b81356fffffffffffffffffffffffffffffffff811681146150d057600080fd5b600080600080600080608087890312156159ee57600080fd5b863595506159fe6020880161594f565b9450604087013567ffffffffffffffff80821115615a1b57600080fd5b615a278a838b01615714565b90965094506060890135915080821115615a4057600080fd5b50615a4d89828a01615714565b979a9699509497509295939492505050565b63ffffffff841681528260208201526060604082015260006119006060830184615876565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600060808284031215615ac557600080fd5b6040516080810181811067ffffffffffffffff82111715615b0f577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115615bc157615bc1615b7f565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203615bf757615bf7615b7f565b5060010190565b600082821015615c1057615c10615b7f565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082615c5357615c53615c15565b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615c9057615c90615b7f565b500290565b600060208284031215615ca757600080fd5b81516150d08161590d565b600060208284031215615cc457600080fd5b5051919050565b600067ffffffffffffffff808316818516808303821115615cee57615cee615b7f565b01949350505050565b600067ffffffffffffffff80831681851681830481118215151615615d1e57615d1e615b7f565b02949350505050565b600067ffffffffffffffff83811690831681811015615d4857615d48615b7f565b039392505050565b60008060408385031215615d6357600080fd5b505080516020909101519092909150565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600084136000841385830485118282161615615db557615db5615b7f565b7f80000000000000000000000000000000000000000000000000000000000000006000871286820588128184161615615df057615df0615b7f565b60008712925087820587128484161615615e0c57615e0c615b7f565b87850587128184161615615e2257615e22615b7f565b505050929093029392505050565b600082615e3f57615e3f615c15565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f800000000000000000000000000000000000000000000000000000000000000083141615615e9357615e93615b7f565b500590565b600082615ea757615ea7615c15565b500690565b60006fffffffffffffffffffffffffffffffff83811690831681811015615d4857615d48615b7f565b60006fffffffffffffffffffffffffffffffff808316818516808303821115615cee57615cee615b7f565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b606081526000615f5d606083018789615f00565b8281036020840152615f70818688615f00565b9150508260408301529695505050505050565b600060ff821660ff841680821015615f9d57615f9d615b7f565b90039392505050565b600060ff831680615fb957615fb9615c15565b8060ff8416069150509291505056fea164736f6c634300080f000a"; } diff --git a/packages/contracts-bedrock/test/legacy/L1BlockNumber.t.sol b/packages/contracts-bedrock/test/legacy/L1BlockNumber.t.sol index 3fad976992321..633a324e40435 100644 --- a/packages/contracts-bedrock/test/legacy/L1BlockNumber.t.sol +++ b/packages/contracts-bedrock/test/legacy/L1BlockNumber.t.sol @@ -1,15 +1,15 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -// Testing utilities +// Testing import { Test } from "forge-std/Test.sol"; -// Target contract dependencies +// Contracts +import { L1BlockNumber } from "src/legacy/L1BlockNumber.sol"; import { L1Block } from "src/L2/L1Block.sol"; -import { Predeploys } from "src/libraries/Predeploys.sol"; -// Target contract -import { L1BlockNumber } from "src/legacy/L1BlockNumber.sol"; +// Libraries +import { Predeploys } from "src/libraries/Predeploys.sol"; contract L1BlockNumberTest is Test { L1Block lb; diff --git a/packages/contracts-bedrock/test/libraries/Blueprint.t.sol b/packages/contracts-bedrock/test/libraries/Blueprint.t.sol new file mode 100644 index 0000000000000..c94616a88e4fe --- /dev/null +++ b/packages/contracts-bedrock/test/libraries/Blueprint.t.sol @@ -0,0 +1,244 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +import { Test } from "forge-std/Test.sol"; +import { Blueprint } from "src/libraries/Blueprint.sol"; + +// Used to test that constructor args are appended properly when deploying from a blueprint. +contract ConstructorArgMock { + uint256 public x; + bytes public y; + + constructor(uint256 _x, bytes memory _y) { + x = _x; + y = _y; + } +} + +// Foundry cheatcodes operate on the next call, and since all library methods are internal we would +// just JUMP to them if called directly in the test. Therefore we wrap the library in a contract. +contract BlueprintHarness { + function blueprintDeployerBytecode(bytes memory _initcode) public pure returns (bytes memory) { + return Blueprint.blueprintDeployerBytecode(_initcode); + } + + function parseBlueprintPreamble(bytes memory _bytecode) public view returns (Blueprint.Preamble memory) { + return Blueprint.parseBlueprintPreamble(_bytecode); + } + + function deployFrom(address _blueprint, bytes32 _salt) public returns (address) { + return Blueprint.deployFrom(_blueprint, _salt); + } + + function deployFrom(address _blueprint, bytes32 _salt, bytes memory _args) public returns (address) { + return Blueprint.deployFrom(_blueprint, _salt, _args); + } + + function bytesToUint(bytes memory _bytes) public pure returns (uint256) { + return Blueprint.bytesToUint(_bytes); + } +} + +contract Blueprint_Test is Test { + BlueprintHarness blueprint; + + function setUp() public { + blueprint = new BlueprintHarness(); + } + + function deployWithCreate2(bytes memory _initcode, bytes32 _salt) public returns (address addr_) { + assembly ("memory-safe") { + addr_ := create2(0, add(_initcode, 0x20), mload(_initcode), _salt) + } + require(addr_ != address(0), "deployWithCreate2: deployment failed"); + } + + // --- We start with the test cases from ERC-5202 --- + + // An example (and trivial!) blueprint contract with no data section, whose initcode is just the STOP instruction. + function test_ERC5202_trivialBlueprint_succeeds() public view { + bytes memory bytecode = hex"FE710000"; + Blueprint.Preamble memory preamble = blueprint.parseBlueprintPreamble(bytecode); + + assertEq(preamble.ercVersion, 0, "100"); + assertEq(preamble.preambleData, hex"", "200"); + assertEq(preamble.initcode, hex"00", "300"); + } + + // An example blueprint contract whose initcode is the trivial STOP instruction and whose data + // section contains the byte 0xFF repeated seven times. + function test_ERC5202_blueprintWithDataSection_succeeds() public view { + // Here, 0xFE71 is the magic header, 0x01 means version 0 + 1 length bit, 0x07 encodes the + // length in bytes of the data section. These are followed by the data section, and then the + // initcode. For illustration, this code with delimiters would be: + // 0xFE71|01|07|FFFFFFFFFFFFFF|00 + bytes memory bytecode = hex"FE710107FFFFFFFFFFFFFF00"; + Blueprint.Preamble memory preamble = blueprint.parseBlueprintPreamble(bytecode); + + assertEq(preamble.ercVersion, 0, "100"); + assertEq(preamble.preambleData, hex"FFFFFFFFFFFFFF", "200"); + assertEq(preamble.initcode, hex"00", "300"); + } + + // An example blueprint whose initcode is the trivial STOP instruction and whose data section + // contains the byte 0xFF repeated 256 times. + function test_ERC5202_blueprintWithLargeDataSection_succeeds() public view { + // Delimited, this would be 0xFE71|02|0100|FF...FF|00 + bytes memory bytecode = + hex"FE71020100FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00"; + Blueprint.Preamble memory preamble = blueprint.parseBlueprintPreamble(bytecode); + + assertEq(preamble.ercVersion, 0, "100"); + assertEq(preamble.preambleData.length, 256, "200"); + for (uint256 i = 0; i < 256; i++) { + assertEq(preamble.preambleData[i], bytes1(0xFF), string.concat("300-", vm.toString(i))); + } + assertEq(preamble.initcode, hex"00", "400"); + } + + // --- Now we add a generic roundtrip test --- + + // Test that a roundtrip from initcode to blueprint to initcode succeeds, i.e. the invariant + // here is that `parseBlueprintPreamble(blueprintDeployerBytecode(x)) = x`. + function testFuzz_roundtrip_succeeds(bytes memory _initcode) public { + vm.assume(_initcode.length > 0); + + // Convert the initcode to match the ERC-5202 blueprint format. + bytes memory blueprintInitcode = blueprint.blueprintDeployerBytecode(_initcode); + + // Deploy the blueprint. + address blueprintAddress = deployWithCreate2(blueprintInitcode, bytes32(0)); + + // Read the blueprint code from the deployed code. + bytes memory blueprintCode = address(blueprintAddress).code; + + // Parse the blueprint preamble and ensure it matches the expected values. + Blueprint.Preamble memory preamble = blueprint.parseBlueprintPreamble(blueprintCode); + assertEq(preamble.ercVersion, 0, "100"); + assertEq(preamble.preambleData, hex"", "200"); + assertEq(preamble.initcode, _initcode, "300"); + } + + // --- Lastly, function-specific unit tests --- + + function test_blueprintDeployerBytecode_emptyInitcode_reverts() public { + bytes memory initcode = ""; + vm.expectRevert(Blueprint.EmptyInitcode.selector); + blueprint.blueprintDeployerBytecode(initcode); + } + + function test_parseBlueprintPreamble_notABlueprint_reverts() public { + // Length too short. + bytes memory invalidBytecode = hex"01"; + vm.expectRevert(Blueprint.NotABlueprint.selector); + blueprint.parseBlueprintPreamble(invalidBytecode); + + // First byte is not 0xFE. + invalidBytecode = hex"0071"; + vm.expectRevert(Blueprint.NotABlueprint.selector); + blueprint.parseBlueprintPreamble(invalidBytecode); + + // Second byte is not 0x71. + invalidBytecode = hex"FE00"; + vm.expectRevert(Blueprint.NotABlueprint.selector); + blueprint.parseBlueprintPreamble(invalidBytecode); + } + + function test_parseBlueprintPreamble_reservedBitsSet_reverts() public { + bytes memory invalidBytecode = hex"FE7103"; + vm.expectRevert(Blueprint.ReservedBitsSet.selector); + blueprint.parseBlueprintPreamble(invalidBytecode); + } + + function test_parseBlueprintPreamble_emptyInitcode_reverts() public { + bytes memory invalidBytecode = hex"FE7100"; + vm.expectRevert(Blueprint.EmptyInitcode.selector); + blueprint.parseBlueprintPreamble(invalidBytecode); + } + + function testFuzz_deployFrom_succeeds(bytes memory _initcode, bytes32 _salt) public { + vm.assume(_initcode.length > 0); + vm.assume(_initcode[0] != 0xef); // https://eips.ethereum.org/EIPS/eip-3541 + + // This deployBytecode prefix is the same bytecode used in `blueprintDeployerBytecode`, and + // it ensures that whatever initcode the fuzzer generates is actually deployable. + bytes memory deployBytecode = bytes.concat(hex"61", bytes2(uint16(_initcode.length)), hex"3d81600a3d39f3"); + bytes memory initcode = bytes.concat(deployBytecode, _initcode); + bytes memory blueprintInitcode = blueprint.blueprintDeployerBytecode(initcode); + + // Deploy the blueprint. + address blueprintAddress = deployWithCreate2(blueprintInitcode, _salt); + + // Deploy from the blueprint. + address deployedContract = Blueprint.deployFrom(blueprintAddress, _salt); + + // Verify the deployment worked. + assertTrue(deployedContract != address(0), "100"); + assertTrue(deployedContract.code.length > 0, "200"); + assertEq(keccak256(deployedContract.code), keccak256(_initcode), "300"); + } + + // Here we deploy a simple mock contract to test that constructor args are appended properly. + function testFuzz_deployFrom_withConstructorArgs_succeeds(uint256 _x, bytes memory _y, bytes32 _salt) public { + bytes memory blueprintInitcode = blueprint.blueprintDeployerBytecode(type(ConstructorArgMock).creationCode); + + // Deploy the blueprint. + address blueprintAddress = deployWithCreate2(blueprintInitcode, _salt); + + // Deploy from the blueprint. + bytes memory args = abi.encode(_x, _y); + address deployedContract = blueprint.deployFrom(blueprintAddress, _salt, args); + + // Verify the deployment worked. + assertTrue(deployedContract != address(0), "100"); + assertTrue(deployedContract.code.length > 0, "200"); + assertEq(keccak256(deployedContract.code), keccak256(type(ConstructorArgMock).runtimeCode), "300"); + assertEq(ConstructorArgMock(deployedContract).x(), _x, "400"); + assertEq(ConstructorArgMock(deployedContract).y(), _y, "500"); + } + + function test_deployFrom_unsupportedERCVersion_reverts() public { + bytes32 salt = bytes32(0); + address blueprintAddress = makeAddr("blueprint"); + + bytes memory invalidBlueprintCode = hex"FE710400"; // ercVersion = uint8(0x04 & 0xfc) >> 2 = 1 + vm.etch(blueprintAddress, invalidBlueprintCode); + vm.expectRevert(abi.encodeWithSelector(Blueprint.UnsupportedERCVersion.selector, 1)); + blueprint.deployFrom(blueprintAddress, salt); + + invalidBlueprintCode = hex"FE71B000"; // ercVersion = uint8(0xB0 & 0xfc) >> 2 = 44 + vm.etch(blueprintAddress, invalidBlueprintCode); + vm.expectRevert(abi.encodeWithSelector(Blueprint.UnsupportedERCVersion.selector, 44)); + blueprint.deployFrom(blueprintAddress, salt); + } + + function test_deployFrom_unexpectedPreambleData_reverts() public { + bytes32 salt = bytes32(0); + address blueprintAddress = makeAddr("blueprint"); + + // Create invalid blueprint code with non-empty preamble data + bytes memory invalidBlueprintCode = hex"FE7101030102030001020304"; + vm.etch(blueprintAddress, invalidBlueprintCode); + + // Expect revert with UnexpectedPreambleData error + vm.expectRevert(abi.encodeWithSelector(Blueprint.UnexpectedPreambleData.selector, hex"010203")); + blueprint.deployFrom(blueprintAddress, salt); + } + + function test_bytesToUint_succeeds() public view { + // These test cases (and the logic for bytesToUint) are taken from forge-std. + assertEq(3, blueprint.bytesToUint(hex"03")); + assertEq(2, blueprint.bytesToUint(hex"02")); + assertEq(255, blueprint.bytesToUint(hex"ff")); + assertEq(29625, blueprint.bytesToUint(hex"73b9")); + + // Additional test cases. + assertEq(0, blueprint.bytesToUint(hex"")); + assertEq(0, blueprint.bytesToUint(hex"00")); + assertEq(3, blueprint.bytesToUint(hex"0003")); + assertEq(3145731, blueprint.bytesToUint(hex"300003")); + assertEq(14545064521499334880, blueprint.bytesToUint(hex"c9da731e871ad8e0")); + assertEq(14545064521499334880, blueprint.bytesToUint(hex"00c9da731e871ad8e0")); + assertEq(type(uint256).max, blueprint.bytesToUint(bytes.concat(bytes32(type(uint256).max)))); + } +} diff --git a/packages/contracts-bedrock/test/periphery/op-nft/Optimist.t.sol b/packages/contracts-bedrock/test/periphery/op-nft/Optimist.t.sol index 9aab06fde007e..22b6effc7ed42 100644 --- a/packages/contracts-bedrock/test/periphery/op-nft/Optimist.t.sol +++ b/packages/contracts-bedrock/test/periphery/op-nft/Optimist.t.sol @@ -3,6 +3,7 @@ pragma solidity >=0.6.2 <0.9.0; // Testing utilities import { Test } from "forge-std/Test.sol"; +import { IMulticall3 } from "forge-std/interfaces/IMulticall3.sol"; import { AttestationStation } from "src/periphery/op-nft/AttestationStation.sol"; import { Optimist } from "src/periphery/op-nft/Optimist.sol"; import { OptimistAllowlist } from "src/periphery/op-nft/OptimistAllowlist.sol"; @@ -11,21 +12,6 @@ import { OptimistInviterHelper } from "test/mocks/OptimistInviterHelper.sol"; import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; import { IERC721 } from "@openzeppelin/contracts/token/ERC721/IERC721.sol"; -interface IMulticall3 { - struct Call3 { - address target; - bool allowFailure; - bytes callData; - } - - struct Result { - bool success; - bytes returnData; - } - - function aggregate3(Call3[] calldata calls) external payable returns (Result[] memory returnData); -} - library Multicall { bytes internal constant code = hex"6080604052600436106100f35760003560e01c80634d2301cc1161008a578063a8b0574e11610059578063a8b0574e1461025a578063bce38bd714610275578063c3077fa914610288578063ee82ac5e1461029b57600080fd5b80634d2301cc146101ec57806372425d9d1461022157806382ad56cb1461023457806386d516e81461024757600080fd5b80633408e470116100c65780633408e47014610191578063399542e9146101a45780633e64a696146101c657806342cbb15c146101d957600080fd5b80630f28c97d146100f8578063174dea711461011a578063252dba421461013a57806327e86d6e1461015b575b600080fd5b34801561010457600080fd5b50425b6040519081526020015b60405180910390f35b61012d610128366004610a85565b6102ba565b6040516101119190610bbe565b61014d610148366004610a85565b6104ef565b604051610111929190610bd8565b34801561016757600080fd5b50437fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0140610107565b34801561019d57600080fd5b5046610107565b6101b76101b2366004610c60565b610690565b60405161011193929190610cba565b3480156101d257600080fd5b5048610107565b3480156101e557600080fd5b5043610107565b3480156101f857600080fd5b50610107610207366004610ce2565b73ffffffffffffffffffffffffffffffffffffffff163190565b34801561022d57600080fd5b5044610107565b61012d610242366004610a85565b6106ab565b34801561025357600080fd5b5045610107565b34801561026657600080fd5b50604051418152602001610111565b61012d610283366004610c60565b61085a565b6101b7610296366004610a85565b610a1a565b3480156102a757600080fd5b506101076102b6366004610d18565b4090565b60606000828067ffffffffffffffff8111156102d8576102d8610d31565b60405190808252806020026020018201604052801561031e57816020015b6040805180820190915260008152606060208201528152602001906001900390816102f65790505b5092503660005b8281101561047757600085828151811061034157610341610d60565b6020026020010151905087878381811061035d5761035d610d60565b905060200281019061036f9190610d8f565b6040810135958601959093506103886020850185610ce2565b73ffffffffffffffffffffffffffffffffffffffff16816103ac6060870187610dcd565b6040516103ba929190610e32565b60006040518083038185875af1925050503d80600081146103f7576040519150601f19603f3d011682016040523d82523d6000602084013e6103fc565b606091505b50602080850191909152901515808452908501351761046d577f08c379a000000000000000000000000000000000000000000000000000000000600052602060045260176024527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060445260846000fd5b5050600101610325565b508234146104e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d756c746963616c6c333a2076616c7565206d69736d6174636800000000000060448201526064015b60405180910390fd5b50505092915050565b436060828067ffffffffffffffff81111561050c5761050c610d31565b60405190808252806020026020018201604052801561053f57816020015b606081526020019060019003908161052a5790505b5091503660005b8281101561068657600087878381811061056257610562610d60565b90506020028101906105749190610e42565b92506105836020840184610ce2565b73ffffffffffffffffffffffffffffffffffffffff166105a66020850185610dcd565b6040516105b4929190610e32565b6000604051808303816000865af19150503d80600081146105f1576040519150601f19603f3d011682016040523d82523d6000602084013e6105f6565b606091505b5086848151811061060957610609610d60565b602090810291909101015290508061067d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060448201526064016104dd565b50600101610546565b5050509250929050565b43804060606106a086868661085a565b905093509350939050565b6060818067ffffffffffffffff8111156106c7576106c7610d31565b60405190808252806020026020018201604052801561070d57816020015b6040805180820190915260008152606060208201528152602001906001900390816106e55790505b5091503660005b828110156104e657600084828151811061073057610730610d60565b6020026020010151905086868381811061074c5761074c610d60565b905060200281019061075e9190610e76565b925061076d6020840184610ce2565b73ffffffffffffffffffffffffffffffffffffffff166107906040850185610dcd565b60405161079e929190610e32565b6000604051808303816000865af19150503d80600081146107db576040519150601f19603f3d011682016040523d82523d6000602084013e6107e0565b606091505b506020808401919091529015158083529084013517610851577f08c379a000000000000000000000000000000000000000000000000000000000600052602060045260176024527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060445260646000fd5b50600101610714565b6060818067ffffffffffffffff81111561087657610876610d31565b6040519080825280602002602001820160405280156108bc57816020015b6040805180820190915260008152606060208201528152602001906001900390816108945790505b5091503660005b82811015610a105760008482815181106108df576108df610d60565b602002602001015190508686838181106108fb576108fb610d60565b905060200281019061090d9190610e42565b925061091c6020840184610ce2565b73ffffffffffffffffffffffffffffffffffffffff1661093f6020850185610dcd565b60405161094d929190610e32565b6000604051808303816000865af19150503d806000811461098a576040519150601f19603f3d011682016040523d82523d6000602084013e61098f565b606091505b506020830152151581528715610a07578051610a07576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060448201526064016104dd565b506001016108c3565b5050509392505050565b6000806060610a2b60018686610690565b919790965090945092505050565b60008083601f840112610a4b57600080fd5b50813567ffffffffffffffff811115610a6357600080fd5b6020830191508360208260051b8501011115610a7e57600080fd5b9250929050565b60008060208385031215610a9857600080fd5b823567ffffffffffffffff811115610aaf57600080fd5b610abb85828601610a39565b90969095509350505050565b6000815180845260005b81811015610aed57602081850181015186830182015201610ad1565b81811115610aff576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600082825180855260208086019550808260051b84010181860160005b84811015610bb1578583037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001895281518051151584528401516040858501819052610b9d81860183610ac7565b9a86019a9450505090830190600101610b4f565b5090979650505050505050565b602081526000610bd16020830184610b32565b9392505050565b600060408201848352602060408185015281855180845260608601915060608160051b870101935082870160005b82811015610c52577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0888703018452610c40868351610ac7565b95509284019290840190600101610c06565b509398975050505050505050565b600080600060408486031215610c7557600080fd5b83358015158114610c8557600080fd5b9250602084013567ffffffffffffffff811115610ca157600080fd5b610cad86828701610a39565b9497909650939450505050565b838152826020820152606060408201526000610cd96060830184610b32565b95945050505050565b600060208284031215610cf457600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610bd157600080fd5b600060208284031215610d2a57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112610dc357600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112610e0257600080fd5b83018035915067ffffffffffffffff821115610e1d57600080fd5b602001915036819003821315610a7e57600080fd5b8183823760009101908152919050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1833603018112610dc357600080fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa1833603018112610dc357600080fdfea2646970667358221220bb2b5c71a328032f97c676ae39a1ec2148d3e5d6f73d95e9b17910152d61f16264736f6c634300080c0033"; diff --git a/packages/contracts-bedrock/test/Safe/DeployOwnership.t.sol b/packages/contracts-bedrock/test/safe/DeployOwnership.t.sol similarity index 95% rename from packages/contracts-bedrock/test/Safe/DeployOwnership.t.sol rename to packages/contracts-bedrock/test/safe/DeployOwnership.t.sol index b3a856e68a406..8e3a939686cb3 100644 --- a/packages/contracts-bedrock/test/Safe/DeployOwnership.t.sol +++ b/packages/contracts-bedrock/test/safe/DeployOwnership.t.sol @@ -15,10 +15,9 @@ import { GnosisSafe as Safe } from "safe-contracts/GnosisSafe.sol"; import { ModuleManager } from "safe-contracts/base/ModuleManager.sol"; import { GuardManager } from "safe-contracts/base/GuardManager.sol"; -import { LivenessGuard } from "src/Safe/LivenessGuard.sol"; -import { LivenessModule } from "src/Safe/LivenessModule.sol"; -import { DeputyGuardianModule } from "src/Safe/DeputyGuardianModule.sol"; -import { SuperchainConfig } from "src/L1/SuperchainConfig.sol"; +import { LivenessGuard } from "src/safe/LivenessGuard.sol"; +import { LivenessModule } from "src/safe/LivenessModule.sol"; +import { DeputyGuardianModule } from "src/safe/DeputyGuardianModule.sol"; contract DeployOwnershipTest is Test, DeployOwnership { address internal constant SENTINEL_MODULES = address(0x1); diff --git a/packages/contracts-bedrock/test/Safe/DeputyGuardianModule.t.sol b/packages/contracts-bedrock/test/safe/DeputyGuardianModule.t.sol similarity index 93% rename from packages/contracts-bedrock/test/Safe/DeputyGuardianModule.t.sol rename to packages/contracts-bedrock/test/safe/DeputyGuardianModule.t.sol index 5470fe33a5e2e..84824a5ff6944 100644 --- a/packages/contracts-bedrock/test/Safe/DeputyGuardianModule.t.sol +++ b/packages/contracts-bedrock/test/safe/DeputyGuardianModule.t.sol @@ -1,18 +1,23 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Testing import { CommonTest } from "test/setup/CommonTest.sol"; import { ForgeArtifacts, Abi } from "scripts/libraries/ForgeArtifacts.sol"; import { GnosisSafe as Safe } from "safe-contracts/GnosisSafe.sol"; import "test/safe-tools/SafeTestTools.sol"; -import { IDisputeGame } from "src/dispute/interfaces/IDisputeGame.sol"; -import { IFaultDisputeGame } from "src/dispute/interfaces/IFaultDisputeGame.sol"; -import { AnchorStateRegistry } from "src/dispute/AnchorStateRegistry.sol"; -import { DeputyGuardianModule } from "src/Safe/DeputyGuardianModule.sol"; +// Contracts +import { DeputyGuardianModule } from "src/safe/DeputyGuardianModule.sol"; +// Libraries import "src/dispute/lib/Types.sol"; +// Interfaces +import { IDisputeGame } from "src/dispute/interfaces/IDisputeGame.sol"; +import { IFaultDisputeGame } from "src/dispute/interfaces/IFaultDisputeGame.sol"; +import { IAnchorStateRegistry } from "src/dispute/interfaces/IAnchorStateRegistry.sol"; + contract DeputyGuardianModule_TestInit is CommonTest, SafeTestTools { using SafeTestLib for SafeInstance; @@ -152,13 +157,13 @@ contract DeputyGuardianModule_Unpause_TestFail is DeputyGuardianModule_Unpause_T contract DeputyGuardianModule_SetAnchorState_TestFail is DeputyGuardianModule_TestInit { function test_setAnchorState_notDeputyGuardian_reverts() external { - AnchorStateRegistry asr = AnchorStateRegistry(makeAddr("asr")); + IAnchorStateRegistry asr = IAnchorStateRegistry(makeAddr("asr")); vm.expectRevert(abi.encodeWithSelector(Unauthorized.selector)); deputyGuardianModule.setAnchorState(asr, IFaultDisputeGame(address(0))); } function test_setAnchorState_targetReverts_reverts() external { - AnchorStateRegistry asr = AnchorStateRegistry(makeAddr("asr")); + IAnchorStateRegistry asr = IAnchorStateRegistry(makeAddr("asr")); vm.mockCallRevert( address(asr), abi.encodeWithSelector(asr.setAnchorState.selector), @@ -174,10 +179,10 @@ contract DeputyGuardianModule_SetAnchorState_TestFail is DeputyGuardianModule_Te contract DeputyGuardianModule_SetAnchorState_Test is DeputyGuardianModule_TestInit { function test_setAnchorState_succeeds() external { - AnchorStateRegistry asr = AnchorStateRegistry(makeAddr("asr")); + IAnchorStateRegistry asr = IAnchorStateRegistry(makeAddr("asr")); vm.mockCall( address(asr), - abi.encodeWithSelector(AnchorStateRegistry.setAnchorState.selector, IFaultDisputeGame(address(0))), + abi.encodeWithSelector(IAnchorStateRegistry.setAnchorState.selector, IFaultDisputeGame(address(0))), "" ); vm.expectEmit(address(safeInstance.safe)); @@ -278,10 +283,12 @@ contract DeputyGuardianModule_NoPortalCollisions_Test is DeputyGuardianModule_Te /// @dev tests that no function selectors in the L1 contracts collide with the OptimismPortal2 functions called by /// the DeputyGuardianModule. function test_noPortalCollisions_succeeds() external { - string[] memory excludes = new string[](3); - excludes[0] = "src/L1/OptimismPortal2.sol"; - excludes[1] = "src/dispute/lib/*"; + string[] memory excludes = new string[](5); + excludes[0] = "src/dispute/lib/*"; + excludes[1] = "src/L1/OptimismPortal2.sol"; excludes[2] = "src/L1/OptimismPortalInterop.sol"; + excludes[3] = "src/L1/interfaces/IOptimismPortal2.sol"; + excludes[4] = "src/L1/interfaces/IOptimismPortalInterop.sol"; Abi[] memory abis = ForgeArtifacts.getContractFunctionAbis("src/{L1,dispute,universal}", excludes); for (uint256 i; i < abis.length; i++) { for (uint256 j; j < abis[i].entries.length; j++) { diff --git a/packages/contracts-bedrock/test/Safe/LivenessGuard.t.sol b/packages/contracts-bedrock/test/safe/LivenessGuard.t.sol similarity index 96% rename from packages/contracts-bedrock/test/Safe/LivenessGuard.t.sol rename to packages/contracts-bedrock/test/safe/LivenessGuard.t.sol index b8d67506da6df..41db45ac974af 100644 --- a/packages/contracts-bedrock/test/Safe/LivenessGuard.t.sol +++ b/packages/contracts-bedrock/test/safe/LivenessGuard.t.sol @@ -10,7 +10,7 @@ import { Enum } from "safe-contracts/common/Enum.sol"; import "test/safe-tools/SafeTestTools.sol"; import { EnumerableSet } from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; -import { LivenessGuard } from "src/Safe/LivenessGuard.sol"; +import { LivenessGuard } from "src/safe/LivenessGuard.sol"; /// @dev A wrapper contract exposing the length of the ownersBefore set in the LivenessGuard. contract WrappedGuard is LivenessGuard { @@ -235,7 +235,16 @@ contract LivenessGuard_FuzzOwnerManagement_Test is StdCheats, StdUtils, Liveness ) external { - vm.assume(changes.length < 20); + // Cut down the changes array to a maximum of 20. + // We don't use vm.assume to avoid throwing out too many inputs. + OwnerChange[] memory boundedChanges = new OwnerChange[](bound(changes.length, 0, 20)); + for (uint256 i; i < boundedChanges.length; i++) { + boundedChanges[i] = changes[i]; + } + + // Update the original array. + changes = boundedChanges; + // Initialize the safe with more owners than changes, to ensure we don't try to remove them all initialOwners = bound(initialOwners, changes.length, 2 * changes.length); diff --git a/packages/contracts-bedrock/test/Safe/LivenessModule.t.sol b/packages/contracts-bedrock/test/safe/LivenessModule.t.sol similarity index 99% rename from packages/contracts-bedrock/test/Safe/LivenessModule.t.sol rename to packages/contracts-bedrock/test/safe/LivenessModule.t.sol index f27e8aab4c508..060dfb389ca4e 100644 --- a/packages/contracts-bedrock/test/Safe/LivenessModule.t.sol +++ b/packages/contracts-bedrock/test/safe/LivenessModule.t.sol @@ -7,8 +7,8 @@ import { OwnerManager } from "safe-contracts/base/OwnerManager.sol"; import { Enum } from "safe-contracts/common/Enum.sol"; import "test/safe-tools/SafeTestTools.sol"; -import { LivenessModule } from "src/Safe/LivenessModule.sol"; -import { LivenessGuard } from "src/Safe/LivenessGuard.sol"; +import { LivenessModule } from "src/safe/LivenessModule.sol"; +import { LivenessGuard } from "src/safe/LivenessGuard.sol"; contract LivenessModule_TestInit is Test, SafeTestTools { using SafeTestLib for SafeInstance; diff --git a/packages/contracts-bedrock/test/Safe/SafeSigners.t.sol b/packages/contracts-bedrock/test/safe/SafeSigners.t.sol similarity index 98% rename from packages/contracts-bedrock/test/Safe/SafeSigners.t.sol rename to packages/contracts-bedrock/test/safe/SafeSigners.t.sol index 2006a44b9e71c..a6caf2a487ff2 100644 --- a/packages/contracts-bedrock/test/Safe/SafeSigners.t.sol +++ b/packages/contracts-bedrock/test/safe/SafeSigners.t.sol @@ -3,7 +3,7 @@ pragma solidity 0.8.15; import { Test } from "forge-std/Test.sol"; import { GnosisSafe as Safe } from "safe-contracts/GnosisSafe.sol"; -import { SafeSigners } from "src/Safe/SafeSigners.sol"; +import { SafeSigners } from "src/safe/SafeSigners.sol"; import "test/safe-tools/SafeTestTools.sol"; contract SafeSigners_Test is Test, SafeTestTools { diff --git a/packages/contracts-bedrock/test/setup/FFIInterface.sol b/packages/contracts-bedrock/test/setup/FFIInterface.sol index c07c9f58fbd55..727402a37c2c1 100644 --- a/packages/contracts-bedrock/test/setup/FFIInterface.sol +++ b/packages/contracts-bedrock/test/setup/FFIInterface.sol @@ -245,6 +245,56 @@ contract FFIInterface { return (memRoot, proof); } + function getCannonMemoryProof( + uint32 pc, + uint32 insn, + uint32 memAddr, + uint32 memVal, + uint32 memAddr2, + uint32 memVal2 + ) + external + returns (bytes32, bytes memory) + { + string[] memory cmds = new string[](9); + cmds[0] = "scripts/go-ffi/go-ffi"; + cmds[1] = "diff"; + cmds[2] = "cannonMemoryProof"; + cmds[3] = vm.toString(pc); + cmds[4] = vm.toString(insn); + cmds[5] = vm.toString(memAddr); + cmds[6] = vm.toString(memVal); + cmds[7] = vm.toString(memAddr2); + cmds[8] = vm.toString(memVal2); + bytes memory result = Process.run(cmds); + (bytes32 memRoot, bytes memory proof) = abi.decode(result, (bytes32, bytes)); + return (memRoot, proof); + } + + function getCannonMemoryProof2( + uint32 pc, + uint32 insn, + uint32 memAddr, + uint32 memVal, + uint32 memAddrForProof + ) + external + returns (bytes32, bytes memory) + { + string[] memory cmds = new string[](8); + cmds[0] = "scripts/go-ffi/go-ffi"; + cmds[1] = "diff"; + cmds[2] = "cannonMemoryProof2"; + cmds[3] = vm.toString(pc); + cmds[4] = vm.toString(insn); + cmds[5] = vm.toString(memAddr); + cmds[6] = vm.toString(memVal); + cmds[7] = vm.toString(memAddrForProof); + bytes memory result = Process.run(cmds); + (bytes32 memRoot, bytes memory proof) = abi.decode(result, (bytes32, bytes)); + return (memRoot, proof); + } + function getCannonMemoryProofWrongLeaf( uint32 pc, uint32 insn, diff --git a/packages/contracts-bedrock/test/setup/Setup.sol b/packages/contracts-bedrock/test/setup/Setup.sol index 0dfb6bd47f248..3a09519203acd 100644 --- a/packages/contracts-bedrock/test/setup/Setup.sol +++ b/packages/contracts-bedrock/test/setup/Setup.sol @@ -1,48 +1,54 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Testing import { console2 as console } from "forge-std/console2.sol"; -import { Predeploys } from "src/libraries/Predeploys.sol"; -import { Preinstalls } from "src/libraries/Preinstalls.sol"; -import { L2CrossDomainMessenger } from "src/L2/L2CrossDomainMessenger.sol"; -import { L2StandardBridgeInterop } from "src/L2/L2StandardBridgeInterop.sol"; -import { L2ToL1MessagePasser } from "src/L2/L2ToL1MessagePasser.sol"; -import { L2ERC721Bridge } from "src/L2/L2ERC721Bridge.sol"; -import { BaseFeeVault } from "src/L2/BaseFeeVault.sol"; -import { SequencerFeeVault } from "src/L2/SequencerFeeVault.sol"; -import { L1FeeVault } from "src/L2/L1FeeVault.sol"; -import { GasPriceOracle } from "src/L2/GasPriceOracle.sol"; -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 { 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 { Vm } from "forge-std/Vm.sol"; + +// Scripts import { DeployConfig } from "scripts/deploy/DeployConfig.s.sol"; import { Deploy } from "scripts/deploy/Deploy.s.sol"; import { Fork, LATEST_FORK } from "scripts/libraries/Config.sol"; import { L2Genesis, L1Dependencies } from "scripts/L2Genesis.s.sol"; import { OutputMode, Fork, ForkUtils } from "scripts/libraries/Config.sol"; -import { L2OutputOracle } from "src/L1/L2OutputOracle.sol"; -import { ProtocolVersions } from "src/L1/ProtocolVersions.sol"; -import { SystemConfig } from "src/L1/SystemConfig.sol"; -import { L1StandardBridge } from "src/L1/L1StandardBridge.sol"; -import { AddressManager } from "src/legacy/AddressManager.sol"; -import { L1ERC721Bridge } from "src/L1/L1ERC721Bridge.sol"; -import { AddressAliasHelper } from "src/vendor/AddressAliasHelper.sol"; import { Executables } from "scripts/libraries/Executables.sol"; -import { Vm } from "forge-std/Vm.sol"; -import { SuperchainConfig } from "src/L1/SuperchainConfig.sol"; -import { DataAvailabilityChallenge } from "src/L1/DataAvailabilityChallenge.sol"; -import { WETH } from "src/L2/WETH.sol"; -import { SuperchainWETH } from "src/L2/SuperchainWETH.sol"; -import { ETHLiquidity } from "src/L2/ETHLiquidity.sol"; + +// Libraries +import { Predeploys } from "src/libraries/Predeploys.sol"; +import { Preinstalls } from "src/libraries/Preinstalls.sol"; +import { AddressAliasHelper } from "src/vendor/AddressAliasHelper.sol"; + +// Interfaces +import { IOptimismPortal } from "src/L1/interfaces/IOptimismPortal.sol"; +import { IOptimismPortal2 } from "src/L1/interfaces/IOptimismPortal2.sol"; +import { IL1CrossDomainMessenger } from "src/L1/interfaces/IL1CrossDomainMessenger.sol"; +import { IL2OutputOracle } from "src/L1/interfaces/IL2OutputOracle.sol"; +import { ISystemConfig } from "src/L1/interfaces/ISystemConfig.sol"; +import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol"; +import { IDataAvailabilityChallenge } from "src/L1/interfaces/IDataAvailabilityChallenge.sol"; +import { IL1StandardBridge } from "src/L1/interfaces/IL1StandardBridge.sol"; +import { IProtocolVersions } from "src/L1/interfaces/IProtocolVersions.sol"; +import { IL1ERC721Bridge } from "src/L1/interfaces/IL1ERC721Bridge.sol"; +import { IDisputeGameFactory } from "src/dispute/interfaces/IDisputeGameFactory.sol"; +import { IDelayedWETH } from "src/dispute/interfaces/IDelayedWETH.sol"; +import { IAnchorStateRegistry } from "src/dispute/interfaces/IAnchorStateRegistry.sol"; +import { IL2CrossDomainMessenger } from "src/L2/interfaces/IL2CrossDomainMessenger.sol"; +import { IL2StandardBridgeInterop } from "src/L2/interfaces/IL2StandardBridgeInterop.sol"; +import { IL2ToL1MessagePasser } from "src/L2/interfaces/IL2ToL1MessagePasser.sol"; +import { IL2ERC721Bridge } from "src/L2/interfaces/IL2ERC721Bridge.sol"; +import { IOptimismMintableERC20Factory } from "src/universal/interfaces/IOptimismMintableERC20Factory.sol"; +import { IAddressManager } from "src/legacy/interfaces/IAddressManager.sol"; +import { IOptimismERC20Factory } from "src/L2/interfaces/IOptimismERC20Factory.sol"; +import { IBaseFeeVault } from "src/L2/interfaces/IBaseFeeVault.sol"; +import { ISequencerFeeVault } from "src/L2/interfaces/ISequencerFeeVault.sol"; +import { IL1FeeVault } from "src/L2/interfaces/IL1FeeVault.sol"; +import { IGasPriceOracle } from "src/L2/interfaces/IGasPriceOracle.sol"; +import { IL1Block } from "src/L2/interfaces/IL1Block.sol"; +import { ISuperchainWETH } from "src/L2/interfaces/ISuperchainWETH.sol"; +import { IETHLiquidity } from "src/L2/interfaces/IETHLiquidity.sol"; +import { IWETH } from "src/universal/interfaces/IWETH.sol"; +import { IGovernanceToken } from "src/governance/interfaces/IGovernanceToken.sol"; +import { ILegacyMessagePasser } from "src/legacy/interfaces/ILegacyMessagePasser.sol"; /// @title Setup /// @dev This contact is responsible for setting up the contracts in state. It currently @@ -65,39 +71,45 @@ contract Setup { // @notice Allows users of Setup to override what L2 genesis is being created. Fork l2Fork = LATEST_FORK; - OptimismPortal optimismPortal; - OptimismPortal2 optimismPortal2; - DisputeGameFactory disputeGameFactory; - DelayedWETH delayedWeth; - L2OutputOracle l2OutputOracle; - SystemConfig systemConfig; - L1StandardBridge l1StandardBridge; - L1CrossDomainMessenger l1CrossDomainMessenger; - AddressManager addressManager; - L1ERC721Bridge l1ERC721Bridge; - OptimismMintableERC20Factory l1OptimismMintableERC20Factory; - ProtocolVersions protocolVersions; - SuperchainConfig superchainConfig; - DataAvailabilityChallenge dataAvailabilityChallenge; - AnchorStateRegistry anchorStateRegistry; - - L2CrossDomainMessenger l2CrossDomainMessenger = - L2CrossDomainMessenger(payable(Predeploys.L2_CROSS_DOMAIN_MESSENGER)); - L2StandardBridgeInterop l2StandardBridge = L2StandardBridgeInterop(payable(Predeploys.L2_STANDARD_BRIDGE)); - L2ToL1MessagePasser l2ToL1MessagePasser = L2ToL1MessagePasser(payable(Predeploys.L2_TO_L1_MESSAGE_PASSER)); - OptimismMintableERC20Factory l2OptimismMintableERC20Factory = - OptimismMintableERC20Factory(Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY); - L2ERC721Bridge l2ERC721Bridge = L2ERC721Bridge(Predeploys.L2_ERC721_BRIDGE); - BaseFeeVault baseFeeVault = BaseFeeVault(payable(Predeploys.BASE_FEE_VAULT)); - SequencerFeeVault sequencerFeeVault = SequencerFeeVault(payable(Predeploys.SEQUENCER_FEE_WALLET)); - L1FeeVault l1FeeVault = L1FeeVault(payable(Predeploys.L1_FEE_VAULT)); - GasPriceOracle gasPriceOracle = GasPriceOracle(Predeploys.GAS_PRICE_ORACLE); - L1Block l1Block = L1Block(Predeploys.L1_BLOCK_ATTRIBUTES); - LegacyMessagePasser legacyMessagePasser = LegacyMessagePasser(Predeploys.LEGACY_MESSAGE_PASSER); - GovernanceToken governanceToken = GovernanceToken(Predeploys.GOVERNANCE_TOKEN); - WETH weth = WETH(payable(Predeploys.WETH)); - SuperchainWETH superchainWeth = SuperchainWETH(payable(Predeploys.SUPERCHAIN_WETH)); - ETHLiquidity ethLiquidity = ETHLiquidity(Predeploys.ETH_LIQUIDITY); + // L1 contracts + IDisputeGameFactory disputeGameFactory; + IAnchorStateRegistry anchorStateRegistry; + IDelayedWETH delayedWeth; + IOptimismPortal optimismPortal; + IOptimismPortal2 optimismPortal2; + IL2OutputOracle l2OutputOracle; + ISystemConfig systemConfig; + IL1StandardBridge l1StandardBridge; + IL1CrossDomainMessenger l1CrossDomainMessenger; + IAddressManager addressManager; + IL1ERC721Bridge l1ERC721Bridge; + IOptimismMintableERC20Factory l1OptimismMintableERC20Factory; + IProtocolVersions protocolVersions; + ISuperchainConfig superchainConfig; + IDataAvailabilityChallenge dataAvailabilityChallenge; + + // L2 contracts + IL2CrossDomainMessenger l2CrossDomainMessenger = + IL2CrossDomainMessenger(payable(Predeploys.L2_CROSS_DOMAIN_MESSENGER)); + IL2StandardBridgeInterop l2StandardBridge = IL2StandardBridgeInterop(payable(Predeploys.L2_STANDARD_BRIDGE)); + IL2ToL1MessagePasser l2ToL1MessagePasser = IL2ToL1MessagePasser(payable(Predeploys.L2_TO_L1_MESSAGE_PASSER)); + IOptimismMintableERC20Factory l2OptimismMintableERC20Factory = + IOptimismMintableERC20Factory(Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY); + IL2ERC721Bridge l2ERC721Bridge = IL2ERC721Bridge(Predeploys.L2_ERC721_BRIDGE); + IBaseFeeVault baseFeeVault = IBaseFeeVault(payable(Predeploys.BASE_FEE_VAULT)); + ISequencerFeeVault sequencerFeeVault = ISequencerFeeVault(payable(Predeploys.SEQUENCER_FEE_WALLET)); + IL1FeeVault l1FeeVault = IL1FeeVault(payable(Predeploys.L1_FEE_VAULT)); + IGasPriceOracle gasPriceOracle = IGasPriceOracle(Predeploys.GAS_PRICE_ORACLE); + IL1Block l1Block = IL1Block(Predeploys.L1_BLOCK_ATTRIBUTES); + IGovernanceToken governanceToken = IGovernanceToken(Predeploys.GOVERNANCE_TOKEN); + ILegacyMessagePasser legacyMessagePasser = ILegacyMessagePasser(Predeploys.LEGACY_MESSAGE_PASSER); + IWETH weth = IWETH(payable(Predeploys.WETH)); + ISuperchainWETH superchainWeth = ISuperchainWETH(payable(Predeploys.SUPERCHAIN_WETH)); + IETHLiquidity ethLiquidity = IETHLiquidity(Predeploys.ETH_LIQUIDITY); + + // TODO: Replace with OptimismSuperchainERC20Factory when updating pragmas + IOptimismERC20Factory l2OptimismSuperchainERC20Factory = + IOptimismERC20Factory(Predeploys.OPTIMISM_SUPERCHAIN_ERC20_FACTORY); /// @dev Deploys the Deploy contract without including its bytecode in the bytecode /// of this contract by fetching the bytecode dynamically using `vm.getCode()`. @@ -131,21 +143,21 @@ contract Setup { deploy.run(); console.log("Setup: completed L1 deployment, registering addresses now"); - 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")); - l1CrossDomainMessenger = L1CrossDomainMessenger(deploy.mustGetAddress("L1CrossDomainMessengerProxy")); - addressManager = AddressManager(deploy.mustGetAddress("AddressManager")); - l1ERC721Bridge = L1ERC721Bridge(deploy.mustGetAddress("L1ERC721BridgeProxy")); + optimismPortal = IOptimismPortal(deploy.mustGetAddress("OptimismPortalProxy")); + optimismPortal2 = IOptimismPortal2(deploy.mustGetAddress("OptimismPortalProxy")); + disputeGameFactory = IDisputeGameFactory(deploy.mustGetAddress("DisputeGameFactoryProxy")); + delayedWeth = IDelayedWETH(deploy.mustGetAddress("DelayedWETHProxy")); + l2OutputOracle = IL2OutputOracle(deploy.mustGetAddress("L2OutputOracleProxy")); + systemConfig = ISystemConfig(deploy.mustGetAddress("SystemConfigProxy")); + l1StandardBridge = IL1StandardBridge(deploy.mustGetAddress("L1StandardBridgeProxy")); + l1CrossDomainMessenger = IL1CrossDomainMessenger(deploy.mustGetAddress("L1CrossDomainMessengerProxy")); + addressManager = IAddressManager(deploy.mustGetAddress("AddressManager")); + l1ERC721Bridge = IL1ERC721Bridge(deploy.mustGetAddress("L1ERC721BridgeProxy")); l1OptimismMintableERC20Factory = - OptimismMintableERC20Factory(deploy.mustGetAddress("OptimismMintableERC20FactoryProxy")); - protocolVersions = ProtocolVersions(deploy.mustGetAddress("ProtocolVersionsProxy")); - superchainConfig = SuperchainConfig(deploy.mustGetAddress("SuperchainConfigProxy")); - anchorStateRegistry = AnchorStateRegistry(deploy.mustGetAddress("AnchorStateRegistryProxy")); + IOptimismMintableERC20Factory(deploy.mustGetAddress("OptimismMintableERC20FactoryProxy")); + protocolVersions = IProtocolVersions(deploy.mustGetAddress("ProtocolVersionsProxy")); + superchainConfig = ISuperchainConfig(deploy.mustGetAddress("SuperchainConfigProxy")); + anchorStateRegistry = IAnchorStateRegistry(deploy.mustGetAddress("AnchorStateRegistryProxy")); vm.label(address(l2OutputOracle), "L2OutputOracle"); vm.label(deploy.mustGetAddress("L2OutputOracleProxy"), "L2OutputOracleProxy"); @@ -174,7 +186,7 @@ contract Setup { if (deploy.cfg().useAltDA()) { dataAvailabilityChallenge = - DataAvailabilityChallenge(deploy.mustGetAddress("DataAvailabilityChallengeProxy")); + IDataAvailabilityChallenge(deploy.mustGetAddress("DataAvailabilityChallengeProxy")); vm.label(address(dataAvailabilityChallenge), "DataAvailabilityChallengeProxy"); vm.label(deploy.mustGetAddress("DataAvailabilityChallenge"), "DataAvailabilityChallenge"); } @@ -217,6 +229,8 @@ contract Setup { labelPredeploy(Predeploys.WETH); labelPredeploy(Predeploys.SUPERCHAIN_WETH); labelPredeploy(Predeploys.ETH_LIQUIDITY); + labelPredeploy(Predeploys.OPTIMISM_SUPERCHAIN_ERC20_FACTORY); + labelPredeploy(Predeploys.OPTIMISM_SUPERCHAIN_ERC20_BEACON); // L2 Preinstalls labelPreinstall(Preinstalls.MultiCall3); @@ -233,6 +247,7 @@ contract Setup { labelPreinstall(Preinstalls.SenderCreator_v070); labelPreinstall(Preinstalls.EntryPoint_v070); labelPreinstall(Preinstalls.BeaconBlockRoots); + labelPreinstall(Preinstalls.CreateX); console.log("Setup: completed L2 genesis"); } diff --git a/packages/contracts-bedrock/test/universal/CrossDomainMessenger.t.sol b/packages/contracts-bedrock/test/universal/CrossDomainMessenger.t.sol index f2a9a8d43d85b..1fab9c6db1ce4 100644 --- a/packages/contracts-bedrock/test/universal/CrossDomainMessenger.t.sol +++ b/packages/contracts-bedrock/test/universal/CrossDomainMessenger.t.sol @@ -11,7 +11,7 @@ import { Predeploys } from "src/libraries/Predeploys.sol"; import { Hashing } from "src/libraries/Hashing.sol"; import { Encoding } from "src/libraries/Encoding.sol"; -import { L1CrossDomainMessenger } from "src/L1/L1CrossDomainMessenger.sol"; +import { IL1CrossDomainMessenger } from "src/L1/interfaces/IL1CrossDomainMessenger.sol"; // CrossDomainMessenger_Test is for testing functionality which is common to both the L1 and L2 // CrossDomainMessenger contracts. For simplicity, we use the L1 Messenger as the test contract. @@ -45,11 +45,11 @@ contract CrossDomainMessenger_BaseGas_Test is Bridge_Initializer { contract ExternalRelay is Test { address internal op; address internal fuzzedSender; - L1CrossDomainMessenger internal l1CrossDomainMessenger; + IL1CrossDomainMessenger internal l1CrossDomainMessenger; event FailedRelayedMessage(bytes32 indexed msgHash); - constructor(L1CrossDomainMessenger _l1Messenger, address _op) { + constructor(IL1CrossDomainMessenger _l1Messenger, address _op) { l1CrossDomainMessenger = _l1Messenger; op = _op; } diff --git a/packages/contracts-bedrock/test/universal/OptimismMintableERC20.t.sol b/packages/contracts-bedrock/test/universal/OptimismMintableERC20.t.sol index 985b7bad8eb9d..1e84ce2958cf3 100644 --- a/packages/contracts-bedrock/test/universal/OptimismMintableERC20.t.sol +++ b/packages/contracts-bedrock/test/universal/OptimismMintableERC20.t.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.15; import { Bridge_Initializer } from "test/setup/Bridge_Initializer.sol"; -import { ILegacyMintableERC20, IOptimismMintableERC20 } from "src/universal/IOptimismMintableERC20.sol"; +import { ILegacyMintableERC20, IOptimismMintableERC20 } from "src/universal/interfaces/IOptimismMintableERC20.sol"; import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; contract OptimismMintableERC20_Test is Bridge_Initializer { @@ -46,6 +46,20 @@ contract OptimismMintableERC20_Test is Bridge_Initializer { assertEq(L2Token.balanceOf(alice), 100); } + function test_allowance_permit2_max() external view { + assertEq(L2Token.allowance(alice, L2Token.PERMIT2()), type(uint256).max); + } + + function test_permit2_transferFrom() external { + vm.prank(address(l2StandardBridge)); + L2Token.mint(alice, 100); + + assertEq(L2Token.balanceOf(bob), 0); + vm.prank(L2Token.PERMIT2()); + L2Token.transferFrom(alice, bob, 100); + assertEq(L2Token.balanceOf(bob), 100); + } + function test_mint_notBridge_reverts() external { // NOT the bridge vm.expectRevert("OptimismMintableERC20: only bridge can mint and burn"); diff --git a/packages/contracts-bedrock/test/universal/OptimismMintableERC20Factory.t.sol b/packages/contracts-bedrock/test/universal/OptimismMintableERC20Factory.t.sol index 85dc4e0d3e9b2..07aa2c61958d6 100644 --- a/packages/contracts-bedrock/test/universal/OptimismMintableERC20Factory.t.sol +++ b/packages/contracts-bedrock/test/universal/OptimismMintableERC20Factory.t.sol @@ -1,17 +1,18 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; -// Testing utilities +// Testing import { Bridge_Initializer } from "test/setup/Bridge_Initializer.sol"; import { NextImpl } from "test/mocks/NextImpl.sol"; import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; -// Target contract dependencies +// Contracts import { OptimismMintableERC20 } from "src/universal/OptimismMintableERC20.sol"; +import { OptimismMintableERC20Factory } from "src/universal/OptimismMintableERC20Factory.sol"; import { Proxy } from "src/universal/Proxy.sol"; -// Target contract -import { OptimismMintableERC20Factory } from "src/universal/OptimismMintableERC20Factory.sol"; +// Interfaces +import { IOptimismMintableERC20Factory } from "src/universal/interfaces/IOptimismMintableERC20Factory.sol"; contract OptimismMintableTokenFactory_Test is Bridge_Initializer { event StandardL2TokenCreated(address indexed remoteToken, address indexed localToken); @@ -19,7 +20,7 @@ contract OptimismMintableTokenFactory_Test is Bridge_Initializer { /// @notice Tests that the constructor is initialized correctly. function test_constructor_succeeds() external { - OptimismMintableERC20Factory impl = new OptimismMintableERC20Factory(); + IOptimismMintableERC20Factory impl = IOptimismMintableERC20Factory(address(new OptimismMintableERC20Factory())); assertEq(address(impl.BRIDGE()), address(0)); assertEq(address(impl.bridge()), address(0)); } diff --git a/packages/contracts-bedrock/test/vendor/Initializable.t.sol b/packages/contracts-bedrock/test/vendor/Initializable.t.sol index 922b1c4bd5b82..7b7596b9bafec 100644 --- a/packages/contracts-bedrock/test/vendor/Initializable.t.sol +++ b/packages/contracts-bedrock/test/vendor/Initializable.t.sol @@ -1,20 +1,28 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.15; +// Testing import { Bridge_Initializer } from "test/setup/Bridge_Initializer.sol"; + +// Scripts import { Executables } from "scripts/libraries/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/libraries/ForgeArtifacts.sol"; +import { ForgeArtifacts, StorageSlot } from "scripts/libraries/ForgeArtifacts.sol"; import { Process } from "scripts/libraries/Process.sol"; -import "src/L1/ProtocolVersions.sol"; + +// Libraries +import { LibString } from "@solady/utils/LibString.sol"; +import { Constants } from "src/libraries/Constants.sol"; +import { GameTypes } from "src/dispute/lib/Types.sol"; import "src/dispute/lib/Types.sol"; import "scripts/deploy/Deployer.sol"; +// Interfaces +import { ISystemConfig } from "src/L1/interfaces/ISystemConfig.sol"; +import { IResourceMetering } from "src/L1/interfaces/IResourceMetering.sol"; +import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol"; +import { ProtocolVersion } from "src/L1/interfaces/IProtocolVersions.sol"; +import { IAnchorStateRegistry } from "src/dispute/interfaces/IAnchorStateRegistry.sol"; + /// @title Initializer_Test /// @dev Ensures that the `initialize()` function on contracts cannot be called more than /// once. This contract inherits from `ERC721Bridge_Initializer` because it is the @@ -24,15 +32,19 @@ contract Initializer_Test is Bridge_Initializer { /// @notice Contains the address of an `Initializable` contract and the calldata /// used to initialize it. struct InitializeableContract { + string name; address target; bytes initCalldata; - uint8 initializedSlotVal; } - /// @notice Contains the addresses of the contracts to test as well as the calldata - /// used to initialize them. + /// @notice Array of contracts to test. InitializeableContract[] contracts; + /// @notice Mapping of nickname to actual contract name. + /// @dev Nicknames are only used when one proxy contract has multiple potential implementations + /// as can happen when a new implementation is being developed. + mapping(string => string) nicknames; + function setUp() public override { super.enableAltDA(); // Run the `Bridge_Initializer`'s `setUp()` function. @@ -44,98 +56,107 @@ contract Initializer_Test is Bridge_Initializer { // SuperchainConfigImpl contracts.push( InitializeableContract({ + name: "SuperchainConfig", target: deploy.mustGetAddress("SuperchainConfig"), - initCalldata: abi.encodeCall(superchainConfig.initialize, (address(0), false)), - initializedSlotVal: deploy.loadInitializedSlot("SuperchainConfig") + initCalldata: abi.encodeCall(superchainConfig.initialize, (address(0), false)) }) ); // SuperchainConfigProxy contracts.push( InitializeableContract({ + name: "SuperchainConfigProxy", target: address(superchainConfig), - initCalldata: abi.encodeCall(superchainConfig.initialize, (address(0), false)), - initializedSlotVal: deploy.loadInitializedSlot("SuperchainConfigProxy") + initCalldata: abi.encodeCall(superchainConfig.initialize, (address(0), false)) }) ); // L1CrossDomainMessengerImpl contracts.push( InitializeableContract({ + name: "L1CrossDomainMessenger", target: deploy.mustGetAddress("L1CrossDomainMessenger"), initCalldata: abi.encodeCall( l1CrossDomainMessenger.initialize, (superchainConfig, optimismPortal, systemConfig) - ), - initializedSlotVal: deploy.loadInitializedSlot("L1CrossDomainMessenger") + ) }) ); // L1CrossDomainMessengerProxy contracts.push( InitializeableContract({ + name: "L1CrossDomainMessengerProxy", target: address(l1CrossDomainMessenger), initCalldata: abi.encodeCall( l1CrossDomainMessenger.initialize, (superchainConfig, optimismPortal, systemConfig) - ), - initializedSlotVal: deploy.loadInitializedSlot("L1CrossDomainMessengerProxy") + ) }) ); // DisputeGameFactoryImpl contracts.push( InitializeableContract({ + name: "DisputeGameFactory", target: deploy.mustGetAddress("DisputeGameFactory"), - initCalldata: abi.encodeCall(disputeGameFactory.initialize, (address(0))), - initializedSlotVal: deploy.loadInitializedSlot("DisputeGameFactory") + initCalldata: abi.encodeCall(disputeGameFactory.initialize, (address(0))) }) ); // DisputeGameFactoryProxy contracts.push( InitializeableContract({ + name: "DisputeGameFactoryProxy", target: address(disputeGameFactory), - initCalldata: abi.encodeCall(disputeGameFactory.initialize, (address(0))), - initializedSlotVal: deploy.loadInitializedSlot("DisputeGameFactoryProxy") + initCalldata: abi.encodeCall(disputeGameFactory.initialize, (address(0))) }) ); // DelayedWETHImpl contracts.push( InitializeableContract({ + name: "DelayedWETH", target: deploy.mustGetAddress("DelayedWETH"), - initCalldata: abi.encodeCall(delayedWeth.initialize, (address(0), SuperchainConfig(address(0)))), - initializedSlotVal: deploy.loadInitializedSlot("DelayedWETH") + initCalldata: abi.encodeCall(delayedWeth.initialize, (address(0), ISuperchainConfig(address(0)))) }) ); // DelayedWETHProxy contracts.push( InitializeableContract({ + name: "DelayedWETHProxy", target: address(delayedWeth), - initCalldata: abi.encodeCall(delayedWeth.initialize, (address(0), SuperchainConfig(address(0)))), - initializedSlotVal: deploy.loadInitializedSlot("DelayedWETHProxy") + initCalldata: abi.encodeCall(delayedWeth.initialize, (address(0), ISuperchainConfig(address(0)))) }) ); // L2OutputOracleImpl contracts.push( InitializeableContract({ + name: "L2OutputOracle", target: deploy.mustGetAddress("L2OutputOracle"), - initCalldata: abi.encodeCall(l2OutputOracle.initialize, (0, 0, 0, 0, address(0), address(0), 0)), - initializedSlotVal: deploy.loadInitializedSlot("L2OutputOracle") + initCalldata: abi.encodeCall(l2OutputOracle.initialize, (0, 0, 0, 0, address(0), address(0), 0)) }) ); // L2OutputOracleProxy contracts.push( InitializeableContract({ + name: "L2OutputOracleProxy", target: address(l2OutputOracle), - initCalldata: abi.encodeCall(l2OutputOracle.initialize, (0, 0, 0, 0, address(0), address(0), 0)), - initializedSlotVal: deploy.loadInitializedSlot("L2OutputOracleProxy") + initCalldata: abi.encodeCall(l2OutputOracle.initialize, (0, 0, 0, 0, address(0), address(0), 0)) }) ); // OptimismPortalImpl contracts.push( InitializeableContract({ + name: "OptimismPortal", target: deploy.mustGetAddress("OptimismPortal"), - initCalldata: abi.encodeCall(optimismPortal.initialize, (l2OutputOracle, systemConfig, superchainConfig)), - initializedSlotVal: deploy.loadInitializedSlot("OptimismPortal") + initCalldata: abi.encodeCall(optimismPortal.initialize, (l2OutputOracle, systemConfig, superchainConfig)) + }) + ); + // OptimismPortalProxy + contracts.push( + InitializeableContract({ + name: "OptimismPortalProxy", + target: address(optimismPortal), + initCalldata: abi.encodeCall(optimismPortal.initialize, (l2OutputOracle, systemConfig, superchainConfig)) }) ); // OptimismPortal2Impl contracts.push( InitializeableContract({ + name: "OptimismPortal2", target: deploy.mustGetAddress("OptimismPortal2"), initCalldata: abi.encodeCall( optimismPortal2.initialize, @@ -145,21 +166,13 @@ contract Initializer_Test is Bridge_Initializer { superchainConfig, GameType.wrap(uint32(deploy.cfg().respectedGameType())) ) - ), - initializedSlotVal: deploy.loadInitializedSlot("OptimismPortal2") - }) - ); - // OptimismPortalProxy - contracts.push( - InitializeableContract({ - target: address(optimismPortal), - initCalldata: abi.encodeCall(optimismPortal.initialize, (l2OutputOracle, systemConfig, superchainConfig)), - initializedSlotVal: deploy.loadInitializedSlot("OptimismPortalProxy") + ) }) ); // SystemConfigImpl contracts.push( InitializeableContract({ + name: "SystemConfig", target: deploy.mustGetAddress("SystemConfig"), initCalldata: abi.encodeCall( systemConfig.initialize, @@ -170,7 +183,7 @@ contract Initializer_Test is Bridge_Initializer { bytes32(0), 1, address(0), - ResourceMetering.ResourceConfig({ + IResourceMetering.ResourceConfig({ maxResourceLimit: 1, elasticityMultiplier: 1, baseFeeMaxChangeDenominator: 2, @@ -179,7 +192,7 @@ contract Initializer_Test is Bridge_Initializer { maximumBaseFee: 0 }), address(0), - SystemConfig.Addresses({ + ISystemConfig.Addresses({ l1CrossDomainMessenger: address(0), l1ERC721Bridge: address(0), l1StandardBridge: address(0), @@ -189,13 +202,13 @@ contract Initializer_Test is Bridge_Initializer { gasPayingToken: Constants.ETHER }) ) - ), - initializedSlotVal: deploy.loadInitializedSlot("SystemConfig") + ) }) ); // SystemConfigProxy contracts.push( InitializeableContract({ + name: "SystemConfigProxy", target: address(systemConfig), initCalldata: abi.encodeCall( systemConfig.initialize, @@ -206,7 +219,7 @@ contract Initializer_Test is Bridge_Initializer { bytes32(0), 1, address(0), - ResourceMetering.ResourceConfig({ + IResourceMetering.ResourceConfig({ maxResourceLimit: 1, elasticityMultiplier: 1, baseFeeMaxChangeDenominator: 2, @@ -215,7 +228,7 @@ contract Initializer_Test is Bridge_Initializer { maximumBaseFee: 0 }), address(0), - SystemConfig.Addresses({ + ISystemConfig.Addresses({ l1CrossDomainMessenger: address(0), l1ERC721Bridge: address(0), l1StandardBridge: address(0), @@ -225,242 +238,286 @@ contract Initializer_Test is Bridge_Initializer { gasPayingToken: Constants.ETHER }) ) - ), - initializedSlotVal: deploy.loadInitializedSlot("SystemConfigProxy") + ) }) ); // ProtocolVersionsImpl contracts.push( InitializeableContract({ + name: "ProtocolVersions", target: deploy.mustGetAddress("ProtocolVersions"), initCalldata: abi.encodeCall( protocolVersions.initialize, (address(0), ProtocolVersion.wrap(1), ProtocolVersion.wrap(2)) - ), - initializedSlotVal: deploy.loadInitializedSlot("ProtocolVersions") + ) }) ); // ProtocolVersionsProxy contracts.push( InitializeableContract({ + name: "ProtocolVersionsProxy", target: address(protocolVersions), initCalldata: abi.encodeCall( protocolVersions.initialize, (address(0), ProtocolVersion.wrap(1), ProtocolVersion.wrap(2)) - ), - initializedSlotVal: deploy.loadInitializedSlot("ProtocolVersionsProxy") + ) }) ); // L2CrossDomainMessenger contracts.push( InitializeableContract({ + name: "L2CrossDomainMessenger", target: address(l2CrossDomainMessenger), - initCalldata: abi.encodeCall(l2CrossDomainMessenger.initialize, (l1CrossDomainMessenger)), - initializedSlotVal: deploy.loadInitializedSlot("L2CrossDomainMessenger") + initCalldata: abi.encodeCall(l2CrossDomainMessenger.initialize, (l1CrossDomainMessenger)) }) ); // L1StandardBridgeImpl contracts.push( InitializeableContract({ + name: "L1StandardBridge", target: deploy.mustGetAddress("L1StandardBridge"), initCalldata: abi.encodeCall( l1StandardBridge.initialize, (l1CrossDomainMessenger, superchainConfig, systemConfig) - ), - initializedSlotVal: deploy.loadInitializedSlot("L1StandardBridge") + ) }) ); // L1StandardBridgeProxy contracts.push( InitializeableContract({ + name: "L1StandardBridgeProxy", target: address(l1StandardBridge), initCalldata: abi.encodeCall( l1StandardBridge.initialize, (l1CrossDomainMessenger, superchainConfig, systemConfig) - ), - initializedSlotVal: deploy.loadInitializedSlot("L1StandardBridgeProxy") + ) }) ); // L2StandardBridge contracts.push( InitializeableContract({ + name: "L2StandardBridge", target: address(l2StandardBridge), - initCalldata: abi.encodeCall(l2StandardBridge.initialize, (l1StandardBridge)), - initializedSlotVal: deploy.loadInitializedSlot("L2StandardBridge") + initCalldata: abi.encodeCall(l2StandardBridge.initialize, (l1StandardBridge)) }) ); // L2StandardBridgeInterop contracts.push( InitializeableContract({ + name: "L2StandardBridgeInterop", target: address(l2StandardBridge), - initCalldata: abi.encodeCall(l2StandardBridge.initialize, (l1StandardBridge)), - initializedSlotVal: deploy.loadInitializedSlot("L2StandardBridgeInterop") + initCalldata: abi.encodeCall(l2StandardBridge.initialize, (l1StandardBridge)) }) ); // L1ERC721BridgeImpl contracts.push( InitializeableContract({ + name: "L1ERC721Bridge", target: deploy.mustGetAddress("L1ERC721Bridge"), - initCalldata: abi.encodeCall(l1ERC721Bridge.initialize, (l1CrossDomainMessenger, superchainConfig)), - initializedSlotVal: deploy.loadInitializedSlot("L1ERC721Bridge") + initCalldata: abi.encodeCall(l1ERC721Bridge.initialize, (l1CrossDomainMessenger, superchainConfig)) }) ); // L1ERC721BridgeProxy contracts.push( InitializeableContract({ + name: "L1ERC721BridgeProxy", target: address(l1ERC721Bridge), - initCalldata: abi.encodeCall(l1ERC721Bridge.initialize, (l1CrossDomainMessenger, superchainConfig)), - initializedSlotVal: deploy.loadInitializedSlot("L1ERC721BridgeProxy") + initCalldata: abi.encodeCall(l1ERC721Bridge.initialize, (l1CrossDomainMessenger, superchainConfig)) }) ); // L2ERC721Bridge contracts.push( InitializeableContract({ + name: "L2ERC721Bridge", target: address(l2ERC721Bridge), - initCalldata: abi.encodeCall(l2ERC721Bridge.initialize, (payable(address(l1ERC721Bridge)))), - initializedSlotVal: deploy.loadInitializedSlot("L2ERC721Bridge") + initCalldata: abi.encodeCall(l2ERC721Bridge.initialize, (payable(address(l1ERC721Bridge)))) }) ); // OptimismMintableERC20FactoryImpl contracts.push( InitializeableContract({ + name: "OptimismMintableERC20Factory", target: deploy.mustGetAddress("OptimismMintableERC20Factory"), - initCalldata: abi.encodeCall(l1OptimismMintableERC20Factory.initialize, (address(l1StandardBridge))), - initializedSlotVal: deploy.loadInitializedSlot("OptimismMintableERC20Factory") + initCalldata: abi.encodeCall(l1OptimismMintableERC20Factory.initialize, (address(l1StandardBridge))) }) ); // OptimismMintableERC20FactoryProxy contracts.push( InitializeableContract({ + name: "OptimismMintableERC20FactoryProxy", target: address(l1OptimismMintableERC20Factory), - initCalldata: abi.encodeCall(l1OptimismMintableERC20Factory.initialize, (address(l1StandardBridge))), - initializedSlotVal: deploy.loadInitializedSlot("OptimismMintableERC20FactoryProxy") + initCalldata: abi.encodeCall(l1OptimismMintableERC20Factory.initialize, (address(l1StandardBridge))) }) ); // DataAvailabilityChallengeImpl contracts.push( InitializeableContract({ + name: "DataAvailabilityChallenge", target: deploy.mustGetAddress("DataAvailabilityChallenge"), - initCalldata: abi.encodeCall(dataAvailabilityChallenge.initialize, (address(0), 0, 0, 0, 0)), - initializedSlotVal: deploy.loadInitializedSlot("DataAvailabilityChallenge") + initCalldata: abi.encodeCall(dataAvailabilityChallenge.initialize, (address(0), 0, 0, 0, 0)) }) ); // DataAvailabilityChallengeProxy contracts.push( InitializeableContract({ + name: "DataAvailabilityChallengeProxy", target: address(dataAvailabilityChallenge), - initCalldata: abi.encodeCall(dataAvailabilityChallenge.initialize, (address(0), 0, 0, 0, 0)), - initializedSlotVal: deploy.loadInitializedSlot("DataAvailabilityChallengeProxy") + initCalldata: abi.encodeCall(dataAvailabilityChallenge.initialize, (address(0), 0, 0, 0, 0)) }) ); + // AnchorStateRegistry + contracts.push( + InitializeableContract({ + name: "AnchorStateRegistry", + target: address(anchorStateRegistry), + initCalldata: abi.encodeCall( + anchorStateRegistry.initialize, + (new IAnchorStateRegistry.StartingAnchorRoot[](1), ISuperchainConfig(address(0))) + ) + }) + ); + // AnchorStateRegistryProxy + contracts.push( + InitializeableContract({ + name: "AnchorStateRegistryProxy", + target: address(anchorStateRegistry), + initCalldata: abi.encodeCall( + anchorStateRegistry.initialize, + (new IAnchorStateRegistry.StartingAnchorRoot[](1), ISuperchainConfig(address(0))) + ) + }) + ); + + // Nicknamed contracts. + nicknames["OptimismPortal2Proxy"] = "OptimismPortalProxy"; } /// @notice Tests that: - /// 1. All `Initializable` contracts in `src/L1` and `src/L2` are accounted for in the `contracts` array. - /// 2. The `_initialized` flag of each contract is properly set to `1`, signifying that the - /// contracts are initialized. - /// 3. The `initialize()` function of each contract cannot be called more than once. + /// 1. All `Initializable` contracts in `src/` (except periphery) are accounted for in `contracts`. + /// 2. The `_initialized` flag of each contract is properly set. + /// 3. The `initialize()` function of each contract cannot be called again. function test_cannotReinitialize_succeeds() public { - // Ensure that all L1, L2 `Initializable` contracts are accounted for, in addition to - // OptimismMintableERC20FactoryImpl, OptimismMintableERC20FactoryProxy, OptimismPortal2, - // DisputeGameFactoryImpl, DisputeGameFactoryProxy, DelayedWETHImpl, DelayedWETHProxy. - // Omitting OptimismSuperchainERC20 due to using OZ v5 Initializable. - assertEq(_getNumInitializable(), contracts.length); + // Collect exclusions. + string[] memory excludes = new string[](8); + // TODO: Neither of these contracts are labeled properly in the deployment script. Both are + // currently being labeled as their non-interop versions. Remove these exclusions once + // the deployment script is fixed. + excludes[0] = "src/L1/SystemConfigInterop.sol"; + excludes[1] = "src/L1/OptimismPortalInterop.sol"; + // Contract is currently not being deployed as part of the standard deployment script. + excludes[2] = "src/L2/OptimismSuperchainERC20.sol"; + // Periphery contracts don't get deployed as part of the standard deployment script. + excludes[3] = "src/periphery/*"; + // TODO: Deployment script is currently "broken" in the sense that it doesn't properly + // label the FaultDisputeGame and PermissionedDisputeGame contracts and instead + // simply deploys them anonymously. Means that functions like "getInitializedSlot" + // don't work properly. Remove these exclusions once the deployment script is fixed. + excludes[4] = "src/dispute/FaultDisputeGame.sol"; + excludes[5] = "src/dispute/PermissionedDisputeGame.sol"; + // TODO: Eventually remove this exclusion. Same reason as above dispute contracts. + excludes[6] = "src/L1/OPContractsManager.sol"; + excludes[7] = "src/L1/OPContractsManagerInterop.sol"; - // Attempt to re-initialize all contracts within the `contracts` array. - for (uint256 i; i < contracts.length; i++) { - InitializeableContract memory _contract = contracts[i]; - uint256 size; - address target = _contract.target; - assembly { - size := extcodesize(target) - } - // Assert that the contract is already initialized. - assertEq(_contract.initializedSlotVal, 1); + // Get all contract names in the src directory, minus the excluded contracts. + string[] memory contractNames = ForgeArtifacts.getContractNames("src/*", excludes); - // Then, attempt to re-initialize the contract. This should fail. - (bool success, bytes memory returnData) = _contract.target.call(_contract.initCalldata); - assertFalse(success); - assertEq(_extractErrorString(returnData), "Initializable: contract is already initialized"); - } - } + // Iterate over all contracts to assert that they are accounted for in the `contracts + // array. All contracts that have an `initialize()` function must be accounted for in the + // `contracts` array or an error will be thrown. If the contract is proxied, both the + // implementation and the proxy must be accounted for in the `contracts` array. + for (uint256 i; i < contractNames.length; i++) { + string memory contractName = contractNames[i]; + string memory contractKind = ForgeArtifacts.getContractKind(contractName); - /// @dev Returns the number of contracts that are `Initializable` in `src/L1` and `src/L2`. - /// For L1 contracts, implementations are considered in addition to proxies - function _getNumInitializable() internal returns (uint256 numContracts_) { - string[] memory command = new string[](3); - command[0] = Executables.bash; - command[1] = "-c"; - // Start by getting L1 contracts - command[2] = string.concat( - Executables.find, - " src/L1 -type f -exec basename {} \\;", - " | ", - Executables.sed, - " 's/\\.[^.]*$//'", - " | ", - Executables.jq, - " -R -s 'split(\"\n\")[:-1]'" - ); - string[] memory l1ContractNames = abi.decode(vm.parseJson(string(Process.run(command))), (string[])); - - for (uint256 i; i < l1ContractNames.length; i++) { - string memory contractName = l1ContractNames[i]; - string memory contractAbi = ForgeArtifacts.getAbi(contractName); + // Filter out non-contracts. + if (!LibString.eq(contractKind, "contract")) { + continue; + } - // Query the contract's ABI for an `initialize()` function. + // Construct the query for the initialize function in the contract's ABI. + string[] memory command = new string[](3); + command[0] = Executables.bash; + command[1] = "-c"; command[2] = string.concat( Executables.echo, " '", - contractAbi, + ForgeArtifacts.getAbi(contractName), "'", " | ", Executables.jq, " '.[] | select(.name == \"initialize\" and .type == \"function\")'" ); - bytes memory res = Process.run(command); - // If the contract has an `initialize()` function, the resulting query will be non-empty. - // In this case, increment the number of `Initializable` contracts. - if (res.length > 0) { - // Count Proxy + Impl - numContracts_ += 2; + // If the contract does not have an `initialize()` function, skip it. + if (Process.run(command).length == 0) { + continue; + } + + // Check if this contract is in the contracts array. + assertTrue( + _hasMatchingContract(contractName), string.concat("Missing ", contractName, " from contracts array") + ); + + // If the contract is proxied, check that the proxy is in the contracts array. + // Skip predeployed contracts for now since we don't yet keep track of the + // implementations inside of the deploy script. + // TODO: We should add support for this in the future so that we can properly check that + // the implementations for predeployed contracts are initialized too. + if (ForgeArtifacts.isProxiedContract(contractName) && !ForgeArtifacts.isPredeployedContract(contractName)) { + assertTrue( + _hasMatchingContract(string.concat(contractName, "Proxy")), + string.concat("Missing ", contractName, "Proxy from contracts array") + ); } } - // Then get L2 contracts - command[2] = string.concat( - Executables.find, - " src/L2 -type f -exec basename {} \\;", - " | ", - Executables.sed, - " 's/\\.[^.]*$//'", - " | ", - Executables.jq, - " -R -s 'split(\"\n\")[:-1]'" - ); - string[] memory l2ContractNames = abi.decode(vm.parseJson(string(Process.run(command))), (string[])); + // Attempt to re-initialize all contracts within the `contracts` array. + for (uint256 i; i < contracts.length; i++) { + InitializeableContract memory _contract = contracts[i]; + string memory name = _getRealContractName(_contract.name); - for (uint256 i; i < l2ContractNames.length; i++) { - string memory contractName = l2ContractNames[i]; - string memory contractAbi = ForgeArtifacts.getAbi(contractName); + // Grab the value of the "initialized" storage slot. Must handle special case for the + // FaultDisputeGame and PermissionedDisputeGame contracts since these have a different + // name for the "initialized" storage slot and are currently not properly labeled in + // the deployment script. + // TODO: Update deployment script to properly label the dispute game contracts. + uint8 initializedSlotVal; + if (LibString.eq(name, "FaultDisputeGame") || LibString.eq(name, "PermissionedDisputeGame")) { + StorageSlot memory slot = ForgeArtifacts.getInitializedSlot(name); + bytes32 slotVal = vm.load(_contract.target, bytes32(vm.parseUint(slot.slot))); + initializedSlotVal = uint8((uint256(slotVal) >> (slot.offset * 8)) & 0xFF); + } else { + initializedSlotVal = deploy.loadInitializedSlot(name); + } - // Query the contract's ABI for an `initialize()` function. - command[2] = string.concat( - Executables.echo, - " '", - contractAbi, - "'", - " | ", - Executables.jq, - " '.[] | select(.name == \"initialize\" and .type == \"function\")'" + // Assert that the contract is already initialized. + assertTrue( + // Either 1 for initialized or type(uint8).max for initializer disabled. + initializedSlotVal == 1 || initializedSlotVal == type(uint8).max, + "Initializable: contract is not initialized" ); - bytes memory res = Process.run(command); - // If the contract has an `initialize()` function, the resulting query will be non-empty. - // In this case, increment the number of `Initializable` contracts. - if (res.length > 0) { - numContracts_++; + // Then, attempt to re-initialize the contract. This should fail. + (bool success, bytes memory returnData) = _contract.target.call(_contract.initCalldata); + assertFalse(success); + assertEq(_extractErrorString(returnData), "Initializable: contract is already initialized"); + } + } + + /// @dev Returns true if the contract with the given name is in the `contracts` array. + /// @param _name The name of the contract to check. + /// @return matching_ True if the contract is in the `contracts` array, false otherwise. + function _hasMatchingContract(string memory _name) internal view returns (bool matching_) { + for (uint256 i; i < contracts.length; i++) { + if (LibString.eq(contracts[i].name, _getRealContractName(_name))) { + matching_ = true; } } } + /// @dev Returns the real name of the contract, including any nicknames. + /// @param _name The name of the contract. + /// @return real_ The real name of the contract. + function _getRealContractName(string memory _name) internal view returns (string memory real_) { + real_ = bytes(nicknames[_name]).length > 0 ? nicknames[_name] : _name; + } + /// @dev Extracts the revert string from returndata encoded in the form of `Error(string)`. function _extractErrorString(bytes memory _returnData) internal pure returns (string memory error_) { // The first 4 bytes of the return data should be the selector for `Error(string)`. If not, revert. diff --git a/versions.json b/versions.json index 21cb42e985c2a..f1ca1a282c0a1 100644 --- a/versions.json +++ b/versions.json @@ -1,7 +1,7 @@ { "go": "1.22.6", "abigen": "v1.10.25", - "foundry": "d28a3377e52e6a4114a8cea2903c115b023279e8", + "foundry": "143abd6a768eeb52a5785240b763d72a56987b4a", "geth": "v1.14.7", "geth_release": "1.14.7-aa55f5ea", "eth2_testnet_genesis": "v0.10.0",