Commit e3949d2b authored by mergify[bot]'s avatar mergify[bot] Committed by GitHub

Merge branch 'develop' into refcell/periphery-styling

parents e175fd8f 982a0865
---
'@eth-optimism/chain-mon': patch
---
Update import path for artifact
---
'@eth-optimism/fault-detector': patch
---
Bump contracts-bedrock version
---
'@eth-optimism/sdk': patch
---
Fixed missing indexes for multicall support
---
'@eth-optimism/sdk': minor
---
Add support for claiming multicall3 withdrawals
---
'@eth-optimism/sdk': minor
---
Fixes issue with legacy withdrawal message status detection
---
'@eth-optimism/contracts-bedrock': patch
'@eth-optimism/fault-detector': patch
'@eth-optimism/core-utils': patch
'@eth-optimism/endpoint-monitor': patch
'@eth-optimism/sdk': patch
---
fix typo
---
'@eth-optimism/fault-detector': minor
---
Remove pre-bedrock support from fault detector.
---
'@eth-optimism/contracts-bedrock': minor
---
Migrate contracts periphery into bedrock
---
'@eth-optimism/contracts-bedrock': patch
'@eth-optimism/core-utils': patch
'@eth-optimism/sdk': patch
---
Delete dead typescript https://github.com/ethereum-optimism/optimism/pull/6148.
---
'@eth-optimism/sdk': patch
---
Update the addresses of the bridges on optimism and optimism goerli for the ECO bridge adapter
---
'@eth-optimism/sdk': minor
---
Added to and from block filters to several methods in CrossChainMessenger
...@@ -140,7 +140,6 @@ jobs: ...@@ -140,7 +140,6 @@ jobs:
- "packages/common-ts/node_modules" - "packages/common-ts/node_modules"
- "packages/contracts-bedrock/node_modules" - "packages/contracts-bedrock/node_modules"
- "packages/core-utils/node_modules" - "packages/core-utils/node_modules"
- "packages/fault-detector/node_modules"
- "packages/replica-healthcheck/node_modules" - "packages/replica-healthcheck/node_modules"
- "packages/sdk/node_modules" - "packages/sdk/node_modules"
- "packages/contracts-ts/node_modules" - "packages/contracts-ts/node_modules"
...@@ -376,7 +375,7 @@ jobs: ...@@ -376,7 +375,7 @@ jobs:
contracts-bedrock-tests: contracts-bedrock-tests:
docker: docker:
- image: us-docker.pkg.dev/oplabs-tools-artifacts/images/ci-builder:latest - image: us-docker.pkg.dev/oplabs-tools-artifacts/images/ci-builder:latest
resource_class: large resource_class: xlarge
steps: steps:
- checkout - checkout
- attach_workspace: { at: "." } - attach_workspace: { at: "." }
...@@ -409,10 +408,12 @@ jobs: ...@@ -409,10 +408,12 @@ jobs:
environment: environment:
FOUNDRY_PROFILE: ci FOUNDRY_PROFILE: ci
working_directory: packages/contracts-bedrock working_directory: packages/contracts-bedrock
no_output_timeout: 15m
contracts-bedrock-checks: contracts-bedrock-checks:
docker: docker:
- image: us-docker.pkg.dev/oplabs-tools-artifacts/images/ci-builder:latest - image: us-docker.pkg.dev/oplabs-tools-artifacts/images/ci-builder:latest
resource_class: xlarge
steps: steps:
- checkout - checkout
- attach_workspace: { at: "." } - attach_workspace: { at: "." }
...@@ -448,6 +449,7 @@ jobs: ...@@ -448,6 +449,7 @@ jobs:
environment: environment:
FOUNDRY_PROFILE: ci FOUNDRY_PROFILE: ci
working_directory: packages/contracts-bedrock working_directory: packages/contracts-bedrock
no_output_timeout: 15m
- run: - run:
name: validate deploy configs name: validate deploy configs
command: | command: |
...@@ -1115,6 +1117,18 @@ jobs: ...@@ -1115,6 +1117,18 @@ jobs:
command: | command: |
docker logs ops-bedrock-op-proposer-1 || echo "No logs." docker logs ops-bedrock-op-proposer-1 || echo "No logs."
when: on_fail when: on_fail
- run:
name: Log deployment artifact
command: |
cat broadcast/Deploy.s.sol/900/run-latest.json || echo "No deployment file found"
when: on_fail
working_directory: packages/contracts-bedrock
- run:
name: Log artifacts directory
command: |
ls -R forge-artifacts || echo "No forge artifacts found"
when: on_fail
working_directory: packages/contracts-bedrock
- when: - when:
condition: condition:
and: and:
...@@ -1348,13 +1362,6 @@ workflows: ...@@ -1348,13 +1362,6 @@ workflows:
dependencies: "(common-ts|contracts-bedrock|core-utils|sdk)" dependencies: "(common-ts|contracts-bedrock|core-utils|sdk)"
requires: requires:
- pnpm-monorepo - pnpm-monorepo
- js-lint-test:
name: fault-detector-tests
coverage_flag: fault-detector-tests
package_name: fault-detector
dependencies: "(common-ts|core-utils|sdk)"
requires:
- pnpm-monorepo
- js-lint-test: - js-lint-test:
name: contracts-ts-tests name: contracts-ts-tests
coverage_flag: contracts-ts-tests coverage_flag: contracts-ts-tests
...@@ -1601,14 +1608,6 @@ workflows: ...@@ -1601,14 +1608,6 @@ workflows:
docker_target: wd-mon docker_target: wd-mon
context: context:
- oplabs-gcr - oplabs-gcr
- docker-publish:
name: fault-detector-docker-publish
docker_file: ./ops/docker/Dockerfile.packages
docker_name: fault-detector
docker_tags: <<pipeline.git.revision>>,<<pipeline.git.branch>>
docker_target: fault-detector
context:
- oplabs-gcr
- hive-test: - hive-test:
name: hive-test-rpc name: hive-test-rpc
version: <<pipeline.git.revision>> version: <<pipeline.git.revision>>
...@@ -1646,7 +1645,7 @@ workflows: ...@@ -1646,7 +1645,7 @@ workflows:
type: approval type: approval
filters: filters:
tags: tags:
only: /^(fault-detector|proxyd|indexer|ci-builder|op-[a-z0-9\-]*)\/v.*/ only: /^(proxyd|indexer|ci-builder|op-[a-z0-9\-]*)\/v.*/
branches: branches:
ignore: /.*/ ignore: /.*/
- docker-release: - docker-release:
...@@ -1713,23 +1712,6 @@ workflows: ...@@ -1713,23 +1712,6 @@ workflows:
- oplabs-gcr-release - oplabs-gcr-release
requires: requires:
- hold - hold
- docker-release:
name: fault-detector-docker-release
filters:
tags:
only: /^fault-detector\/v.*/
branches:
ignore: /.*/
docker_file: ./ops/docker/Dockerfile.packages
docker_name: fault-detector
docker_tags: <<pipeline.git.revision>>,<<pipeline.git.branch>>
docker_target: fault-detector
docker_context: .
platforms: "linux/amd64,linux/arm64"
context:
- oplabs-gcr-release
requires:
- hold
- docker-build: - docker-build:
name: op-migrate-docker-release name: op-migrate-docker-release
filters: filters:
......
...@@ -3,14 +3,14 @@ ...@@ -3,14 +3,14 @@
/packages/contracts @ethereum-optimism/contract-reviewers /packages/contracts @ethereum-optimism/contract-reviewers
/packages/contracts-bedrock @ethereum-optimism/contract-reviewers /packages/contracts-bedrock @ethereum-optimism/contract-reviewers
/packages/core-utils @ethereum-optimism/legacy-reviewers /packages/core-utils @ethereum-optimism/legacy-reviewers
/packages/chain-mon @smartcontracts /packages/chain-mon @ethereum-optimism/devxpod
/packages/fault-detector @ethereum-optimism/devxpod
/packages/replica-healthcheck @ethereum-optimism/legacy-reviewers /packages/replica-healthcheck @ethereum-optimism/legacy-reviewers
/packages/sdk @ethereum-optimism/devxpod /packages/sdk @ethereum-optimism/devxpod
/packages/atst @ethereum-optimism/devxpod /packages/atst @ethereum-optimism/devxpod
# Bedrock codebases # Bedrock codebases
/bedrock-devnet @ethereum-optimism/go-reviewers /bedrock-devnet @ethereum-optimism/go-reviewers
/cannon @ethereum-optimism/go-reviewers
/op-batcher @ethereum-optimism/go-reviewers /op-batcher @ethereum-optimism/go-reviewers
/op-chain-ops @ethereum-optimism/go-reviewers /op-chain-ops @ethereum-optimism/go-reviewers
/op-e2e @ethereum-optimism/go-reviewers /op-e2e @ethereum-optimism/go-reviewers
...@@ -35,3 +35,11 @@ ...@@ -35,3 +35,11 @@
/infra @ethereum-optimism/infra-reviewers /infra @ethereum-optimism/infra-reviewers
/specs @ethereum-optimism/contract-reviewers @ethereum-optimism/go-reviewers /specs @ethereum-optimism/contract-reviewers @ethereum-optimism/go-reviewers
/endpoint-monitor @ethereum-optimism/infra-reviewers /endpoint-monitor @ethereum-optimism/infra-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
...@@ -15,7 +15,7 @@ jobs: ...@@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
# map the step outputs to job outputs # map the step outputs to job outputs
outputs: outputs:
fault-detector: ${{ steps.packages.outputs.fault-detector }} fault-mon: ${{ steps.packages.outputs.fault-mon }}
balance-mon: ${{ steps.packages.outputs.balance-mon }} balance-mon: ${{ steps.packages.outputs.balance-mon }}
drippie-mon: ${{ steps.packages.outputs.drippie-mon }} drippie-mon: ${{ steps.packages.outputs.drippie-mon }}
wd-mon: ${{ steps.packages.outputs.wd-mon }} wd-mon: ${{ steps.packages.outputs.wd-mon }}
...@@ -43,10 +43,10 @@ jobs: ...@@ -43,10 +43,10 @@ jobs:
env: env:
CUSTOM_IMAGE_NAME: ${{ github.event.inputs.customImageName }} CUSTOM_IMAGE_NAME: ${{ github.event.inputs.customImageName }}
fault-detector: fault-mon:
name: Publish Fault Detector Version ${{ needs.canary-publish.outputs.canary-docker-tag }} name: Publish fault-mon Version ${{ needs.canary-publish.outputs.canary-docker-tag }}
needs: canary-publish needs: canary-publish
if: needs.canary-publish.outputs.fault-detector != '' if: needs.canary-publish.outputs.fault-mon != ''
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
...@@ -66,9 +66,9 @@ jobs: ...@@ -66,9 +66,9 @@ jobs:
with: with:
context: . context: .
file: ./ops/docker/Dockerfile.packages file: ./ops/docker/Dockerfile.packages
target: fault-detector target: fault-mon
push: true push: true
tags: ethereumoptimism/fault-detector:${{ needs.canary-publish.outputs.canary-docker-tag }} tags: ethereumoptimism/fault-mon:${{ needs.canary-publish.outputs.canary-docker-tag }}
balance-mon: balance-mon:
name: Publish Balance Monitor Version ${{ needs.canary-publish.outputs.canary-docker-tag }} name: Publish Balance Monitor Version ${{ needs.canary-publish.outputs.canary-docker-tag }}
......
...@@ -16,7 +16,7 @@ jobs: ...@@ -16,7 +16,7 @@ jobs:
if: github.repository == 'ethereum-optimism/optimism' if: github.repository == 'ethereum-optimism/optimism'
# map the step outputs to job outputs # map the step outputs to job outputs
outputs: outputs:
fault-detector: ${{ steps.packages.outputs.fault-detector }} fault-mon: ${{ steps.packages.outputs.fault-mon }}
balance-mon: ${{ steps.packages.outputs.drippie-mon }} balance-mon: ${{ steps.packages.outputs.drippie-mon }}
drippie-mon: ${{ steps.packages.outputs.drippie-mon }} drippie-mon: ${{ steps.packages.outputs.drippie-mon }}
wd-mon: ${{ steps.packages.outputs.wd-mon }} wd-mon: ${{ steps.packages.outputs.wd-mon }}
...@@ -100,10 +100,10 @@ jobs: ...@@ -100,10 +100,10 @@ jobs:
GITCOMMIT=${{ steps.build_args.outputs.GITCOMMIT }} GITCOMMIT=${{ steps.build_args.outputs.GITCOMMIT }}
GITVERSION=${{ steps.build_args.outputs.GITVERSION }} GITVERSION=${{ steps.build_args.outputs.GITVERSION }}
fault-detector: fault-mon:
name: Publish Fault Detector Version ${{ needs.release.outputs.fault-detector }} name: Publish fault-mon Version ${{ needs.release.outputs.fault-mon }}
needs: release needs: release
if: needs.release.outputs.fault-detector != '' if: needs.release.outputs.fault-mon != ''
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
...@@ -123,9 +123,9 @@ jobs: ...@@ -123,9 +123,9 @@ jobs:
with: with:
context: . context: .
file: ./ops/docker/Dockerfile.packages file: ./ops/docker/Dockerfile.packages
target: fault-detector target: fault-mon
push: true push: true
tags: ethereumoptimism/fault-detector:${{ needs.release.outputs.fault-detector }},ethereumoptimism/fault-detector:latest tags: ethereumoptimism/fault-mon:${{ needs.release.outputs.fault-mon }},ethereumoptimism/fault-mon:latest
wd-mon: wd-mon:
name: Publish Withdrawal Monitor Version ${{ needs.release.outputs.wd-mon }} name: Publish Withdrawal Monitor Version ${{ needs.release.outputs.wd-mon }}
......
...@@ -26,6 +26,8 @@ on: ...@@ -26,6 +26,8 @@ on:
- op-proposer - op-proposer
- op-ufm - op-ufm
- proxyd - proxyd
- indexer
- ci-builder
prerelease: prerelease:
description: Increment major/minor/patch as prerelease? description: Increment major/minor/patch as prerelease?
required: false required: false
......
...@@ -19,14 +19,10 @@ ...@@ -19,14 +19,10 @@
{ {
"directory": "packages/chain-mon", "directory": "packages/chain-mon",
"changeProcessCWD": true "changeProcessCWD": true
},
{
"directory": "packages/fault-detector",
"changeProcessCWD": true
} }
], ],
"eslint.nodePath": "./node_modules/eslint/bin/", "eslint.nodePath": "./node_modules/eslint/bin/",
"eslint.format.enable": true, "eslint.format.enable": true,
"editorconfig.generateAuto": false, "editorconfig.generateAuto": false,
"files.trimTrailingWhitespace": true "files.trimTrailingWhitespace": true
} }
\ No newline at end of file
...@@ -130,4 +130,6 @@ update-op-geth: ...@@ -130,4 +130,6 @@ update-op-geth:
.PHONY: update-op-geth .PHONY: update-op-geth
bedrock-markdown-links: bedrock-markdown-links:
docker run --init -it -v `pwd`:/input lycheeverse/lychee --verbose --no-progress --exclude-loopback --exclude twitter.com --exclude explorer.optimism.io --exclude-mail /input/README.md "/input/specs/**/*.md" docker run --init -it -v `pwd`:/input lycheeverse/lychee --verbose --no-progress --exclude-loopback \
--exclude twitter.com --exclude explorer.optimism.io --exclude linux-mips.org \
--exclude-mail /input/README.md "/input/specs/**/*.md"
...@@ -54,7 +54,6 @@ Refer to the Directory Structure section below to understand which packages are ...@@ -54,7 +54,6 @@ Refer to the Directory Structure section below to understand which packages are
│ ├── <a href="./packages/contracts-bedrock">contracts-bedrock</a>: Bedrock smart contracts. │ ├── <a href="./packages/contracts-bedrock">contracts-bedrock</a>: Bedrock smart contracts.
│ ├── <a href="./packages/core-utils">core-utils</a>: Low-level utilities that make building Optimism easier │ ├── <a href="./packages/core-utils">core-utils</a>: Low-level utilities that make building Optimism easier
│ ├── <a href="./packages/chain-mon">chain-mon</a>: Chain monitoring services │ ├── <a href="./packages/chain-mon">chain-mon</a>: Chain monitoring services
│ ├── <a href="./packages/fault-detector">fault-detector</a>: Service for detecting Sequencer faults
│ ├── <a href="./packages/replica-healthcheck">replica-healthcheck</a>: Service for monitoring the health of a replica node │ ├── <a href="./packages/replica-healthcheck">replica-healthcheck</a>: Service for monitoring the health of a replica node
│ └── <a href="./packages/sdk">sdk</a>: provides a set of tools for interacting with Optimism │ └── <a href="./packages/sdk">sdk</a>: provides a set of tools for interacting with Optimism
├── <a href="./op-bindings">op-bindings</a>: Go bindings for Bedrock smart contracts. ├── <a href="./op-bindings">op-bindings</a>: Go bindings for Bedrock smart contracts.
...@@ -80,7 +79,6 @@ Refer to the Directory Structure section below to understand which packages are ...@@ -80,7 +79,6 @@ Refer to the Directory Structure section below to understand which packages are
│ ├── <a href="./packages/common-ts">common-ts</a>: Common tools for building apps in TypeScript │ ├── <a href="./packages/common-ts">common-ts</a>: Common tools for building apps in TypeScript
│ ├── <a href="./packages/core-utils">core-utils</a>: Low-level utilities that make building Optimism easier │ ├── <a href="./packages/core-utils">core-utils</a>: Low-level utilities that make building Optimism easier
│ ├── <a href="./packages/chain-mon">chain-mon</a>: Chain monitoring services │ ├── <a href="./packages/chain-mon">chain-mon</a>: Chain monitoring services
│ ├── <a href="./packages/fault-detector">fault-detector</a>: Service for detecting Sequencer faults
│ ├── <a href="./packages/replica-healthcheck">replica-healthcheck</a>: Service for monitoring the health of a replica node │ ├── <a href="./packages/replica-healthcheck">replica-healthcheck</a>: Service for monitoring the health of a replica node
│ └── <a href="./packages/sdk">sdk</a>: provides a set of tools for interacting with Optimism │ └── <a href="./packages/sdk">sdk</a>: provides a set of tools for interacting with Optimism
├── <a href="./indexer">indexer</a>: indexes and syncs transactions ├── <a href="./indexer">indexer</a>: indexes and syncs transactions
......
...@@ -44,48 +44,17 @@ There are 3 types of witness data involved in onchain execution: ...@@ -44,48 +44,17 @@ There are 3 types of witness data involved in onchain execution:
### Packed State ### Packed State
The following state is packed together, and provided in every executed onchain instruction: The Packed State is provided in every executed onchain instruction.
```solidity See [Cannon VM Specs](../../specs/cannon-fault-proof-vm.md#state) for
struct State { details on the state structure.
bytes32 memRoot;
bytes32 preimageKey;
uint32 preimageOffset;
uint32 pc;
uint32 nextPC;
uint32 lo;
uint32 hi;
uint32 heap;
uint8 exitCode;
bool exited;
uint64 step;
uint32[32] registers;
}
```
The packed state is small! The `State` data can be packed in such a small amount of EVM words, The packed state is small! The `State` data can be packed in such a small amount of EVM words,
that it is more efficient to fully provide it, than to create a proof for each individual part involved in execution. that it is more efficient to fully provide it, than to create a proof for each individual part involved in execution.
The memory is represented as a merkle-tree root, committing to a binary merkle tree of all memory data,
see [memory proofs](#memory-proofs).
The `State` covers all general purpose registers, as well as the `lo`, `hi` and `pc` values.
`nextPC` helps pre-schedule the program counter change, to emulate delay-slot behavior of MIPS
after branch and jump instructions.
The program stops changing the state when `exited` is set to true. The exit-code is remembered, The program stops changing the state when `exited` is set to true. The exit-code is remembered,
to determine if the program is successful, or panicked/exited in some unexpected way. to determine if the program is successful, or panicked/exited in some unexpected way.
This outcome can be used to determine truthiness of claims that are verified as part of the program execution. This outcome can be used to determine truthiness of claims that are verified as part of the program execution.
The `heap` value is a special value, used to emulate a growing heap, to map new memory upon `mmap` calls by the program.
No memory reads/writes are actually illegal however, mmap-ing is purely to satisfy program runtimes that
need the memory-pointer result of the syscall to locate free memory.
The `preimageKey` and `preimageOffset` are backing the in-flight communication of [pre-image data](#pre-image-data).
The VM `stateHash` is computed as `keccak256(encoded_packed_state)`,
where `encoded_packed_state` is the concatenation of all state-values (all `uint` values are big-endian).
### Memory proofs ### Memory proofs
...@@ -133,11 +102,7 @@ Pre-image data is accessed through syscalls exclusively. ...@@ -133,11 +102,7 @@ Pre-image data is accessed through syscalls exclusively.
The OP-stack fault-proof [Pre-image Oracle specs](../../specs/fault-proof.md#pre-image-oracle) The OP-stack fault-proof [Pre-image Oracle specs](../../specs/fault-proof.md#pre-image-oracle)
define the ABI for communicating pre-images. define the ABI for communicating pre-images.
This ABI is implemented by the VM by intercepting the `read`/`write` syscalls to specific file descriptors: This ABI is implemented by the VM by intercepting the `read`/`write` syscalls to specific file descriptors. See [Cannon VM Specs](../../specs/cannon-fault-proof-vm.md#io) for more details.
- `hint client read = 3`: used by the client to send hint data to the host. Optional, implemented as blocking.
- `hint client write = 4`: used by the client to wait for the host. Always instant, since the above is implemented as blocking.
- `preimage client read = 5`: used by the client to read pre-image data, starting from the latest pre-image reading offset.
- `preimage client write = 6`: used by the client to change the pre-image key. The key may change a little bit at a time. The last 32 written bytes count as key for retrieval when reading the pre-image. Changing the key also resets the read offset to 0.
The data is loaded into `PreimageOracle.sol` using the respective loading function based on the pre-image type. The data is loaded into `PreimageOracle.sol` using the respective loading function based on the pre-image type.
And then retrieved during execution of the `read` syscall. And then retrieved during execution of the `read` syscall.
......
...@@ -8,6 +8,7 @@ ignore: ...@@ -8,6 +8,7 @@ ignore:
- "op-bindings/bindings/*.go" - "op-bindings/bindings/*.go"
- "packages/contracts-bedrock/contracts/vendor/WETH9.sol" - "packages/contracts-bedrock/contracts/vendor/WETH9.sol"
- "packages/contracts-bedrock/contracts/cannon" # tested through Go tests - "packages/contracts-bedrock/contracts/cannon" # tested through Go tests
- 'packages/contracts-bedrock/contracts/EAS/**/*.sol'
coverage: coverage:
status: status:
patch: patch:
...@@ -35,6 +36,5 @@ flag_management: ...@@ -35,6 +36,5 @@ flag_management:
- name: core-utils-tests - name: core-utils-tests
- name: dtl-tests - name: dtl-tests
- name: chain-mon-tests - name: chain-mon-tests
- name: fault-detector-tests
- name: replica-healthcheck-tests - name: replica-healthcheck-tests
- name: sdk-tests - name: sdk-tests
...@@ -13,7 +13,7 @@ OP Stack configuration is an active work in progress and will likely evolve sign ...@@ -13,7 +13,7 @@ OP Stack configuration is an active work in progress and will likely evolve sign
## New Blockchain Configuration ## New Blockchain Configuration
New OP Stack blockchains are currently configured with a JSON file inside the Optimism repository. The file is `<optimism repository>/packages/contracts-bedrock/deploy-config/<chain name>.json`. For example, [this is the configuration file for the tutorial blockchain](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/deploy-config/getting-started.json). New OP Stack blockchains are currently configured with a JSON file inside the Optimism repository. The file is `<optimism repository>/packages/contracts-bedrock/deploy-config/<chain name>.json`. For example, [this is the configuration file for the tutorial blockchain](https://github.com/ethereum-optimism/optimism/blob/129032f15b76b0d2a940443a39433de931a97a44/packages/contracts-bedrock/deploy-config/getting-started.json).
### Admin accounts ### Admin accounts
......
...@@ -40,10 +40,10 @@ An example of an EVM-Ordered Alternative DA module can be found within [this mod ...@@ -40,10 +40,10 @@ An example of an EVM-Ordered Alternative DA module can be found within [this mod
### Non-EVM DA ### Non-EVM DA
A non-EVM DA module uses a chain not based on the EVM to manage both the ordering and storage of raw input data. Such a modification would require relatively significant modifications to the [derivation portion](https://github.com/ethereum-optimism/optimism/tree/develop/op-node/rollup/derive) of the `op-node`. No such fully-independent DA modules have been developed yet — be the first! A non-EVM DA module uses a chain not based on the EVM to manage both the ordering and storage of raw input data. Such a modification would require relatively significant modifications to the [derivation portion](https://github.com/ethereum-optimism/optimism/tree/129032f15b76b0d2a940443a39433de931a97a44/op-node/rollup/derive) of the `op-node`. No such fully-independent DA modules have been developed yet — be the first!
### Multiple DA ### Multiple DA
It is possible to use multiple Data Availability Layer modules at the same time. For instance, one could source data from two EVM-based chains simultaneously in order to form a bridge between the two chains. When using multiple Data Availability Layer modules, it is imperative to establish a global ordering between the two chains. One option for establishing this ordering is to use the timestamps of blocks from each chain. It is possible to use multiple Data Availability Layer modules at the same time. For instance, one could source data from two EVM-based chains simultaneously in order to form a bridge between the two chains. When using multiple Data Availability Layer modules, it is imperative to establish a global ordering between the two chains. One option for establishing this ordering is to use the timestamps of blocks from each chain.
Like a non-EVM DA module, a system with multiple Data Availability modules would need to make significant modifications to the [derivation portion](https://github.com/ethereum-optimism/optimism/tree/develop/op-node/rollup/derive) of the `op-node`. No such projects have been constructed yet. Like a non-EVM DA module, a system with multiple Data Availability modules would need to make significant modifications to the [derivation portion](https://github.com/ethereum-optimism/optimism/tree/129032f15b76b0d2a940443a39433de931a97a44/op-node/rollup/derive) of the `op-node`. No such projects have been constructed yet.
\ No newline at end of file \ No newline at end of file
...@@ -178,7 +178,7 @@ The `cast wallet new` tool is *not* designed for production deployments. If you ...@@ -178,7 +178,7 @@ The `cast wallet new` tool is *not* designed for production deployments. If you
## Configure your network ## Configure your network
Once you’ve built both repositories, you’ll need head back to the Optimism Monorepo to set up the configuration for your chain. Currently, chain configuration lives inside of the [`contracts-bedrock`](https://github.com/ethereum-optimism/optimism/tree/develop/packages/contracts-bedrock) package. Once you’ve built both repositories, you’ll need head back to the Optimism Monorepo to set up the configuration for your chain. Currently, chain configuration lives inside of the [`contracts-bedrock`](https://github.com/ethereum-optimism/optimism/tree/129032f15b76b0d2a940443a39433de931a97a44/packages/contracts-bedrock) package.
1. Enter the Optimism Monorepo: 1. Enter the Optimism Monorepo:
...@@ -226,7 +226,7 @@ Once you’ve built both repositories, you’ll need head back to the Optimism M ...@@ -226,7 +226,7 @@ Once you’ve built both repositories, you’ll need head back to the Optimism M
timestamp 1676253324 timestamp 1676253324
``` ```
1. Fill out the remainder of the pre-populated config file found at [`deploy-config/getting-started.json`](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/deploy-config/getting-started.json). Use the default values in the config file and make following modifications: 1. Fill out the remainder of the pre-populated config file found at [`deploy-config/getting-started.json`](https://github.com/ethereum-optimism/optimism/blob/129032f15b76b0d2a940443a39433de931a97a44/packages/contracts-bedrock/deploy-config/getting-started.json). Use the default values in the config file and make following modifications:
- Replace `"ADMIN"` with the address of the Admin account you generated earlier. - Replace `"ADMIN"` with the address of the Admin account you generated earlier.
- Replace `"PROPOSER"` with the address of the Proposer account you generated earlier. - Replace `"PROPOSER"` with the address of the Proposer account you generated earlier.
......
...@@ -10,11 +10,11 @@ OP Stack Hacks are not for the faint of heart. You will not be able to receive s ...@@ -10,11 +10,11 @@ OP Stack Hacks are not for the faint of heart. You will not be able to receive s
::: :::
OP Stack blockchains have a number of [predeployed contracts](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/constants.ts) that provide important functionality. OP Stack blockchains have a number of [predeployed contracts](https://github.com/ethereum-optimism/optimism/blob/129032f15b76b0d2a940443a39433de931a97a44/packages/contracts-bedrock/src/constants.ts) that provide important functionality.
Most of those contracts are proxies that can be upgraded using the `proxyAdminOwner` which was configured when the network was initially deployed. Most of those contracts are proxies that can be upgraded using the `proxyAdminOwner` which was configured when the network was initially deployed.
The predeploys are controlled from a predeploy called [`ProxyAdmin`](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/contracts/universal/ProxyAdmin.sol), whose address is `0x4200000000000000000000000000000000000018`. The predeploys are controlled from a predeploy called [`ProxyAdmin`](https://github.com/ethereum-optimism/optimism/blob/129032f15b76b0d2a940443a39433de931a97a44/packages/contracts-bedrock/contracts/universal/ProxyAdmin.sol), whose address is `0x4200000000000000000000000000000000000018`.
The function to call is [`upgrade(address,address)`](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/contracts/universal/ProxyAdmin.sol#L211-L229). The function to call is [`upgrade(address,address)`](https://github.com/ethereum-optimism/optimism/blob/129032f15b76b0d2a940443a39433de931a97a44/packages/contracts-bedrock/contracts/universal/ProxyAdmin.sol#L205-L229).
The first parameter is the proxy to upgrade, and the second is the address of a new implementation. The first parameter is the proxy to upgrade, and the second is the address of a new implementation.
For example, the legacy `L1BlockNumber` contract is at `0x420...013`. For example, the legacy `L1BlockNumber` contract is at `0x420...013`.
......
...@@ -5,7 +5,7 @@ lang: en-US ...@@ -5,7 +5,7 @@ lang: en-US
## Overview ## Overview
The first release of the OP Stack codebase is called **Bedrock**. The first release of the OP Stack codebase is called **Bedrock**.
The Bedrock release primarily consists of the core software required to run L2 blockchains and was originally designed to power an upgrade to the Optimism Mainnet network. The Bedrock release primarily consists of the core software required to run L2 blockchains and was originally designed to power an upgrade to the Optimism Mainnet network.
## Resources ## Resources
...@@ -20,15 +20,15 @@ Learn all about the Bedrock release of the OP Stack by reading the [Bedrock Expl ...@@ -20,15 +20,15 @@ Learn all about the Bedrock release of the OP Stack by reading the [Bedrock Expl
### Specifications ### Specifications
Dive deep into the specifications for the Bedrock release in the [specs folder of the Optimism Monorepo](https://github.com/ethereum-optimism/optimism/blob/develop/specs/README.md). Dive deep into the specifications for the Bedrock release in the [specs folder of the Optimism Monorepo](https://github.com/ethereum-optimism/optimism/blob/d69cb12f6dcbe3d5355beca8997fbac611b7fe37/specs/README.md).
## Components ## Components
- [`op-node`](https://github.com/ethereum-optimism/optimism/tree/develop/op-node) - [`op-node`](https://github.com/ethereum-optimism/optimism/tree/d69cb12f6dcbe3d5355beca8997fbac611b7fe37/op-node)
- [`op-geth`](https://github.com/ethereum-optimism/op-geth) - [`op-geth`](https://github.com/ethereum-optimism/op-geth)
- [`op-batcher`](https://github.com/ethereum-optimism/optimism/tree/develop/op-batcher) - [`op-batcher`](https://github.com/ethereum-optimism/optimism/tree/d69cb12f6dcbe3d5355beca8997fbac611b7fe37/op-batcher)
- [`op-proposer`](https://github.com/ethereum-optimism/optimism/tree/develop/op-proposer) - [`op-proposer`](https://github.com/ethereum-optimism/optimism/tree/d69cb12f6dcbe3d5355beca8997fbac611b7fe37/op-proposer)
- [`contracts-bedrock`](https://github.com/ethereum-optimism/optimism/tree/develop/packages/contracts-bedrock) - [`contracts-bedrock`](https://github.com/ethereum-optimism/optimism/tree/d69cb12f6dcbe3d5355beca8997fbac611b7fe37/packages/contracts-bedrock)
- [`fault-detector`](https://github.com/ethereum-optimism/optimism/tree/develop/packages/fault-detector) - [`fault-detector`](https://github.com/ethereum-optimism/optimism/tree/d69cb12f6dcbe3d5355beca8997fbac611b7fe37/packages/fault-detector)
- [`sdk`](https://github.com/ethereum-optimism/optimism/tree/develop/packages/sdk) - [`sdk`](https://github.com/ethereum-optimism/optimism/tree/d69cb12f6dcbe3d5355beca8997fbac611b7fe37/packages/sdk)
- [`chain-mon`](https://github.com/ethereum-optimism/optimism/tree/develop/packages/chain-mon) - [`chain-mon`](https://github.com/ethereum-optimism/optimism/tree/d69cb12f6dcbe3d5355beca8997fbac611b7fe37/packages/chain-mon)
\ No newline at end of file
...@@ -31,7 +31,7 @@ However, there could be edge cases we did not think about where this matters. ...@@ -31,7 +31,7 @@ However, there could be edge cases we did not think about where this matters.
### Accessing L1 information ### Accessing L1 information
If you need the equivalent information from the latest L1 block, you can get it from [the `L1Block` contract](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/contracts/L2/L1Block.sol). If you need the equivalent information from the latest L1 block, you can get it from [the `L1Block` contract](https://github.com/ethereum-optimism/optimism/blob/129032f15b76b0d2a940443a39433de931a97a44/packages/contracts-bedrock/contracts/L2/L1Block.sol).
This contract is a predeploy at address [`0x4200000000000000000000000000000000000015`](https://goerli-optimism.etherscan.io/address/0x4200000000000000000000000000000000000015). This contract is a predeploy at address [`0x4200000000000000000000000000000000000015`](https://goerli-optimism.etherscan.io/address/0x4200000000000000000000000000000000000015).
You can use [the getter functions](https://docs.soliditylang.org/en/v0.8.12/contracts.html#getter-functions) to get these parameters: You can use [the getter functions](https://docs.soliditylang.org/en/v0.8.12/contracts.html#getter-functions) to get these parameters:
...@@ -117,7 +117,7 @@ There are several differences in the way blocks are produced between L1 Ethereum ...@@ -117,7 +117,7 @@ There are several differences in the way blocks are produced between L1 Ethereum
(1) This is the ideal. (1) This is the ideal.
If any blocks are missed it could be an integer multiple such as 24 seconds, 36 seconds, etc. If any blocks are missed it could be an integer multiple such as 24 seconds, 36 seconds, etc.
**Note:** The L1 Ethereum parameter values are taken from [ethereum.org](https://ethereum.org/en/developers/docs/blocks/#block-time). The Optimism Bedrock values are taken from [the Optimism specs](https://github.com/ethereum-optimism/optimism/blob/develop/specs/guaranteed-gas-market.md#limiting-guaranteed-gas). **Note:** The L1 Ethereum parameter values are taken from [ethereum.org](https://ethereum.org/en/developers/docs/blocks/#block-time). The Optimism Bedrock values are taken from [the Optimism specs](https://github.com/ethereum-optimism/optimism/blob/129032f15b76b0d2a940443a39433de931a97a44/specs/guaranteed-gas-market.md#limiting-guaranteed-gas).
......
...@@ -108,7 +108,7 @@ A **deposited transaction** is the transaction on the rollup that is made as a p ...@@ -108,7 +108,7 @@ A **deposited transaction** is the transaction on the rollup that is made as a p
Bedrock defines a **deposit contract** that is available on the L1: it is a smart contract that L1 accounts and contracts can interact with to write to the L2. [Deposited transactions](#arbitrary-message-passing-from-l1) on the L2 are derived from the values in the event(s) emitted by this [deposit](#deposits) contract, which include expected parameters such as from, to, and data. Bedrock defines a **deposit contract** that is available on the L1: it is a smart contract that L1 accounts and contracts can interact with to write to the L2. [Deposited transactions](#arbitrary-message-passing-from-l1) on the L2 are derived from the values in the event(s) emitted by this [deposit](#deposits) contract, which include expected parameters such as from, to, and data.
For full details, see the [deposit contract](https://github.com/ethereum-optimism/optimism/blob/develop/specs/deposits.md#deposit-contract) section of the protocol specifications. For full details, see the [deposit contract](https://github.com/ethereum-optimism/optimism/blob/d69cb12f6dcbe3d5355beca8997fbac611b7fe37/specs/deposits.md#deposit-contract) section of the protocol specifications.
#### Purchasing guaranteed L2 gas on L1 #### Purchasing guaranteed L2 gas on L1
...@@ -116,19 +116,19 @@ Bedrock also specifies a gas burn mechanism and a fee market for [deposits](#dep ...@@ -116,19 +116,19 @@ Bedrock also specifies a gas burn mechanism and a fee market for [deposits](#dep
The gas provided to [deposited transactions](#arbitrary-message-passing-from-l1) is sometimes called "guaranteed gas." Guaranteed gas is unique in that it is paid for by burning gas on L1 and is therefore not refundable.The total amount of L1 gas that must be burned per unit of guaranteed L2 gas requested depends on the price of L2 gas reported by a EIP-1559 style fee mechanism. Furthermore, users receive a dynamic gas stipend based on the amount of L1 gas spent to compute updates to the fee mechanism. The gas provided to [deposited transactions](#arbitrary-message-passing-from-l1) is sometimes called "guaranteed gas." Guaranteed gas is unique in that it is paid for by burning gas on L1 and is therefore not refundable.The total amount of L1 gas that must be burned per unit of guaranteed L2 gas requested depends on the price of L2 gas reported by a EIP-1559 style fee mechanism. Furthermore, users receive a dynamic gas stipend based on the amount of L1 gas spent to compute updates to the fee mechanism.
For a deeper explanation, read the [deposits section](https://github.com/ethereum-optimism/optimism/blob/develop/specs/deposits.md#deposits) of the protocol specifications. For a deeper explanation, read the [deposits section](https://github.com/ethereum-optimism/optimism/blob/d69cb12f6dcbe3d5355beca8997fbac611b7fe37/specs/deposits.md#deposits) of the protocol specifications.
### Withdrawals ### Withdrawals
**Withdrawals** are cross-domain transactions that are initiated on L2 and finalized by a transaction executed on L1. Notably, withdrawals may be used by an L2 account to call an L1 contract, or to transfer ETH from an L2 account to an L1 account. **Withdrawals** are cross-domain transactions that are initiated on L2 and finalized by a transaction executed on L1. Notably, withdrawals may be used by an L2 account to call an L1 contract, or to transfer ETH from an L2 account to an L1 account.
Withdrawals are initiated on L2 via a call to the **Message Passer** predeploy contract, which records the important properties of the message in its storage. Withdrawals are finalized on L1 via a call to the [OptimismPortal](https://github.com/ethereum-optimism/optimism/blob/develop/specs/withdrawals.md#the-optimism-portal-contract) contract, which proves the inclusion of this withdrawal message. In this way, withdrawals are different from [deposits](#deposits). Instead of relying on [block derivation](#block-derivation), withdrawal transactions must use smart contracts on L1 for finalization. Withdrawals are initiated on L2 via a call to the **Message Passer** predeploy contract, which records the important properties of the message in its storage. Withdrawals are finalized on L1 via a call to the [OptimismPortal](https://github.com/ethereum-optimism/optimism/blob/d69cb12f6dcbe3d5355beca8997fbac611b7fe37/specs/withdrawals.md#the-optimism-portal-contract) contract, which proves the inclusion of this withdrawal message. In this way, withdrawals are different from [deposits](#deposits). Instead of relying on [block derivation](#block-derivation), withdrawal transactions must use smart contracts on L1 for finalization.
#### Two-step withdrawals #### Two-step withdrawals
Withdrawal proof validation bugs have been the root cause of many of the biggest bridge hacks of the last few years. The Bedrock release introduces an additional step in the withdrawals’ process of prior versions meant to provide an extra layer of defense against these types of bugs. In the two-step withdrawal process, a Merkle proof corresponding to the withdrawal must be submitted 7 days before the withdrawal can be finalized.. This new safety mechanism gives monitoring tools a full 7 days to find and detect invalid withdrawal proofs . If the [withdrawal](#withdrawals) proof is found to be invalid, a contract fix can be deployed before funds are lost. This dramatically reduces the risk of a bridge compromise. Withdrawal proof validation bugs have been the root cause of many of the biggest bridge hacks of the last few years. The Bedrock release introduces an additional step in the withdrawals’ process of prior versions meant to provide an extra layer of defense against these types of bugs. In the two-step withdrawal process, a Merkle proof corresponding to the withdrawal must be submitted 7 days before the withdrawal can be finalized.. This new safety mechanism gives monitoring tools a full 7 days to find and detect invalid withdrawal proofs . If the [withdrawal](#withdrawals) proof is found to be invalid, a contract fix can be deployed before funds are lost. This dramatically reduces the risk of a bridge compromise.
For full details, see the [withdrawals](https://github.com/ethereum-optimism/optimism/blob/develop/specs/withdrawals.md) section of the protocol specification. For full details, see the [withdrawals](https://github.com/ethereum-optimism/optimism/blob/d69cb12f6dcbe3d5355beca8997fbac611b7fe37/specs/withdrawals.md) section of the protocol specification.
### Batches ### Batches
...@@ -136,7 +136,7 @@ In Bedrock, a wire format is defined for messaging between the L1 and L2 (i.e., ...@@ -136,7 +136,7 @@ In Bedrock, a wire format is defined for messaging between the L1 and L2 (i.e.,
#### Optimized data compression #### Optimized data compression
To optimize data compression, lists of L2 transactions called **sequencer batches** are organized into groups of objects called **channels**, each of which have a maximum size that is defined in a [configurable parameter](https://github.com/ethereum-optimism/optimism/blob/develop/specs/derivation.md#channel-format) that will initially be set to ~9.5Mb. These [channels](#optimized-data-compression) are expected to be compressed using a compression function and submitted to the L1. To optimize data compression, lists of L2 transactions called **sequencer batches** are organized into groups of objects called **channels**, each of which have a maximum size that is defined in a [configurable parameter](https://github.com/ethereum-optimism/optimism/blob/d69cb12f6dcbe3d5355beca8997fbac611b7fe37/specs/derivation.md#channel-format) that will initially be set to ~9.5Mb. These [channels](#optimized-data-compression) are expected to be compressed using a compression function and submitted to the L1.
#### Parallelized batch submission #### Parallelized batch submission
...@@ -150,7 +150,7 @@ Batches are still subject to validity checks (i.e. they have to be encoded corre ...@@ -150,7 +150,7 @@ Batches are still subject to validity checks (i.e. they have to be encoded corre
> Note: Ethereum will soon upgrade to include [EIP-4844](https://eip4844.com/), which introduces a separate fee market for writing data and an increased cap of the amount of data the Ethereum protocol is willing to store. This change is expected to further decrease the costs associated with posting data to an L1. > Note: Ethereum will soon upgrade to include [EIP-4844](https://eip4844.com/), which introduces a separate fee market for writing data and an increased cap of the amount of data the Ethereum protocol is willing to store. This change is expected to further decrease the costs associated with posting data to an L1.
For a deeper explanation, read [the wire format specifications](https://github.com/ethereum-optimism/optimism/blob/develop/specs/derivation.md#overview). For a deeper explanation, read [the wire format specifications](https://github.com/ethereum-optimism/optimism/blob/d69cb12f6dcbe3d5355beca8997fbac611b7fe37/specs/derivation.md#overview).
### Block Derivation ### Block Derivation
...@@ -189,8 +189,8 @@ The [canonical L2 chain](#protocol) can be processed from scratch by starting wi ...@@ -189,8 +189,8 @@ The [canonical L2 chain](#protocol) can be processed from scratch by starting wi
| Read from L1 | Epochs are defined by L1 blocks. Contained within an L2 block is data pertaining to [batcher transactions](#minimized-usage-of-ethereum-gas) or [deposits](#deposits) which must be included in the [canonical L2 chain](#protocol) | | Read from L1 | Epochs are defined by L1 blocks. Contained within an L2 block is data pertaining to [batcher transactions](#minimized-usage-of-ethereum-gas) or [deposits](#deposits) which must be included in the [canonical L2 chain](#protocol) |
| Buffer and decode into [channels](#optimized-data-compression) | The data from L1 blocks contains unordered [channel frames](#parallelized-batch-submission), which must all be collected before reconstructing them into channels. | | Buffer and decode into [channels](#optimized-data-compression) | The data from L1 blocks contains unordered [channel frames](#parallelized-batch-submission), which must all be collected before reconstructing them into channels. |
| Decompress [channels](#optimized-data-compression) into [batches](#optimized-data-compression) | Since [channels](#optimized-data-compression) are [compressed](#optimized-data-compression) to minimize data fee costs on the L1, they must be decompressed. | | Decompress [channels](#optimized-data-compression) into [batches](#optimized-data-compression) | Since [channels](#optimized-data-compression) are [compressed](#optimized-data-compression) to minimize data fee costs on the L1, they must be decompressed. |
| Queue [batches](#optimized-data-compression) into sequential order | With the latest information from L1, [batches](#optimized-data-compression) can be validated and processed sequentially. There are some nuances to what the correct ordering is in relation to [epochs](#guaranteed-inclusion-of-deposits) and timestamps from L2, see the full specification [here](https://github.com/ethereum-optimism/optimism/blob/develop/specs/derivation.md#batch-queue). | | Queue [batches](#optimized-data-compression) into sequential order | With the latest information from L1, [batches](#optimized-data-compression) can be validated and processed sequentially. There are some nuances to what the correct ordering is in relation to [epochs](#guaranteed-inclusion-of-deposits) and timestamps from L2, see the full specification [here](https://github.com/ethereum-optimism/optimism/blob/d69cb12f6dcbe3d5355beca8997fbac611b7fe37/specs/derivation.md#batch-queue). |
| Interpret as L2 blocks | At this point, the correct ordering of [batches](#optimized-data-compression) can be determined.<br><br>Following this, the [execution client](#execution-client) can interpret them into L2 blocks. For implementation details pertaining to [execution clients](#execution-client), see the [engine queue](https://github.com/ethereum-optimism/optimism/blob/develop/specs/derivation.md#engine-queue) section of the protocol specifications. | | Interpret as L2 blocks | At this point, the correct ordering of [batches](#optimized-data-compression) can be determined.<br><br>Following this, the [execution client](#execution-client) can interpret them into L2 blocks. For implementation details pertaining to [execution clients](#execution-client), see the [engine queue](https://github.com/ethereum-optimism/optimism/blob/d69cb12f6dcbe3d5355beca8997fbac611b7fe37/specs/derivation.md#engine-queue) section of the protocol specifications. |
### Fault Proofs ### Fault Proofs
...@@ -200,7 +200,7 @@ In Bedrock, outputs are hashed in a tree-structured form which minimizes the cos ...@@ -200,7 +200,7 @@ In Bedrock, outputs are hashed in a tree-structured form which minimizes the cos
Future upgrades of the OP Stack codebase should include a specification for a variation of a fault proof with bonding included to create incentives for proposers to propose correct output roots. Future upgrades of the OP Stack codebase should include a specification for a variation of a fault proof with bonding included to create incentives for proposers to propose correct output roots.
For full details, read the [L2 Output Root Proposals section](https://github.com/ethereum-optimism/optimism/blob/develop/specs/proposals.md#l2-output-root-proposals-specification) of the protocol specifications. For full details, read the [L2 Output Root Proposals section](https://github.com/ethereum-optimism/optimism/blob/d69cb12f6dcbe3d5355beca8997fbac611b7fe37/specs/proposals.md#l2-output-root-proposals-specification) of the protocol specifications.
## Implementation ## Implementation
...@@ -216,7 +216,7 @@ There are two fundamental reasons for having any diff at all: handling deposited ...@@ -216,7 +216,7 @@ There are two fundamental reasons for having any diff at all: handling deposited
#### Handling deposited transactions #### Handling deposited transactions
To represent [deposited transactions](#arbitrary-message-passing-from-l1) in the rollup, there is an additional transaction type introduced. The [execution client](#execution-client) implements this [new transaction type](https://github.com/ethereum-optimism/optimism/blob/develop/specs/%5Bdeposits%5D(#deposits).md%23the-deposited-transaction-type) according to the [EIP-2718 typed transactions](https://eips.ethereum.org/EIPS/eip-2718) standard. To represent [deposited transactions](#arbitrary-message-passing-from-l1) in the rollup, there is an additional transaction type introduced. The [execution client](#execution-client) implements this [new transaction type](https://github.com/ethereum-optimism/optimism/blob/7f5b9ea7bf6dce12dbf709c27c25ee1681df7f7e/specs/deposits.md#the-deposited-transaction-type) according to the [EIP-2718 typed transactions](https://eips.ethereum.org/EIPS/eip-2718) standard.
#### Charging transaction fees #### Charging transaction fees
...@@ -230,7 +230,7 @@ The cost of operating a sequencer is computed using the same gas table as Ethere ...@@ -230,7 +230,7 @@ The cost of operating a sequencer is computed using the same gas table as Ethere
Data availability costs are associated with writing [batcher transactions](#minimized-usage-of-ethereum-gas) to the L1. These fees are intended to cover the cost that sequencers need to pay to submit [batcher transactions](#minimized-usage-of-ethereum-gas) to the L1. Data availability costs are associated with writing [batcher transactions](#minimized-usage-of-ethereum-gas) to the L1. These fees are intended to cover the cost that sequencers need to pay to submit [batcher transactions](#minimized-usage-of-ethereum-gas) to the L1.
In Bedrock, the data availability portion of the fee is determined based on information in a system contract on the rollup called a [GasPriceOracle](https://github.com/ethereum-optimism/optimism/blob/develop/specs/predeploys.md#gaspriceoracle). This contract is updated during [block derivation](#block-derivation) from the gas pricing information retrieved from the L1 block attributes that get inserted at the beginning of every [epoch](#guaranteed-inclusion-of-deposits). In Bedrock, the data availability portion of the fee is determined based on information in a system contract on the rollup called a [GasPriceOracle](https://github.com/ethereum-optimism/optimism/blob/d69cb12f6dcbe3d5355beca8997fbac611b7fe37/specs/predeploys.md#gaspriceoracle). This contract is updated during [block derivation](#block-derivation) from the gas pricing information retrieved from the L1 block attributes that get inserted at the beginning of every [epoch](#guaranteed-inclusion-of-deposits).
Bedrock specifies that both of these fees are added up into a single `gasPrice` field when using the JSON-RPC. Bedrock specifies that both of these fees are added up into a single `gasPrice` field when using the JSON-RPC.
...@@ -246,7 +246,7 @@ The multiple uses of a rollup node are outlined below. ...@@ -246,7 +246,7 @@ The multiple uses of a rollup node are outlined below.
The simplest mode of running a [rollup node](#rollup-node) is to only follow the [canonical L2 chain](#protocol). In this mode, the [rollup node](#rollup-node) has no peers and is strictly used to read data from the L1 and to interpret it according to [block derivation](#block-derivation) protocol rules. The simplest mode of running a [rollup node](#rollup-node) is to only follow the [canonical L2 chain](#protocol). In this mode, the [rollup node](#rollup-node) has no peers and is strictly used to read data from the L1 and to interpret it according to [block derivation](#block-derivation) protocol rules.
One purpose of this kind of node is to verify that any output roots shared by other nodes or posted on the L1 are correct according to protocol definition. Additionally, proposers intending to submit output roots to the L1 themselves can generate the output roots they need using the [optimism_outputAtBlock](https://github.com/ethereum-optimism/optimism/blob/develop/specs/rollup-node.md#l2-output-rpc-method) of the node which returns a 32-byte hash corresponding to the L2 output root. One purpose of this kind of node is to verify that any output roots shared by other nodes or posted on the L1 are correct according to protocol definition. Additionally, proposers intending to submit output roots to the L1 themselves can generate the output roots they need using the [optimism_outputAtBlock](https://github.com/ethereum-optimism/optimism/blob/d69cb12f6dcbe3d5355beca8997fbac611b7fe37/specs/rollup-node.md#l2-output-rpc-method) of the node which returns a 32-byte hash corresponding to the L2 output root.
For this purpose, nodes should only need to follow the finalized head. The term ["finalized"](https://ethereum.org/en/developers/docs/consensus-mechanisms/pos/#finality) refers to the Ethereum proof-of-stake consensus (i.e. canonical and practically irreversible) — the finalized L2 head is the head of the [canonical L2 chain](#protocol) that is derived only from finalized L1 blocks. For this purpose, nodes should only need to follow the finalized head. The term ["finalized"](https://ethereum.org/en/developers/docs/consensus-mechanisms/pos/#finality) refers to the Ethereum proof-of-stake consensus (i.e. canonical and practically irreversible) — the finalized L2 head is the head of the [canonical L2 chain](#protocol) that is derived only from finalized L1 blocks.
...@@ -257,7 +257,7 @@ The most common way to use a [rollup node](#rollup-node) is to participate in a ...@@ -257,7 +257,7 @@ The most common way to use a [rollup node](#rollup-node) is to participate in a
Nodes participating in the network may make use of the safe and unsafe heads of the L2 they're syncing. Nodes participating in the network may make use of the safe and unsafe heads of the L2 they're syncing.
- The **safe L2 head** represents the rollup that can be constructed where every block up to and including the head can be fully derived from the reference L1 chain, before L1 has necessarily finalized (i.e., a re-org may occur on L1 still). - The **safe L2 head** represents the rollup that can be constructed where every block up to and including the head can be fully derived from the reference L1 chain, before L1 has necessarily finalized (i.e., a re-org may occur on L1 still).
- The **unsafe L2 head** includes [unsafe blocks](https://github.com/ethereum-optimism/optimism/blob/develop/specs/glossary.md#unsafe-l2-block) that have not yet been derived from L1. These blocks either come from operating the [rollup node](#rollup-node) as a sequencer or from [unsafe sync](https://github.com/ethereum-optimism/optimism/blob/develop/specs/glossary.md#unsafe-sync) with the sequencer. This is also known as the "latest" head. The safe L2 head is always chosen over the unsafe L2 head in cases of disagreements. When disagreements occur, the unsafe portion of the chain will reorg. - The **unsafe L2 head** includes [unsafe blocks](https://github.com/ethereum-optimism/optimism/blob/d69cb12f6dcbe3d5355beca8997fbac611b7fe37/specs/glossary.md#unsafe-l2-block) that have not yet been derived from L1. These blocks either come from operating the [rollup node](#rollup-node) as a sequencer or from [unsafe sync](https://github.com/ethereum-optimism/optimism/blob/d69cb12f6dcbe3d5355beca8997fbac611b7fe37/specs/glossary.md#unsafe-sync) with the sequencer. This is also known as the "latest" head. The safe L2 head is always chosen over the unsafe L2 head in cases of disagreements. When disagreements occur, the unsafe portion of the chain will reorg.
For most purposes, nodes in the L2 network will refer to the unsafe L2 head for end-user applications. For most purposes, nodes in the L2 network will refer to the unsafe L2 head for end-user applications.
...@@ -269,15 +269,15 @@ The sequencer is also responsible for posting batches to L1 for other nodes in t ...@@ -269,15 +269,15 @@ The sequencer is also responsible for posting batches to L1 for other nodes in t
### Batcher ### Batcher
The role of a sequencer is to produce [batches](#batches). To do this, a sequencer can run [rollup nodes](#rollup-node) and have separate processes which perform [batching](#batches) by reading from a trusted [rollup node](#rollup-node) they run. This warrants an additional component of the OP Stack called a [batcher](https://github.com/ethereum-optimism/optimism/blob/develop/specs/glossary.md#batcher) that reads transaction data from a [rollup node](#rollup-node) and interprets it into [batcher transactions](#minimized-usage-of-ethereum-gas) to be written to the L1. The batcher component is responsible for reading the unsafe L2 head of a [rollup node](#rollup-node) run by a sequencer, creating batcher transactions, and writing them to the L1. The role of a sequencer is to produce [batches](#batches). To do this, a sequencer can run [rollup nodes](#rollup-node) and have separate processes which perform [batching](#batches) by reading from a trusted [rollup node](#rollup-node) they run. This warrants an additional component of the OP Stack called a [batcher](https://github.com/ethereum-optimism/optimism/blob/d69cb12f6dcbe3d5355beca8997fbac611b7fe37/specs/glossary.md#batcher) that reads transaction data from a [rollup node](#rollup-node) and interprets it into [batcher transactions](#minimized-usage-of-ethereum-gas) to be written to the L1. The batcher component is responsible for reading the unsafe L2 head of a [rollup node](#rollup-node) run by a sequencer, creating batcher transactions, and writing them to the L1.
### Standard Bridge Contracts ### Standard Bridge Contracts
Bedrock also includes a pair of bridge contracts used for the most common kinds of [deposits](#deposits) called the [standard bridges](https://github.com/ethereum-optimism/optimism/blob/develop/specs/bridges.md#standard-bridges). These contracts wrap the [deposit](#deposits) and [withdrawal](#withdrawals) contracts to provide simple interfaces for [depositing](#deposits) and [withdrawing](#withdrawals) ETH and ERC-20 tokens. Bedrock also includes a pair of bridge contracts used for the most common kinds of [deposits](#deposits) called the [standard bridges](https://github.com/ethereum-optimism/optimism/blob/d69cb12f6dcbe3d5355beca8997fbac611b7fe37/specs/bridges.md#standard-bridges). These contracts wrap the [deposit](#deposits) and [withdrawal](#withdrawals) contracts to provide simple interfaces for [depositing](#deposits) and [withdrawing](#withdrawals) ETH and ERC-20 tokens.
These bridges are designed to involve a native token on one side of the bridge, and a wrapped token on the other side that can manage minting and burning. Bridging a native token involves locking the native token in a contract and then minting an equivalent amount of mintable token on the other side of the bridge. These bridges are designed to involve a native token on one side of the bridge, and a wrapped token on the other side that can manage minting and burning. Bridging a native token involves locking the native token in a contract and then minting an equivalent amount of mintable token on the other side of the bridge.
For full details, see the [standard bridge](https://github.com/ethereum-optimism/optimism/blob/develop/specs/bridges.md#standard-bridges) section of the protocol specifications. For full details, see the [standard bridge](https://github.com/ethereum-optimism/optimism/blob/d69cb12f6dcbe3d5355beca8997fbac611b7fe37/specs/bridges.md#standard-bridges) section of the protocol specifications.
### Cannon ### Cannon
...@@ -287,7 +287,7 @@ Although fault proof construction and verification is implemented in the [Cannon ...@@ -287,7 +287,7 @@ Although fault proof construction and verification is implemented in the [Cannon
### Protocol Specification ### Protocol Specification
The protocol specification defines the technical details of the OP Stack codebase. It is the most up-to-date source of truth for the inner workings of the protocol. The protocol specification is located in the ethereum-optimism [monorepo](https://github.com/ethereum-optimism/optimism/blob/develop/specs/README.md). The protocol specification defines the technical details of the OP Stack codebase. It is the most up-to-date source of truth for the inner workings of the protocol. The protocol specification is located in the ethereum-optimism [monorepo](https://github.com/ethereum-optimism/optimism/blob/d69cb12f6dcbe3d5355beca8997fbac611b7fe37/specs/README.md).
### Bedrock Differences ### Bedrock Differences
......
...@@ -19,7 +19,7 @@ The OP Stack is a decentralized development stack that powers Optimism. Componen ...@@ -19,7 +19,7 @@ The OP Stack is a decentralized development stack that powers Optimism. Componen
The security model of an OP Stack based blockchain depends on the modules used for its components. Because of the flexibility provided by OP Stack, it is always possible to set up an insecure blockchain using OP Stack components. **The goal of the OP Stack is to provide safe defaults.** The security model of an OP Stack based blockchain depends on the modules used for its components. Because of the flexibility provided by OP Stack, it is always possible to set up an insecure blockchain using OP Stack components. **The goal of the OP Stack is to provide safe defaults.**
Please also keep in mind that just like any other system, **the OP Stack may contain unknown bugs** that could lead to the loss of some or all of the assets held within an OP Stack based system. [Many components of the OP Stack codebase have been audited](https://github.com/ethereum-optimism/optimism/tree/develop/technical-documents/security-reviews) but **audits are not a stamp of approval** and **a completed audit does not mean that the audited codebase is free of bugs.** It’s important to understand that using the OP Stack inherently exposes you to the risk of bugs within the OP Stack codebase. Please also keep in mind that just like any other system, **the OP Stack may contain unknown bugs** that could lead to the loss of some or all of the assets held within an OP Stack based system. [Many components of the OP Stack codebase have been audited](https://github.com/ethereum-optimism/optimism/tree/129032f15b76b0d2a940443a39433de931a97a44/technical-documents/security-reviews) but **audits are not a stamp of approval** and **a completed audit does not mean that the audited codebase is free of bugs.** It’s important to understand that using the OP Stack inherently exposes you to the risk of bugs within the OP Stack codebase.
### Is the OP Stack safe to modify? ### Is the OP Stack safe to modify?
......
...@@ -60,7 +60,7 @@ The easiest way to withdraw ETH is to send it to the bridge, or the cross domain ...@@ -60,7 +60,7 @@ The easiest way to withdraw ETH is to send it to the bridge, or the cross domain
transferAmt = BigInt(0.01 * 1e18) transferAmt = BigInt(0.01 * 1e18)
``` ```
1. Create a contract object for the [`OptimismPortal`](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/contracts/L1/OptimismPortal.sol) contract. 1. Create a contract object for the [`OptimismPortal`](https://github.com/ethereum-optimism/optimism/blob/129032f15b76b0d2a940443a39433de931a97a44/packages/contracts-bedrock/contracts/L1/OptimismPortal.sol) contract.
```js ```js
optimismContracts = require("@eth-optimism/contracts-bedrock") optimismContracts = require("@eth-optimism/contracts-bedrock")
......
...@@ -13,8 +13,8 @@ An OP Stack chain does not have to specify a usable `GUARDIAN` address if it doe ...@@ -13,8 +13,8 @@ An OP Stack chain does not have to specify a usable `GUARDIAN` address if it doe
## Who can do it? ## Who can do it?
[`OptimismPortal`](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/contracts/L1/OptimismPortal.sol) has an immutable `GUARDIAN`. [`OptimismPortal`](https://github.com/ethereum-optimism/optimism/blob/129032f15b76b0d2a940443a39433de931a97a44/packages/contracts-bedrock/contracts/L1/OptimismPortal.sol) has an immutable `GUARDIAN`.
That address can call [`pause`](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/contracts/L1/OptimismPortal.sol#L166-L170) and [`unpause`](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/contracts/L1/OptimismPortal.sol#L175-L179). That address can call [`pause`](https://github.com/ethereum-optimism/optimism/blob/129032f15b76b0d2a940443a39433de931a97a44/packages/contracts-bedrock/contracts/L1/OptimismPortal.sol#L171-L178) and [`unpause`](https://github.com/ethereum-optimism/optimism/blob/129032f15b76b0d2a940443a39433de931a97a44/packages/contracts-bedrock/contracts/L1/OptimismPortal.sol#L180-L187).
### Changing the guardian ### Changing the guardian
...@@ -23,7 +23,7 @@ The guardian created by the setup script is the admin account. ...@@ -23,7 +23,7 @@ The guardian created by the setup script is the admin account.
This is sufficient for testing, but for a production system you would want the guardian to be a multisig with trusted security council. This is sufficient for testing, but for a production system you would want the guardian to be a multisig with trusted security council.
The `GUARDIAN` variable is immutable, but the `OptimismPortal` contract sits behind a proxy, so the `GUARDIAN` can be modified by changing the `OptimismPortal` proxy to point to a new implementation contract. The `GUARDIAN` variable is immutable, but the `OptimismPortal` contract sits behind a proxy, so the `GUARDIAN` can be modified by changing the `OptimismPortal` proxy to point to a new implementation contract.
You do this using the L1 [`ProxyAdmin`](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/contracts/universal/ProxyAdmin.sol) contract. You do this using the L1 [`ProxyAdmin`](https://github.com/ethereum-optimism/optimism/blob/129032f15b76b0d2a940443a39433de931a97a44/packages/contracts-bedrock/contracts/universal/ProxyAdmin.sol) contract.
<!-- <!--
## Seeing it in action ## Seeing it in action
......
...@@ -35,8 +35,8 @@ The Data Availability Layer defines where the raw inputs to an OP Stack based ch ...@@ -35,8 +35,8 @@ The Data Availability Layer defines where the raw inputs to an OP Stack based ch
Ethereum DA is currently the most widely used Data Availability module for the OP Stack. When using the Ethereum DA module, source data can be derived from any piece of information accessible on the Ethereum blockchain. This includes Ethereum calldata, events, and 4844 data blobs. Ethereum DA is currently the most widely used Data Availability module for the OP Stack. When using the Ethereum DA module, source data can be derived from any piece of information accessible on the Ethereum blockchain. This includes Ethereum calldata, events, and 4844 data blobs.
- [Specifications](https://github.com/ethereum-optimism/optimism/blob/develop/specs/derivation.md#batch-submission-wire-format) - [Specifications](https://github.com/ethereum-optimism/optimism/blob/129032f15b76b0d2a940443a39433de931a97a44/specs/derivation.md#batch-submission-wire-format)
- [Source code](https://github.com/ethereum-optimism/optimism/tree/develop/op-batcher) - [Source code](https://github.com/ethereum-optimism/optimism/tree/129032f15b76b0d2a940443a39433de931a97a44/op-batcher)
### Sequencing ### Sequencing
...@@ -58,8 +58,8 @@ The Derivation Layer defines how the raw data in the Data Availability Layer is ...@@ -58,8 +58,8 @@ The Derivation Layer defines how the raw data in the Data Availability Layer is
The Rollup module derives Engine API inputs from Ethereum block data, Sequencer transaction batches, Deposited transaction events, and more. The Rollup module derives Engine API inputs from Ethereum block data, Sequencer transaction batches, Deposited transaction events, and more.
- [Specifications](https://github.com/ethereum-optimism/optimism/blob/develop/specs/derivation.md#l2-chain-derivation-pipeline) - [Specifications](https://github.com/ethereum-optimism/optimism/blob/129032f15b76b0d2a940443a39433de931a97a44/specs/derivation.md#l2-chain-derivation-pipeline)
- [Source code](https://github.com/ethereum-optimism/optimism/tree/develop/op-node) - [Source code](https://github.com/ethereum-optimism/optimism/tree/129032f15b76b0d2a940443a39433de931a97a44/op-node)
#### Indexer (proposed) #### Indexer (proposed)
...@@ -73,8 +73,8 @@ The Execution Layer defines the structure of state within an OP Stack system and ...@@ -73,8 +73,8 @@ The Execution Layer defines the structure of state within an OP Stack system and
The EVM is an Execution Layer module that uses the same state representation and state transition function as the Ethereum Virtual Machine. The EVM module in the Ethereum Rollup configuration of the OP Stack is a [lightly modified](https://op-geth.optimism.io/) version of the EVM that adds support for L2 transactions initiated on Ethereum and adds an extra L1 Data Fee to each transaction to account for the cost of publishing transactions to Ethereum. The EVM is an Execution Layer module that uses the same state representation and state transition function as the Ethereum Virtual Machine. The EVM module in the Ethereum Rollup configuration of the OP Stack is a [lightly modified](https://op-geth.optimism.io/) version of the EVM that adds support for L2 transactions initiated on Ethereum and adds an extra L1 Data Fee to each transaction to account for the cost of publishing transactions to Ethereum.
- [Specifications](https://github.com/ethereum-optimism/optimism/blob/develop/specs/exec-engine.md) (where it differs from [geth](https://geth.ethereum.org/)) - [Specifications](https://github.com/ethereum-optimism/optimism/blob/129032f15b76b0d2a940443a39433de931a97a44/specs/exec-engine.md) (where it differs from [geth](https://geth.ethereum.org/))
- [Source code](https://github.com/ethereum-optimism/op-geth) - [Source code](https://github.com/ethereum-optimism/op-geth/tree/09ade3df6d1d3a4f8f308553825348be132bc960)
### Settlement Layer ### Settlement Layer
...@@ -89,8 +89,8 @@ Once a transaction is published and finalized on the corresponding Data Availabi ...@@ -89,8 +89,8 @@ Once a transaction is published and finalized on the corresponding Data Availabi
An Attestation-based Fault Proof mechanism uses an optimistic protocol to establish a view of an OP Stack chain. In optimistic settlement mechanisms generally, **Proposer** entities can propose what they believe to be the current valid state of the OP Stack chain. If these proposals are not invalidated within a certain period of time (the “challenge period”), then the proposals are assumed by the mechanism to be correct. In the Attestation Proof mechanism in particular, a proposal can be invalidated if some threshold of pre-defined parties provide attestations to a valid state that is different than the state in the proposal. This places a trust assumption on the honesty of at least a threshold number of the pre-defined participants. An Attestation-based Fault Proof mechanism uses an optimistic protocol to establish a view of an OP Stack chain. In optimistic settlement mechanisms generally, **Proposer** entities can propose what they believe to be the current valid state of the OP Stack chain. If these proposals are not invalidated within a certain period of time (the “challenge period”), then the proposals are assumed by the mechanism to be correct. In the Attestation Proof mechanism in particular, a proposal can be invalidated if some threshold of pre-defined parties provide attestations to a valid state that is different than the state in the proposal. This places a trust assumption on the honesty of at least a threshold number of the pre-defined participants.
- [Specifications](https://github.com/ethereum-optimism/optimism/blob/develop/specs/withdrawals.md) (called [withdrawal transactions](https://community.optimism.io/docs/developers/bridge/messaging/#)) - [Specifications](https://github.com/ethereum-optimism/optimism/blob/129032f15b76b0d2a940443a39433de931a97a44/specs/withdrawals.md) (called [withdrawal transactions](https://community.optimism.io/docs/developers/bridge/messaging/#))
- [Source code](https://github.com/ethereum-optimism/optimism/tree/develop/packages/contracts-bedrock/contracts) - [Source code](https://github.com/ethereum-optimism/optimism/tree/129032f15b76b0d2a940443a39433de931a97a44/packages/contracts-bedrock/contracts)
#### Fault Proof Optimistic Settlement (proposed) #### Fault Proof Optimistic Settlement (proposed)
......
# @eth-optimism/endpoint-monitor # @eth-optimism/endpoint-monitor
## 1.0.2
### Patch Changes
- [#6164](https://github.com/ethereum-optimism/optimism/pull/6164) [`c11039060`](https://github.com/ethereum-optimism/optimism/commit/c11039060bc037a88916c2cba602687b6d69ad1a) Thanks [@pengin7384](https://github.com/pengin7384)! - fix typo
## 1.0.1 ## 1.0.1
### Patch Changes ### Patch Changes
......
{ {
"name": "@eth-optimism/endpoint-monitor", "name": "@eth-optimism/endpoint-monitor",
"version": "1.0.1", "version": "1.0.2",
"private": true, "private": true,
"dependencies": {} "dependencies": {}
} }
...@@ -23,6 +23,7 @@ require ( ...@@ -23,6 +23,7 @@ require (
github.com/ipfs/go-datastore v0.6.0 github.com/ipfs/go-datastore v0.6.0
github.com/ipfs/go-ds-leveldb v0.5.0 github.com/ipfs/go-ds-leveldb v0.5.0
github.com/jackc/pgtype v1.14.0 github.com/jackc/pgtype v1.14.0
github.com/jackc/pgx/v5 v5.3.1
github.com/lib/pq v1.10.9 github.com/lib/pq v1.10.9
github.com/libp2p/go-libp2p v0.25.1 github.com/libp2p/go-libp2p v0.25.1
github.com/libp2p/go-libp2p-pubsub v0.9.3 github.com/libp2p/go-libp2p-pubsub v0.9.3
...@@ -105,7 +106,6 @@ require ( ...@@ -105,7 +106,6 @@ require (
github.com/jackc/pgio v1.0.0 // indirect github.com/jackc/pgio v1.0.0 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
github.com/jackc/pgx/v5 v5.3.1 // indirect
github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect
github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect
github.com/jbenet/goprocess v0.1.4 // indirect github.com/jbenet/goprocess v0.1.4 // indirect
......
...@@ -21,8 +21,8 @@ const ( ...@@ -21,8 +21,8 @@ const (
) )
// DepositsByAddress mocks returning deposits by an address // DepositsByAddress mocks returning deposits by an address
func (mbv *MockBridgeView) DepositsByAddress(address common.Address) ([]*database.DepositWithTransactionHash, error) { func (mbv *MockBridgeView) DepositsByAddress(address common.Address) ([]*database.DepositWithTransactionHashes, error) {
return []*database.DepositWithTransactionHash{ return []*database.DepositWithTransactionHashes{
{ {
Deposit: database.Deposit{ Deposit: database.Deposit{
GUID: uuid.MustParse(guid1), GUID: uuid.MustParse(guid1),
......
package cli package cli
import ( import (
"context"
"fmt" "fmt"
"os"
"github.com/ethereum-optimism/optimism/indexer"
"github.com/ethereum-optimism/optimism/indexer/config" "github.com/ethereum-optimism/optimism/indexer/config"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum-optimism/optimism/op-service/log"
"github.com/ethereum-optimism/optimism/op-service/opio"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
) )
...@@ -20,16 +24,26 @@ type Cli struct { ...@@ -20,16 +24,26 @@ type Cli struct {
func runIndexer(ctx *cli.Context) error { func runIndexer(ctx *cli.Context) error {
configPath := ctx.String(ConfigFlag.Name) configPath := ctx.String(ConfigFlag.Name)
conf, err := config.LoadConfig(configPath) cfg, err := config.LoadConfig(configPath)
if err != nil {
return err
}
fmt.Println(conf) // setup logger
cfg.Logger = log.NewLogger(log.ReadCLIConfig(ctx))
indexer, err := indexer.NewIndexer(cfg)
if err != nil { if err != nil {
log.Crit("Failed to load config", "message", err) return err
} }
// finish me indexerCtx, indexerCancel := context.WithCancel(context.Background())
return nil go func() {
opio.BlockOnInterrupts()
indexerCancel()
}()
return indexer.Run(indexerCtx)
} }
func runApi(ctx *cli.Context) error { func runApi(ctx *cli.Context) error {
...@@ -39,8 +53,9 @@ func runApi(ctx *cli.Context) error { ...@@ -39,8 +53,9 @@ func runApi(ctx *cli.Context) error {
fmt.Println(conf) fmt.Println(conf)
if err != nil { if err != nil {
log.Crit("Failed to load config", "message", err) panic(err)
} }
// finish me // finish me
return nil return nil
} }
...@@ -71,17 +86,7 @@ func (c *Cli) Run(args []string) error { ...@@ -71,17 +86,7 @@ func (c *Cli) Run(args []string) error {
} }
func NewCli(GitVersion string, GitCommit string, GitDate string) *Cli { func NewCli(GitVersion string, GitCommit string, GitDate string) *Cli {
log.Root().SetHandler( flags := append([]cli.Flag{ConfigFlag}, log.CLIFlags("INDEXER")...)
log.LvlFilterHandler(
log.LvlInfo,
log.StreamHandler(os.Stdout, log.TerminalFormat(true)),
),
)
flags := []cli.Flag{
ConfigFlag,
}
app := &cli.App{ app := &cli.App{
Version: fmt.Sprintf("%s-%s", GitVersion, params.VersionWithCommit(GitCommit, GitDate)), Version: fmt.Sprintf("%s-%s", GitVersion, params.VersionWithCommit(GitCommit, GitDate)),
Description: "An indexer of all optimism events with a serving api layer", Description: "An indexer of all optimism events with a serving api layer",
......
...@@ -4,6 +4,8 @@ import ( ...@@ -4,6 +4,8 @@ import (
"os" "os"
"github.com/BurntSushi/toml" "github.com/BurntSushi/toml"
"github.com/ethereum/go-ethereum/log"
) )
// Config represents the `indexer.toml` file used to configure the indexer // Config represents the `indexer.toml` file used to configure the indexer
...@@ -13,6 +15,7 @@ type Config struct { ...@@ -13,6 +15,7 @@ type Config struct {
DB DBConfig DB DBConfig
API APIConfig API APIConfig
Metrics MetricsConfig Metrics MetricsConfig
Logger log.Logger `toml:"-"`
} }
// ChainConfig configures of the chain being indexed // ChainConfig configures of the chain being indexed
...@@ -31,6 +34,7 @@ type RPCsConfig struct { ...@@ -31,6 +34,7 @@ type RPCsConfig struct {
type DBConfig struct { type DBConfig struct {
Host string Host string
Port int Port int
Name string
User string User string
Password string Password string
} }
......
...@@ -3,6 +3,7 @@ package database ...@@ -3,6 +3,7 @@ package database
import ( import (
"context" "context"
"errors" "errors"
"math/big"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
...@@ -53,15 +54,20 @@ type LegacyStateBatch struct { ...@@ -53,15 +54,20 @@ type LegacyStateBatch struct {
type OutputProposal struct { type OutputProposal struct {
OutputRoot common.Hash `gorm:"primaryKey;serializer:json"` OutputRoot common.Hash `gorm:"primaryKey;serializer:json"`
L2OutputIndex U256
L2BlockNumber U256 L2BlockNumber U256
L1ContractEventGUID uuid.UUID L1ContractEventGUID uuid.UUID
} }
type BlocksView interface { type BlocksView interface {
L1BlockHeader(*big.Int) (*L1BlockHeader, error)
LatestL1BlockHeader() (*L1BlockHeader, error) LatestL1BlockHeader() (*L1BlockHeader, error)
LatestCheckpointedOutput() (*OutputProposal, error) LatestCheckpointedOutput() (*OutputProposal, error)
OutputProposal(index *big.Int) (*OutputProposal, error)
L2BlockHeader(*big.Int) (*L2BlockHeader, error)
LatestL2BlockHeader() (*L2BlockHeader, error) LatestL2BlockHeader() (*L2BlockHeader, error)
} }
...@@ -104,6 +110,20 @@ func (db *blocksDB) StoreOutputProposals(outputs []*OutputProposal) error { ...@@ -104,6 +110,20 @@ func (db *blocksDB) StoreOutputProposals(outputs []*OutputProposal) error {
return result.Error return result.Error
} }
func (db *blocksDB) L1BlockHeader(height *big.Int) (*L1BlockHeader, error) {
var l1Header L1BlockHeader
result := db.gorm.Where(&BlockHeader{Number: U256{Int: height}}).Take(&l1Header)
if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, nil
}
return nil, result.Error
}
return &l1Header, nil
}
func (db *blocksDB) LatestL1BlockHeader() (*L1BlockHeader, error) { func (db *blocksDB) LatestL1BlockHeader() (*L1BlockHeader, error) {
var l1Header L1BlockHeader var l1Header L1BlockHeader
result := db.gorm.Order("number DESC").Take(&l1Header) result := db.gorm.Order("number DESC").Take(&l1Header)
...@@ -120,7 +140,21 @@ func (db *blocksDB) LatestL1BlockHeader() (*L1BlockHeader, error) { ...@@ -120,7 +140,21 @@ func (db *blocksDB) LatestL1BlockHeader() (*L1BlockHeader, error) {
func (db *blocksDB) LatestCheckpointedOutput() (*OutputProposal, error) { func (db *blocksDB) LatestCheckpointedOutput() (*OutputProposal, error) {
var outputProposal OutputProposal var outputProposal OutputProposal
result := db.gorm.Order("l2_block_number DESC").Take(&outputProposal) result := db.gorm.Order("l2_output_index DESC").Take(&outputProposal)
if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, nil
}
return nil, result.Error
}
return &outputProposal, nil
}
func (db *blocksDB) OutputProposal(index *big.Int) (*OutputProposal, error) {
var outputProposal OutputProposal
result := db.gorm.Where(&OutputProposal{L2OutputIndex: U256{Int: index}}).Take(&outputProposal)
if result.Error != nil { if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) { if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, nil return nil, nil
...@@ -139,6 +173,20 @@ func (db *blocksDB) StoreL2BlockHeaders(headers []*L2BlockHeader) error { ...@@ -139,6 +173,20 @@ func (db *blocksDB) StoreL2BlockHeaders(headers []*L2BlockHeader) error {
return result.Error return result.Error
} }
func (db *blocksDB) L2BlockHeader(height *big.Int) (*L2BlockHeader, error) {
var l2Header L2BlockHeader
result := db.gorm.Where(&BlockHeader{Number: U256{Int: height}}).Take(&l2Header)
if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, nil
}
return nil, result.Error
}
return &l2Header, nil
}
func (db *blocksDB) LatestL2BlockHeader() (*L2BlockHeader, error) { func (db *blocksDB) LatestL2BlockHeader() (*L2BlockHeader, error) {
var l2Header L2BlockHeader var l2Header L2BlockHeader
result := db.gorm.Order("number DESC").Take(&l2Header) result := db.gorm.Order("number DESC").Take(&l2Header)
......
...@@ -48,9 +48,11 @@ type Deposit struct { ...@@ -48,9 +48,11 @@ type Deposit struct {
TokenPair TokenPair `gorm:"embedded"` TokenPair TokenPair `gorm:"embedded"`
} }
type DepositWithTransactionHash struct { type DepositWithTransactionHashes struct {
Deposit Deposit `gorm:"embedded"` Deposit Deposit `gorm:"embedded"`
L1TransactionHash common.Hash `gorm:"serializer:json"` L1TransactionHash common.Hash `gorm:"serializer:json"`
FinalizedL2TransactionHash common.Hash `gorm:"serializer:json"`
} }
type Withdrawal struct { type Withdrawal struct {
...@@ -77,12 +79,12 @@ type WithdrawalWithTransactionHashes struct { ...@@ -77,12 +79,12 @@ type WithdrawalWithTransactionHashes struct {
Withdrawal Withdrawal `gorm:"embedded"` Withdrawal Withdrawal `gorm:"embedded"`
L2TransactionHash common.Hash `gorm:"serializer:json"` L2TransactionHash common.Hash `gorm:"serializer:json"`
ProvenL1TransactionHash *common.Hash `gorm:"serializer:json"` ProvenL1TransactionHash common.Hash `gorm:"serializer:json"`
FinalizedL1TransactionHash *common.Hash `gorm:"serializer:json"` FinalizedL1TransactionHash common.Hash `gorm:"serializer:json"`
} }
type BridgeView interface { type BridgeView interface {
DepositsByAddress(address common.Address) ([]*DepositWithTransactionHash, error) DepositsByAddress(address common.Address) ([]*DepositWithTransactionHashes, error)
DepositByMessageNonce(*big.Int) (*Deposit, error) DepositByMessageNonce(*big.Int) (*Deposit, error)
LatestDepositMessageNonce() (*big.Int, error) LatestDepositMessageNonce() (*big.Int, error)
...@@ -122,14 +124,16 @@ func (db *bridgeDB) StoreDeposits(deposits []*Deposit) error { ...@@ -122,14 +124,16 @@ func (db *bridgeDB) StoreDeposits(deposits []*Deposit) error {
return result.Error return result.Error
} }
func (db *bridgeDB) DepositsByAddress(address common.Address) ([]*DepositWithTransactionHash, error) { func (db *bridgeDB) DepositsByAddress(address common.Address) ([]*DepositWithTransactionHashes, error) {
depositsQuery := db.gorm.Table("deposits").Select("deposits.*, l1_contract_events.transaction_hash AS l1_transaction_hash") depositsQuery := db.gorm.Table("deposits").Select("deposits.*, l1_contract_events.transaction_hash AS l1_transaction_hash, l2_contract_events.transaction_hash AS finalized_l2_transaction_hash")
eventsJoinQuery := depositsQuery.Joins("LEFT JOIN l1_contract_events ON deposits.initiated_l1_event_guid = l1_contract_events.guid")
initiatedJoinQuery := depositsQuery.Joins("LEFT JOIN l1_contract_events ON deposits.initiated_l1_event_guid = l1_contract_events.guid")
finalizedJoinQuery := initiatedJoinQuery.Joins("LEFT JOIN l2_contract_events ON deposits.finalized_l2_event_guid = l2_contract_events.guid")
// add in cursoring options // add in cursoring options
filteredQuery := eventsJoinQuery.Where(&Transaction{FromAddress: address}).Order("deposits.timestamp DESC").Limit(100) filteredQuery := finalizedJoinQuery.Where(&Transaction{FromAddress: address}).Order("deposits.timestamp DESC").Limit(100)
deposits := make([]*DepositWithTransactionHash, 100) deposits := make([]*DepositWithTransactionHashes, 100)
result := filteredQuery.Scan(&deposits) result := filteredQuery.Scan(&deposits)
if result.Error != nil { if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) { if errors.Is(result.Error, gorm.ErrRecordNotFound) {
...@@ -144,7 +148,7 @@ func (db *bridgeDB) DepositsByAddress(address common.Address) ([]*DepositWithTra ...@@ -144,7 +148,7 @@ func (db *bridgeDB) DepositsByAddress(address common.Address) ([]*DepositWithTra
func (db *bridgeDB) DepositByMessageNonce(nonce *big.Int) (*Deposit, error) { func (db *bridgeDB) DepositByMessageNonce(nonce *big.Int) (*Deposit, error) {
var deposit Deposit var deposit Deposit
result := db.gorm.First(&deposit, "sent_message_nonce = ?", U256{Int: nonce}) result := db.gorm.Where(&Deposit{SentMessageNonce: U256{Int: nonce}}).Take(&deposit)
if result.Error != nil { if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) { if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, nil return nil, nil
...@@ -172,7 +176,7 @@ func (db *bridgeDB) LatestDepositMessageNonce() (*big.Int, error) { ...@@ -172,7 +176,7 @@ func (db *bridgeDB) LatestDepositMessageNonce() (*big.Int, error) {
func (db *bridgeDB) MarkFinalizedDepositEvent(guid, finalizationEventGUID uuid.UUID) error { func (db *bridgeDB) MarkFinalizedDepositEvent(guid, finalizationEventGUID uuid.UUID) error {
var deposit Deposit var deposit Deposit
result := db.gorm.First(&deposit, "guid = ?", guid) result := db.gorm.Where(&Deposit{GUID: guid}).Take(&deposit)
if result.Error != nil { if result.Error != nil {
return result.Error return result.Error
} }
...@@ -191,7 +195,7 @@ func (db *bridgeDB) StoreWithdrawals(withdrawals []*Withdrawal) error { ...@@ -191,7 +195,7 @@ func (db *bridgeDB) StoreWithdrawals(withdrawals []*Withdrawal) error {
func (db *bridgeDB) MarkProvenWithdrawalEvent(guid, provenL1EventGuid uuid.UUID) error { func (db *bridgeDB) MarkProvenWithdrawalEvent(guid, provenL1EventGuid uuid.UUID) error {
var withdrawal Withdrawal var withdrawal Withdrawal
result := db.gorm.First(&withdrawal, "guid = ?", guid) result := db.gorm.Where(&Withdrawal{GUID: guid}).Take(&withdrawal)
if result.Error != nil { if result.Error != nil {
return result.Error return result.Error
} }
...@@ -203,7 +207,7 @@ func (db *bridgeDB) MarkProvenWithdrawalEvent(guid, provenL1EventGuid uuid.UUID) ...@@ -203,7 +207,7 @@ func (db *bridgeDB) MarkProvenWithdrawalEvent(guid, provenL1EventGuid uuid.UUID)
func (db *bridgeDB) MarkFinalizedWithdrawalEvent(guid, finalizedL1EventGuid uuid.UUID) error { func (db *bridgeDB) MarkFinalizedWithdrawalEvent(guid, finalizedL1EventGuid uuid.UUID) error {
var withdrawal Withdrawal var withdrawal Withdrawal
result := db.gorm.First(&withdrawal, "guid = ?", guid) result := db.gorm.Where(&Withdrawal{GUID: guid}).Take(&withdrawal)
if result.Error != nil { if result.Error != nil {
return result.Error return result.Error
} }
...@@ -242,7 +246,7 @@ func (db *bridgeDB) WithdrawalsByAddress(address common.Address) ([]*WithdrawalW ...@@ -242,7 +246,7 @@ func (db *bridgeDB) WithdrawalsByAddress(address common.Address) ([]*WithdrawalW
func (db *bridgeDB) WithdrawalByMessageNonce(nonce *big.Int) (*Withdrawal, error) { func (db *bridgeDB) WithdrawalByMessageNonce(nonce *big.Int) (*Withdrawal, error) {
var withdrawal Withdrawal var withdrawal Withdrawal
result := db.gorm.First(&withdrawal, "sent_message_nonce = ?", U256{Int: nonce}) result := db.gorm.Where(&Withdrawal{SentMessageNonce: U256{Int: nonce}}).Take(&withdrawal)
if result.Error != nil { if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) { if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, nil return nil, nil
...@@ -256,7 +260,7 @@ func (db *bridgeDB) WithdrawalByMessageNonce(nonce *big.Int) (*Withdrawal, error ...@@ -256,7 +260,7 @@ func (db *bridgeDB) WithdrawalByMessageNonce(nonce *big.Int) (*Withdrawal, error
func (db *bridgeDB) WithdrawalByHash(hash common.Hash) (*Withdrawal, error) { func (db *bridgeDB) WithdrawalByHash(hash common.Hash) (*Withdrawal, error) {
var withdrawal Withdrawal var withdrawal Withdrawal
result := db.gorm.First(&withdrawal, "withdrawal_hash = ?", hash.String()) result := db.gorm.Where(&Withdrawal{WithdrawalHash: hash}).Take(&withdrawal)
if result.Error != nil { if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) { if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, nil return nil, nil
......
package database package database
import ( import (
"errors"
"gorm.io/gorm" "gorm.io/gorm"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
...@@ -46,6 +48,11 @@ type L2ContractEvent struct { ...@@ -46,6 +48,11 @@ type L2ContractEvent struct {
} }
type ContractEventsView interface { type ContractEventsView interface {
L1ContractEvent(uuid.UUID) (*L1ContractEvent, error)
L1ContractEventByTxLogIndex(common.Hash, uint64) (*L1ContractEvent, error)
L2ContractEvent(uuid.UUID) (*L2ContractEvent, error)
L2ContractEventByTxLogIndex(common.Hash, uint64) (*L2ContractEvent, error)
} }
type ContractEventsDB interface { type ContractEventsDB interface {
...@@ -74,9 +81,65 @@ func (db *contractEventsDB) StoreL1ContractEvents(events []*L1ContractEvent) err ...@@ -74,9 +81,65 @@ func (db *contractEventsDB) StoreL1ContractEvents(events []*L1ContractEvent) err
return result.Error return result.Error
} }
func (db *contractEventsDB) L1ContractEvent(uuid uuid.UUID) (*L1ContractEvent, error) {
var l1ContractEvent L1ContractEvent
result := db.gorm.Where(&ContractEvent{GUID: uuid}).Take(&l1ContractEvent)
if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, nil
}
return nil, result.Error
}
return &l1ContractEvent, nil
}
func (db *contractEventsDB) L1ContractEventByTxLogIndex(txHash common.Hash, logIndex uint64) (*L1ContractEvent, error) {
var l1ContractEvent L1ContractEvent
result := db.gorm.Where(&ContractEvent{TransactionHash: txHash, LogIndex: logIndex}).Take(&l1ContractEvent)
if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, nil
}
return nil, result.Error
}
return &l1ContractEvent, nil
}
// L2 // L2
func (db *contractEventsDB) StoreL2ContractEvents(events []*L2ContractEvent) error { func (db *contractEventsDB) StoreL2ContractEvents(events []*L2ContractEvent) error {
result := db.gorm.Create(&events) result := db.gorm.Create(&events)
return result.Error return result.Error
} }
func (db *contractEventsDB) L2ContractEvent(uuid uuid.UUID) (*L2ContractEvent, error) {
var l2ContractEvent L2ContractEvent
result := db.gorm.Where(&ContractEvent{GUID: uuid}).Take(&l2ContractEvent)
if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, nil
}
return nil, result.Error
}
return &l2ContractEvent, nil
}
func (db *contractEventsDB) L2ContractEventByTxLogIndex(txHash common.Hash, logIndex uint64) (*L2ContractEvent, error) {
var l2ContractEvent L2ContractEvent
result := db.gorm.Where(&ContractEvent{TransactionHash: txHash, LogIndex: logIndex}).Take(&l2ContractEvent)
if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, nil
}
return nil, result.Error
}
return &l2ContractEvent, nil
}
...@@ -4,6 +4,7 @@ package database ...@@ -4,6 +4,7 @@ package database
import ( import (
"gorm.io/driver/postgres" "gorm.io/driver/postgres"
"gorm.io/gorm" "gorm.io/gorm"
"gorm.io/gorm/logger"
) )
type DB struct { type DB struct {
...@@ -19,6 +20,10 @@ func NewDB(dsn string) (*DB, error) { ...@@ -19,6 +20,10 @@ func NewDB(dsn string) (*DB, error) {
// The indexer will explicitly manage the transaction // The indexer will explicitly manage the transaction
// flow processing blocks // flow processing blocks
SkipDefaultTransaction: true, SkipDefaultTransaction: true,
// We may choose to create an adapter such that the
// logger emits to the geth logger when on DEBUG mode
Logger: logger.Default.LogMode(logger.Silent),
}) })
if err != nil { if err != nil {
...@@ -43,6 +48,15 @@ func (db *DB) Transaction(fn func(db *DB) error) error { ...@@ -43,6 +48,15 @@ func (db *DB) Transaction(fn func(db *DB) error) error {
}) })
} }
func (db *DB) Close() error {
sql, err := db.gorm.DB()
if err != nil {
return err
}
return sql.Close()
}
func dbFromGormTx(tx *gorm.DB) *DB { func dbFromGormTx(tx *gorm.DB) *DB {
return &DB{ return &DB{
gorm: tx, gorm: tx,
......
package e2e_tests
import (
"context"
"math/big"
"testing"
"time"
"github.com/ethereum-optimism/optimism/indexer/node"
"github.com/ethereum-optimism/optimism/indexer/processor"
"github.com/ethereum-optimism/optimism/op-service/client/utils"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/crypto"
"github.com/stretchr/testify/require"
)
func TestE2EBlockHeaders(t *testing.T) {
testSuite := createE2ETestSuite(t)
l1Client := testSuite.OpSys.Clients["l1"]
l2Client := testSuite.OpSys.Clients["sequencer"]
l2OutputOracle, err := bindings.NewL2OutputOracleCaller(predeploys.DevL2OutputOracleAddr, l1Client)
require.NoError(t, err)
// a minute for total setup to finish
setupCtx, cancel := context.WithTimeout(context.Background(), time.Minute)
defer cancel()
// wait for at least 10 L2 blocks to be created & posted on L1
require.NoError(t, utils.WaitFor(setupCtx, time.Second, func() (bool, error) {
l2Height, err := l2OutputOracle.LatestBlockNumber(&bind.CallOpts{Context: setupCtx})
return l2Height != nil && l2Height.Uint64() >= 9, err
}))
// ensure the processors are caught up to this state
l1Height, err := l1Client.BlockNumber(setupCtx)
require.NoError(t, err)
require.NoError(t, utils.WaitFor(setupCtx, time.Second, func() (bool, error) {
l1Header := testSuite.Indexer.L1Processor.LatestProcessedHeader()
l2Header := testSuite.Indexer.L2Processor.LatestProcessedHeader()
return (l1Header != nil && l1Header.Number.Uint64() >= l1Height) && (l2Header != nil && l2Header.Number.Uint64() >= 9), nil
}))
t.Run("indexes L2 blocks", func(t *testing.T) {
latestL2Header, err := testSuite.DB.Blocks.LatestL2BlockHeader()
require.NoError(t, err)
require.NotNil(t, latestL2Header)
require.True(t, latestL2Header.Number.Int.Uint64() >= 9)
for i := int64(0); i < 10; i++ {
height := big.NewInt(i)
indexedHeader, err := testSuite.DB.Blocks.L2BlockHeader(height)
require.NoError(t, err)
require.NotNil(t, indexedHeader)
header, err := l2Client.HeaderByNumber(context.Background(), height)
require.NoError(t, err)
require.NotNil(t, indexedHeader)
require.Equal(t, header.Number.Int64(), indexedHeader.Number.Int.Int64())
require.Equal(t, header.Hash(), indexedHeader.Hash)
require.Equal(t, header.ParentHash, indexedHeader.ParentHash)
require.Equal(t, header.Time, indexedHeader.Timestamp)
}
})
t.Run("indexes L2 checkpoints", func(t *testing.T) {
latestOutput, err := testSuite.DB.Blocks.LatestCheckpointedOutput()
require.NoError(t, err)
require.NotNil(t, latestOutput)
require.GreaterOrEqual(t, latestOutput.L2BlockNumber.Int.Uint64(), uint64(9))
l2EthClient, err := node.DialEthClient(testSuite.OpSys.Nodes["sequencer"].HTTPEndpoint())
require.NoError(t, err)
submissionInterval := testSuite.OpCfg.DeployConfig.L2OutputOracleSubmissionInterval
numOutputs := latestOutput.L2BlockNumber.Int.Uint64() / submissionInterval
for i := int64(0); i < int64(numOutputs); i++ {
blockNumber := big.NewInt((i + 1) * int64(submissionInterval))
output, err := testSuite.DB.Blocks.OutputProposal(big.NewInt(i))
require.NoError(t, err)
require.NotNil(t, output)
require.Equal(t, i, output.L2OutputIndex.Int.Int64())
require.Equal(t, blockNumber, output.L2BlockNumber.Int)
require.NotEmpty(t, output.L1ContractEventGUID)
// we may as well check the integrity of the output root
l2Block, err := l2Client.BlockByNumber(context.Background(), blockNumber)
require.NoError(t, err)
messagePasserStorageHash, err := l2EthClient.StorageHash(predeploys.L2ToL1MessagePasserAddr, blockNumber)
require.NoError(t, err)
// construct and check output root
outputRootPreImage := [128]byte{} // 4 words (first 32 are zero for version 0)
copy(outputRootPreImage[32:64], l2Block.Root().Bytes()) // state root
copy(outputRootPreImage[64:96], messagePasserStorageHash.Bytes()) // message passer storage root
copy(outputRootPreImage[96:128], l2Block.Hash().Bytes()) // block hash
require.Equal(t, crypto.Keccak256Hash(outputRootPreImage[:]), output.OutputRoot)
}
})
t.Run("indexes L1 logs and associated blocks", func(t *testing.T) {
testCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
devContracts := processor.DevL1Contracts().ToSlice()
logFilter := ethereum.FilterQuery{FromBlock: big.NewInt(0), ToBlock: big.NewInt(int64(l1Height)), Addresses: devContracts}
logs, err := l1Client.FilterLogs(testCtx, logFilter) // []types.Log
require.NoError(t, err)
for _, log := range logs {
contractEvent, err := testSuite.DB.ContractEvents.L1ContractEventByTxLogIndex(log.TxHash, uint64(log.Index))
require.NoError(t, err)
require.Equal(t, log.Topics[0], contractEvent.EventSignature)
require.Equal(t, log.BlockHash, contractEvent.BlockHash)
require.Equal(t, log.TxHash, contractEvent.TransactionHash)
require.Equal(t, log.Index, uint(contractEvent.LogIndex))
// ensure the block is also indexed
block, err := l1Client.BlockByNumber(testCtx, big.NewInt(int64(log.BlockNumber)))
require.NoError(t, err)
require.Equal(t, block.Time(), contractEvent.Timestamp)
l1BlockHeader, err := testSuite.DB.Blocks.L1BlockHeader(block.Number())
require.NoError(t, err)
require.Equal(t, block.Hash(), l1BlockHeader.Hash)
require.Equal(t, block.ParentHash(), l1BlockHeader.ParentHash)
require.Equal(t, block.Number(), l1BlockHeader.Number.Int)
require.Equal(t, block.Time(), l1BlockHeader.Timestamp)
}
})
}
package e2e_tests
import (
"context"
"math/big"
"testing"
"time"
"github.com/ethereum-optimism/optimism/indexer/processor"
"github.com/ethereum-optimism/optimism/op-service/client/utils"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys"
op_e2e "github.com/ethereum-optimism/optimism/op-e2e"
"github.com/ethereum-optimism/optimism/op-node/rollup/derive"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
"github.com/stretchr/testify/require"
)
func TestE2EBridge(t *testing.T) {
testSuite := createE2ETestSuite(t)
l1Client := testSuite.OpSys.Clients["l1"]
l2Client := testSuite.OpSys.Clients["sequencer"]
l1StandardBridge, err := bindings.NewL1StandardBridge(predeploys.DevL1StandardBridgeAddr, l1Client)
require.NoError(t, err)
l2StandardBridge, err := bindings.NewL2StandardBridge(predeploys.L2StandardBridgeAddr, l2Client)
require.NoError(t, err)
// pre-emptively conduct a deposit & withdrawal to speed up the test
setupCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
aliceAddr := testSuite.OpCfg.Secrets.Addresses().Alice
l1Opts, err := bind.NewKeyedTransactorWithChainID(testSuite.OpCfg.Secrets.Alice, testSuite.OpCfg.L1ChainIDBig())
require.NoError(t, err)
l2Opts, err := bind.NewKeyedTransactorWithChainID(testSuite.OpCfg.Secrets.Alice, testSuite.OpCfg.L2ChainIDBig())
require.NoError(t, err)
l1Opts.Value = big.NewInt(params.Ether)
l2Opts.Value = big.NewInt(params.Ether)
depositTx, err := l1StandardBridge.DepositETH(l1Opts, 200_000, []byte{byte(1)})
require.NoError(t, err)
withdrawTx, err := l2StandardBridge.Withdraw(l2Opts, processor.EthAddress, big.NewInt(params.Ether), 200_000, []byte{byte(1)})
require.NoError(t, err)
depositReceipt, err := utils.WaitReceiptOK(setupCtx, l1Client, depositTx.Hash())
require.NoError(t, err)
withdrawalReceipt, err := utils.WaitReceiptOK(setupCtx, l2Client, withdrawTx.Hash())
require.NoError(t, err)
t.Run("indexes ETH deposits", func(t *testing.T) {
testCtx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
defer cancel()
// Pause the L2Processor so that we can test for finalization separately. A pause is
// required since deposit inclusion is apart of the L2 block derivation process
testSuite.Indexer.L2Processor.PauseForTest()
// (1) Test Deposit Initiation
// wait for processor catchup
require.NoError(t, utils.WaitFor(testCtx, 500*time.Millisecond, func() (bool, error) {
l1Header := testSuite.Indexer.L1Processor.LatestProcessedHeader()
return l1Header != nil && l1Header.Number.Uint64() >= depositReceipt.BlockNumber.Uint64(), nil
}))
aliceDeposits, err := testSuite.DB.Bridge.DepositsByAddress(aliceAddr)
require.NoError(t, err)
require.Len(t, aliceDeposits, 1)
require.Equal(t, depositTx.Hash(), aliceDeposits[0].L1TransactionHash)
require.Empty(t, aliceDeposits[0].FinalizedL2TransactionHash)
deposit := aliceDeposits[0].Deposit
require.Nil(t, deposit.FinalizedL2EventGUID)
require.Equal(t, processor.EthAddress, deposit.TokenPair.L1TokenAddress)
require.Equal(t, processor.EthAddress, deposit.TokenPair.L2TokenAddress)
require.Equal(t, big.NewInt(params.Ether), deposit.Tx.Amount.Int)
require.Equal(t, aliceAddr, deposit.Tx.FromAddress)
require.Equal(t, aliceAddr, deposit.Tx.ToAddress)
require.Equal(t, byte(1), deposit.Tx.Data[0])
// (2) Test Deposit Finalization
testSuite.Indexer.L2Processor.ResumeForTest()
// finalization hash can be deterministically derived from TransactionDeposited log
var depositTxHash common.Hash
for _, log := range depositReceipt.Logs {
if log.Topics[0] == derive.DepositEventABIHash {
deposit, err := derive.UnmarshalDepositLogEvent(log)
require.NoError(t, err)
depositTxHash = types.NewTx(deposit).Hash()
break
}
}
// wait for the l2 processor to catch this deposit in the derivation process
_, err = utils.WaitReceiptOK(testCtx, l2Client, depositTxHash)
require.NoError(t, err)
l2Height, err := l2Client.BlockNumber(testCtx)
require.NoError(t, err)
require.NoError(t, utils.WaitFor(testCtx, 500*time.Millisecond, func() (bool, error) {
l2Header := testSuite.Indexer.L2Processor.LatestProcessedHeader()
return l2Header != nil && l2Header.Number.Uint64() >= l2Height, nil
}))
aliceDeposits, err = testSuite.DB.Bridge.DepositsByAddress(aliceAddr)
require.NoError(t, err)
require.Equal(t, depositTxHash, aliceDeposits[0].FinalizedL2TransactionHash)
require.NotNil(t, aliceDeposits[0].Deposit.FinalizedL2EventGUID)
})
t.Run("indexes ETH withdrawals", func(t *testing.T) {
testCtx, cancel := context.WithTimeout(context.Background(), 1*time.Minute)
defer cancel()
// (1) Test Withdrawal Initiation
// wait for processor catchup
require.NoError(t, utils.WaitFor(testCtx, 500*time.Millisecond, func() (bool, error) {
l2Header := testSuite.Indexer.L2Processor.LatestProcessedHeader()
return l2Header != nil && l2Header.Number.Uint64() >= withdrawalReceipt.BlockNumber.Uint64(), nil
}))
aliceWithdrawals, err := testSuite.DB.Bridge.WithdrawalsByAddress(aliceAddr)
require.NoError(t, err)
require.Len(t, aliceWithdrawals, 1)
require.Equal(t, withdrawTx.Hash(), aliceWithdrawals[0].L2TransactionHash)
require.Empty(t, aliceWithdrawals[0].ProvenL1TransactionHash)
require.Empty(t, aliceWithdrawals[0].FinalizedL1TransactionHash)
withdrawal := aliceWithdrawals[0].Withdrawal
require.Nil(t, withdrawal.ProvenL1EventGUID)
require.Nil(t, withdrawal.FinalizedL1EventGUID)
require.Equal(t, processor.EthAddress, withdrawal.TokenPair.L1TokenAddress)
require.Equal(t, processor.EthAddress, withdrawal.TokenPair.L2TokenAddress)
require.Equal(t, big.NewInt(params.Ether), withdrawal.Tx.Amount.Int)
require.Equal(t, aliceAddr, withdrawal.Tx.FromAddress)
require.Equal(t, aliceAddr, withdrawal.Tx.ToAddress)
require.Equal(t, byte(1), withdrawal.Tx.Data[0])
// (2) Test Withdrawal Proven
// prove & wait for processor catchup
withdrawParams, proveReceipt := op_e2e.ProveWithdrawal(t, *testSuite.OpCfg, l1Client, testSuite.OpSys.Nodes["sequencer"], testSuite.OpCfg.Secrets.Alice, withdrawalReceipt)
require.NoError(t, utils.WaitFor(testCtx, 500*time.Millisecond, func() (bool, error) {
l1Header := testSuite.Indexer.L1Processor.LatestProcessedHeader()
return l1Header != nil && l1Header.Number.Uint64() >= proveReceipt.BlockNumber.Uint64(), nil
}))
aliceWithdrawals, err = testSuite.DB.Bridge.WithdrawalsByAddress(aliceAddr)
require.NoError(t, err)
require.Empty(t, aliceWithdrawals[0].FinalizedL1TransactionHash)
require.Equal(t, proveReceipt.TxHash, aliceWithdrawals[0].ProvenL1TransactionHash)
// (3) Test Withdrawal Finalization
// finalize & wait for processor catchup
finalizeReceipt := op_e2e.FinalizeWithdrawal(t, *testSuite.OpCfg, l1Client, testSuite.OpCfg.Secrets.Alice, withdrawalReceipt, withdrawParams)
require.NoError(t, utils.WaitFor(testCtx, 500*time.Millisecond, func() (bool, error) {
l1Header := testSuite.Indexer.L1Processor.LatestProcessedHeader()
return l1Header != nil && l1Header.Number.Uint64() >= finalizeReceipt.BlockNumber.Uint64(), nil
}))
aliceWithdrawals, err = testSuite.DB.Bridge.WithdrawalsByAddress(aliceAddr)
require.NoError(t, err)
require.Equal(t, finalizeReceipt.TxHash, aliceWithdrawals[0].FinalizedL1TransactionHash)
})
}
package e2e_tests
import (
"context"
"database/sql"
"fmt"
"io/fs"
"os"
"path/filepath"
"testing"
"time"
"github.com/ethereum-optimism/optimism/indexer"
"github.com/ethereum-optimism/optimism/indexer/config"
"github.com/ethereum-optimism/optimism/indexer/database"
op_e2e "github.com/ethereum-optimism/optimism/op-e2e"
"github.com/ethereum-optimism/optimism/op-node/testlog"
"github.com/ethereum/go-ethereum/log"
_ "github.com/jackc/pgx/v5/stdlib"
"github.com/stretchr/testify/require"
)
type E2ETestSuite struct {
t *testing.T
// Indexer
DB *database.DB
Indexer *indexer.Indexer
// Rollup
OpCfg *op_e2e.SystemConfig
OpSys *op_e2e.System
}
func createE2ETestSuite(t *testing.T) E2ETestSuite {
dbUser := os.Getenv("DB_USER")
dbName := setupTestDatabase(t)
// Replace the handler of the global logger with the testlog
logger := testlog.Logger(t, log.LvlInfo)
log.Root().SetHandler(logger.GetHandler())
// Rollup System Configuration and Start
opCfg := op_e2e.DefaultSystemConfig(t)
opCfg.DeployConfig.FinalizationPeriodSeconds = 2
opSys, err := opCfg.Start()
require.NoError(t, err)
// Indexer Configuration and Start
indexerCfg := config.Config{
DB: config.DBConfig{
Host: "127.0.0.1",
Port: 5432,
Name: dbName,
User: dbUser,
},
RPCs: config.RPCsConfig{
L1RPC: opSys.Nodes["l1"].HTTPEndpoint(),
L2RPC: opSys.Nodes["sequencer"].HTTPEndpoint(),
},
Logger: logger,
}
db, err := database.NewDB(fmt.Sprintf("postgres://%s@localhost:5432/%s?sslmode=disable", dbUser, dbName))
require.NoError(t, err)
indexer, err := indexer.NewIndexer(indexerCfg)
require.NoError(t, err)
indexerCtx, indexerStop := context.WithCancel(context.Background())
go func() {
err := indexer.Run(indexerCtx)
require.NoError(t, err)
indexer.Cleanup()
}()
t.Cleanup(func() {
indexerStop()
// wait a second for the stop signal to be received
time.Sleep(1 * time.Second)
indexer.Cleanup()
db.Close()
opSys.Close()
})
return E2ETestSuite{
t: t,
DB: db,
Indexer: indexer,
OpCfg: &opCfg,
OpSys: opSys,
}
}
func setupTestDatabase(t *testing.T) string {
user := os.Getenv("DB_USER")
pg, err := sql.Open("pgx", fmt.Sprintf("postgres://%s@localhost:5432?sslmode=disable", user))
require.NoError(t, err)
require.NoError(t, pg.Ping())
// create database
dbName := fmt.Sprintf("indexer_test_%d", time.Now().UnixNano())
_, err = pg.Exec("CREATE DATABASE " + dbName)
require.NoError(t, err)
t.Cleanup(func() {
_, err := pg.Exec("DROP DATABASE " + dbName)
require.NoError(t, err)
pg.Close()
})
// setup schema, migration files ware walked in lexical order
t.Logf("created database %s", dbName)
db, err := sql.Open("pgx", fmt.Sprintf("postgres://%s@localhost:5432/%s?sslmode=disable", user, dbName))
require.NoError(t, err)
require.NoError(t, db.Ping())
defer db.Close()
t.Logf("running schema migrations...")
require.NoError(t, filepath.Walk("../migrations", func(path string, info fs.FileInfo, err error) error {
if err != nil {
return err
} else if info.IsDir() {
return nil
}
t.Logf("running schema migration: %s", path)
data, err := os.ReadFile(path)
if err != nil {
return err
}
_, err = db.Exec(string(data))
return err
}))
t.Logf("schema loaded")
return dbName
}
package indexer package indexer
import ( import (
"context"
"fmt" "fmt"
"os" "sync"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum-optimism/optimism/indexer/config"
"github.com/ethereum-optimism/optimism/indexer/database" "github.com/ethereum-optimism/optimism/indexer/database"
"github.com/ethereum-optimism/optimism/indexer/flags"
"github.com/ethereum-optimism/optimism/indexer/node" "github.com/ethereum-optimism/optimism/indexer/node"
"github.com/ethereum-optimism/optimism/indexer/processor" "github.com/ethereum-optimism/optimism/indexer/processor"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
"github.com/urfave/cli"
) )
// Main is the entrypoint into the indexer service. This method returns // Indexer contains the necessary resources for
// a closure that executes the service and blocks until the service exits. The // indexing the configured L1 and L2 chains
// use of a closure allows the parameters bound to the top-level main package,
// e.g. GitVersion, to be captured and used once the function is executed.
func Main(gitVersion string) func(ctx *cli.Context) error {
return func(ctx *cli.Context) error {
log.Info("initializing indexer")
indexer, err := NewIndexer(ctx)
if err != nil {
log.Error("unable to initialize indexer", "err", err)
return err
}
log.Info("starting indexer")
if err := indexer.Start(); err != nil {
log.Error("unable to start indexer", "err", err)
}
defer indexer.Stop()
log.Info("indexer started")
// Never terminate
<-(chan struct{})(nil)
return nil
}
}
// Indexer is a service that configures the necessary resources for
// running the Sync and BlockHandler sub-services.
type Indexer struct { type Indexer struct {
db *database.DB db *database.DB
log log.Logger
l1Processor *processor.L1Processor L1Processor *processor.L1Processor
l2Processor *processor.L2Processor L2Processor *processor.L2Processor
} }
// NewIndexer initializes the Indexer, gathering any resources // NewIndexer initializes an instance of the Indexer
// that will be needed by the TxIndexer and StateIndexer func NewIndexer(cfg config.Config) (*Indexer, error) {
// sub-services. dsn := fmt.Sprintf("host=%s port=%d dbname=%s sslmode=disable", cfg.DB.Host, cfg.DB.Port, cfg.DB.Name)
func NewIndexer(ctx *cli.Context) (*Indexer, error) { if cfg.DB.User != "" {
// TODO https://linear.app/optimism/issue/DX-55/api-implement-rest-api-with-mocked-data dsn += fmt.Sprintf(" user=%s", cfg.DB.User)
// do json format too }
// TODO https://linear.app/optimism/issue/DX-55/api-implement-rest-api-with-mocked-data if cfg.DB.Password != "" {
dsn += fmt.Sprintf(" password=%s", cfg.DB.Password)
logLevel, err := log.LvlFromString(ctx.GlobalString(flags.LogLevelFlag.Name))
if err != nil {
return nil, err
} }
logHandler := log.StreamHandler(os.Stdout, log.TerminalFormat(true))
log.Root().SetHandler(log.LvlFilterHandler(logLevel, logHandler))
dsn := fmt.Sprintf("database=%s", ctx.GlobalString(flags.DBNameFlag.Name))
db, err := database.NewDB(dsn) db, err := database.NewDB(dsn)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// L1 Processor (hardhat devnet contracts). Make this configurable // L1 Processor (hardhat devnet contracts). Make this configurable
l1Contracts := processor.L1Contracts{ l1Contracts := processor.DevL1Contracts()
OptimismPortal: common.HexToAddress("0x6900000000000000000000000000000000000000"), l1EthClient, err := node.DialEthClient(cfg.RPCs.L1RPC)
L2OutputOracle: common.HexToAddress("0x6900000000000000000000000000000000000001"),
L1CrossDomainMessenger: common.HexToAddress("0x6900000000000000000000000000000000000002"),
L1StandardBridge: common.HexToAddress("0x6900000000000000000000000000000000000003"),
L1ERC721Bridge: common.HexToAddress("0x6900000000000000000000000000000000000004"),
}
l1EthClient, err := node.NewEthClient(ctx.GlobalString(flags.L1EthRPCFlag.Name))
if err != nil { if err != nil {
return nil, err return nil, err
} }
l1Processor, err := processor.NewL1Processor(l1EthClient, db, l1Contracts) l1Processor, err := processor.NewL1Processor(cfg.Logger, l1EthClient, db, l1Contracts)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// L2Processor // L2Processor (predeploys). Although most likely the right setting, make this configurable?
l2Contracts := processor.L2ContractPredeploys() // Make this configurable l2Contracts := processor.L2ContractPredeploys()
l2EthClient, err := node.NewEthClient(ctx.GlobalString(flags.L2EthRPCFlag.Name)) l2EthClient, err := node.DialEthClient(cfg.RPCs.L2RPC)
if err != nil { if err != nil {
return nil, err return nil, err
} }
l2Processor, err := processor.NewL2Processor(l2EthClient, db, l2Contracts) l2Processor, err := processor.NewL2Processor(cfg.Logger, l2EthClient, db, l2Contracts)
if err != nil { if err != nil {
return nil, err return nil, err
} }
indexer := &Indexer{ indexer := &Indexer{
db: db, db: db,
l1Processor: l1Processor, log: cfg.Logger,
l2Processor: l2Processor, L1Processor: l1Processor,
L2Processor: l2Processor,
} }
return indexer, nil return indexer, nil
} }
// Serve spins up a REST API server at the given hostname and port. // Start starts the indexing service on L1 and L2 chains
func (b *Indexer) Serve() error { func (i *Indexer) Run(ctx context.Context) error {
return nil var wg sync.WaitGroup
} errCh := make(chan error)
// If either processor errors out, we stop
processorCtx, cancel := context.WithCancel(ctx)
run := func(start func(ctx context.Context) error) {
wg.Add(1)
defer wg.Done()
err := start(processorCtx)
if err != nil {
i.log.Error("halting indexer on error", "err", err)
cancel()
errCh <- err
}
}
// Start starts the starts the indexing service on L1 and L2 chains and also // Kick off the processors
// starts the REST server. go run(i.L1Processor.Start)
func (b *Indexer) Start() error { go run(i.L2Processor.Start)
go b.l1Processor.Start() err := <-errCh
go b.l2Processor.Start()
return nil // ensure both processors have halted before returning
wg.Wait()
return err
} }
// Stop stops the indexing service on L1 and L2 chains. // Cleanup releases any resources that might be currently held by the indexer
func (b *Indexer) Stop() { func (i *Indexer) Cleanup() {
i.db.Close()
} }
...@@ -56,6 +56,8 @@ CREATE TABLE IF NOT EXISTS legacy_state_batches ( ...@@ -56,6 +56,8 @@ CREATE TABLE IF NOT EXISTS legacy_state_batches (
CREATE TABLE IF NOT EXISTS output_proposals ( CREATE TABLE IF NOT EXISTS output_proposals (
output_root VARCHAR NOT NULL PRIMARY KEY, output_root VARCHAR NOT NULL PRIMARY KEY,
l2_output_index UINT256,
l2_block_number UINT256, l2_block_number UINT256,
l1_contract_event_guid VARCHAR REFERENCES l1_contract_events(guid) l1_contract_event_guid VARCHAR REFERENCES l1_contract_events(guid)
......
...@@ -3,6 +3,7 @@ package node ...@@ -3,6 +3,7 @@ package node
import ( import (
"context" "context"
"errors" "errors"
"fmt"
"math/big" "math/big"
"time" "time"
...@@ -29,6 +30,8 @@ type EthClient interface { ...@@ -29,6 +30,8 @@ type EthClient interface {
BlockHeadersByRange(*big.Int, *big.Int) ([]*types.Header, error) BlockHeadersByRange(*big.Int, *big.Int) ([]*types.Header, error)
BlockHeaderByHash(common.Hash) (*types.Header, error) BlockHeaderByHash(common.Hash) (*types.Header, error)
StorageHash(common.Address, *big.Int) (common.Hash, error)
RawRpcClient() *rpc.Client RawRpcClient() *rpc.Client
} }
...@@ -36,7 +39,7 @@ type client struct { ...@@ -36,7 +39,7 @@ type client struct {
rpcClient *rpc.Client rpcClient *rpc.Client
} }
func NewEthClient(rpcUrl string) (EthClient, error) { func DialEthClient(rpcUrl string) (EthClient, error) {
ctxwt, cancel := context.WithTimeout(context.Background(), defaultDialTimeout) ctxwt, cancel := context.WithTimeout(context.Background(), defaultDialTimeout)
defer cancel() defer cancel()
...@@ -49,6 +52,10 @@ func NewEthClient(rpcUrl string) (EthClient, error) { ...@@ -49,6 +52,10 @@ func NewEthClient(rpcUrl string) (EthClient, error) {
return client, nil return client, nil
} }
func NewEthClient(rpcClient *rpc.Client) EthClient {
return &client{rpcClient}
}
func (c *client) RawRpcClient() *rpc.Client { func (c *client) RawRpcClient() *rpc.Client {
return c.rpcClient return c.rpcClient
} }
...@@ -136,15 +143,33 @@ func (c *client) BlockHeadersByRange(startHeight, endHeight *big.Int) ([]*types. ...@@ -136,15 +143,33 @@ func (c *client) BlockHeadersByRange(startHeight, endHeight *big.Int) ([]*types.
return headers, nil return headers, nil
} }
// StorageHash returns the sha3 of the storage root for the specified account
func (c *client) StorageHash(address common.Address, blockNumber *big.Int) (common.Hash, error) {
ctxwt, cancel := context.WithTimeout(context.Background(), defaultRequestTimeout)
defer cancel()
proof := struct{ StorageHash common.Hash }{}
err := c.rpcClient.CallContext(ctxwt, &proof, "eth_getProof", address, nil, toBlockNumArg(blockNumber))
if err != nil {
return common.Hash{}, err
}
return proof.StorageHash, nil
}
func toBlockNumArg(number *big.Int) string { func toBlockNumArg(number *big.Int) string {
if number == nil { if number == nil {
return "latest" return "latest"
} else if number.Sign() >= 0 {
return hexutil.EncodeBig(number)
} }
pending := big.NewInt(-1) // It's negative.
if number.Cmp(pending) == 0 { if number.IsInt64() {
return "pending" tag, _ := rpc.BlockNumber(number.Int64()).MarshalText()
return string(tag)
} }
return hexutil.EncodeBig(number) // It's negative and large, which is invalid.
return fmt.Sprintf("<invalid %d>", number)
} }
...@@ -31,6 +31,11 @@ func (m *MockEthClient) BlockHeaderByHash(hash common.Hash) (*types.Header, erro ...@@ -31,6 +31,11 @@ func (m *MockEthClient) BlockHeaderByHash(hash common.Hash) (*types.Header, erro
return args.Get(0).(*types.Header), args.Error(1) return args.Get(0).(*types.Header), args.Error(1)
} }
func (m *MockEthClient) StorageHash(address common.Address, blockNumber *big.Int) (common.Hash, error) {
args := m.Called(address, blockNumber)
return args.Get(0).(common.Hash), args.Error(1)
}
func (m *MockEthClient) RawRpcClient() *rpc.Client { func (m *MockEthClient) RawRpcClient() *rpc.Client {
args := m.Called() args := m.Called()
return args.Get(0).(*rpc.Client) return args.Get(0).(*rpc.Client)
......
...@@ -4,8 +4,8 @@ import ( ...@@ -4,8 +4,8 @@ import (
"math/big" "math/big"
"testing" "testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock" "github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
) )
...@@ -43,8 +43,8 @@ func TestHeaderTraversalNextFinalizedHeadersNoOp(t *testing.T) { ...@@ -43,8 +43,8 @@ func TestHeaderTraversalNextFinalizedHeadersNoOp(t *testing.T) {
// no new headers when matched with head // no new headers when matched with head
client.On("FinalizedBlockHeight").Return(big.NewInt(10), nil) client.On("FinalizedBlockHeight").Return(big.NewInt(10), nil)
headers, err := headerTraversal.NextFinalizedHeaders(100) headers, err := headerTraversal.NextFinalizedHeaders(100)
assert.NoError(t, err) require.NoError(t, err)
assert.Empty(t, headers) require.Empty(t, headers)
} }
func TestHeaderTraversalNextFinalizedHeadersCursored(t *testing.T) { func TestHeaderTraversalNextFinalizedHeadersCursored(t *testing.T) {
...@@ -58,16 +58,16 @@ func TestHeaderTraversalNextFinalizedHeadersCursored(t *testing.T) { ...@@ -58,16 +58,16 @@ func TestHeaderTraversalNextFinalizedHeadersCursored(t *testing.T) {
client.On("FinalizedBlockHeight").Return(big.NewInt(4), nil).Times(1) // Times so that we can override next client.On("FinalizedBlockHeight").Return(big.NewInt(4), nil).Times(1) // Times so that we can override next
client.On("BlockHeadersByRange", mock.MatchedBy(bigIntMatcher(0)), mock.MatchedBy(bigIntMatcher(4))).Return(headers, nil) client.On("BlockHeadersByRange", mock.MatchedBy(bigIntMatcher(0)), mock.MatchedBy(bigIntMatcher(4))).Return(headers, nil)
headers, err := headerTraversal.NextFinalizedHeaders(5) headers, err := headerTraversal.NextFinalizedHeaders(5)
assert.NoError(t, err) require.NoError(t, err)
assert.Len(t, headers, 5) require.Len(t, headers, 5)
// blocks [5..9] // blocks [5..9]
headers = makeHeaders(5, headers[len(headers)-1]) headers = makeHeaders(5, headers[len(headers)-1])
client.On("FinalizedBlockHeight").Return(big.NewInt(9), nil) client.On("FinalizedBlockHeight").Return(big.NewInt(9), nil)
client.On("BlockHeadersByRange", mock.MatchedBy(bigIntMatcher(5)), mock.MatchedBy(bigIntMatcher(9))).Return(headers, nil) client.On("BlockHeadersByRange", mock.MatchedBy(bigIntMatcher(5)), mock.MatchedBy(bigIntMatcher(9))).Return(headers, nil)
headers, err = headerTraversal.NextFinalizedHeaders(5) headers, err = headerTraversal.NextFinalizedHeaders(5)
assert.NoError(t, err) require.NoError(t, err)
assert.Len(t, headers, 5) require.Len(t, headers, 5)
} }
func TestHeaderTraversalNextFinalizedHeadersMaxSize(t *testing.T) { func TestHeaderTraversalNextFinalizedHeadersMaxSize(t *testing.T) {
...@@ -83,15 +83,15 @@ func TestHeaderTraversalNextFinalizedHeadersMaxSize(t *testing.T) { ...@@ -83,15 +83,15 @@ func TestHeaderTraversalNextFinalizedHeadersMaxSize(t *testing.T) {
headers := makeHeaders(5, nil) headers := makeHeaders(5, nil)
client.On("BlockHeadersByRange", mock.MatchedBy(bigIntMatcher(0)), mock.MatchedBy(bigIntMatcher(4))).Return(headers, nil) client.On("BlockHeadersByRange", mock.MatchedBy(bigIntMatcher(0)), mock.MatchedBy(bigIntMatcher(4))).Return(headers, nil)
headers, err := headerTraversal.NextFinalizedHeaders(5) headers, err := headerTraversal.NextFinalizedHeaders(5)
assert.NoError(t, err) require.NoError(t, err)
assert.Len(t, headers, 5) require.Len(t, headers, 5)
// clamped by the supplied size. FinalizedHeight == 100 // clamped by the supplied size. FinalizedHeight == 100
headers = makeHeaders(10, headers[len(headers)-1]) headers = makeHeaders(10, headers[len(headers)-1])
client.On("BlockHeadersByRange", mock.MatchedBy(bigIntMatcher(5)), mock.MatchedBy(bigIntMatcher(14))).Return(headers, nil) client.On("BlockHeadersByRange", mock.MatchedBy(bigIntMatcher(5)), mock.MatchedBy(bigIntMatcher(14))).Return(headers, nil)
headers, err = headerTraversal.NextFinalizedHeaders(10) headers, err = headerTraversal.NextFinalizedHeaders(10)
assert.NoError(t, err) require.NoError(t, err)
assert.Len(t, headers, 10) require.Len(t, headers, 10)
} }
func TestHeaderTraversalMismatchedProviderStateError(t *testing.T) { func TestHeaderTraversalMismatchedProviderStateError(t *testing.T) {
...@@ -105,14 +105,14 @@ func TestHeaderTraversalMismatchedProviderStateError(t *testing.T) { ...@@ -105,14 +105,14 @@ func TestHeaderTraversalMismatchedProviderStateError(t *testing.T) {
client.On("FinalizedBlockHeight").Return(big.NewInt(4), nil).Times(1) // Times so that we can override next client.On("FinalizedBlockHeight").Return(big.NewInt(4), nil).Times(1) // Times so that we can override next
client.On("BlockHeadersByRange", mock.MatchedBy(bigIntMatcher(0)), mock.MatchedBy(bigIntMatcher(4))).Return(headers, nil) client.On("BlockHeadersByRange", mock.MatchedBy(bigIntMatcher(0)), mock.MatchedBy(bigIntMatcher(4))).Return(headers, nil)
headers, err := headerTraversal.NextFinalizedHeaders(5) headers, err := headerTraversal.NextFinalizedHeaders(5)
assert.NoError(t, err) require.NoError(t, err)
assert.Len(t, headers, 5) require.Len(t, headers, 5)
// blocks [5..9]. Next batch is not chained correctly (starts again from genesis) // blocks [5..9]. Next batch is not chained correctly (starts again from genesis)
headers = makeHeaders(5, nil) headers = makeHeaders(5, nil)
client.On("FinalizedBlockHeight").Return(big.NewInt(9), nil) client.On("FinalizedBlockHeight").Return(big.NewInt(9), nil)
client.On("BlockHeadersByRange", mock.MatchedBy(bigIntMatcher(5)), mock.MatchedBy(bigIntMatcher(9))).Return(headers, nil) client.On("BlockHeadersByRange", mock.MatchedBy(bigIntMatcher(5)), mock.MatchedBy(bigIntMatcher(9))).Return(headers, nil)
headers, err = headerTraversal.NextFinalizedHeaders(5) headers, err = headerTraversal.NextFinalizedHeaders(5)
assert.Nil(t, headers) require.Nil(t, headers)
assert.Equal(t, ErrHeaderTraversalAndProviderMismatchedState, err) require.Equal(t, ErrHeaderTraversalAndProviderMismatchedState, err)
} }
...@@ -2,9 +2,7 @@ package processor ...@@ -2,9 +2,7 @@ package processor
import ( import (
"context" "context"
"encoding/hex"
"errors" "errors"
"math/big"
"reflect" "reflect"
"github.com/google/uuid" "github.com/google/uuid"
...@@ -36,12 +34,17 @@ type L1Contracts struct { ...@@ -36,12 +34,17 @@ type L1Contracts struct {
// Remove afterwards? // Remove afterwards?
} }
type checkpointAbi struct { func DevL1Contracts() L1Contracts {
l2OutputOracle *abi.ABI return L1Contracts{
legacyStateCommitmentChain *abi.ABI OptimismPortal: common.HexToAddress("0x6900000000000000000000000000000000000000"),
L2OutputOracle: common.HexToAddress("0x6900000000000000000000000000000000000001"),
L1CrossDomainMessenger: common.HexToAddress("0x6900000000000000000000000000000000000002"),
L1StandardBridge: common.HexToAddress("0x6900000000000000000000000000000000000003"),
L1ERC721Bridge: common.HexToAddress("0x6900000000000000000000000000000000000004"),
}
} }
func (c L1Contracts) toSlice() []common.Address { func (c L1Contracts) ToSlice() []common.Address {
fields := reflect.VisibleFields(reflect.TypeOf(c)) fields := reflect.VisibleFields(reflect.TypeOf(c))
v := reflect.ValueOf(c) v := reflect.ValueOf(c)
...@@ -53,12 +56,17 @@ func (c L1Contracts) toSlice() []common.Address { ...@@ -53,12 +56,17 @@ func (c L1Contracts) toSlice() []common.Address {
return contracts return contracts
} }
type checkpointAbi struct {
l2OutputOracle *abi.ABI
legacyStateCommitmentChain *abi.ABI
}
type L1Processor struct { type L1Processor struct {
processor processor
} }
func NewL1Processor(ethClient node.EthClient, db *database.DB, l1Contracts L1Contracts) (*L1Processor, error) { func NewL1Processor(logger log.Logger, ethClient node.EthClient, db *database.DB, l1Contracts L1Contracts) (*L1Processor, error) {
l1ProcessLog := log.New("processor", "l1") l1ProcessLog := logger.New("processor", "l1")
l1ProcessLog.Info("initializing processor") l1ProcessLog.Info("initializing processor")
l2OutputOracleABI, err := bindings.L2OutputOracleMetaData.GetAbi() l2OutputOracleABI, err := bindings.L2OutputOracleMetaData.GetAbi()
...@@ -109,14 +117,16 @@ func NewL1Processor(ethClient node.EthClient, db *database.DB, l1Contracts L1Con ...@@ -109,14 +117,16 @@ func NewL1Processor(ethClient node.EthClient, db *database.DB, l1Contracts L1Con
func l1ProcessFn(processLog log.Logger, ethClient node.EthClient, l1Contracts L1Contracts, checkpointAbi checkpointAbi) ProcessFn { func l1ProcessFn(processLog log.Logger, ethClient node.EthClient, l1Contracts L1Contracts, checkpointAbi checkpointAbi) ProcessFn {
rawEthClient := ethclient.NewClient(ethClient.RawRpcClient()) rawEthClient := ethclient.NewClient(ethClient.RawRpcClient())
contractAddrs := l1Contracts.toSlice() contractAddrs := l1Contracts.ToSlice()
processLog.Info("processor configured with contracts", "contracts", l1Contracts) processLog.Info("processor configured with contracts", "contracts", l1Contracts)
outputProposedEventSig := checkpointAbi.l2OutputOracle.Events["OutputProposed"].ID outputProposedEventName := "OutputProposed"
legacyStateBatchAppendedEventSig := checkpointAbi.legacyStateCommitmentChain.Events["StateBatchAppended"].ID outputProposedEventSig := checkpointAbi.l2OutputOracle.Events[outputProposedEventName].ID
legacyStateBatchAppendedEventName := "StateBatchAppended"
legacyStateBatchAppendedEventSig := checkpointAbi.legacyStateCommitmentChain.Events[legacyStateBatchAppendedEventName].ID
return func(db *database.DB, headers []*types.Header) error { return func(db *database.DB, headers []*types.Header) error {
numHeaders := len(headers)
headerMap := make(map[common.Hash]*types.Header) headerMap := make(map[common.Hash]*types.Header)
for _, header := range headers { for _, header := range headers {
headerMap[header.Hash()] = header headerMap[header.Hash()] = header
...@@ -124,7 +134,7 @@ func l1ProcessFn(processLog log.Logger, ethClient node.EthClient, l1Contracts L1 ...@@ -124,7 +134,7 @@ func l1ProcessFn(processLog log.Logger, ethClient node.EthClient, l1Contracts L1
/** Watch for all Optimism Contract Events **/ /** Watch for all Optimism Contract Events **/
logFilter := ethereum.FilterQuery{FromBlock: headers[0].Number, ToBlock: headers[numHeaders-1].Number, Addresses: contractAddrs} logFilter := ethereum.FilterQuery{FromBlock: headers[0].Number, ToBlock: headers[len(headers)-1].Number, Addresses: contractAddrs}
logs, err := rawEthClient.FilterLogs(context.Background(), logFilter) // []types.Log logs, err := rawEthClient.FilterLogs(context.Background(), logFilter) // []types.Log
if err != nil { if err != nil {
return err return err
...@@ -138,41 +148,43 @@ func l1ProcessFn(processLog log.Logger, ethClient node.EthClient, l1Contracts L1 ...@@ -138,41 +148,43 @@ func l1ProcessFn(processLog log.Logger, ethClient node.EthClient, l1Contracts L1
l1ContractEvents := make([]*database.L1ContractEvent, len(logs)) l1ContractEvents := make([]*database.L1ContractEvent, len(logs))
processedContractEvents := NewProcessedContractEvents() processedContractEvents := NewProcessedContractEvents()
for i, log := range logs { for i := range logs {
log := &logs[i]
header, ok := headerMap[log.BlockHash] header, ok := headerMap[log.BlockHash]
if !ok { if !ok {
processLog.Error("contract event found with associated header not in the batch", "header", log.BlockHash, "log_index", log.Index) processLog.Error("contract event found with associated header not in the batch", "header", log.BlockHash, "log_index", log.Index)
return errors.New("parsed log with a block hash not in this batch") return errors.New("parsed log with a block hash not in this batch")
} }
contractEvent := processedContractEvents.AddLog(&logs[i], header.Time) contractEvent := processedContractEvents.AddLog(log, header.Time)
l1HeadersOfInterest[log.BlockHash] = true l1HeadersOfInterest[log.BlockHash] = true
l1ContractEvents[i] = &database.L1ContractEvent{ContractEvent: *contractEvent} l1ContractEvents[i] = &database.L1ContractEvent{ContractEvent: *contractEvent}
// Track Checkpoint Events for L2 // Track Checkpoint Events for L2
switch contractEvent.EventSignature { switch contractEvent.EventSignature {
case outputProposedEventSig: case outputProposedEventSig:
if len(log.Topics) != 4 { var outputProposed bindings.L2OutputOracleOutputProposed
processLog.Error("parsed unexpected number of L2OutputOracle#OutputProposed log topics", "log_topics", log.Topics) err := UnpackLog(&outputProposed, log, outputProposedEventName, checkpointAbi.l2OutputOracle)
return errors.New("parsed unexpected OutputProposed event") if err != nil {
return err
} }
outputProposals = append(outputProposals, &database.OutputProposal{ outputProposals = append(outputProposals, &database.OutputProposal{
OutputRoot: log.Topics[1], OutputRoot: outputProposed.OutputRoot,
L2BlockNumber: database.U256{Int: new(big.Int).SetBytes(log.Topics[2].Bytes())}, L2OutputIndex: database.U256{Int: outputProposed.L2OutputIndex},
L2BlockNumber: database.U256{Int: outputProposed.L2BlockNumber},
L1ContractEventGUID: contractEvent.GUID, L1ContractEventGUID: contractEvent.GUID,
}) })
case legacyStateBatchAppendedEventSig: case legacyStateBatchAppendedEventSig:
var stateBatchAppended legacy_bindings.StateCommitmentChainStateBatchAppended var stateBatchAppended legacy_bindings.StateCommitmentChainStateBatchAppended
err := checkpointAbi.l2OutputOracle.UnpackIntoInterface(&stateBatchAppended, "StateBatchAppended", log.Data) err := UnpackLog(&stateBatchAppended, log, legacyStateBatchAppendedEventName, checkpointAbi.legacyStateCommitmentChain)
if err != nil || len(log.Topics) != 2 { if err != nil {
processLog.Error("unexpected StateCommitmentChain#StateBatchAppended log data or log topics", "log_topics", log.Topics, "log_data", hex.EncodeToString(log.Data), "err", err)
return err return err
} }
legacyStateBatches = append(legacyStateBatches, &database.LegacyStateBatch{ legacyStateBatches = append(legacyStateBatches, &database.LegacyStateBatch{
Index: new(big.Int).SetBytes(log.Topics[1].Bytes()).Uint64(), Index: stateBatchAppended.BatchIndex.Uint64(),
Root: stateBatchAppended.BatchRoot, Root: stateBatchAppended.BatchRoot,
Size: stateBatchAppended.BatchSize.Uint64(), Size: stateBatchAppended.BatchSize.Uint64(),
PrevTotal: stateBatchAppended.PrevTotalElements.Uint64(), PrevTotal: stateBatchAppended.PrevTotalElements.Uint64(),
...@@ -199,7 +211,7 @@ func l1ProcessFn(processLog log.Logger, ethClient node.EthClient, l1Contracts L1 ...@@ -199,7 +211,7 @@ func l1ProcessFn(processLog log.Logger, ethClient node.EthClient, l1Contracts L1
numIndexedL1Headers := len(indexedL1Headers) numIndexedL1Headers := len(indexedL1Headers)
if numIndexedL1Headers > 0 { if numIndexedL1Headers > 0 {
processLog.Info("saving l1 blocks with optimism logs", "size", numIndexedL1Headers, "batch_size", numHeaders) processLog.Info("saving l1 blocks with optimism logs", "size", numIndexedL1Headers, "batch_size", len(headers))
err = db.Blocks.StoreL1BlockHeaders(indexedL1Headers) err = db.Blocks.StoreL1BlockHeaders(indexedL1Headers)
if err != nil { if err != nil {
return err return err
...@@ -296,15 +308,16 @@ func l1BridgeProcessContractEvents(processLog log.Logger, db *database.DB, ethCl ...@@ -296,15 +308,16 @@ func l1BridgeProcessContractEvents(processLog log.Logger, db *database.DB, ethCl
// Check if the L2Processor is behind or really has missed an event. We can compare against the // Check if the L2Processor is behind or really has missed an event. We can compare against the
// OptimismPortal#ProvenWithdrawal on-chain mapping relative to the latest indexed L2 height // OptimismPortal#ProvenWithdrawal on-chain mapping relative to the latest indexed L2 height
if withdrawal == nil { if withdrawal == nil {
bridgeAddress := l1Contracts.L1StandardBridge
portalAddress := l1Contracts.OptimismPortal // This needs to be updated to read from config as well as correctly identify if the CrossDomainMessenger message is a standard
if provenWithdrawalEvent.From != bridgeAddress || provenWithdrawalEvent.To != bridgeAddress { // bridge message. This will easier to do once we index passed messages separately which will include the right To/From fields
if provenWithdrawalEvent.From != common.HexToAddress("0x4200000000000000000000000000000000000007") || provenWithdrawalEvent.To != l1Contracts.L1CrossDomainMessenger {
// non-bridge withdrawal // non-bridge withdrawal
continue continue
} }
// Query for the the proven withdrawal on-chain // Query for the the proven withdrawal on-chain
provenWithdrawal, err := OptimismPortalQueryProvenWithdrawal(rawEthClient, portalAddress, withdrawalHash) provenWithdrawal, err := OptimismPortalQueryProvenWithdrawal(rawEthClient, l1Contracts.OptimismPortal, withdrawalHash)
if err != nil { if err != nil {
return err return err
} }
...@@ -349,8 +362,8 @@ func l1BridgeProcessContractEvents(processLog log.Logger, db *database.DB, ethCl ...@@ -349,8 +362,8 @@ func l1BridgeProcessContractEvents(processLog log.Logger, db *database.DB, ethCl
return err return err
} }
// Since we have to prove the event on-chain first, we don't need to check if the processor is // Since we have to prove the event on-chain first, we don't need to check if the processor is behind
// behind. we're definitely in an error state if we cannot find the withdrawal when parsing this even // We're definitely in an error state if we cannot find the withdrawal when parsing this event
if withdrawal == nil { if withdrawal == nil {
processLog.Crit("missing indexed withdrawal for this finalization event") processLog.Crit("missing indexed withdrawal for this finalization event")
return errors.New("missing withdrawal message") return errors.New("missing withdrawal message")
......
...@@ -39,7 +39,7 @@ func L2ContractPredeploys() L2Contracts { ...@@ -39,7 +39,7 @@ func L2ContractPredeploys() L2Contracts {
} }
} }
func (c L2Contracts) toSlice() []common.Address { func (c L2Contracts) ToSlice() []common.Address {
fields := reflect.VisibleFields(reflect.TypeOf(c)) fields := reflect.VisibleFields(reflect.TypeOf(c))
v := reflect.ValueOf(c) v := reflect.ValueOf(c)
...@@ -55,8 +55,8 @@ type L2Processor struct { ...@@ -55,8 +55,8 @@ type L2Processor struct {
processor processor
} }
func NewL2Processor(ethClient node.EthClient, db *database.DB, l2Contracts L2Contracts) (*L2Processor, error) { func NewL2Processor(logger log.Logger, ethClient node.EthClient, db *database.DB, l2Contracts L2Contracts) (*L2Processor, error) {
l2ProcessLog := log.New("processor", "l2") l2ProcessLog := logger.New("processor", "l2")
l2ProcessLog.Info("initializing processor") l2ProcessLog.Info("initializing processor")
latestHeader, err := db.Blocks.LatestL2BlockHeader() latestHeader, err := db.Blocks.LatestL2BlockHeader()
...@@ -94,7 +94,7 @@ func NewL2Processor(ethClient node.EthClient, db *database.DB, l2Contracts L2Con ...@@ -94,7 +94,7 @@ func NewL2Processor(ethClient node.EthClient, db *database.DB, l2Contracts L2Con
func l2ProcessFn(processLog log.Logger, ethClient node.EthClient, l2Contracts L2Contracts) ProcessFn { func l2ProcessFn(processLog log.Logger, ethClient node.EthClient, l2Contracts L2Contracts) ProcessFn {
rawEthClient := ethclient.NewClient(ethClient.RawRpcClient()) rawEthClient := ethclient.NewClient(ethClient.RawRpcClient())
contractAddrs := l2Contracts.toSlice() contractAddrs := l2Contracts.ToSlice()
processLog.Info("processor configured with contracts", "contracts", l2Contracts) processLog.Info("processor configured with contracts", "contracts", l2Contracts)
return func(db *database.DB, headers []*types.Header) error { return func(db *database.DB, headers []*types.Header) error {
numHeaders := len(headers) numHeaders := len(headers)
...@@ -127,14 +127,15 @@ func l2ProcessFn(processLog log.Logger, ethClient node.EthClient, l2Contracts L2 ...@@ -127,14 +127,15 @@ func l2ProcessFn(processLog log.Logger, ethClient node.EthClient, l2Contracts L2
l2ContractEvents := make([]*database.L2ContractEvent, len(logs)) l2ContractEvents := make([]*database.L2ContractEvent, len(logs))
processedContractEvents := NewProcessedContractEvents() processedContractEvents := NewProcessedContractEvents()
for i, log := range logs { for i := range logs {
log := &logs[i]
header, ok := l2HeaderMap[log.BlockHash] header, ok := l2HeaderMap[log.BlockHash]
if !ok { if !ok {
processLog.Error("contract event found with associated header not in the batch", "header", header, "log_index", log.Index) processLog.Error("contract event found with associated header not in the batch", "header", header, "log_index", log.Index)
return errors.New("parsed log with a block hash not in this batch") return errors.New("parsed log with a block hash not in this batch")
} }
contractEvent := processedContractEvents.AddLog(&logs[i], header.Time) contractEvent := processedContractEvents.AddLog(log, header.Time)
l2ContractEvents[i] = &database.L2ContractEvent{ContractEvent: *contractEvent} l2ContractEvents[i] = &database.L2ContractEvent{ContractEvent: *contractEvent}
} }
......
...@@ -30,11 +30,20 @@ func OptimismPortalWithdrawalProvenEvents(events *ProcessedContractEvents) ([]Op ...@@ -30,11 +30,20 @@ func OptimismPortalWithdrawalProvenEvents(events *ProcessedContractEvents) ([]Op
return nil, err return nil, err
} }
processedWithdrawalProvenEvents := events.eventsBySignature[optimismPortalAbi.Events["WithdrawalProven"].ID] eventName := "WithdrawalProven"
processedWithdrawalProvenEvents := events.eventsBySignature[optimismPortalAbi.Events[eventName].ID]
provenEvents := make([]OptimismPortalWithdrawalProvenEvent, len(processedWithdrawalProvenEvents)) provenEvents := make([]OptimismPortalWithdrawalProvenEvent, len(processedWithdrawalProvenEvents))
for i, provenEvent := range processedWithdrawalProvenEvents { for i, provenEvent := range processedWithdrawalProvenEvents {
log := events.eventLog[provenEvent.GUID]
var withdrawalProven bindings.OptimismPortalWithdrawalProven
err := UnpackLog(&withdrawalProven, log, eventName, optimismPortalAbi)
if err != nil {
return nil, err
}
provenEvents[i] = OptimismPortalWithdrawalProvenEvent{nil, provenEvent} provenEvents[i] = OptimismPortalWithdrawalProvenEvent{&withdrawalProven, provenEvent}
} }
return provenEvents, nil return provenEvents, nil
......
package processor package processor
import ( import (
"context"
"time" "time"
"github.com/ethereum-optimism/optimism/indexer/database" "github.com/ethereum-optimism/optimism/indexer/database"
...@@ -25,46 +26,81 @@ type processor struct { ...@@ -25,46 +26,81 @@ type processor struct {
db *database.DB db *database.DB
processFn ProcessFn processFn ProcessFn
processLog log.Logger processLog log.Logger
paused bool
latestProcessedHeader *types.Header
} }
// Start kicks off the processing loop // Start kicks off the processing loop. This is a block operation
func (p processor) Start() { // unless the processor encountering an error, abrupting the loop,
// or the supplied context is cancelled.
func (p *processor) Start(ctx context.Context) error {
done := ctx.Done()
pollTicker := time.NewTicker(defaultLoopInterval) pollTicker := time.NewTicker(defaultLoopInterval)
defer pollTicker.Stop() defer pollTicker.Stop()
p.processLog.Info("starting processor...") p.processLog.Info("starting processor...")
var unprocessedHeaders []*types.Header var unprocessedHeaders []*types.Header
for range pollTicker.C { for {
if len(unprocessedHeaders) == 0 { select {
newHeaders, err := p.headerTraversal.NextFinalizedHeaders(defaultHeaderBufferSize) case <-done:
if err != nil { p.processLog.Info("stopping processor")
p.processLog.Error("error querying for headers", "err", err) return nil
continue
} else if len(newHeaders) == 0 { case <-pollTicker.C:
// Logged as an error since this loop should be operating at a longer interval than the provider if p.paused {
p.processLog.Error("no new headers. processor unexpectedly at head...") p.processLog.Warn("processor is paused...")
continue continue
} }
unprocessedHeaders = newHeaders if len(unprocessedHeaders) == 0 {
} else { newHeaders, err := p.headerTraversal.NextFinalizedHeaders(defaultHeaderBufferSize)
p.processLog.Info("retrying previous batch") if err != nil {
} p.processLog.Error("error querying for headers", "err", err)
continue
} else if len(newHeaders) == 0 {
// Logged as an error since this loop should be operating at a longer interval than the provider
p.processLog.Error("no new headers. processor unexpectedly at head...")
continue
}
unprocessedHeaders = newHeaders
} else {
p.processLog.Info("retrying previous batch")
}
firstHeader := unprocessedHeaders[0] firstHeader := unprocessedHeaders[0]
lastHeader := unprocessedHeaders[len(unprocessedHeaders)-1] lastHeader := unprocessedHeaders[len(unprocessedHeaders)-1]
batchLog := p.processLog.New("batch_start_block_number", firstHeader.Number, "batch_end_block_number", lastHeader.Number) batchLog := p.processLog.New("batch_start_block_number", firstHeader.Number, "batch_end_block_number", lastHeader.Number)
err := p.db.Transaction(func(db *database.DB) error { err := p.db.Transaction(func(db *database.DB) error {
batchLog.Info("processing batch") batchLog.Info("processing batch")
return p.processFn(db, unprocessedHeaders) return p.processFn(db, unprocessedHeaders)
}) })
if err != nil { // Eventually, we want to halt the processor on any error rather than rely
batchLog.Warn("error processing batch. no operations committed", "err", err) // on this loop for retry functionality.
} else { if err != nil {
batchLog.Info("fully committed batch") batchLog.Warn("error processing batch. no operations committed", "err", err)
unprocessedHeaders = nil } else {
batchLog.Info("fully committed batch")
unprocessedHeaders = nil
p.latestProcessedHeader = lastHeader
}
} }
} }
} }
func (p processor) LatestProcessedHeader() *types.Header {
return p.latestProcessedHeader
}
// Useful ONLY for tests!
func (p *processor) PauseForTest() {
p.paused = true
}
func (p *processor) ResumeForTest() {
p.paused = false
}
...@@ -4,6 +4,7 @@ import ( ...@@ -4,6 +4,7 @@ import (
"bytes" "bytes"
"context" "context"
"errors" "errors"
"fmt"
"math/big" "math/big"
"github.com/ethereum-optimism/optimism/indexer/database" "github.com/ethereum-optimism/optimism/indexer/database"
...@@ -14,7 +15,7 @@ import ( ...@@ -14,7 +15,7 @@ import (
) )
var ( var (
ethAddress = common.HexToAddress("0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000") EthAddress = common.HexToAddress("0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000")
) )
type StandardBridgeInitiatedEvent struct { type StandardBridgeInitiatedEvent struct {
...@@ -131,7 +132,7 @@ func _standardBridgeInitiatedEvents[BridgeEvent bindings.L1StandardBridgeETHBrid ...@@ -131,7 +132,7 @@ func _standardBridgeInitiatedEvents[BridgeEvent bindings.L1StandardBridgeETHBrid
// represent eth bridge as an erc20 // represent eth bridge as an erc20
erc20BridgeData = &bindings.L1StandardBridgeERC20BridgeInitiated{ erc20BridgeData = &bindings.L1StandardBridgeERC20BridgeInitiated{
// Represent ETH using the hardcoded address // Represent ETH using the hardcoded address
LocalToken: ethAddress, RemoteToken: ethAddress, LocalToken: EthAddress, RemoteToken: EthAddress,
// Bridge data // Bridge data
From: ethBridgeData.From, To: ethBridgeData.To, Amount: ethBridgeData.Amount, ExtraData: ethBridgeData.ExtraData, From: ethBridgeData.From, To: ethBridgeData.To, Amount: ethBridgeData.Amount, ExtraData: ethBridgeData.ExtraData,
} }
...@@ -170,8 +171,14 @@ func _standardBridgeFinalizedEvents[BridgeEvent bindings.L1StandardBridgeETHBrid ...@@ -170,8 +171,14 @@ func _standardBridgeFinalizedEvents[BridgeEvent bindings.L1StandardBridgeETHBrid
return nil, err return nil, err
} }
optimismPortalAbi, err := bindings.OptimismPortalMetaData.GetAbi()
if err != nil {
return nil, err
}
relayedMessageEventAbi := l1CrossDomainMessengerABI.Events["RelayedMessage"] relayedMessageEventAbi := l1CrossDomainMessengerABI.Events["RelayedMessage"]
relayMessageMethodAbi := l1CrossDomainMessengerABI.Methods["relayMessage"] relayMessageMethodAbi := l1CrossDomainMessengerABI.Methods["relayMessage"]
finalizeWithdrawalTransactionMethodAbi := optimismPortalAbi.Methods["finalizeWithdrawalTransaction"]
var bridgeData BridgeEvent var bridgeData BridgeEvent
var eventName string var eventName string
...@@ -201,27 +208,52 @@ func _standardBridgeFinalizedEvents[BridgeEvent bindings.L1StandardBridgeETHBrid ...@@ -201,27 +208,52 @@ func _standardBridgeFinalizedEvents[BridgeEvent bindings.L1StandardBridgeETHBrid
return nil, errors.New("unexpected bridge event ordering") return nil, errors.New("unexpected bridge event ordering")
} }
// There's no way to extract the nonce on the relayed message event. we can extract // There's no way to extract the nonce on the relayed message event. we can extract the nonce by
// the nonce by unpacking the transaction input for the `relayMessage` transaction // by unpacking the transaction input for the `relayMessage` transaction. Since bedrock has OptimismPortal
// as on L1 as an intermediary for finalization, we have to check both scenarios
tx, isPending, err := rawEthClient.TransactionByHash(context.Background(), relayedMsgLog.TxHash) tx, isPending, err := rawEthClient.TransactionByHash(context.Background(), relayedMsgLog.TxHash)
if err != nil || isPending { if err != nil || isPending {
return nil, errors.New("unable to query relayMessage tx for bridge finalization event") return nil, errors.New("unable to query relayMessage tx for bridge finalization event")
} }
txData := tx.Data() // If this is a finalization step with the optimism portal, the calldata for relayMessage invocation can be
if !bytes.Equal(txData[:4], relayMessageMethodAbi.ID) { // extracted from the withdrawal transaction.
return nil, errors.New("bridge finalization event does not match relayMessage tx invocation")
// NOTE: the L2CrossDomainMessenger nonce may not match the L2ToL1MessagePasser nonce, hence the additional
// layer of decoding vs reading the nocne of the withdrawal transaction. Both nonces have a similar but
// different lifeycle that might not match (i.e L2ToL1MessagePasser can be invoced directly)
var relayMsgCallData []byte
switch {
case bytes.Equal(tx.Data()[:4], relayMessageMethodAbi.ID):
relayMsgCallData = tx.Data()[4:]
case bytes.Equal(tx.Data()[:4], finalizeWithdrawalTransactionMethodAbi.ID):
data, err := finalizeWithdrawalTransactionMethodAbi.Inputs.Unpack(tx.Data()[4:])
if err != nil {
return nil, err
}
finalizeWithdrawTransactionInput := new(struct {
Tx bindings.TypesWithdrawalTransaction
})
err = finalizeWithdrawalTransactionMethodAbi.Inputs.Copy(finalizeWithdrawTransactionInput, data)
if err != nil {
return nil, fmt.Errorf("unable extract withdrawal tx input from finalizeWithdrawalTransaction calldata: %w", err)
} else if !bytes.Equal(finalizeWithdrawTransactionInput.Tx.Data[:4], relayMessageMethodAbi.ID) {
return nil, errors.New("finalizeWithdrawalTransaction calldata does not match relayMessage invocation")
}
relayMsgCallData = finalizeWithdrawTransactionInput.Tx.Data[4:]
default:
return nil, errors.New("bridge finalization event does not correlate with a relayMessage tx invocation")
} }
inputsMap := make(map[string]interface{}) inputsMap := make(map[string]interface{})
err = relayMessageMethodAbi.Inputs.UnpackIntoMap(inputsMap, txData[4:]) err = relayMessageMethodAbi.Inputs.UnpackIntoMap(inputsMap, relayMsgCallData)
if err != nil { if err != nil {
return nil, err return nil, err
} }
nonce, ok := inputsMap["_nonce"].(*big.Int) nonce, ok := inputsMap["_nonce"].(*big.Int)
if !ok { if !ok {
return nil, errors.New("unable to extract `_nonce` parameter from relayMessage transaction") return nil, errors.New("unable to extract `_nonce` parameter from relayMessage calldata")
} }
var erc20BridgeData *bindings.L1StandardBridgeERC20BridgeFinalized var erc20BridgeData *bindings.L1StandardBridgeERC20BridgeFinalized
...@@ -230,7 +262,7 @@ func _standardBridgeFinalizedEvents[BridgeEvent bindings.L1StandardBridgeETHBrid ...@@ -230,7 +262,7 @@ func _standardBridgeFinalizedEvents[BridgeEvent bindings.L1StandardBridgeETHBrid
ethBridgeData := any(bridgeData).(bindings.L1StandardBridgeETHBridgeFinalized) ethBridgeData := any(bridgeData).(bindings.L1StandardBridgeETHBridgeFinalized)
erc20BridgeData = &bindings.L1StandardBridgeERC20BridgeFinalized{ erc20BridgeData = &bindings.L1StandardBridgeERC20BridgeFinalized{
// Represent ETH using the hardcoded address // Represent ETH using the hardcoded address
LocalToken: ethAddress, RemoteToken: ethAddress, LocalToken: EthAddress, RemoteToken: EthAddress,
// Bridge data // Bridge data
From: ethBridgeData.From, To: ethBridgeData.To, Amount: ethBridgeData.Amount, ExtraData: ethBridgeData.ExtraData, From: ethBridgeData.From, To: ethBridgeData.To, Amount: ethBridgeData.Amount, ExtraData: ethBridgeData.ExtraData,
} }
......
...@@ -28,8 +28,11 @@ ...@@ -28,8 +28,11 @@
"L1BlockNumber", "L1BlockNumber",
"DisputeGameFactory", "DisputeGameFactory",
"FaultDisputeGame", "FaultDisputeGame",
"AlphabetVM",
"StandardBridge", "StandardBridge",
"CrossDomainMessenger", "CrossDomainMessenger",
"MIPS", "MIPS",
"PreimageOracle" "PreimageOracle",
"EAS",
"SchemaRegistry"
] ]
// Code generated - DO NOT EDIT.
// This file is a generated binding and any manual changes will be lost.
package bindings
import (
"errors"
"math/big"
"strings"
ethereum "github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/event"
)
// Reference imports to suppress errors if they are not otherwise used.
var (
_ = errors.New
_ = big.NewInt
_ = strings.NewReader
_ = ethereum.NotFound
_ = bind.Bind
_ = common.Big1
_ = types.BloomLookup
_ = event.NewSubscription
)
// AlphabetVMMetaData contains all meta data concerning the AlphabetVM contract.
var AlphabetVMMetaData = &bind.MetaData{
ABI: "[{\"inputs\":[{\"internalType\":\"Claim\",\"name\":\"_absolutePrestate\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_stateData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"step\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"postState_\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]",
Bin: "0x60a060405234801561001057600080fd5b5060405161030438038061030483398101604081905261002f91610037565b608052610050565b60006020828403121561004957600080fd5b5051919050565b60805161029a61006a6000396000605c015261029a6000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063f8e0cb9614610030575b600080fd5b61004361003e366004610157565b610055565b60405190815260200160405180910390f35b60008060007f0000000000000000000000000000000000000000000000000000000000000000878760405161008b9291906101c3565b6040518091039020036100af57600091506100a8868801886101d3565b90506100ce565b6100bb868801886101ec565b9092509050816100ca8161023d565b9250505b816100da826001610275565b6040805160208101939093528201526060016040516020818303038152906040528051906020012092505050949350505050565b60008083601f84011261012057600080fd5b50813567ffffffffffffffff81111561013857600080fd5b60208301915083602082850101111561015057600080fd5b9250929050565b6000806000806040858703121561016d57600080fd5b843567ffffffffffffffff8082111561018557600080fd5b6101918883890161010e565b909650945060208701359150808211156101aa57600080fd5b506101b78782880161010e565b95989497509550505050565b8183823760009101908152919050565b6000602082840312156101e557600080fd5b5035919050565b600080604083850312156101ff57600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361026e5761026e61020e565b5060010190565b600082198211156102885761028861020e565b50019056fea164736f6c634300080f000a",
}
// AlphabetVMABI is the input ABI used to generate the binding from.
// Deprecated: Use AlphabetVMMetaData.ABI instead.
var AlphabetVMABI = AlphabetVMMetaData.ABI
// AlphabetVMBin is the compiled bytecode used for deploying new contracts.
// Deprecated: Use AlphabetVMMetaData.Bin instead.
var AlphabetVMBin = AlphabetVMMetaData.Bin
// DeployAlphabetVM deploys a new Ethereum contract, binding an instance of AlphabetVM to it.
func DeployAlphabetVM(auth *bind.TransactOpts, backend bind.ContractBackend, _absolutePrestate [32]byte) (common.Address, *types.Transaction, *AlphabetVM, error) {
parsed, err := AlphabetVMMetaData.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(AlphabetVMBin), backend, _absolutePrestate)
if err != nil {
return common.Address{}, nil, nil, err
}
return address, tx, &AlphabetVM{AlphabetVMCaller: AlphabetVMCaller{contract: contract}, AlphabetVMTransactor: AlphabetVMTransactor{contract: contract}, AlphabetVMFilterer: AlphabetVMFilterer{contract: contract}}, nil
}
// AlphabetVM is an auto generated Go binding around an Ethereum contract.
type AlphabetVM struct {
AlphabetVMCaller // Read-only binding to the contract
AlphabetVMTransactor // Write-only binding to the contract
AlphabetVMFilterer // Log filterer for contract events
}
// AlphabetVMCaller is an auto generated read-only Go binding around an Ethereum contract.
type AlphabetVMCaller struct {
contract *bind.BoundContract // Generic contract wrapper for the low level calls
}
// AlphabetVMTransactor is an auto generated write-only Go binding around an Ethereum contract.
type AlphabetVMTransactor struct {
contract *bind.BoundContract // Generic contract wrapper for the low level calls
}
// AlphabetVMFilterer is an auto generated log filtering Go binding around an Ethereum contract events.
type AlphabetVMFilterer struct {
contract *bind.BoundContract // Generic contract wrapper for the low level calls
}
// AlphabetVMSession is an auto generated Go binding around an Ethereum contract,
// with pre-set call and transact options.
type AlphabetVMSession struct {
Contract *AlphabetVM // 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
}
// AlphabetVMCallerSession is an auto generated read-only Go binding around an Ethereum contract,
// with pre-set call options.
type AlphabetVMCallerSession struct {
Contract *AlphabetVMCaller // Generic contract caller binding to set the session for
CallOpts bind.CallOpts // Call options to use throughout this session
}
// AlphabetVMTransactorSession is an auto generated write-only Go binding around an Ethereum contract,
// with pre-set transact options.
type AlphabetVMTransactorSession struct {
Contract *AlphabetVMTransactor // Generic contract transactor binding to set the session for
TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
}
// AlphabetVMRaw is an auto generated low-level Go binding around an Ethereum contract.
type AlphabetVMRaw struct {
Contract *AlphabetVM // Generic contract binding to access the raw methods on
}
// AlphabetVMCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract.
type AlphabetVMCallerRaw struct {
Contract *AlphabetVMCaller // Generic read-only contract binding to access the raw methods on
}
// AlphabetVMTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract.
type AlphabetVMTransactorRaw struct {
Contract *AlphabetVMTransactor // Generic write-only contract binding to access the raw methods on
}
// NewAlphabetVM creates a new instance of AlphabetVM, bound to a specific deployed contract.
func NewAlphabetVM(address common.Address, backend bind.ContractBackend) (*AlphabetVM, error) {
contract, err := bindAlphabetVM(address, backend, backend, backend)
if err != nil {
return nil, err
}
return &AlphabetVM{AlphabetVMCaller: AlphabetVMCaller{contract: contract}, AlphabetVMTransactor: AlphabetVMTransactor{contract: contract}, AlphabetVMFilterer: AlphabetVMFilterer{contract: contract}}, nil
}
// NewAlphabetVMCaller creates a new read-only instance of AlphabetVM, bound to a specific deployed contract.
func NewAlphabetVMCaller(address common.Address, caller bind.ContractCaller) (*AlphabetVMCaller, error) {
contract, err := bindAlphabetVM(address, caller, nil, nil)
if err != nil {
return nil, err
}
return &AlphabetVMCaller{contract: contract}, nil
}
// NewAlphabetVMTransactor creates a new write-only instance of AlphabetVM, bound to a specific deployed contract.
func NewAlphabetVMTransactor(address common.Address, transactor bind.ContractTransactor) (*AlphabetVMTransactor, error) {
contract, err := bindAlphabetVM(address, nil, transactor, nil)
if err != nil {
return nil, err
}
return &AlphabetVMTransactor{contract: contract}, nil
}
// NewAlphabetVMFilterer creates a new log filterer instance of AlphabetVM, bound to a specific deployed contract.
func NewAlphabetVMFilterer(address common.Address, filterer bind.ContractFilterer) (*AlphabetVMFilterer, error) {
contract, err := bindAlphabetVM(address, nil, nil, filterer)
if err != nil {
return nil, err
}
return &AlphabetVMFilterer{contract: contract}, nil
}
// bindAlphabetVM binds a generic wrapper to an already deployed contract.
func bindAlphabetVM(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) {
parsed, err := abi.JSON(strings.NewReader(AlphabetVMABI))
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 (_AlphabetVM *AlphabetVMRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error {
return _AlphabetVM.Contract.AlphabetVMCaller.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 (_AlphabetVM *AlphabetVMRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
return _AlphabetVM.Contract.AlphabetVMTransactor.contract.Transfer(opts)
}
// Transact invokes the (paid) contract method with params as input values.
func (_AlphabetVM *AlphabetVMRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
return _AlphabetVM.Contract.AlphabetVMTransactor.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 (_AlphabetVM *AlphabetVMCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error {
return _AlphabetVM.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 (_AlphabetVM *AlphabetVMTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
return _AlphabetVM.Contract.contract.Transfer(opts)
}
// Transact invokes the (paid) contract method with params as input values.
func (_AlphabetVM *AlphabetVMTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
return _AlphabetVM.Contract.contract.Transact(opts, method, params...)
}
// Step is a free data retrieval call binding the contract method 0xf8e0cb96.
//
// Solidity: function step(bytes _stateData, bytes ) view returns(bytes32 postState_)
func (_AlphabetVM *AlphabetVMCaller) Step(opts *bind.CallOpts, _stateData []byte, arg1 []byte) ([32]byte, error) {
var out []interface{}
err := _AlphabetVM.contract.Call(opts, &out, "step", _stateData, arg1)
if err != nil {
return *new([32]byte), err
}
out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte)
return out0, err
}
// Step is a free data retrieval call binding the contract method 0xf8e0cb96.
//
// Solidity: function step(bytes _stateData, bytes ) view returns(bytes32 postState_)
func (_AlphabetVM *AlphabetVMSession) Step(_stateData []byte, arg1 []byte) ([32]byte, error) {
return _AlphabetVM.Contract.Step(&_AlphabetVM.CallOpts, _stateData, arg1)
}
// Step is a free data retrieval call binding the contract method 0xf8e0cb96.
//
// Solidity: function step(bytes _stateData, bytes ) view returns(bytes32 postState_)
func (_AlphabetVM *AlphabetVMCallerSession) Step(_stateData []byte, arg1 []byte) ([32]byte, error) {
return _AlphabetVM.Contract.Step(&_AlphabetVM.CallOpts, _stateData, arg1)
}
// Code generated - DO NOT EDIT.
// This file is a generated binding and any manual changes will be lost.
package bindings
import (
"encoding/json"
"github.com/ethereum-optimism/optimism/op-bindings/solc"
)
const AlphabetVMStorageLayoutJSON = "{\"storage\":null,\"types\":{}}"
var AlphabetVMStorageLayout = new(solc.StorageLayout)
var AlphabetVMDeployedBin = "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063f8e0cb9614610030575b600080fd5b61004361003e366004610157565b610055565b60405190815260200160405180910390f35b60008060007f0000000000000000000000000000000000000000000000000000000000000000878760405161008b9291906101c3565b6040518091039020036100af57600091506100a8868801886101d3565b90506100ce565b6100bb868801886101ec565b9092509050816100ca8161023d565b9250505b816100da826001610275565b6040805160208101939093528201526060016040516020818303038152906040528051906020012092505050949350505050565b60008083601f84011261012057600080fd5b50813567ffffffffffffffff81111561013857600080fd5b60208301915083602082850101111561015057600080fd5b9250929050565b6000806000806040858703121561016d57600080fd5b843567ffffffffffffffff8082111561018557600080fd5b6101918883890161010e565b909650945060208701359150808211156101aa57600080fd5b506101b78782880161010e565b95989497509550505050565b8183823760009101908152919050565b6000602082840312156101e557600080fd5b5035919050565b600080604083850312156101ff57600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361026e5761026e61020e565b5060010190565b600082198211156102885761028861020e565b50019056fea164736f6c634300080f000a"
func init() {
if err := json.Unmarshal([]byte(AlphabetVMStorageLayoutJSON), AlphabetVMStorageLayout); err != nil {
panic(err)
}
layouts["AlphabetVM"] = AlphabetVMStorageLayout
deployedBytecodes["AlphabetVM"] = AlphabetVMDeployedBin
}
This source diff could not be displayed because it is too large. You can view the blob instead.
// Code generated - DO NOT EDIT.
// This file is a generated binding and any manual changes will be lost.
package bindings
import (
"encoding/json"
"github.com/ethereum-optimism/optimism/op-bindings/solc"
)
const EASStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contract\":\"contracts/EAS/EAS.sol:EAS\",\"label\":\"_nonces\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_mapping(t_address,t_uint256)\"},{\"astId\":1001,\"contract\":\"contracts/EAS/EAS.sol:EAS\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_array(t_uint256)49_storage\"},{\"astId\":1002,\"contract\":\"contracts/EAS/EAS.sol:EAS\",\"label\":\"_db\",\"offset\":0,\"slot\":\"50\",\"type\":\"t_mapping(t_bytes32,t_struct(Attestation)1006_storage)\"},{\"astId\":1003,\"contract\":\"contracts/EAS/EAS.sol:EAS\",\"label\":\"_timestamps\",\"offset\":0,\"slot\":\"51\",\"type\":\"t_mapping(t_bytes32,t_uint64)\"},{\"astId\":1004,\"contract\":\"contracts/EAS/EAS.sol:EAS\",\"label\":\"_revocationsOffchain\",\"offset\":0,\"slot\":\"52\",\"type\":\"t_mapping(t_address,t_mapping(t_bytes32,t_uint64))\"},{\"astId\":1005,\"contract\":\"contracts/EAS/EAS.sol:EAS\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"53\",\"type\":\"t_array(t_uint256)47_storage\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_array(t_uint256)47_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[47]\",\"numberOfBytes\":\"1504\",\"base\":\"t_uint256\"},\"t_array(t_uint256)49_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[49]\",\"numberOfBytes\":\"1568\",\"base\":\"t_uint256\"},\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_bytes32\":{\"encoding\":\"inplace\",\"label\":\"bytes32\",\"numberOfBytes\":\"32\"},\"t_bytes_storage\":{\"encoding\":\"bytes\",\"label\":\"bytes\",\"numberOfBytes\":\"32\"},\"t_mapping(t_address,t_mapping(t_bytes32,t_uint64))\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e mapping(bytes32 =\u003e uint64))\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_mapping(t_bytes32,t_uint64)\"},\"t_mapping(t_address,t_uint256)\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e uint256)\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_uint256\"},\"t_mapping(t_bytes32,t_struct(Attestation)1006_storage)\":{\"encoding\":\"mapping\",\"label\":\"mapping(bytes32 =\u003e struct Attestation)\",\"numberOfBytes\":\"32\",\"key\":\"t_bytes32\",\"value\":\"t_struct(Attestation)1006_storage\"},\"t_mapping(t_bytes32,t_uint64)\":{\"encoding\":\"mapping\",\"label\":\"mapping(bytes32 =\u003e uint64)\",\"numberOfBytes\":\"32\",\"key\":\"t_bytes32\",\"value\":\"t_uint64\"},\"t_struct(Attestation)1006_storage\":{\"encoding\":\"inplace\",\"label\":\"struct Attestation\",\"numberOfBytes\":\"224\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"},\"t_uint64\":{\"encoding\":\"inplace\",\"label\":\"uint64\",\"numberOfBytes\":\"8\"}}}"
var EASStorageLayout = new(solc.StorageLayout)
var EASDeployedBin = "0x6080604052600436106101805760003560e01c8063b469318d116100d6578063e45d03f91161007f578063ed24911d11610059578063ed24911d1461049e578063f10b5cc8146104b3578063f17325e7146104e257600080fd5b8063e45d03f914610458578063e57a6b1b1461046b578063e71ff3651461047e57600080fd5b8063d45c4435116100b0578063d45c4435146103cf578063e13458fc14610406578063e30bb5631461041957600080fd5b8063b469318d14610322578063b83010d31461037c578063cf190f34146103af57600080fd5b8063469262671161013857806354fd4d501161011257806354fd4d50146102cd578063831e05a1146102e2578063a3112a64146102f557600080fd5b806346926267146102855780634cb7e9e51461029a5780634d003070146102ad57600080fd5b806317d7de7c1161016957806317d7de7c146102005780632d0335ab1461022257806344adc90e1461026557600080fd5b806312b11a171461018557806313893f61146101c7575b600080fd5b34801561019157600080fd5b507fdbfdf8dc2b135c26253e00d5b6cbe6f20457e003fd526d97cea183883570de615b6040519081526020015b60405180910390f35b3480156101d357600080fd5b506101e76101e23660046133ee565b6104f5565b60405167ffffffffffffffff90911681526020016101be565b34801561020c57600080fd5b5061021561053a565b6040516101be919061349e565b34801561022e57600080fd5b506101b461023d3660046134ea565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6102786102733660046133ee565b61056a565b6040516101be9190613507565b61029861029336600461354b565b6106a1565b005b6102986102a83660046133ee565b610725565b3480156102b957600080fd5b506101e76102c8366004613563565b61080d565b3480156102d957600080fd5b5061021561081a565b6102786102f03660046133ee565b6108bd565b34801561030157600080fd5b50610315610310366004613563565b610b0e565b6040516101be9190613663565b34801561032e57600080fd5b506101e761033d366004613676565b73ffffffffffffffffffffffffffffffffffffffff919091166000908152603460209081526040808320938352929052205467ffffffffffffffff1690565b34801561038857600080fd5b507fa98d02348410c9c76735e0d0bb1396f4015ac2bb9615f9c2611d19d7a8a996506101b4565b3480156103bb57600080fd5b506101e76103ca366004613563565b610cd1565b3480156103db57600080fd5b506101e76103ea366004613563565b60009081526033602052604090205467ffffffffffffffff1690565b6101b46104143660046136a2565b610cdf565b34801561042557600080fd5b50610448610434366004613563565b600090815260326020526040902054151590565b60405190151581526020016101be565b6102986104663660046133ee565b610de2565b6102986104793660046136dd565b610f5d565b34801561048a57600080fd5b506101e76104993660046133ee565b611002565b3480156104aa57600080fd5b506101b461103a565b3480156104bf57600080fd5b5060405173420000000000000000000000000000000000002081526020016101be565b6101b46104f03660046136ef565b611044565b60004282825b8181101561052e57610526338787848181106105195761051961372a565b9050602002013585611102565b6001016104fb565b50909150505b92915050565b60606105657f0000000000000000000000000000000000000000000000000000000000000000611201565b905090565b606060008267ffffffffffffffff81111561058757610587613759565b6040519080825280602002602001820160405280156105ba57816020015b60608152602001906001900390816105a55790505b509050600034815b8581101561068c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff86018114368888848181106106025761060261372a565b90506020028101906106149190613788565b9050600061063b823561062a60208501856137c6565b61063391613a3f565b33888761138f565b805190915061064a9086613ae2565b945080602001518785815181106106635761066361372a565b6020026020010181905250806020015151860195505050506106858160010190565b90506105c2565b506106978383611aa1565b9695505050505050565b604080516001808252818301909252600091816020015b60408051808201909152600080825260208201528152602001906001900390816106b85790505090506106f336839003830160208401613b44565b816000815181106107065761070661372a565b602090810291909101015261072082358233346001611b6e565b505050565b3460005b82811015610807577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83018114368585848181106107695761076961372a565b905060200281019061077b9190613788565b90506107e8813561078f6020840184613b60565b808060200260200160405190810160405280939291908181526020016000905b828210156107db576107cc60408302860136819003810190613b44565b815260200190600101906107af565b5050505050338786611b6e565b6107f29085613ae2565b935050506108008160010190565b9050610729565b50505050565b60004261053483826121a8565b60606108457f000000000000000000000000000000000000000000000000000000000000000061226a565b61086e7f000000000000000000000000000000000000000000000000000000000000000061226a565b6108977f000000000000000000000000000000000000000000000000000000000000000061226a565b6040516020016108a993929190613bc8565b604051602081830303815290604052905090565b606060008267ffffffffffffffff8111156108da576108da613759565b60405190808252806020026020018201604052801561090d57816020015b60608152602001906001900390816108f85790505b509050600034815b8581101561068c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff86018114368888848181106109555761095561372a565b90506020028101906109679190613c3e565b905036600061097960208401846137c6565b909250905080158061099957506109936040840184613c72565b82141590505b156109d0576040517f947d5a8400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015610a9257610a8a604051806080016040528086600001358152602001858585818110610a0557610a0561372a565b9050602002810190610a179190613cd9565b610a2090613d0d565b8152602001610a326040880188613c72565b85818110610a4257610a4261372a565b905060600201803603810190610a589190613d84565b8152602001610a6d60808801606089016134ea565b73ffffffffffffffffffffffffffffffffffffffff1690526123a7565b6001016109d3565b506000610abb8435610aa48486613a3f565b610ab460808801606089016134ea565b8a8961138f565b8051909150610aca9088613ae2565b96508060200151898781518110610ae357610ae361372a565b6020026020010181905250806020015151880197505050505050610b078160010190565b9050610915565b604080516101408101825260008082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e0820183905261010082019290925261012081019190915260008281526032602090815260409182902082516101408101845281548152600182015492810192909252600281015467ffffffffffffffff808216948401949094526801000000000000000081048416606084015270010000000000000000000000000000000090049092166080820152600382015460a0820152600482015473ffffffffffffffffffffffffffffffffffffffff90811660c0830152600583015490811660e083015274010000000000000000000000000000000000000000900460ff16151561010082015260068201805491929161012084019190610c4890613da0565b80601f0160208091040260200160405190810160405280929190818152602001828054610c7490613da0565b8015610cc15780601f10610c9657610100808354040283529160200191610cc1565b820191906000526020600020905b815481529060010190602001808311610ca457829003601f168201915b5050505050815250509050919050565b600042610534338483611102565b6000610cf2610ced83613ded565b6123a7565b604080516001808252818301909252600091816020015b6040805160c081018252600080825260208083018290529282018190526060808301829052608083015260a082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff909201910181610d09579050509050610d776020840184613cd9565b610d8090613d0d565b81600081518110610d9357610d9361372a565b6020908102919091010152610dbc833582610db460c0870160a088016134ea565b34600161138f565b60200151600081518110610dd257610dd261372a565b6020026020010151915050919050565b3460005b82811015610807577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff830181146000858584818110610e2757610e2761372a565b9050602002810190610e399190613c3e565b610e4290613ed2565b60208101518051919250901580610e5f5750816040015151815114155b15610e96576040517f947d5a8400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8151811015610f2757610f1f604051806080016040528085600001518152602001848481518110610ecc57610ecc61372a565b6020026020010151815260200185604001518481518110610eef57610eef61372a565b60200260200101518152602001856060015173ffffffffffffffffffffffffffffffffffffffff16815250612536565b600101610e99565b50610f3d82600001518284606001518887611b6e565b610f479086613ae2565b9450505050610f568160010190565b9050610de6565b610f74610f6f36839003830183613fb1565b612536565b604080516001808252818301909252600091816020015b6040805180820190915260008082526020820152815260200190600190039081610f8b579050509050610fc636839003830160208401613b44565b81600081518110610fd957610fd961372a565b6020908102919091010152610720823582610ffa60e0860160c087016134ea565b346001611b6e565b60004282825b8181101561052e576110328686838181106110255761102561372a565b90506020020135846121a8565b600101611008565b60006105656125c4565b604080516001808252818301909252600091829190816020015b6040805160c081018252600080825260208083018290529282018190526060808301829052608083015260a082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90920191018161105e5790505090506110cc6020840184613cd9565b6110d590613d0d565b816000815181106110e8576110e861372a565b6020908102919091010152610dbc8335823334600161138f565b73ffffffffffffffffffffffffffffffffffffffff83166000908152603460209081526040808320858452918290529091205467ffffffffffffffff1615611176576040517fec9d6eeb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008381526020829052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff861690811790915590519091859173ffffffffffffffffffffffffffffffffffffffff8816917f92a1f7a41a7c585a8b09e25b195e225b1d43248daca46b0faf9e0792777a222991a450505050565b604080516020808252818301909252606091600091906020820181803683370190505090506000805b60208110156112cc5760008582602081106112475761124761372a565b1a60f81b90507fff00000000000000000000000000000000000000000000000000000000000000811660000361127d57506112cc565b808484815181106112905761129061372a565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350506001918201910161122a565b5060008167ffffffffffffffff8111156112e8576112e8613759565b6040519080825280601f01601f191660200182016040528015611312576020820181803683370190505b50905060005b82811015611386578381815181106113325761133261372a565b602001015160f81c60f81b82828151811061134f5761134f61372a565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600101611318565b50949350505050565b60408051808201909152600081526060602082015284516040805180820190915260008152606060208201528167ffffffffffffffff8111156113d4576113d4613759565b6040519080825280602002602001820160405280156113fd578160200160208202803683370190505b5060208201526040517fa2ea7c6e000000000000000000000000000000000000000000000000000000008152600481018990526000907342000000000000000000000000000000000000209063a2ea7c6e90602401600060405180830381865afa15801561146f573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526114b5919081019061400d565b80519091506114f0576040517fbf37b20e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008367ffffffffffffffff81111561150b5761150b613759565b6040519080825280602002602001820160405280156115aa57816020015b60408051610140810182526000808252602080830182905292820181905260608083018290526080830182905260a0830182905260c0830182905260e0830182905261010083019190915261012082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816115295790505b50905060008467ffffffffffffffff8111156115c8576115c8613759565b6040519080825280602002602001820160405280156115f1578160200160208202803683370190505b50905060005b85811015611a805760008b82815181106116135761161361372a565b60200260200101519050600067ffffffffffffffff16816020015167ffffffffffffffff161415801561165e57504267ffffffffffffffff16816020015167ffffffffffffffff1611155b15611695576040517f08e8b93700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84604001511580156116a8575080604001515b156116df576040517f157bd4c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040518061014001604052806000801b81526020018f81526020016117034290565b67ffffffffffffffff168152602001836020015167ffffffffffffffff168152602001600067ffffffffffffffff16815260200183606001518152602001836000015173ffffffffffffffffffffffffffffffffffffffff1681526020018d73ffffffffffffffffffffffffffffffffffffffff16815260200183604001511515815260200183608001518152509050600080600090505b6117a583826126f8565b600081815260326020526040902054909250156117c45760010161179b565b81835260008281526032602090815260409182902085518155908501516001820155908401516002820180546060870151608088015167ffffffffffffffff908116700100000000000000000000000000000000027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff92821668010000000000000000027fffffffffffffffffffffffffffffffff000000000000000000000000000000009094169190951617919091171691909117905560a0840151600382015560c084015160048201805473ffffffffffffffffffffffffffffffffffffffff9283167fffffffffffffffffffffffff000000000000000000000000000000000000000090911617905560e0850151600583018054610100880151151574010000000000000000000000000000000000000000027fffffffffffffffffffffff000000000000000000000000000000000000000000909116929093169190911791909117905561012084015184919060068201906119449082614133565b50505060608401511561199b57606084015160009081526032602052604090205461199b576040517fc5723b5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b828786815181106119ae576119ae61372a565b60200260200101819052508360a001518686815181106119d0576119d061372a565b60200260200101818152505081896020015186815181106119f3576119f361372a565b6020026020010181815250508f8e73ffffffffffffffffffffffffffffffffffffffff16856000015173ffffffffffffffffffffffffffffffffffffffff167f8bf46bf4cfd674fa735a3d63ec1c9ad4153f033c290341f3a588b75685141b3585604051611a6391815260200190565b60405180910390a450505050611a798160010190565b90506115f7565b50611a9083838360008c8c612757565b845250919998505050505050505050565b606060008267ffffffffffffffff811115611abe57611abe613759565b604051908082528060200260200182016040528015611ae7578160200160208202803683370190505b5090506000805b855181101561052e576000868281518110611b0b57611b0b61372a565b6020026020010151905060005b8151811015611b6457818181518110611b3357611b3361372a565b6020026020010151858581518110611b4d57611b4d61372a565b602090810291909101015260019384019301611b18565b5050600101611aee565b6040517fa2ea7c6e0000000000000000000000000000000000000000000000000000000081526004810186905260009081907342000000000000000000000000000000000000209063a2ea7c6e90602401600060405180830381865afa158015611bdc573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611c22919081019061400d565b8051909150611c5d576040517fbf37b20e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b855160008167ffffffffffffffff811115611c7a57611c7a613759565b604051908082528060200260200182016040528015611d1957816020015b60408051610140810182526000808252602080830182905292820181905260608083018290526080830182905260a0830182905260c0830182905260e0830182905261010083019190915261012082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff909201910181611c985790505b50905060008267ffffffffffffffff811115611d3757611d37613759565b604051908082528060200260200182016040528015611d60578160200160208202803683370190505b50905060005b8381101561218a5760008a8281518110611d8257611d8261372a565b6020908102919091018101518051600090815260329092526040909120805491925090611ddb576040517fc5723b5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8c816001015414611e18576040517fbf37b20e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600581015473ffffffffffffffffffffffffffffffffffffffff8c8116911614611e6e576040517f4ca8886700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600581015474010000000000000000000000000000000000000000900460ff16611ec4576040517f157bd4c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002810154700100000000000000000000000000000000900467ffffffffffffffff1615611f1e576040517f905e710700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b426002820180547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff811670010000000000000000000000000000000067ffffffffffffffff948516810291821793849055604080516101408101825287548152600188015460208201529386169286169290921791830191909152680100000000000000008304841660608301529091049091166080820152600382015460a0820152600482015473ffffffffffffffffffffffffffffffffffffffff90811660c0830152600583015490811660e083015274010000000000000000000000000000000000000000900460ff161515610100820152600682018054839161012084019161202a90613da0565b80601f016020809104026020016040519081016040528092919081815260200182805461205690613da0565b80156120a35780601f10612078576101008083540402835291602001916120a3565b820191906000526020600020905b81548152906001019060200180831161208657829003601f168201915b5050505050815250508584815181106120be576120be61372a565b602002602001018190525081602001518484815181106120e0576120e061372a565b60200260200101818152505080600101548b73ffffffffffffffffffffffffffffffffffffffff168260040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167ff930a6e2523c9cc298691873087a740550b8fc85a0680830414c148ed927f615856000015160405161217891815260200190565b60405180910390a45050600101611d66565b5061219a84838360018b8b612757565b9a9950505050505050505050565b60008281526033602052604090205467ffffffffffffffff16156121f8576040517f2e26794600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526033602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff85169081179091559051909184917f5aafceeb1c7ad58e4a84898bdee37c02c0fc46e7d24e6b60e8209449f183459f9190a35050565b6060816000036122ad57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156122d757806122c18161424d565b91506122d09050600a836142b4565b91506122b1565b60008167ffffffffffffffff8111156122f2576122f2613759565b6040519080825280601f01601f19166020018201604052801561231c576020820181803683370190505b5090505b841561239f57612331600183613ae2565b915061233e600a866142c8565b6123499060306142dc565b60f81b81838151811061235e5761235e61372a565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350612398600a866142b4565b9450612320565b949350505050565b60208082015160408084015160608086015173ffffffffffffffffffffffffffffffffffffffff1660009081528086528381208054600181019091558751865187890151878901519589015160808a01518051908c01209851999a9799949895976124ad97612492977fdbfdf8dc2b135c26253e00d5b6cbe6f20457e003fd526d97cea183883570de619791939290918c9101978852602088019690965273ffffffffffffffffffffffffffffffffffffffff94909416604087015267ffffffffffffffff9290921660608601521515608085015260a084015260c083015260e08201526101000190565b60405160208183030381529060405280519060200120612b31565b9050846060015173ffffffffffffffffffffffffffffffffffffffff166124e282856000015186602001518760400151612b44565b73ffffffffffffffffffffffffffffffffffffffff161461252f576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b60208181015160408084015160608086015173ffffffffffffffffffffffffffffffffffffffff1660009081528086528381208054600181019091558751865186517fa98d02348410c9c76735e0d0bb1396f4015ac2bb9615f9c2611d19d7a8a99650998101999099529588015291860193909352608085018190529293909291906124ad9060a001612492565b60003073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614801561262a57507f000000000000000000000000000000000000000000000000000000000000000046145b1561265457507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b60208083015160c084015160e0850151604080870151606088015161010089015160a08a01516101208b0151945160009961273999989796918c91016142ef565b60405160208183030381529060405280519060200120905092915050565b845160009060018190036127af576127a7888860008151811061277c5761277c61372a565b6020026020010151886000815181106127975761279761372a565b6020026020010151888888612b6c565b915050610697565b602088015173ffffffffffffffffffffffffffffffffffffffff81166128415760005b82811015612835578781815181106127ec576127ec61372a565b602002602001015160001461282d576040517f1574f9f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001016127d2565b50600092505050610697565b6000805b8381101561296b5760008982815181106128615761286161372a565b60200260200101519050806000141580156128e857508373ffffffffffffffffffffffffffffffffffffffff1663ce46e0466040518163ffffffff1660e01b8152600401602060405180830381865afa1580156128c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128e691906143cd565b155b1561291f576040517f1574f9f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87811115612959576040517f1101129400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b96879003969190910190600101612845565b508615612a46576040517f88e5b2d900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316906388e5b2d99083906129c8908d908d906004016143ea565b60206040518083038185885af11580156129e6573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612a0b91906143cd565b612a41576040517fbf2f3a8b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612b15565b6040517f91db0b7e00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316906391db0b7e908390612a9c908d908d906004016143ea565b60206040518083038185885af1158015612aba573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612adf91906143cd565b612b15576040517fe8bee83900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8415612b2457612b2486612e82565b9998505050505050505050565b6000610534612b3e6125c4565b83612e95565b6000806000612b5587878787612ed7565b91509150612b6281612fef565b5095945050505050565b602086015160009073ffffffffffffffffffffffffffffffffffffffff8116612bd1578515612bc7576040517f1574f9f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000915050610697565b8515801590612c4c57508073ffffffffffffffffffffffffffffffffffffffff1663ce46e0466040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c26573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c4a91906143cd565b155b15612c83576040517f1574f9f300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83861115612cbd576040517f1101129400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b85840393508415612d9a576040517fe49617e100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063e49617e1908890612d1c908b90600401613663565b60206040518083038185885af1158015612d3a573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612d5f91906143cd565b612d95576040517fccf3bb2700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612e67565b6040517fe60c350500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063e60c3505908890612dee908b90600401613663565b60206040518083038185885af1158015612e0c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612e3191906143cd565b612e67576040517fbd8ba84d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8215612e7657612e7684612e82565b50939695505050505050565b8015612e9257612e923382613248565b50565b6040517f190100000000000000000000000000000000000000000000000000000000000060208201526022810183905260428101829052600090606201612739565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115612f0e5750600090506003612fe6565b8460ff16601b14158015612f2657508460ff16601c14155b15612f375750600090506004612fe6565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015612f8b573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff8116612fdf57600060019250925050612fe6565b9150600090505b94509492505050565b6000816004811115613003576130036144a3565b0361300b5750565b600181600481111561301f5761301f6144a3565b0361308b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064015b60405180910390fd5b600281600481111561309f5761309f6144a3565b03613106576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401613082565b600381600481111561311a5761311a6144a3565b036131a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c60448201527f75650000000000000000000000000000000000000000000000000000000000006064820152608401613082565b60048160048111156131bb576131bb6144a3565b03612e92576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c60448201527f75650000000000000000000000000000000000000000000000000000000000006064820152608401613082565b804710156132b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e63650000006044820152606401613082565b60008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d806000811461330c576040519150601f19603f3d011682016040523d82523d6000602084013e613311565b606091505b5050905080610720576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608401613082565b60008083601f8401126133b457600080fd5b50813567ffffffffffffffff8111156133cc57600080fd5b6020830191508360208260051b85010111156133e757600080fd5b9250929050565b6000806020838503121561340157600080fd5b823567ffffffffffffffff81111561341857600080fd5b613424858286016133a2565b90969095509350505050565b60005b8381101561344b578181015183820152602001613433565b50506000910152565b6000815180845261346c816020860160208601613430565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006134b16020830184613454565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff81168114612e9257600080fd5b80356134e5816134b8565b919050565b6000602082840312156134fc57600080fd5b81356134b1816134b8565b6020808252825182820181905260009190848201906040850190845b8181101561353f57835183529284019291840191600101613523565b50909695505050505050565b60006060828403121561355d57600080fd5b50919050565b60006020828403121561357557600080fd5b5035919050565b6000610140825184526020830151602085015260408301516135aa604086018267ffffffffffffffff169052565b5060608301516135c6606086018267ffffffffffffffff169052565b5060808301516135e2608086018267ffffffffffffffff169052565b5060a083015160a085015260c083015161361460c086018273ffffffffffffffffffffffffffffffffffffffff169052565b5060e083015161363c60e086018273ffffffffffffffffffffffffffffffffffffffff169052565b50610100838101511515908501526101208084015181860183905261069783870182613454565b6020815260006134b1602083018461357c565b6000806040838503121561368957600080fd5b8235613694816134b8565b946020939093013593505050565b6000602082840312156136b457600080fd5b813567ffffffffffffffff8111156136cb57600080fd5b820160c081850312156134b157600080fd5b600060e0828403121561355d57600080fd5b60006020828403121561370157600080fd5b813567ffffffffffffffff81111561371857600080fd5b8201604081850312156134b157600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18336030181126137bc57600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126137fb57600080fd5b83018035915067ffffffffffffffff82111561381657600080fd5b6020019150600581901b36038213156133e757600080fd5b60405160c0810167ffffffffffffffff8111828210171561385157613851613759565b60405290565b6040516080810167ffffffffffffffff8111828210171561385157613851613759565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156138c1576138c1613759565b604052919050565b600067ffffffffffffffff8211156138e3576138e3613759565b5060051b60200190565b8015158114612e9257600080fd5b80356134e5816138ed565b600067ffffffffffffffff82111561392057613920613759565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261395d57600080fd5b813561397061396b82613906565b61387a565b81815284602083860101111561398557600080fd5b816020850160208301376000918101602001919091529392505050565b600060c082840312156139b457600080fd5b6139bc61382e565b905081356139c9816134b8565b8152602082013567ffffffffffffffff80821682146139e757600080fd5b8160208401526139f9604085016138fb565b6040840152606084013560608401526080840135915080821115613a1c57600080fd5b50613a298482850161394c565b60808301525060a082013560a082015292915050565b6000613a4d61396b846138c9565b80848252602080830192508560051b850136811115613a6b57600080fd5b855b81811015613aa757803567ffffffffffffffff811115613a8d5760008081fd5b613a9936828a016139a2565b865250938201938201613a6d565b50919695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111561053457610534613ab3565b600060408284031215613b0757600080fd5b6040516040810181811067ffffffffffffffff82111715613b2a57613b2a613759565b604052823581526020928301359281019290925250919050565b600060408284031215613b5657600080fd5b6134b18383613af5565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613b9557600080fd5b83018035915067ffffffffffffffff821115613bb057600080fd5b6020019150600681901b36038213156133e757600080fd5b60008451613bda818460208901613430565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551613c16816001850160208a01613430565b60019201918201528351613c31816002840160208801613430565b0160020195945050505050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff818336030181126137bc57600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613ca757600080fd5b83018035915067ffffffffffffffff821115613cc257600080fd5b60200191506060810236038213156133e757600080fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff418336030181126137bc57600080fd5b600061053436836139a2565b600060608284031215613d2b57600080fd5b6040516060810181811067ffffffffffffffff82111715613d4e57613d4e613759565b604052905080823560ff81168114613d6557600080fd5b8082525060208301356020820152604083013560408201525092915050565b600060608284031215613d9657600080fd5b6134b18383613d19565b600181811c90821680613db457607f821691505b60208210810361355d577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060c08236031215613dff57600080fd5b613e07613857565b82358152602083013567ffffffffffffffff811115613e2557600080fd5b613e31368286016139a2565b602083015250613e443660408501613d19565b604082015260a0830135613e57816134b8565b606082015292915050565b600082601f830112613e7357600080fd5b81356020613e8361396b836138c9565b82815260609283028501820192828201919087851115613ea257600080fd5b8387015b85811015613ec557613eb88982613d19565b8452928401928101613ea6565b5090979650505050505050565b600060808236031215613ee457600080fd5b613eec613857565b8235815260208084013567ffffffffffffffff80821115613f0c57600080fd5b9085019036601f830112613f1f57600080fd5b8135613f2d61396b826138c9565b81815260069190911b83018401908481019036831115613f4c57600080fd5b938501935b82851015613f7557613f633686613af5565b82528582019150604085019450613f51565b80868801525050506040860135925080831115613f9157600080fd5b5050613f9f36828601613e62565b604083015250613e57606084016134da565b600060e08284031215613fc357600080fd5b613fcb613857565b82358152613fdc8460208501613af5565b6020820152613fee8460608501613d19565b604082015260c0830135614001816134b8565b60608201529392505050565b6000602080838503121561402057600080fd5b825167ffffffffffffffff8082111561403857600080fd5b908401906080828703121561404c57600080fd5b614054613857565b8251815283830151614065816134b8565b818501526040830151614077816138ed565b604082015260608301518281111561408e57600080fd5b80840193505086601f8401126140a357600080fd5b825191506140b361396b83613906565b82815287858486010111156140c757600080fd5b6140d683868301878701613430565b60608201529695505050505050565b601f82111561072057600081815260208120601f850160051c8101602086101561410c5750805b601f850160051c820191505b8181101561412b57828155600101614118565b505050505050565b815167ffffffffffffffff81111561414d5761414d613759565b6141618161415b8454613da0565b846140e5565b602080601f8311600181146141b4576000841561417e5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b17855561412b565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015614201578886015182559484019460019091019084016141e2565b508582101561423d57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361427e5761427e613ab3565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826142c3576142c3614285565b500490565b6000826142d7576142d7614285565b500690565b8082018082111561053457610534613ab3565b89815260007fffffffffffffffffffffffffffffffffffffffff000000000000000000000000808b60601b166020840152808a60601b166034840152507fffffffffffffffff000000000000000000000000000000000000000000000000808960c01b166048840152808860c01b1660508401525085151560f81b60588301528460598301528351614388816079850160208801613430565b80830190507fffffffff000000000000000000000000000000000000000000000000000000008460e01b166079820152607d81019150509a9950505050505050505050565b6000602082840312156143df57600080fd5b81516134b1816138ed565b6000604082016040835280855180835260608501915060608160051b8601019250602080880160005b8381101561445f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa088870301855261444d86835161357c565b95509382019390820190600101614413565b50508584038187015286518085528782019482019350915060005b828110156144965784518452938101939281019260010161447a565b5091979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea164736f6c6343000813000a"
func init() {
if err := json.Unmarshal([]byte(EASStorageLayoutJSON), EASStorageLayout); err != nil {
panic(err)
}
layouts["EAS"] = EASStorageLayout
deployedBytecodes["EAS"] = EASDeployedBin
}
...@@ -9,7 +9,7 @@ import ( ...@@ -9,7 +9,7 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/solc" "github.com/ethereum-optimism/optimism/op-bindings/solc"
) )
const ERC20StorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contract\":\"node_modules/.pnpm/@openzeppelin+contracts@4.7.3/node_modules/@openzeppelin/contracts/token/ERC20/ERC20.sol:ERC20\",\"label\":\"_balances\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_mapping(t_address,t_uint256)\"},{\"astId\":1001,\"contract\":\"node_modules/.pnpm/@openzeppelin+contracts@4.7.3/node_modules/@openzeppelin/contracts/token/ERC20/ERC20.sol:ERC20\",\"label\":\"_allowances\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_mapping(t_address,t_mapping(t_address,t_uint256))\"},{\"astId\":1002,\"contract\":\"node_modules/.pnpm/@openzeppelin+contracts@4.7.3/node_modules/@openzeppelin/contracts/token/ERC20/ERC20.sol:ERC20\",\"label\":\"_totalSupply\",\"offset\":0,\"slot\":\"2\",\"type\":\"t_uint256\"},{\"astId\":1003,\"contract\":\"node_modules/.pnpm/@openzeppelin+contracts@4.7.3/node_modules/@openzeppelin/contracts/token/ERC20/ERC20.sol:ERC20\",\"label\":\"_name\",\"offset\":0,\"slot\":\"3\",\"type\":\"t_string_storage\"},{\"astId\":1004,\"contract\":\"node_modules/.pnpm/@openzeppelin+contracts@4.7.3/node_modules/@openzeppelin/contracts/token/ERC20/ERC20.sol:ERC20\",\"label\":\"_symbol\",\"offset\":0,\"slot\":\"4\",\"type\":\"t_string_storage\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_mapping(t_address,t_mapping(t_address,t_uint256))\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e mapping(address =\u003e uint256))\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_mapping(t_address,t_uint256)\"},\"t_mapping(t_address,t_uint256)\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e uint256)\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_uint256\"},\"t_string_storage\":{\"encoding\":\"bytes\",\"label\":\"string\",\"numberOfBytes\":\"32\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"}}}" const ERC20StorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contract\":\"node_modules/@openzeppelin/contracts/token/ERC20/ERC20.sol:ERC20\",\"label\":\"_balances\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_mapping(t_address,t_uint256)\"},{\"astId\":1001,\"contract\":\"node_modules/@openzeppelin/contracts/token/ERC20/ERC20.sol:ERC20\",\"label\":\"_allowances\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_mapping(t_address,t_mapping(t_address,t_uint256))\"},{\"astId\":1002,\"contract\":\"node_modules/@openzeppelin/contracts/token/ERC20/ERC20.sol:ERC20\",\"label\":\"_totalSupply\",\"offset\":0,\"slot\":\"2\",\"type\":\"t_uint256\"},{\"astId\":1003,\"contract\":\"node_modules/@openzeppelin/contracts/token/ERC20/ERC20.sol:ERC20\",\"label\":\"_name\",\"offset\":0,\"slot\":\"3\",\"type\":\"t_string_storage\"},{\"astId\":1004,\"contract\":\"node_modules/@openzeppelin/contracts/token/ERC20/ERC20.sol:ERC20\",\"label\":\"_symbol\",\"offset\":0,\"slot\":\"4\",\"type\":\"t_string_storage\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_mapping(t_address,t_mapping(t_address,t_uint256))\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e mapping(address =\u003e uint256))\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_mapping(t_address,t_uint256)\"},\"t_mapping(t_address,t_uint256)\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e uint256)\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_uint256\"},\"t_string_storage\":{\"encoding\":\"bytes\",\"label\":\"string\",\"numberOfBytes\":\"32\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"}}}"
var ERC20StorageLayout = new(solc.StorageLayout) var ERC20StorageLayout = new(solc.StorageLayout)
......
...@@ -31,7 +31,7 @@ var ( ...@@ -31,7 +31,7 @@ var (
// PreimageOracleMetaData contains all meta data concerning the PreimageOracle contract. // PreimageOracleMetaData contains all meta data concerning the PreimageOracle contract.
var PreimageOracleMetaData = &bind.MetaData{ var PreimageOracleMetaData = &bind.MetaData{
ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"partOffset\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"key\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"part\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"size\",\"type\":\"uint256\"}],\"name\":\"cheat\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_preimage\",\"type\":\"bytes\"}],\"name\":\"computePreimageKey\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"key_\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_partOffset\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_preimage\",\"type\":\"bytes\"}],\"name\":\"loadKeccak256PreimagePart\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"preimageLengths\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"preimagePartOk\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"preimageParts\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_key\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_offset\",\"type\":\"uint256\"}],\"name\":\"readPreimage\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"dat_\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"datLen_\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"partOffset\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"key\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"part\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"size\",\"type\":\"uint256\"}],\"name\":\"cheat\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_preimage\",\"type\":\"bytes\"}],\"name\":\"computePreimageKey\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"key_\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_partOffset\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_preimage\",\"type\":\"bytes\"}],\"name\":\"loadKeccak256PreimagePart\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"preimageLengths\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"preimagePartOk\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"preimageParts\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_key\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_offset\",\"type\":\"uint256\"}],\"name\":\"readPreimage\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"dat_\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"datLen_\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]",
Bin: "0x608060405234801561001057600080fd5b506105e2806100206000396000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c8063e03110e11161005b578063e03110e114610111578063e159261114610139578063fe4ac08e1461014e578063fef2b4ed146101c357600080fd5b806361238bde146100825780638542cf50146100c0578063a57c202c146100fe575b600080fd5b6100ad610090366004610433565b600160209081526000928352604080842090915290825290205481565b6040519081526020015b60405180910390f35b6100ee6100ce366004610433565b600260209081526000928352604080842090915290825290205460ff1681565b60405190151581526020016100b7565b6100ad61010c36600461049e565b6101e3565b61012461011f366004610433565b610242565b604080519283526020830191909152016100b7565b61014c6101473660046104e0565b610333565b005b61014c61015c36600461052c565b6000838152600260209081526040808320878452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558684528252808320968352958152858220939093559283529082905291902055565b6100ad6101d136600461055e565b60006020819052908152604090205481565b60243560c081901b608052600090608881858237207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0200000000000000000000000000000000000000000000000000000000000000179392505050565b6000828152600260209081526040808320848452909152812054819060ff166102cb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f7072652d696d616765206d757374206578697374000000000000000000000000604482015260640160405180910390fd5b50600083815260208181526040909120546102e78160086105a6565b6102f28560206105a6565b1061031057836103038260086105a6565b61030d91906105be565b91505b506000938452600160209081526040808620948652939052919092205492909150565b6044356000806008830186111561034957600080fd5b60c083901b6080526088838682378087017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80151908490207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f02000000000000000000000000000000000000000000000000000000000000001760008181526002602090815260408083208b8452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845282528083209a83529981528982209390935590815290819052959095209190915550505050565b6000806040838503121561044657600080fd5b50508035926020909101359150565b60008083601f84011261046757600080fd5b50813567ffffffffffffffff81111561047f57600080fd5b60208301915083602082850101111561049757600080fd5b9250929050565b600080602083850312156104b157600080fd5b823567ffffffffffffffff8111156104c857600080fd5b6104d485828601610455565b90969095509350505050565b6000806000604084860312156104f557600080fd5b83359250602084013567ffffffffffffffff81111561051357600080fd5b61051f86828701610455565b9497909650939450505050565b6000806000806080858703121561054257600080fd5b5050823594602084013594506040840135936060013592509050565b60006020828403121561057057600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156105b9576105b9610577565b500190565b6000828210156105d0576105d0610577565b50039056fea164736f6c634300080f000a", Bin: "0x608060405234801561001057600080fd5b506105df806100206000396000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c8063e03110e11161005b578063e03110e114610111578063e159261114610139578063fe4ac08e1461014e578063fef2b4ed146101c357600080fd5b806361238bde146100825780638542cf50146100c0578063a57c202c146100fe575b600080fd5b6100ad610090366004610433565b600160209081526000928352604080842090915290825290205481565b6040519081526020015b60405180910390f35b6100ee6100ce366004610433565b600260209081526000928352604080842090915290825290205460ff1681565b60405190151581526020016100b7565b6100ad61010c36600461049e565b6101e3565b61012461011f366004610433565b610242565b604080519283526020830191909152016100b7565b61014c6101473660046104e0565b610333565b005b61014c61015c36600461052c565b6000838152600260209081526040808320878452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558684528252808320968352958152858220939093559283529082905291902055565b6100ad6101d136600461055e565b60006020819052908152604090205481565b60243560c081901b608052600090608881858237207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0200000000000000000000000000000000000000000000000000000000000000179392505050565b6000828152600260209081526040808320848452909152812054819060ff166102cb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f7072652d696d616765206d757374206578697374000000000000000000000000604482015260640160405180910390fd5b50600083815260208181526040909120546102e78160086105a6565b6102f28560206105a6565b1061031057836103038260086105a6565b61030d91906105bf565b91505b506000938452600160209081526040808620948652939052919092205492909150565b6044356000806008830186111561034957600080fd5b60c083901b6080526088838682378087017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80151908490207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f02000000000000000000000000000000000000000000000000000000000000001760008181526002602090815260408083208b8452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845282528083209a83529981528982209390935590815290819052959095209190915550505050565b6000806040838503121561044657600080fd5b50508035926020909101359150565b60008083601f84011261046757600080fd5b50813567ffffffffffffffff81111561047f57600080fd5b60208301915083602082850101111561049757600080fd5b9250929050565b600080602083850312156104b157600080fd5b823567ffffffffffffffff8111156104c857600080fd5b6104d485828601610455565b90969095509350505050565b6000806000604084860312156104f557600080fd5b83359250602084013567ffffffffffffffff81111561051357600080fd5b61051f86828701610455565b9497909650939450505050565b6000806000806080858703121561054257600080fd5b5050823594602084013594506040840135936060013592509050565b60006020828403121561057057600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156105b9576105b9610577565b92915050565b818103818111156105b9576105b961057756fea164736f6c6343000813000a",
} }
// PreimageOracleABI is the input ABI used to generate the binding from. // PreimageOracleABI is the input ABI used to generate the binding from.
......
...@@ -13,9 +13,9 @@ const PreimageOracleStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contrac ...@@ -13,9 +13,9 @@ const PreimageOracleStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contrac
var PreimageOracleStorageLayout = new(solc.StorageLayout) var PreimageOracleStorageLayout = new(solc.StorageLayout)
var PreimageOracleDeployedBin = "0x608060405234801561001057600080fd5b506004361061007d5760003560e01c8063e03110e11161005b578063e03110e114610111578063e159261114610139578063fe4ac08e1461014e578063fef2b4ed146101c357600080fd5b806361238bde146100825780638542cf50146100c0578063a57c202c146100fe575b600080fd5b6100ad610090366004610433565b600160209081526000928352604080842090915290825290205481565b6040519081526020015b60405180910390f35b6100ee6100ce366004610433565b600260209081526000928352604080842090915290825290205460ff1681565b60405190151581526020016100b7565b6100ad61010c36600461049e565b6101e3565b61012461011f366004610433565b610242565b604080519283526020830191909152016100b7565b61014c6101473660046104e0565b610333565b005b61014c61015c36600461052c565b6000838152600260209081526040808320878452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558684528252808320968352958152858220939093559283529082905291902055565b6100ad6101d136600461055e565b60006020819052908152604090205481565b60243560c081901b608052600090608881858237207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0200000000000000000000000000000000000000000000000000000000000000179392505050565b6000828152600260209081526040808320848452909152812054819060ff166102cb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f7072652d696d616765206d757374206578697374000000000000000000000000604482015260640160405180910390fd5b50600083815260208181526040909120546102e78160086105a6565b6102f28560206105a6565b1061031057836103038260086105a6565b61030d91906105be565b91505b506000938452600160209081526040808620948652939052919092205492909150565b6044356000806008830186111561034957600080fd5b60c083901b6080526088838682378087017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80151908490207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f02000000000000000000000000000000000000000000000000000000000000001760008181526002602090815260408083208b8452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845282528083209a83529981528982209390935590815290819052959095209190915550505050565b6000806040838503121561044657600080fd5b50508035926020909101359150565b60008083601f84011261046757600080fd5b50813567ffffffffffffffff81111561047f57600080fd5b60208301915083602082850101111561049757600080fd5b9250929050565b600080602083850312156104b157600080fd5b823567ffffffffffffffff8111156104c857600080fd5b6104d485828601610455565b90969095509350505050565b6000806000604084860312156104f557600080fd5b83359250602084013567ffffffffffffffff81111561051357600080fd5b61051f86828701610455565b9497909650939450505050565b6000806000806080858703121561054257600080fd5b5050823594602084013594506040840135936060013592509050565b60006020828403121561057057600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156105b9576105b9610577565b500190565b6000828210156105d0576105d0610577565b50039056fea164736f6c634300080f000a" var PreimageOracleDeployedBin = "0x608060405234801561001057600080fd5b506004361061007d5760003560e01c8063e03110e11161005b578063e03110e114610111578063e159261114610139578063fe4ac08e1461014e578063fef2b4ed146101c357600080fd5b806361238bde146100825780638542cf50146100c0578063a57c202c146100fe575b600080fd5b6100ad610090366004610433565b600160209081526000928352604080842090915290825290205481565b6040519081526020015b60405180910390f35b6100ee6100ce366004610433565b600260209081526000928352604080842090915290825290205460ff1681565b60405190151581526020016100b7565b6100ad61010c36600461049e565b6101e3565b61012461011f366004610433565b610242565b604080519283526020830191909152016100b7565b61014c6101473660046104e0565b610333565b005b61014c61015c36600461052c565b6000838152600260209081526040808320878452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558684528252808320968352958152858220939093559283529082905291902055565b6100ad6101d136600461055e565b60006020819052908152604090205481565b60243560c081901b608052600090608881858237207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0200000000000000000000000000000000000000000000000000000000000000179392505050565b6000828152600260209081526040808320848452909152812054819060ff166102cb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f7072652d696d616765206d757374206578697374000000000000000000000000604482015260640160405180910390fd5b50600083815260208181526040909120546102e78160086105a6565b6102f28560206105a6565b1061031057836103038260086105a6565b61030d91906105bf565b91505b506000938452600160209081526040808620948652939052919092205492909150565b6044356000806008830186111561034957600080fd5b60c083901b6080526088838682378087017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80151908490207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f02000000000000000000000000000000000000000000000000000000000000001760008181526002602090815260408083208b8452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845282528083209a83529981528982209390935590815290819052959095209190915550505050565b6000806040838503121561044657600080fd5b50508035926020909101359150565b60008083601f84011261046757600080fd5b50813567ffffffffffffffff81111561047f57600080fd5b60208301915083602082850101111561049757600080fd5b9250929050565b600080602083850312156104b157600080fd5b823567ffffffffffffffff8111156104c857600080fd5b6104d485828601610455565b90969095509350505050565b6000806000604084860312156104f557600080fd5b83359250602084013567ffffffffffffffff81111561051357600080fd5b61051f86828701610455565b9497909650939450505050565b6000806000806080858703121561054257600080fd5b5050823594602084013594506040840135936060013592509050565b60006020828403121561057057600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156105b9576105b9610577565b92915050565b818103818111156105b9576105b961057756fea164736f6c6343000813000a"
var PreimageOracleDeployedSourceMap = "144:4615:67:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;357:68;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;413:25:283;;;401:2;386:18;357:68:67;;;;;;;;501:66;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;614:14:283;;607:22;589:41;;577:2;562:18;501:66:67;449:187:283;2154:850:67;;;;;;:::i;:::-;;:::i;838:564::-;;;;;;:::i;:::-;;:::i;:::-;;;;1581:25:283;;;1637:2;1622:18;;1615:34;;;;1554:18;838:564:67;1407:248:283;3295:1462:67;;;;;;:::i;:::-;;:::i;:::-;;1744:262;;;;;;:::i;:::-;1877:19;;;;:14;:19;;;;;;;;:31;;;;;;;;:38;;;;1911:4;1877:38;;;;;;1925:18;;;;;;;;:30;;;;;;;;;:37;;;;1972:20;;;;;;;;;;:27;1744:262;238:50;;;;;;:::i;:::-;;;;;;;;;;;;;;;2154:850;2321:4;2308:18;2567:3;2563:14;;;2458:4;2551:27;2231:12;;2598:11;2308:18;2718:16;2598:11;2700:41;2840:20;2954:19;2947:27;2976:11;2944:44;;2154:850;-1:-1:-1;;;2154:850:67:o;838:564::-;938:12;991:20;;;:14;:20;;;;;;;;:29;;;;;;;;;938:12;;991:29;;983:62;;;;;;;3101:2:283;983:62:67;;;3083:21:283;3140:2;3120:18;;;3113:30;3179:22;3159:18;;;3152:50;3219:18;;983:62:67;;;;;;;;-1:-1:-1;1176:14:67;1193:21;;;1164:2;1193:21;;;;;;;;1244:10;1193:21;1253:1;1244:10;:::i;:::-;1228:12;:7;1238:2;1228:12;:::i;:::-;:26;1224:87;;1293:7;1280:10;:6;1289:1;1280:10;:::i;:::-;:20;;;;:::i;:::-;1270:30;;1224:87;-1:-1:-1;1367:19:67;;;;:13;:19;;;;;;;;:28;;;;;;;;;;;;838:564;;-1:-1:-1;838:564:67:o;3295:1462::-;3591:4;3578:18;3396:12;;3720:1;3710:12;;3694:29;;3691:77;;;3752:1;3749;3742:12;3691:77;4011:3;4007:14;;;3911:4;3995:27;4042:11;4016:4;4161:16;4042:11;4143:41;4374:29;;;4378:11;4374:29;4368:36;4426:20;;;;4573:19;4566:27;4595:11;4563:44;4626:19;;;;4604:1;4626:19;;;;;;;;:32;;;;;;;;:39;;;;4661:4;4626:39;;;;;;4675:18;;;;;;;;:31;;;;;;;;;:38;;;;4723:20;;;;;;;;;;;:27;;;;-1:-1:-1;;;;3295:1462:67:o;14:248:283:-;82:6;90;143:2;131:9;122:7;118:23;114:32;111:52;;;159:1;156;149:12;111:52;-1:-1:-1;;182:23:283;;;252:2;237:18;;;224:32;;-1:-1:-1;14:248:283:o;641:347::-;692:8;702:6;756:3;749:4;741:6;737:17;733:27;723:55;;774:1;771;764:12;723:55;-1:-1:-1;797:20:283;;840:18;829:30;;826:50;;;872:1;869;862:12;826:50;909:4;901:6;897:17;885:29;;961:3;954:4;945:6;937;933:19;929:30;926:39;923:59;;;978:1;975;968:12;923:59;641:347;;;;;:::o;993:409::-;1063:6;1071;1124:2;1112:9;1103:7;1099:23;1095:32;1092:52;;;1140:1;1137;1130:12;1092:52;1180:9;1167:23;1213:18;1205:6;1202:30;1199:50;;;1245:1;1242;1235:12;1199:50;1284:58;1334:7;1325:6;1314:9;1310:22;1284:58;:::i;:::-;1361:8;;1258:84;;-1:-1:-1;993:409:283;-1:-1:-1;;;;993:409:283:o;1660:477::-;1739:6;1747;1755;1808:2;1796:9;1787:7;1783:23;1779:32;1776:52;;;1824:1;1821;1814:12;1776:52;1860:9;1847:23;1837:33;;1921:2;1910:9;1906:18;1893:32;1948:18;1940:6;1937:30;1934:50;;;1980:1;1977;1970:12;1934:50;2019:58;2069:7;2060:6;2049:9;2045:22;2019:58;:::i;:::-;1660:477;;2096:8;;-1:-1:-1;1993:84:283;;-1:-1:-1;;;;1660:477:283:o;2142:385::-;2228:6;2236;2244;2252;2305:3;2293:9;2284:7;2280:23;2276:33;2273:53;;;2322:1;2319;2312:12;2273:53;-1:-1:-1;;2345:23:283;;;2415:2;2400:18;;2387:32;;-1:-1:-1;2466:2:283;2451:18;;2438:32;;2517:2;2502:18;2489:32;;-1:-1:-1;2142:385:283;-1:-1:-1;2142:385:283:o;2532:180::-;2591:6;2644:2;2632:9;2623:7;2619:23;2615:32;2612:52;;;2660:1;2657;2650:12;2612:52;-1:-1:-1;2683:23:283;;2532:180;-1:-1:-1;2532:180:283:o;3248:184::-;3300:77;3297:1;3290:88;3397:4;3394:1;3387:15;3421:4;3418:1;3411:15;3437:128;3477:3;3508:1;3504:6;3501:1;3498:13;3495:39;;;3514:18;;:::i;:::-;-1:-1:-1;3550:9:283;;3437:128::o;3570:125::-;3610:4;3638:1;3635;3632:8;3629:34;;;3643:18;;:::i;:::-;-1:-1:-1;3680:9:283;;3570:125::o" var PreimageOracleDeployedSourceMap = "144:4615:32:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;357:68;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;413:25:104;;;401:2;386:18;357:68:32;;;;;;;;501:66;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;614:14:104;;607:22;589:41;;577:2;562:18;501:66:32;449:187:104;2154:850:32;;;;;;:::i;:::-;;:::i;838:564::-;;;;;;:::i;:::-;;:::i;:::-;;;;1581:25:104;;;1637:2;1622:18;;1615:34;;;;1554:18;838:564:32;1407:248:104;3295:1462:32;;;;;;:::i;:::-;;:::i;:::-;;1744:262;;;;;;:::i;:::-;1877:19;;;;:14;:19;;;;;;;;:31;;;;;;;;:38;;;;1911:4;1877:38;;;;;;1925:18;;;;;;;;:30;;;;;;;;;:37;;;;1972:20;;;;;;;;;;:27;1744:262;238:50;;;;;;:::i;:::-;;;;;;;;;;;;;;;2154:850;2321:4;2308:18;2567:3;2563:14;;;2458:4;2551:27;2231:12;;2598:11;2308:18;2718:16;2598:11;2700:41;2840:20;2954:19;2947:27;2976:11;2944:44;;2154:850;-1:-1:-1;;;2154:850:32:o;838:564::-;938:12;991:20;;;:14;:20;;;;;;;;:29;;;;;;;;;938:12;;991:29;;983:62;;;;;;;3101:2:104;983:62:32;;;3083:21:104;3140:2;3120:18;;;3113:30;3179:22;3159:18;;;3152:50;3219:18;;983:62:32;;;;;;;;-1:-1:-1;1176:14:32;1193:21;;;1164:2;1193:21;;;;;;;;1244:10;1193:21;1253:1;1244:10;:::i;:::-;1228:12;:7;1238:2;1228:12;:::i;:::-;:26;1224:87;;1293:7;1280:10;:6;1289:1;1280:10;:::i;:::-;:20;;;;:::i;:::-;1270:30;;1224:87;-1:-1:-1;1367:19:32;;;;:13;:19;;;;;;;;:28;;;;;;;;;;;;838:564;;-1:-1:-1;838:564:32:o;3295:1462::-;3591:4;3578:18;3396:12;;3720:1;3710:12;;3694:29;;3691:77;;;3752:1;3749;3742:12;3691:77;4011:3;4007:14;;;3911:4;3995:27;4042:11;4016:4;4161:16;4042:11;4143:41;4374:29;;;4378:11;4374:29;4368:36;4426:20;;;;4573:19;4566:27;4595:11;4563:44;4626:19;;;;4604:1;4626:19;;;;;;;;:32;;;;;;;;:39;;;;4661:4;4626:39;;;;;;4675:18;;;;;;;;:31;;;;;;;;;:38;;;;4723:20;;;;;;;;;;;:27;;;;-1:-1:-1;;;;3295:1462:32:o;14:248:104:-;82:6;90;143:2;131:9;122:7;118:23;114:32;111:52;;;159:1;156;149:12;111:52;-1:-1:-1;;182:23:104;;;252:2;237:18;;;224:32;;-1:-1:-1;14:248:104:o;641:347::-;692:8;702:6;756:3;749:4;741:6;737:17;733:27;723:55;;774:1;771;764:12;723:55;-1:-1:-1;797:20:104;;840:18;829:30;;826:50;;;872:1;869;862:12;826:50;909:4;901:6;897:17;885:29;;961:3;954:4;945:6;937;933:19;929:30;926:39;923:59;;;978:1;975;968:12;923:59;641:347;;;;;:::o;993:409::-;1063:6;1071;1124:2;1112:9;1103:7;1099:23;1095:32;1092:52;;;1140:1;1137;1130:12;1092:52;1180:9;1167:23;1213:18;1205:6;1202:30;1199:50;;;1245:1;1242;1235:12;1199:50;1284:58;1334:7;1325:6;1314:9;1310:22;1284:58;:::i;:::-;1361:8;;1258:84;;-1:-1:-1;993:409:104;-1:-1:-1;;;;993:409:104:o;1660:477::-;1739:6;1747;1755;1808:2;1796:9;1787:7;1783:23;1779:32;1776:52;;;1824:1;1821;1814:12;1776:52;1860:9;1847:23;1837:33;;1921:2;1910:9;1906:18;1893:32;1948:18;1940:6;1937:30;1934:50;;;1980:1;1977;1970:12;1934:50;2019:58;2069:7;2060:6;2049:9;2045:22;2019:58;:::i;:::-;1660:477;;2096:8;;-1:-1:-1;1993:84:104;;-1:-1:-1;;;;1660:477:104:o;2142:385::-;2228:6;2236;2244;2252;2305:3;2293:9;2284:7;2280:23;2276:33;2273:53;;;2322:1;2319;2312:12;2273:53;-1:-1:-1;;2345:23:104;;;2415:2;2400:18;;2387:32;;-1:-1:-1;2466:2:104;2451:18;;2438:32;;2517:2;2502:18;2489:32;;-1:-1:-1;2142:385:104;-1:-1:-1;2142:385:104:o;2532:180::-;2591:6;2644:2;2632:9;2623:7;2619:23;2615:32;2612:52;;;2660:1;2657;2650:12;2612:52;-1:-1:-1;2683:23:104;;2532:180;-1:-1:-1;2532:180:104:o;3248:184::-;3300:77;3297:1;3290:88;3397:4;3394:1;3387:15;3421:4;3418:1;3411:15;3437:125;3502:9;;;3523:10;;;3520:36;;;3536:18;;:::i;:::-;3437:125;;;;:::o;3567:128::-;3634:9;;;3655:11;;;3652:37;;;3669:18;;:::i"
func init() { func init() {
if err := json.Unmarshal([]byte(PreimageOracleStorageLayoutJSON), PreimageOracleStorageLayout); err != nil { if err := json.Unmarshal([]byte(PreimageOracleStorageLayoutJSON), PreimageOracleStorageLayout); err != nil {
......
// Code generated - DO NOT EDIT.
// This file is a generated binding and any manual changes will be lost.
package bindings
import (
"errors"
"math/big"
"strings"
ethereum "github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/event"
)
// Reference imports to suppress errors if they are not otherwise used.
var (
_ = errors.New
_ = big.NewInt
_ = strings.NewReader
_ = ethereum.NotFound
_ = bind.Bind
_ = common.Big1
_ = types.BloomLookup
_ = event.NewSubscription
)
// SchemaRecord is an auto generated low-level Go binding around an user-defined struct.
type SchemaRecord struct {
Uid [32]byte
Resolver common.Address
Revocable bool
Schema string
}
// SchemaRegistryMetaData contains all meta data concerning the SchemaRegistry contract.
var SchemaRegistryMetaData = &bind.MetaData{
ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AlreadyExists\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"registerer\",\"type\":\"address\"}],\"name\":\"Registered\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\"}],\"name\":\"getSchema\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\"},{\"internalType\":\"contractISchemaResolver\",\"name\":\"resolver\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"revocable\",\"type\":\"bool\"},{\"internalType\":\"string\",\"name\":\"schema\",\"type\":\"string\"}],\"internalType\":\"structSchemaRecord\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"schema\",\"type\":\"string\"},{\"internalType\":\"contractISchemaResolver\",\"name\":\"resolver\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"revocable\",\"type\":\"bool\"}],\"name\":\"register\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]",
Bin: "0x60e060405234801561001057600080fd5b5060016080819052600060a081905260c081905280610b166100478239600060fe0152600060d50152600060ac0152610b166000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c806354fd4d501461004657806360d7a27814610064578063a2ea7c6e14610085575b600080fd5b61004e6100a5565b60405161005b9190610604565b60405180910390f35b61007761007236600461061e565b610148565b60405190815260200161005b565b6100986100933660046106d0565b6102f1565b60405161005b91906106e9565b60606100d07f0000000000000000000000000000000000000000000000000000000000000000610419565b6100f97f0000000000000000000000000000000000000000000000000000000000000000610419565b6101227f0000000000000000000000000000000000000000000000000000000000000000610419565b6040516020016101349392919061073a565b604051602081830303815290604052905090565b60008060405180608001604052806000801b81526020018573ffffffffffffffffffffffffffffffffffffffff168152602001841515815260200187878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920182905250939094525092935091506101ca905082610556565b60008181526020819052604090205490915015610213576040517f23369fa600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80825260008181526020818152604091829020845181559084015160018201805493860151151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00000000000000000000000000000000000000000090941673ffffffffffffffffffffffffffffffffffffffff9092169190911792909217909155606083015183919060028201906102af9082610881565b50506040513381528291507f7d917fcbc9a29a9705ff9936ffa599500e4fd902e4486bae317414fe967b307c9060200160405180910390a29695505050505050565b604080516080810182526000808252602082018190529181019190915260608082015260008281526020818152604091829020825160808101845281548152600182015473ffffffffffffffffffffffffffffffffffffffff8116938201939093527401000000000000000000000000000000000000000090920460ff16151592820192909252600282018054919291606084019190610390906107df565b80601f01602080910402602001604051908101604052809291908181526020018280546103bc906107df565b80156104095780601f106103de57610100808354040283529160200191610409565b820191906000526020600020905b8154815290600101906020018083116103ec57829003601f168201915b5050505050815250509050919050565b60608160000361045c57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156104865780610470816109ca565b915061047f9050600a83610a31565b9150610460565b60008167ffffffffffffffff8111156104a1576104a16107b0565b6040519080825280601f01601f1916602001820160405280156104cb576020820181803683370190505b5090505b841561054e576104e0600183610a45565b91506104ed600a86610a5e565b6104f8906030610a72565b60f81b81838151811061050d5761050d610a85565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610547600a86610a31565b94506104cf565b949350505050565b600081606001518260200151836040015160405160200161057993929190610ab4565b604051602081830303815290604052805190602001209050919050565b60005b838110156105b1578181015183820152602001610599565b50506000910152565b600081518084526105d2816020860160208601610596565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061061760208301846105ba565b9392505050565b6000806000806060858703121561063457600080fd5b843567ffffffffffffffff8082111561064c57600080fd5b818701915087601f83011261066057600080fd5b81358181111561066f57600080fd5b88602082850101111561068157600080fd5b6020928301965094505085013573ffffffffffffffffffffffffffffffffffffffff811681146106b057600080fd5b9150604085013580151581146106c557600080fd5b939692955090935050565b6000602082840312156106e257600080fd5b5035919050565b602081528151602082015273ffffffffffffffffffffffffffffffffffffffff60208301511660408201526040820151151560608201526000606083015160808084015261054e60a08401826105ba565b6000845161074c818460208901610596565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551610788816001850160208a01610596565b600192019182015283516107a3816002840160208801610596565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600181811c908216806107f357607f821691505b60208210810361082c577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f82111561087c57600081815260208120601f850160051c810160208610156108595750805b601f850160051c820191505b8181101561087857828155600101610865565b5050505b505050565b815167ffffffffffffffff81111561089b5761089b6107b0565b6108af816108a984546107df565b84610832565b602080601f83116001811461090257600084156108cc5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610878565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561094f57888601518255948401946001909101908401610930565b508582101561098b57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036109fb576109fb61099b565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082610a4057610a40610a02565b500490565b81810381811115610a5857610a5861099b565b92915050565b600082610a6d57610a6d610a02565b500690565b80820180821115610a5857610a5861099b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008451610ac6818460208901610596565b60609490941b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000169190930190815290151560f81b60148201526015019291505056fea164736f6c6343000813000a",
}
// SchemaRegistryABI is the input ABI used to generate the binding from.
// Deprecated: Use SchemaRegistryMetaData.ABI instead.
var SchemaRegistryABI = SchemaRegistryMetaData.ABI
// SchemaRegistryBin is the compiled bytecode used for deploying new contracts.
// Deprecated: Use SchemaRegistryMetaData.Bin instead.
var SchemaRegistryBin = SchemaRegistryMetaData.Bin
// DeploySchemaRegistry deploys a new Ethereum contract, binding an instance of SchemaRegistry to it.
func DeploySchemaRegistry(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *SchemaRegistry, error) {
parsed, err := SchemaRegistryMetaData.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(SchemaRegistryBin), backend)
if err != nil {
return common.Address{}, nil, nil, err
}
return address, tx, &SchemaRegistry{SchemaRegistryCaller: SchemaRegistryCaller{contract: contract}, SchemaRegistryTransactor: SchemaRegistryTransactor{contract: contract}, SchemaRegistryFilterer: SchemaRegistryFilterer{contract: contract}}, nil
}
// SchemaRegistry is an auto generated Go binding around an Ethereum contract.
type SchemaRegistry struct {
SchemaRegistryCaller // Read-only binding to the contract
SchemaRegistryTransactor // Write-only binding to the contract
SchemaRegistryFilterer // Log filterer for contract events
}
// SchemaRegistryCaller is an auto generated read-only Go binding around an Ethereum contract.
type SchemaRegistryCaller struct {
contract *bind.BoundContract // Generic contract wrapper for the low level calls
}
// SchemaRegistryTransactor is an auto generated write-only Go binding around an Ethereum contract.
type SchemaRegistryTransactor struct {
contract *bind.BoundContract // Generic contract wrapper for the low level calls
}
// SchemaRegistryFilterer is an auto generated log filtering Go binding around an Ethereum contract events.
type SchemaRegistryFilterer struct {
contract *bind.BoundContract // Generic contract wrapper for the low level calls
}
// SchemaRegistrySession is an auto generated Go binding around an Ethereum contract,
// with pre-set call and transact options.
type SchemaRegistrySession struct {
Contract *SchemaRegistry // 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
}
// SchemaRegistryCallerSession is an auto generated read-only Go binding around an Ethereum contract,
// with pre-set call options.
type SchemaRegistryCallerSession struct {
Contract *SchemaRegistryCaller // Generic contract caller binding to set the session for
CallOpts bind.CallOpts // Call options to use throughout this session
}
// SchemaRegistryTransactorSession is an auto generated write-only Go binding around an Ethereum contract,
// with pre-set transact options.
type SchemaRegistryTransactorSession struct {
Contract *SchemaRegistryTransactor // Generic contract transactor binding to set the session for
TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
}
// SchemaRegistryRaw is an auto generated low-level Go binding around an Ethereum contract.
type SchemaRegistryRaw struct {
Contract *SchemaRegistry // Generic contract binding to access the raw methods on
}
// SchemaRegistryCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract.
type SchemaRegistryCallerRaw struct {
Contract *SchemaRegistryCaller // Generic read-only contract binding to access the raw methods on
}
// SchemaRegistryTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract.
type SchemaRegistryTransactorRaw struct {
Contract *SchemaRegistryTransactor // Generic write-only contract binding to access the raw methods on
}
// NewSchemaRegistry creates a new instance of SchemaRegistry, bound to a specific deployed contract.
func NewSchemaRegistry(address common.Address, backend bind.ContractBackend) (*SchemaRegistry, error) {
contract, err := bindSchemaRegistry(address, backend, backend, backend)
if err != nil {
return nil, err
}
return &SchemaRegistry{SchemaRegistryCaller: SchemaRegistryCaller{contract: contract}, SchemaRegistryTransactor: SchemaRegistryTransactor{contract: contract}, SchemaRegistryFilterer: SchemaRegistryFilterer{contract: contract}}, nil
}
// NewSchemaRegistryCaller creates a new read-only instance of SchemaRegistry, bound to a specific deployed contract.
func NewSchemaRegistryCaller(address common.Address, caller bind.ContractCaller) (*SchemaRegistryCaller, error) {
contract, err := bindSchemaRegistry(address, caller, nil, nil)
if err != nil {
return nil, err
}
return &SchemaRegistryCaller{contract: contract}, nil
}
// NewSchemaRegistryTransactor creates a new write-only instance of SchemaRegistry, bound to a specific deployed contract.
func NewSchemaRegistryTransactor(address common.Address, transactor bind.ContractTransactor) (*SchemaRegistryTransactor, error) {
contract, err := bindSchemaRegistry(address, nil, transactor, nil)
if err != nil {
return nil, err
}
return &SchemaRegistryTransactor{contract: contract}, nil
}
// NewSchemaRegistryFilterer creates a new log filterer instance of SchemaRegistry, bound to a specific deployed contract.
func NewSchemaRegistryFilterer(address common.Address, filterer bind.ContractFilterer) (*SchemaRegistryFilterer, error) {
contract, err := bindSchemaRegistry(address, nil, nil, filterer)
if err != nil {
return nil, err
}
return &SchemaRegistryFilterer{contract: contract}, nil
}
// bindSchemaRegistry binds a generic wrapper to an already deployed contract.
func bindSchemaRegistry(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) {
parsed, err := abi.JSON(strings.NewReader(SchemaRegistryABI))
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 (_SchemaRegistry *SchemaRegistryRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error {
return _SchemaRegistry.Contract.SchemaRegistryCaller.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 (_SchemaRegistry *SchemaRegistryRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
return _SchemaRegistry.Contract.SchemaRegistryTransactor.contract.Transfer(opts)
}
// Transact invokes the (paid) contract method with params as input values.
func (_SchemaRegistry *SchemaRegistryRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
return _SchemaRegistry.Contract.SchemaRegistryTransactor.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 (_SchemaRegistry *SchemaRegistryCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error {
return _SchemaRegistry.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 (_SchemaRegistry *SchemaRegistryTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
return _SchemaRegistry.Contract.contract.Transfer(opts)
}
// Transact invokes the (paid) contract method with params as input values.
func (_SchemaRegistry *SchemaRegistryTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
return _SchemaRegistry.Contract.contract.Transact(opts, method, params...)
}
// GetSchema is a free data retrieval call binding the contract method 0xa2ea7c6e.
//
// Solidity: function getSchema(bytes32 uid) view returns((bytes32,address,bool,string))
func (_SchemaRegistry *SchemaRegistryCaller) GetSchema(opts *bind.CallOpts, uid [32]byte) (SchemaRecord, error) {
var out []interface{}
err := _SchemaRegistry.contract.Call(opts, &out, "getSchema", uid)
if err != nil {
return *new(SchemaRecord), err
}
out0 := *abi.ConvertType(out[0], new(SchemaRecord)).(*SchemaRecord)
return out0, err
}
// GetSchema is a free data retrieval call binding the contract method 0xa2ea7c6e.
//
// Solidity: function getSchema(bytes32 uid) view returns((bytes32,address,bool,string))
func (_SchemaRegistry *SchemaRegistrySession) GetSchema(uid [32]byte) (SchemaRecord, error) {
return _SchemaRegistry.Contract.GetSchema(&_SchemaRegistry.CallOpts, uid)
}
// GetSchema is a free data retrieval call binding the contract method 0xa2ea7c6e.
//
// Solidity: function getSchema(bytes32 uid) view returns((bytes32,address,bool,string))
func (_SchemaRegistry *SchemaRegistryCallerSession) GetSchema(uid [32]byte) (SchemaRecord, error) {
return _SchemaRegistry.Contract.GetSchema(&_SchemaRegistry.CallOpts, uid)
}
// Version is a free data retrieval call binding the contract method 0x54fd4d50.
//
// Solidity: function version() view returns(string)
func (_SchemaRegistry *SchemaRegistryCaller) Version(opts *bind.CallOpts) (string, error) {
var out []interface{}
err := _SchemaRegistry.contract.Call(opts, &out, "version")
if err != nil {
return *new(string), err
}
out0 := *abi.ConvertType(out[0], new(string)).(*string)
return out0, err
}
// Version is a free data retrieval call binding the contract method 0x54fd4d50.
//
// Solidity: function version() view returns(string)
func (_SchemaRegistry *SchemaRegistrySession) Version() (string, error) {
return _SchemaRegistry.Contract.Version(&_SchemaRegistry.CallOpts)
}
// Version is a free data retrieval call binding the contract method 0x54fd4d50.
//
// Solidity: function version() view returns(string)
func (_SchemaRegistry *SchemaRegistryCallerSession) Version() (string, error) {
return _SchemaRegistry.Contract.Version(&_SchemaRegistry.CallOpts)
}
// Register is a paid mutator transaction binding the contract method 0x60d7a278.
//
// Solidity: function register(string schema, address resolver, bool revocable) returns(bytes32)
func (_SchemaRegistry *SchemaRegistryTransactor) Register(opts *bind.TransactOpts, schema string, resolver common.Address, revocable bool) (*types.Transaction, error) {
return _SchemaRegistry.contract.Transact(opts, "register", schema, resolver, revocable)
}
// Register is a paid mutator transaction binding the contract method 0x60d7a278.
//
// Solidity: function register(string schema, address resolver, bool revocable) returns(bytes32)
func (_SchemaRegistry *SchemaRegistrySession) Register(schema string, resolver common.Address, revocable bool) (*types.Transaction, error) {
return _SchemaRegistry.Contract.Register(&_SchemaRegistry.TransactOpts, schema, resolver, revocable)
}
// Register is a paid mutator transaction binding the contract method 0x60d7a278.
//
// Solidity: function register(string schema, address resolver, bool revocable) returns(bytes32)
func (_SchemaRegistry *SchemaRegistryTransactorSession) Register(schema string, resolver common.Address, revocable bool) (*types.Transaction, error) {
return _SchemaRegistry.Contract.Register(&_SchemaRegistry.TransactOpts, schema, resolver, revocable)
}
// SchemaRegistryRegisteredIterator is returned from FilterRegistered and is used to iterate over the raw logs and unpacked data for Registered events raised by the SchemaRegistry contract.
type SchemaRegistryRegisteredIterator struct {
Event *SchemaRegistryRegistered // 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 *SchemaRegistryRegisteredIterator) 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(SchemaRegistryRegistered)
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(SchemaRegistryRegistered)
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 *SchemaRegistryRegisteredIterator) Error() error {
return it.fail
}
// Close terminates the iteration process, releasing any pending underlying
// resources.
func (it *SchemaRegistryRegisteredIterator) Close() error {
it.sub.Unsubscribe()
return nil
}
// SchemaRegistryRegistered represents a Registered event raised by the SchemaRegistry contract.
type SchemaRegistryRegistered struct {
Uid [32]byte
Registerer common.Address
Raw types.Log // Blockchain specific contextual infos
}
// FilterRegistered is a free log retrieval operation binding the contract event 0x7d917fcbc9a29a9705ff9936ffa599500e4fd902e4486bae317414fe967b307c.
//
// Solidity: event Registered(bytes32 indexed uid, address registerer)
func (_SchemaRegistry *SchemaRegistryFilterer) FilterRegistered(opts *bind.FilterOpts, uid [][32]byte) (*SchemaRegistryRegisteredIterator, error) {
var uidRule []interface{}
for _, uidItem := range uid {
uidRule = append(uidRule, uidItem)
}
logs, sub, err := _SchemaRegistry.contract.FilterLogs(opts, "Registered", uidRule)
if err != nil {
return nil, err
}
return &SchemaRegistryRegisteredIterator{contract: _SchemaRegistry.contract, event: "Registered", logs: logs, sub: sub}, nil
}
// WatchRegistered is a free log subscription operation binding the contract event 0x7d917fcbc9a29a9705ff9936ffa599500e4fd902e4486bae317414fe967b307c.
//
// Solidity: event Registered(bytes32 indexed uid, address registerer)
func (_SchemaRegistry *SchemaRegistryFilterer) WatchRegistered(opts *bind.WatchOpts, sink chan<- *SchemaRegistryRegistered, uid [][32]byte) (event.Subscription, error) {
var uidRule []interface{}
for _, uidItem := range uid {
uidRule = append(uidRule, uidItem)
}
logs, sub, err := _SchemaRegistry.contract.WatchLogs(opts, "Registered", uidRule)
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(SchemaRegistryRegistered)
if err := _SchemaRegistry.contract.UnpackLog(event, "Registered", 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
}
// ParseRegistered is a log parse operation binding the contract event 0x7d917fcbc9a29a9705ff9936ffa599500e4fd902e4486bae317414fe967b307c.
//
// Solidity: event Registered(bytes32 indexed uid, address registerer)
func (_SchemaRegistry *SchemaRegistryFilterer) ParseRegistered(log types.Log) (*SchemaRegistryRegistered, error) {
event := new(SchemaRegistryRegistered)
if err := _SchemaRegistry.contract.UnpackLog(event, "Registered", log); err != nil {
return nil, err
}
event.Raw = log
return event, nil
}
// Code generated - DO NOT EDIT.
// This file is a generated binding and any manual changes will be lost.
package bindings
import (
"encoding/json"
"github.com/ethereum-optimism/optimism/op-bindings/solc"
)
const SchemaRegistryStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contract\":\"contracts/EAS/SchemaRegistry.sol:SchemaRegistry\",\"label\":\"_registry\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_mapping(t_bytes32,t_struct(SchemaRecord)1003_storage)\"},{\"astId\":1001,\"contract\":\"contracts/EAS/SchemaRegistry.sol:SchemaRegistry\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_array(t_uint256)49_storage\"}],\"types\":{\"t_array(t_uint256)49_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[49]\",\"numberOfBytes\":\"1568\",\"base\":\"t_uint256\"},\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_bytes32\":{\"encoding\":\"inplace\",\"label\":\"bytes32\",\"numberOfBytes\":\"32\"},\"t_contract(ISchemaResolver)1002\":{\"encoding\":\"inplace\",\"label\":\"contract ISchemaResolver\",\"numberOfBytes\":\"20\"},\"t_mapping(t_bytes32,t_struct(SchemaRecord)1003_storage)\":{\"encoding\":\"mapping\",\"label\":\"mapping(bytes32 =\u003e struct SchemaRecord)\",\"numberOfBytes\":\"32\",\"key\":\"t_bytes32\",\"value\":\"t_struct(SchemaRecord)1003_storage\"},\"t_string_storage\":{\"encoding\":\"bytes\",\"label\":\"string\",\"numberOfBytes\":\"32\"},\"t_struct(SchemaRecord)1003_storage\":{\"encoding\":\"inplace\",\"label\":\"struct SchemaRecord\",\"numberOfBytes\":\"96\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"}}}"
var SchemaRegistryStorageLayout = new(solc.StorageLayout)
var SchemaRegistryDeployedBin = "0x608060405234801561001057600080fd5b50600436106100415760003560e01c806354fd4d501461004657806360d7a27814610064578063a2ea7c6e14610085575b600080fd5b61004e6100a5565b60405161005b9190610604565b60405180910390f35b61007761007236600461061e565b610148565b60405190815260200161005b565b6100986100933660046106d0565b6102f1565b60405161005b91906106e9565b60606100d07f0000000000000000000000000000000000000000000000000000000000000000610419565b6100f97f0000000000000000000000000000000000000000000000000000000000000000610419565b6101227f0000000000000000000000000000000000000000000000000000000000000000610419565b6040516020016101349392919061073a565b604051602081830303815290604052905090565b60008060405180608001604052806000801b81526020018573ffffffffffffffffffffffffffffffffffffffff168152602001841515815260200187878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920182905250939094525092935091506101ca905082610556565b60008181526020819052604090205490915015610213576040517f23369fa600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80825260008181526020818152604091829020845181559084015160018201805493860151151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00000000000000000000000000000000000000000090941673ffffffffffffffffffffffffffffffffffffffff9092169190911792909217909155606083015183919060028201906102af9082610881565b50506040513381528291507f7d917fcbc9a29a9705ff9936ffa599500e4fd902e4486bae317414fe967b307c9060200160405180910390a29695505050505050565b604080516080810182526000808252602082018190529181019190915260608082015260008281526020818152604091829020825160808101845281548152600182015473ffffffffffffffffffffffffffffffffffffffff8116938201939093527401000000000000000000000000000000000000000090920460ff16151592820192909252600282018054919291606084019190610390906107df565b80601f01602080910402602001604051908101604052809291908181526020018280546103bc906107df565b80156104095780601f106103de57610100808354040283529160200191610409565b820191906000526020600020905b8154815290600101906020018083116103ec57829003601f168201915b5050505050815250509050919050565b60608160000361045c57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156104865780610470816109ca565b915061047f9050600a83610a31565b9150610460565b60008167ffffffffffffffff8111156104a1576104a16107b0565b6040519080825280601f01601f1916602001820160405280156104cb576020820181803683370190505b5090505b841561054e576104e0600183610a45565b91506104ed600a86610a5e565b6104f8906030610a72565b60f81b81838151811061050d5761050d610a85565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610547600a86610a31565b94506104cf565b949350505050565b600081606001518260200151836040015160405160200161057993929190610ab4565b604051602081830303815290604052805190602001209050919050565b60005b838110156105b1578181015183820152602001610599565b50506000910152565b600081518084526105d2816020860160208601610596565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061061760208301846105ba565b9392505050565b6000806000806060858703121561063457600080fd5b843567ffffffffffffffff8082111561064c57600080fd5b818701915087601f83011261066057600080fd5b81358181111561066f57600080fd5b88602082850101111561068157600080fd5b6020928301965094505085013573ffffffffffffffffffffffffffffffffffffffff811681146106b057600080fd5b9150604085013580151581146106c557600080fd5b939692955090935050565b6000602082840312156106e257600080fd5b5035919050565b602081528151602082015273ffffffffffffffffffffffffffffffffffffffff60208301511660408201526040820151151560608201526000606083015160808084015261054e60a08401826105ba565b6000845161074c818460208901610596565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551610788816001850160208a01610596565b600192019182015283516107a3816002840160208801610596565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600181811c908216806107f357607f821691505b60208210810361082c577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f82111561087c57600081815260208120601f850160051c810160208610156108595750805b601f850160051c820191505b8181101561087857828155600101610865565b5050505b505050565b815167ffffffffffffffff81111561089b5761089b6107b0565b6108af816108a984546107df565b84610832565b602080601f83116001811461090257600084156108cc5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610878565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561094f57888601518255948401946001909101908401610930565b508582101561098b57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036109fb576109fb61099b565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082610a4057610a40610a02565b500490565b81810381811115610a5857610a5861099b565b92915050565b600082610a6d57610a6d610a02565b500690565b80820180821115610a5857610a5861099b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008451610ac6818460208901610596565b60609490941b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000169190930190815290151560f81b60148201526015019291505056fea164736f6c6343000813000a"
func init() {
if err := json.Unmarshal([]byte(SchemaRegistryStorageLayoutJSON), SchemaRegistryStorageLayout); err != nil {
panic(err)
}
layouts["SchemaRegistry"] = SchemaRegistryStorageLayout
deployedBytecodes["SchemaRegistry"] = SchemaRegistryDeployedBin
}
...@@ -9,6 +9,7 @@ import ( ...@@ -9,6 +9,7 @@ import (
"os/exec" "os/exec"
"path" "path"
"path/filepath" "path/filepath"
"regexp"
"strings" "strings"
"text/template" "text/template"
...@@ -84,17 +85,22 @@ func main() { ...@@ -84,17 +85,22 @@ func main() {
// and hold a mapping from the contract name to the contract path. // and hold a mapping from the contract name to the contract path.
// Walk walks the directory deterministically, so the later instance // Walk walks the directory deterministically, so the later instance
// of the contract with the same name will be used // of the contract with the same name will be used
re := regexp.MustCompile(`\.\d+\.\d+\.\d+`)
artifactPaths := make(map[string]string) artifactPaths := make(map[string]string)
if err := filepath.Walk(f.ForgeArtifacts, if err := filepath.Walk(f.ForgeArtifacts,
func(path string, info os.FileInfo, err error) error { func(path string, info os.FileInfo, err error) error {
if err != nil { if err != nil {
return err return err
} }
base := filepath.Base(path)
if strings.HasSuffix(base, ".json") { if strings.HasSuffix(path, ".json") {
name := base[:len(base)-5] base := filepath.Base(path)
if _, ok := artifactPaths[name]; !ok { name := strings.TrimSuffix(base, ".json")
artifactPaths[name] = path
// remove the compiler version from the name
sanitized := re.ReplaceAllString(name, "")
if _, ok := artifactPaths[sanitized]; !ok {
artifactPaths[sanitized] = path
} }
} }
return nil return nil
...@@ -108,6 +114,7 @@ func main() { ...@@ -108,6 +114,7 @@ func main() {
artifactPath := path.Join(f.ForgeArtifacts, name+".sol", name+".json") artifactPath := path.Join(f.ForgeArtifacts, name+".sol", name+".json")
forgeArtifactData, err := os.ReadFile(artifactPath) forgeArtifactData, err := os.ReadFile(artifactPath)
if errors.Is(err, os.ErrNotExist) { if errors.Is(err, os.ErrNotExist) {
log.Printf("cannot find forge-artifact for %s at standard path %s, trying %s\n", name, artifactPath, artifactPaths[name])
artifactPath = artifactPaths[name] artifactPath = artifactPaths[name]
forgeArtifactData, err = os.ReadFile(artifactPath) forgeArtifactData, err = os.ReadFile(artifactPath)
if errors.Is(err, os.ErrNotExist) { if errors.Is(err, os.ErrNotExist) {
......
...@@ -23,6 +23,8 @@ const ( ...@@ -23,6 +23,8 @@ const (
ProxyAdmin = "0x4200000000000000000000000000000000000018" ProxyAdmin = "0x4200000000000000000000000000000000000018"
BaseFeeVault = "0x4200000000000000000000000000000000000019" BaseFeeVault = "0x4200000000000000000000000000000000000019"
L1FeeVault = "0x420000000000000000000000000000000000001a" L1FeeVault = "0x420000000000000000000000000000000000001a"
SchemaRegistry = "0x4200000000000000000000000000000000000020"
EAS = "0x4200000000000000000000000000000000000021"
) )
var ( var (
...@@ -43,6 +45,8 @@ var ( ...@@ -43,6 +45,8 @@ var (
ProxyAdminAddr = common.HexToAddress(ProxyAdmin) ProxyAdminAddr = common.HexToAddress(ProxyAdmin)
BaseFeeVaultAddr = common.HexToAddress(BaseFeeVault) BaseFeeVaultAddr = common.HexToAddress(BaseFeeVault)
L1FeeVaultAddr = common.HexToAddress(L1FeeVault) L1FeeVaultAddr = common.HexToAddress(L1FeeVault)
SchemaRegistryAddr = common.HexToAddress(SchemaRegistry)
EASAddr = common.HexToAddress(EAS)
Predeploys = make(map[string]*common.Address) Predeploys = make(map[string]*common.Address)
) )
...@@ -76,4 +80,6 @@ func init() { ...@@ -76,4 +80,6 @@ func init() {
Predeploys["ProxyAdmin"] = &ProxyAdminAddr Predeploys["ProxyAdmin"] = &ProxyAdminAddr
Predeploys["BaseFeeVault"] = &BaseFeeVaultAddr Predeploys["BaseFeeVault"] = &BaseFeeVaultAddr
Predeploys["L1FeeVault"] = &L1FeeVaultAddr Predeploys["L1FeeVault"] = &L1FeeVaultAddr
Predeploys["SchemaRegistry"] = &SchemaRegistryAddr
Predeploys["EAS"] = &EASAddr
} }
...@@ -44,7 +44,7 @@ func Main(cliCtx *cli.Context) error { ...@@ -44,7 +44,7 @@ func Main(cliCtx *cli.Context) error {
m := metrics.NewMetrics("default") m := metrics.NewMetrics("default")
ctx := context.Background() ctx := context.Background()
config, err := opnode.NewRollupConfig(cliCtx) config, err := opnode.NewRollupConfig(logger, cliCtx)
if err != nil { if err != nil {
return err return err
} }
......
...@@ -225,6 +225,16 @@ func checkPredeployConfig(client *ethclient.Client, name string) error { ...@@ -225,6 +225,16 @@ func checkPredeployConfig(client *ethclient.Client, name string) error {
if err := checkL2ToL1MessagePasser(p, client); err != nil { if err := checkL2ToL1MessagePasser(p, client); err != nil {
return err return err
} }
case predeploys.SchemaRegistryAddr:
if err := checkSchemaRegistry(p, client); err != nil {
return err
}
case predeploys.EASAddr:
if err := checkEAS(p, client); err != nil {
return err
}
} }
return nil return nil
}) })
...@@ -712,6 +722,43 @@ func checkDeployerWhitelist(addr common.Address, client *ethclient.Client) error ...@@ -712,6 +722,43 @@ func checkDeployerWhitelist(addr common.Address, client *ethclient.Client) error
return nil return nil
} }
func checkSchemaRegistry(addr common.Address, client *ethclient.Client) error {
contract, err := bindings.NewSchemaRegistry(addr, client)
if err != nil {
return err
}
version, err := contract.Version(&bind.CallOpts{})
if err != nil {
return err
}
log.Info("SchemaRegistry version", "version", version)
return nil
}
func checkEAS(addr common.Address, client *ethclient.Client) error {
contract, err := bindings.NewEAS(addr, client)
if err != nil {
return err
}
registry, err := contract.GetSchemaRegistry(&bind.CallOpts{})
if err != nil {
return err
}
if registry != predeploys.SchemaRegistryAddr {
return fmt.Errorf("Incorrect registry address %s", registry)
}
log.Info("EAS", "registry", registry)
version, err := contract.Version(&bind.CallOpts{})
if err != nil {
return err
}
log.Info("EAS version", "version", version)
return nil
}
func getEIP1967AdminAddress(client *ethclient.Client, addr common.Address) (common.Address, error) { func getEIP1967AdminAddress(client *ethclient.Client, addr common.Address) (common.Address, error) {
slot, err := client.StorageAt(context.Background(), addr, util.EIP1967AdminSlot, nil) slot, err := client.StorageAt(context.Background(), addr, util.EIP1967AdminSlot, nil)
if err != nil { if err != nil {
......
...@@ -61,6 +61,7 @@ func BuildL2Genesis(config *DeployConfig, l1StartBlock *types.Block) (*core.Gene ...@@ -61,6 +61,7 @@ func BuildL2Genesis(config *DeployConfig, l1StartBlock *types.Block) (*core.Gene
} }
db.CreateAccount(codeAddr) db.CreateAccount(codeAddr)
db.SetState(addr, ImplementationSlot, codeAddr.Hash()) db.SetState(addr, ImplementationSlot, codeAddr.Hash())
log.Info("Set proxy", "name", name, "address", addr, "implementation", codeAddr)
} else { } else {
db.DeleteState(addr, AdminSlot) db.DeleteState(addr, AdminSlot)
} }
......
...@@ -81,7 +81,7 @@ func TestBuildL2DeveloperGenesis(t *testing.T) { ...@@ -81,7 +81,7 @@ func TestBuildL2DeveloperGenesis(t *testing.T) {
err = config.InitDeveloperDeployedAddresses() err = config.InitDeveloperDeployedAddresses()
require.NoError(t, err) require.NoError(t, err)
gen := testBuildL2Genesis(t, config) gen := testBuildL2Genesis(t, config)
require.Equal(t, 2342, len(gen.Alloc)) require.Equal(t, 2344, len(gen.Alloc))
} }
func TestBuildL2MainnetGenesis(t *testing.T) { func TestBuildL2MainnetGenesis(t *testing.T) {
...@@ -90,7 +90,7 @@ func TestBuildL2MainnetGenesis(t *testing.T) { ...@@ -90,7 +90,7 @@ func TestBuildL2MainnetGenesis(t *testing.T) {
config.EnableGovernance = true config.EnableGovernance = true
config.FundDevAccounts = false config.FundDevAccounts = false
gen := testBuildL2Genesis(t, config) gen := testBuildL2Genesis(t, config)
require.Equal(t, 2064, len(gen.Alloc)) require.Equal(t, 2066, len(gen.Alloc))
} }
func TestBuildL2MainnetNoGovernanceGenesis(t *testing.T) { func TestBuildL2MainnetNoGovernanceGenesis(t *testing.T) {
...@@ -99,5 +99,5 @@ func TestBuildL2MainnetNoGovernanceGenesis(t *testing.T) { ...@@ -99,5 +99,5 @@ func TestBuildL2MainnetNoGovernanceGenesis(t *testing.T) {
config.EnableGovernance = false config.EnableGovernance = false
config.FundDevAccounts = false config.FundDevAccounts = false
gen := testBuildL2Genesis(t, config) gen := testBuildL2Genesis(t, config)
require.Equal(t, 2064, len(gen.Alloc)) require.Equal(t, 2066, len(gen.Alloc))
} }
...@@ -144,6 +144,12 @@ func BuildOptimism(immutable ImmutableConfig) (DeploymentResults, error) { ...@@ -144,6 +144,12 @@ func BuildOptimism(immutable ImmutableConfig) (DeploymentResults, error) {
{ {
Name: "LegacyERC20ETH", Name: "LegacyERC20ETH",
}, },
{
Name: "EAS",
},
{
Name: "SchemaRegistry",
},
} }
return BuildL2(deployments) return BuildL2(deployments)
} }
...@@ -239,6 +245,10 @@ func l2Deployer(backend *backends.SimulatedBackend, opts *bind.TransactOpts, dep ...@@ -239,6 +245,10 @@ func l2Deployer(backend *backends.SimulatedBackend, opts *bind.TransactOpts, dep
_, tx, _, err = bindings.DeployOptimismMintableERC721Factory(opts, backend, bridge, remoteChainId) _, tx, _, err = bindings.DeployOptimismMintableERC721Factory(opts, backend, bridge, remoteChainId)
case "LegacyERC20ETH": case "LegacyERC20ETH":
_, tx, _, err = bindings.DeployLegacyERC20ETH(opts, backend) _, tx, _, err = bindings.DeployLegacyERC20ETH(opts, backend)
case "EAS":
_, tx, _, err = bindings.DeployEAS(opts, backend)
case "SchemaRegistry":
_, tx, _, err = bindings.DeploySchemaRegistry(opts, backend)
default: default:
return tx, fmt.Errorf("unknown contract: %s", deployment.Name) return tx, fmt.Errorf("unknown contract: %s", deployment.Name)
} }
......
...@@ -63,6 +63,8 @@ func TestBuildOptimism(t *testing.T) { ...@@ -63,6 +63,8 @@ func TestBuildOptimism(t *testing.T) {
"L2ERC721Bridge": true, "L2ERC721Bridge": true,
"OptimismMintableERC721Factory": true, "OptimismMintableERC721Factory": true,
"LegacyERC20ETH": true, "LegacyERC20ETH": true,
"EAS": true,
"SchemaRegistry": true,
} }
// Only the exact contracts that we care about are being // Only the exact contracts that we care about are being
......
package op_challenger package op_challenger
import ( import (
"context"
"fmt" "fmt"
"time" "time"
...@@ -14,7 +15,7 @@ import ( ...@@ -14,7 +15,7 @@ import (
) )
// Main is the programmatic entry-point for running op-challenger // Main is the programmatic entry-point for running op-challenger
func Main(logger log.Logger, cfg *config.Config) error { func Main(ctx context.Context, logger log.Logger, cfg *config.Config) error {
client, err := ethclient.Dial(cfg.L1EthRpc) client, err := ethclient.Dial(cfg.L1EthRpc)
if err != nil { if err != nil {
return fmt.Errorf("failed to dial L1: %w", err) return fmt.Errorf("failed to dial L1: %w", err)
...@@ -48,8 +49,19 @@ func Main(logger log.Logger, cfg *config.Config) error { ...@@ -48,8 +49,19 @@ func Main(logger log.Logger, cfg *config.Config) error {
for { for {
logger.Info("Performing action") logger.Info("Performing action")
_ = agent.Act() _ = agent.Act(ctx)
caller.LogGameInfo() status, _ := caller.GetGameStatus(ctx)
time.Sleep(300 * time.Millisecond) if status != 0 {
caller.LogGameStatus(ctx)
return nil
} else {
caller.LogGameInfo(ctx)
}
select {
case <-time.After(300 * time.Millisecond):
// Continue
case <-ctx.Done():
return ctx.Err()
}
} }
} }
package main package main
import ( import (
"context"
"fmt" "fmt"
"os" "os"
...@@ -41,7 +42,7 @@ func main() { ...@@ -41,7 +42,7 @@ func main() {
} }
} }
type ConfigAction func(log log.Logger, config *config.Config) error type ConfigAction func(ctx context.Context, log log.Logger, config *config.Config) error
func run(args []string, action ConfigAction) error { func run(args []string, action ConfigAction) error {
oplog.SetupDefaults() oplog.SetupDefaults()
...@@ -63,7 +64,7 @@ func run(args []string, action ConfigAction) error { ...@@ -63,7 +64,7 @@ func run(args []string, action ConfigAction) error {
if err != nil { if err != nil {
return err return err
} }
return action(logger, cfg) return action(ctx.Context, logger, cfg)
} }
return app.Run(args) return app.Run(args)
} }
......
package main package main
import ( import (
"context"
"fmt" "fmt"
"testing" "testing"
...@@ -137,7 +138,7 @@ func runWithArgs(cliArgs []string) (log.Logger, config.Config, error) { ...@@ -137,7 +138,7 @@ func runWithArgs(cliArgs []string) (log.Logger, config.Config, error) {
cfg := new(config.Config) cfg := new(config.Config)
var logger log.Logger var logger log.Logger
fullArgs := append([]string{"op-challenger"}, cliArgs...) fullArgs := append([]string{"op-challenger"}, cliArgs...)
err := run(fullArgs, func(log log.Logger, config *config.Config) error { err := run(fullArgs, func(ctx context.Context, log log.Logger, config *config.Config) error {
logger = log logger = log
cfg = config cfg = config
return nil return nil
......
...@@ -29,27 +29,43 @@ func NewAgent(loader Loader, maxDepth int, trace TraceProvider, responder Respon ...@@ -29,27 +29,43 @@ func NewAgent(loader Loader, maxDepth int, trace TraceProvider, responder Respon
} }
// Act iterates the game & performs all of the next actions. // Act iterates the game & performs all of the next actions.
func (a *Agent) Act() error { func (a *Agent) Act(ctx context.Context) error {
game, err := a.newGameFromContracts(context.Background()) if a.tryResolve(ctx) {
return nil
}
game, err := a.newGameFromContracts(ctx)
if err != nil { if err != nil {
a.log.Error("Failed to create new game", "err", err) a.log.Error("Failed to create new game", "err", err)
return err return err
} }
// Create counter claims // Create counter claims
for _, claim := range game.Claims() { for _, claim := range game.Claims() {
if err := a.move(claim, game); err != nil { if err := a.move(ctx, claim, game); err != nil {
log.Error("Failed to move", "err", err) log.Error("Failed to move", "err", err)
} }
} }
// Step on all leaf claims // Step on all leaf claims
for _, claim := range game.Claims() { for _, claim := range game.Claims() {
if err := a.step(claim, game); err != nil { if err := a.step(ctx, claim, game); err != nil {
log.Error("Failed to step", "err", err) log.Error("Failed to step", "err", err)
} }
} }
return nil return nil
} }
// tryResolve resolves the game if it is in a terminal state
// and returns true if the game resolves successfully.
func (a *Agent) tryResolve(ctx context.Context) bool {
if a.responder.CanResolve(ctx) {
err := a.responder.Resolve(ctx)
if err != nil {
return true
}
a.log.Error("failed to resolve the game", "err", err)
}
return false
}
// newGameFromContracts initializes a new game state from the state in the contract // newGameFromContracts initializes a new game state from the state in the contract
func (a *Agent) newGameFromContracts(ctx context.Context) (Game, error) { func (a *Agent) newGameFromContracts(ctx context.Context) (Game, error) {
claims, err := a.loader.FetchClaims(ctx) claims, err := a.loader.FetchClaims(ctx)
...@@ -67,7 +83,7 @@ func (a *Agent) newGameFromContracts(ctx context.Context) (Game, error) { ...@@ -67,7 +83,7 @@ func (a *Agent) newGameFromContracts(ctx context.Context) (Game, error) {
} }
// move determines & executes the next move given a claim // move determines & executes the next move given a claim
func (a *Agent) move(claim Claim, game Game) error { func (a *Agent) move(ctx context.Context, claim Claim, game Game) error {
nextMove, err := a.solver.NextMove(claim, game.AgreeWithClaimLevel(claim)) nextMove, err := a.solver.NextMove(claim, game.AgreeWithClaimLevel(claim))
if err != nil { if err != nil {
a.log.Warn("Failed to execute the next move", "err", err) a.log.Warn("Failed to execute the next move", "err", err)
...@@ -86,11 +102,11 @@ func (a *Agent) move(claim Claim, game Game) error { ...@@ -86,11 +102,11 @@ func (a *Agent) move(claim Claim, game Game) error {
return nil return nil
} }
log.Info("Performing move") log.Info("Performing move")
return a.responder.Respond(context.TODO(), move) return a.responder.Respond(ctx, move)
} }
// step determines & executes the next step against a leaf claim through the responder // step determines & executes the next step against a leaf claim through the responder
func (a *Agent) step(claim Claim, game Game) error { func (a *Agent) step(ctx context.Context, claim Claim, game Game) error {
if claim.Depth() != a.maxDepth { if claim.Depth() != a.maxDepth {
return nil return nil
} }
...@@ -119,6 +135,7 @@ func (a *Agent) step(claim Claim, game Game) error { ...@@ -119,6 +135,7 @@ func (a *Agent) step(claim Claim, game Game) error {
ClaimIndex: uint64(step.LeafClaim.ContractIndex), ClaimIndex: uint64(step.LeafClaim.ContractIndex),
IsAttack: step.IsAttack, IsAttack: step.IsAttack,
StateData: step.PreState, StateData: step.PreState,
Proof: step.ProofData,
} }
return a.responder.Step(context.TODO(), callData) return a.responder.Step(ctx, callData)
} }
...@@ -26,21 +26,21 @@ func NewAlphabetProvider(state string, depth uint64) *AlphabetProvider { ...@@ -26,21 +26,21 @@ func NewAlphabetProvider(state string, depth uint64) *AlphabetProvider {
} }
// GetPreimage returns the preimage for the given hash. // GetPreimage returns the preimage for the given hash.
func (ap *AlphabetProvider) GetPreimage(i uint64) ([]byte, error) { func (ap *AlphabetProvider) GetPreimage(i uint64) ([]byte, []byte, error) {
// The index cannot be larger than the maximum index as computed by the depth. // The index cannot be larger than the maximum index as computed by the depth.
if i >= ap.maxLen { if i >= ap.maxLen {
return []byte{}, ErrIndexTooLarge return nil, nil, ErrIndexTooLarge
} }
// We extend the deepest hash to the maximum depth if the trace is not expansive. // We extend the deepest hash to the maximum depth if the trace is not expansive.
if i >= uint64(len(ap.state)) { if i >= uint64(len(ap.state)) {
return ap.GetPreimage(uint64(len(ap.state)) - 1) return ap.GetPreimage(uint64(len(ap.state)) - 1)
} }
return BuildAlphabetPreimage(i, ap.state[i]), nil return BuildAlphabetPreimage(i, ap.state[i]), []byte{}, nil
} }
// Get returns the claim value at the given index in the trace. // Get returns the claim value at the given index in the trace.
func (ap *AlphabetProvider) Get(i uint64) (common.Hash, error) { func (ap *AlphabetProvider) Get(i uint64) (common.Hash, error) {
claimBytes, err := ap.GetPreimage(i) claimBytes, _, err := ap.GetPreimage(i)
if err != nil { if err != nil {
return common.Hash{}, err return common.Hash{}, err
} }
...@@ -48,9 +48,7 @@ func (ap *AlphabetProvider) Get(i uint64) (common.Hash, error) { ...@@ -48,9 +48,7 @@ func (ap *AlphabetProvider) Get(i uint64) (common.Hash, error) {
} }
func (ap *AlphabetProvider) AbsolutePreState() []byte { func (ap *AlphabetProvider) AbsolutePreState() []byte {
out := make([]byte, 32) return common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000060")
out[31] = 96 // ascii character 96 is "`"
return out
} }
// BuildAlphabetPreimage constructs the claim bytes for the index and state item. // BuildAlphabetPreimage constructs the claim bytes for the index and state item.
......
...@@ -55,16 +55,17 @@ func FuzzIndexToBytes(f *testing.F) { ...@@ -55,16 +55,17 @@ func FuzzIndexToBytes(f *testing.F) {
func TestGetPreimage_Succeeds(t *testing.T) { func TestGetPreimage_Succeeds(t *testing.T) {
ap := NewAlphabetProvider("abc", 2) ap := NewAlphabetProvider("abc", 2)
expected := BuildAlphabetPreimage(0, "a'") expected := BuildAlphabetPreimage(0, "a'")
retrieved, err := ap.GetPreimage(uint64(0)) retrieved, proof, err := ap.GetPreimage(uint64(0))
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, expected, retrieved) require.Equal(t, expected, retrieved)
require.Empty(t, proof)
} }
// TestGetPreimage_TooLargeIndex_Fails tests the GetPreimage // TestGetPreimage_TooLargeIndex_Fails tests the GetPreimage
// function errors if the index is too large. // function errors if the index is too large.
func TestGetPreimage_TooLargeIndex_Fails(t *testing.T) { func TestGetPreimage_TooLargeIndex_Fails(t *testing.T) {
ap := NewAlphabetProvider("abc", 2) ap := NewAlphabetProvider("abc", 2)
_, err := ap.GetPreimage(4) _, _, err := ap.GetPreimage(4)
require.ErrorIs(t, err, ErrIndexTooLarge) require.ErrorIs(t, err, ErrIndexTooLarge)
} }
......
...@@ -44,13 +44,13 @@ func NewFaultCallerFromBindings(fdgAddr common.Address, client *ethclient.Client ...@@ -44,13 +44,13 @@ func NewFaultCallerFromBindings(fdgAddr common.Address, client *ethclient.Client
} }
// LogGameInfo logs the game info. // LogGameInfo logs the game info.
func (fc *FaultCaller) LogGameInfo() { func (fc *FaultCaller) LogGameInfo(ctx context.Context) {
status, err := fc.GetGameStatus(context.Background()) status, err := fc.GetGameStatus(ctx)
if err != nil { if err != nil {
fc.log.Error("failed to get game status", "err", err) fc.log.Error("failed to get game status", "err", err)
return return
} }
claimLen, err := fc.GetClaimDataLength(context.Background()) claimLen, err := fc.GetClaimDataLength(ctx)
if err != nil { if err != nil {
fc.log.Error("failed to get claim count", "err", err) fc.log.Error("failed to get claim count", "err", err)
return return
...@@ -66,8 +66,8 @@ func (fc *FaultCaller) GetGameStatus(ctx context.Context) (uint8, error) { ...@@ -66,8 +66,8 @@ func (fc *FaultCaller) GetGameStatus(ctx context.Context) (uint8, error) {
return fc.Status(&bind.CallOpts{Context: ctx}) return fc.Status(&bind.CallOpts{Context: ctx})
} }
func (fc *FaultCaller) LogGameStatus() { func (fc *FaultCaller) LogGameStatus(ctx context.Context) {
status, err := fc.GetGameStatus(context.Background()) status, err := fc.GetGameStatus(ctx)
if err != nil { if err != nil {
fc.log.Error("failed to get game status", "err", err) fc.log.Error("failed to get game status", "err", err)
return return
...@@ -80,8 +80,8 @@ func (fc *FaultCaller) GetClaimDataLength(ctx context.Context) (*big.Int, error) ...@@ -80,8 +80,8 @@ func (fc *FaultCaller) GetClaimDataLength(ctx context.Context) (*big.Int, error)
return fc.ClaimDataLen(&bind.CallOpts{Context: ctx}) return fc.ClaimDataLen(&bind.CallOpts{Context: ctx})
} }
func (fc *FaultCaller) LogClaimDataLength() { func (fc *FaultCaller) LogClaimDataLength(ctx context.Context) {
claimLen, err := fc.GetClaimDataLength(context.Background()) claimLen, err := fc.GetClaimDataLength(ctx)
if err != nil { if err != nil {
fc.log.Error("failed to get claim count", "err", err) fc.log.Error("failed to get claim count", "err", err)
return return
......
...@@ -43,16 +43,20 @@ func (p *CannonTraceProvider) Get(i uint64) (common.Hash, error) { ...@@ -43,16 +43,20 @@ func (p *CannonTraceProvider) Get(i uint64) (common.Hash, error) {
return value, nil return value, nil
} }
func (p *CannonTraceProvider) GetPreimage(i uint64) ([]byte, error) { func (p *CannonTraceProvider) GetPreimage(i uint64) ([]byte, []byte, error) {
proof, err := p.loadProof(i) proof, err := p.loadProof(i)
if err != nil { if err != nil {
return nil, err return nil, nil, err
} }
value := ([]byte)(proof.StateData) value := ([]byte)(proof.StateData)
if len(value) == 0 { if len(value) == 0 {
return nil, errors.New("proof missing state data") return nil, nil, errors.New("proof missing state data")
} }
return value, nil data := ([]byte)(proof.ProofData)
if len(data) == 0 {
return nil, nil, errors.New("proof missing proof data")
}
return value, data, nil
} }
func (p *CannonTraceProvider) AbsolutePreState() []byte { func (p *CannonTraceProvider) AbsolutePreState() []byte {
......
...@@ -43,27 +43,31 @@ func TestGet(t *testing.T) { ...@@ -43,27 +43,31 @@ func TestGet(t *testing.T) {
func TestGetPreimage(t *testing.T) { func TestGetPreimage(t *testing.T) {
provider := setupWithTestData(t) provider := setupWithTestData(t)
t.Run("ExistingProof", func(t *testing.T) { t.Run("ExistingProof", func(t *testing.T) {
value, err := provider.GetPreimage(0) value, proof, err := provider.GetPreimage(0)
require.NoError(t, err) require.NoError(t, err)
expected := common.Hex2Bytes("b8f068de604c85ea0e2acd437cdb47add074a2d70b81d018390c504b71fe26f400000000000000000000000000000000000000000000000000000000000000000000000000") expected := common.Hex2Bytes("b8f068de604c85ea0e2acd437cdb47add074a2d70b81d018390c504b71fe26f400000000000000000000000000000000000000000000000000000000000000000000000000")
require.Equal(t, expected, value) require.Equal(t, expected, value)
expectedProof := common.Hex2Bytes("08028e3c0000000000000000000000003c01000a24210b7c00200008000000008fa40004")
require.Equal(t, expectedProof, proof)
}) })
t.Run("ProofUnavailable", func(t *testing.T) { t.Run("ProofUnavailable", func(t *testing.T) {
_, err := provider.GetPreimage(7) _, _, err := provider.GetPreimage(7)
require.ErrorIs(t, err, os.ErrNotExist) require.ErrorIs(t, err, os.ErrNotExist)
}) })
t.Run("MissingStateData", func(t *testing.T) { t.Run("MissingStateData", func(t *testing.T) {
_, err := provider.GetPreimage(1) _, _, err := provider.GetPreimage(1)
require.ErrorContains(t, err, "missing state data") require.ErrorContains(t, err, "missing state data")
}) })
t.Run("IgnoreUnknownFields", func(t *testing.T) { t.Run("IgnoreUnknownFields", func(t *testing.T) {
value, err := provider.GetPreimage(2) value, proof, err := provider.GetPreimage(2)
require.NoError(t, err) require.NoError(t, err)
expected := common.Hex2Bytes("cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc") expected := common.Hex2Bytes("cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc")
require.Equal(t, expected, value) require.Equal(t, expected, value)
expectedProof := common.Hex2Bytes("dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd")
require.Equal(t, expectedProof, proof)
}) })
} }
......
{"step":0,"pre":"0x71f9eb93ff904e5c03c3425228ef75766db0c906ad239df9a7a7f0d9c6a89705","post":"0x45fd9aa59768331c726e719e76aa343e73123af888804604785ae19506e65e87","state-data":"0xb8f068de604c85ea0e2acd437cdb47add074a2d70b81d018390c504b71fe26f400000000000000000000000000000000000000000000000000000000000000000000000000","proof-data":"0x08028e3c0000000000000000000000003c01000a24210b7c00200008000000008fa40004240210960000000c0000003403e00008000000008fa100040000102571c0e460346a89963488f904199fc7b4dc3dce2ddadfe484510463ae5014a79df9d922ef2cb84325e4e13ad98828ed29937c1440d8ea9eb19cab7474243c2d0b1a83646e420529153298f3a914a2550658c930f5e519b1d8dd151cf828116697d27264e6fad331820ecf3855adcc68dc529acfc33ecfa45a3a33c9ac766edc1f437988f2abab9dce36d3bac27b0f7b58a06d125acd50a1bf14bb8c7f6c1618465a532f945043b5a9ebc800d7336673019654eb76f8c10cff4f794ee586dc9992c318cef3dfa57032e2dd2fc5cb2dcfebd05551301704dd37a7c169448ec02574f706e38c20963616dae4e03cc91f39a4c3f9608119212965b72948f0ee15feb48b758f050691197816dc3ca919bbb3b50624d195c82d644025647ac8ba07206e5eb830799dfa896506743e81856edf8a31fef737fb4f44501dc71f019bdb12ed9cf0b9fba40ef98e5091b70484ba4f6af7711ec8b0ba4f4f2c4b11455a9e071f465817724159ddeea1170f4dd912c3a5a10ec6b046aa3c4a9febddfeeaa47e3ef06e1758694515562c958dc1b018149c7e4fcd91b9033ee216fea2ea498acd065e61fd436f26c31654bfd27c13ab67707384ad7a84a4b085e890e998e8a9655da954db3d279d598343a4706a2272fca526caeddb017627ecaf0138f1446c82e16d0926c0c510773e2b439c2c71414deb9b739fa370c010380d9ed5927fd7f4bb84ac22747f1bd405830b65d9e04c5efddc2c4dc89ba294c7568b9952193172d75ed8ea3e0fe57c8ad6636da54921ab52a8a0f54920d124f43b9fd3577690140cb46a28b6f55540f89444f63de0378e3d121be09e06cc9ded1c20e65876d36aa0c65e9645644786b620e2dd2ad648ddfcbf4a7e5b1a3a4ecfe7f64667a3f0b7e2f4418588ed35a2458cffeb39b93d26f18d2ab13bdce6aee58e7b99359ec2dfd95a9c16dc00d6ef18b7933a6f8dc65ccb55667138776f7dea101070dc8796e3774df84f40ae0c8229d0d6069e5c8f39a7c299677a09d367fc7b05e3bc380ee652cdc72595f74c7b1043d0e1ffbab734648c838dfb0527d971b602bc216c9619ef6834d8ef8faaf96b7b45235297538a266eb882b8b5680f621aab3417d43cdc2eb8cd74046ff337f0a7bf2c8e03e10f642c1886798d71806ab1e888d9e5ee87d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","step-input":"0xf8e0cb960000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000014200000000000000000000000000000000000000000000000000000000000000e2b8f068de604c85ea0e2acd437cdb47add074a2d70b81d018390c504b71fe26f4000000000000000000000000000000000000000000000000000000000000000000000000000a3900000a39040000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007fffd0000000000000000000000000000000000000000000000000000000000000000000000000000000070008028e3c0000000000000000000000003c01000a24210b7c00200008000000008fa40004240210960000000c0000003403e00008000000008fa100040000102571c0e460346a89963488f904199fc7b4dc3dce2ddadfe484510463ae5014a79df9d922ef2cb84325e4e13ad98828ed29937c1440d8ea9eb19cab7474243c2d0b1a83646e420529153298f3a914a2550658c930f5e519b1d8dd151cf828116697d27264e6fad331820ecf3855adcc68dc529acfc33ecfa45a3a33c9ac766edc1f437988f2abab9dce36d3bac27b0f7b58a06d125acd50a1bf14bb8c7f6c1618465a532f945043b5a9ebc800d7336673019654eb76f8c10cff4f794ee586dc9992c318cef3dfa57032e2dd2fc5cb2dcfebd05551301704dd37a7c169448ec02574f706e38c20963616dae4e03cc91f39a4c3f9608119212965b72948f0ee15feb48b758f050691197816dc3ca919bbb3b50624d195c82d644025647ac8ba07206e5eb830799dfa896506743e81856edf8a31fef737fb4f44501dc71f019bdb12ed9cf0b9fba40ef98e5091b70484ba4f6af7711ec8b0ba4f4f2c4b11455a9e071f465817724159ddeea1170f4dd912c3a5a10ec6b046aa3c4a9febddfeeaa47e3ef06e1758694515562c958dc1b018149c7e4fcd91b9033ee216fea2ea498acd065e61fd436f26c31654bfd27c13ab67707384ad7a84a4b085e890e998e8a9655da954db3d279d598343a4706a2272fca526caeddb017627ecaf0138f1446c82e16d0926c0c510773e2b439c2c71414deb9b739fa370c010380d9ed5927fd7f4bb84ac22747f1bd405830b65d9e04c5efddc2c4dc89ba294c7568b9952193172d75ed8ea3e0fe57c8ad6636da54921ab52a8a0f54920d124f43b9fd3577690140cb46a28b6f55540f89444f63de0378e3d121be09e06cc9ded1c20e65876d36aa0c65e9645644786b620e2dd2ad648ddfcbf4a7e5b1a3a4ecfe7f64667a3f0b7e2f4418588ed35a2458cffeb39b93d26f18d2ab13bdce6aee58e7b99359ec2dfd95a9c16dc00d6ef18b7933a6f8dc65ccb55667138776f7dea101070dc8796e3774df84f40ae0c8229d0d6069e5c8f39a7c299677a09d367fc7b05e3bc380ee652cdc72595f74c7b1043d0e1ffbab734648c838dfb0527d971b602bc216c9619ef6834d8ef8faaf96b7b45235297538a266eb882b8b5680f621aab3417d43cdc2eb8cd74046ff337f0a7bf2c8e03e10f642c1886798d71806ab1e888d9e5ee87d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","oracle-input":"0x"} {"step":0,"pre":"0x71f9eb93ff904e5c03c3425228ef75766db0c906ad239df9a7a7f0d9c6a89705","post":"0x45fd9aa59768331c726e719e76aa343e73123af888804604785ae19506e65e87","state-data":"0xb8f068de604c85ea0e2acd437cdb47add074a2d70b81d018390c504b71fe26f400000000000000000000000000000000000000000000000000000000000000000000000000","proof-data":"0x08028e3c0000000000000000000000003c01000a24210b7c00200008000000008fa40004","step-input":"0xf8e0cb960000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000014200000000000000000000000000000000000000000000000000000000000000e2b8f068de604c85ea0e2acd437cdb47add074a2d70b81d018390c504b71fe26f4000000000000000000000000000000000000000000000000000000000000000000000000000a3900000a39040000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007fffd0000000000000000000000000000000000000000000000000000000000000000000000000000000070008028e3c0000000000000000000000003c01000a24210b7c00200008000000008fa40004240210960000000c0000003403e00008000000008fa100040000102571c0e460346a89963488f904199fc7b4dc3dce2ddadfe484510463ae5014a79df9d922ef2cb84325e4e13ad98828ed29937c1440d8ea9eb19cab7474243c2d0b1a83646e420529153298f3a914a2550658c930f5e519b1d8dd151cf828116697d27264e6fad331820ecf3855adcc68dc529acfc33ecfa45a3a33c9ac766edc1f437988f2abab9dce36d3bac27b0f7b58a06d125acd50a1bf14bb8c7f6c1618465a532f945043b5a9ebc800d7336673019654eb76f8c10cff4f794ee586dc9992c318cef3dfa57032e2dd2fc5cb2dcfebd05551301704dd37a7c169448ec02574f706e38c20963616dae4e03cc91f39a4c3f9608119212965b72948f0ee15feb48b758f050691197816dc3ca919bbb3b50624d195c82d644025647ac8ba07206e5eb830799dfa896506743e81856edf8a31fef737fb4f44501dc71f019bdb12ed9cf0b9fba40ef98e5091b70484ba4f6af7711ec8b0ba4f4f2c4b11455a9e071f465817724159ddeea1170f4dd912c3a5a10ec6b046aa3c4a9febddfeeaa47e3ef06e1758694515562c958dc1b018149c7e4fcd91b9033ee216fea2ea498acd065e61fd436f26c31654bfd27c13ab67707384ad7a84a4b085e890e998e8a9655da954db3d279d598343a4706a2272fca526caeddb017627ecaf0138f1446c82e16d0926c0c510773e2b439c2c71414deb9b739fa370c010380d9ed5927fd7f4bb84ac22747f1bd405830b65d9e04c5efddc2c4dc89ba294c7568b9952193172d75ed8ea3e0fe57c8ad6636da54921ab52a8a0f54920d124f43b9fd3577690140cb46a28b6f55540f89444f63de0378e3d121be09e06cc9ded1c20e65876d36aa0c65e9645644786b620e2dd2ad648ddfcbf4a7e5b1a3a4ecfe7f64667a3f0b7e2f4418588ed35a2458cffeb39b93d26f18d2ab13bdce6aee58e7b99359ec2dfd95a9c16dc00d6ef18b7933a6f8dc65ccb55667138776f7dea101070dc8796e3774df84f40ae0c8229d0d6069e5c8f39a7c299677a09d367fc7b05e3bc380ee652cdc72595f74c7b1043d0e1ffbab734648c838dfb0527d971b602bc216c9619ef6834d8ef8faaf96b7b45235297538a266eb882b8b5680f621aab3417d43cdc2eb8cd74046ff337f0a7bf2c8e03e10f642c1886798d71806ab1e888d9e5ee87d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","oracle-input":"0x"}
{"foo":0,"bar":"0x71f9eb93ff904e5c03c3425228ef75766db0c906ad239df9a7a7f0d9c6a89705","post":"0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb","state-data":"0xcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc","proof-data":"0x08028e3c0000000000000000000000003c01000a24210b7c00200008000000008fa40004240210960000000c0000003403e00008000000008fa100040000102571c0e460346a89963488f904199fc7b4dc3dce2ddadfe484510463ae5014a79df9d922ef2cb84325e4e13ad98828ed29937c1440d8ea9eb19cab7474243c2d0b1a83646e420529153298f3a914a2550658c930f5e519b1d8dd151cf828116697d27264e6fad331820ecf3855adcc68dc529acfc33ecfa45a3a33c9ac766edc1f437988f2abab9dce36d3bac27b0f7b58a06d125acd50a1bf14bb8c7f6c1618465a532f945043b5a9ebc800d7336673019654eb76f8c10cff4f794ee586dc9992c318cef3dfa57032e2dd2fc5cb2dcfebd05551301704dd37a7c169448ec02574f706e38c20963616dae4e03cc91f39a4c3f9608119212965b72948f0ee15feb48b758f050691197816dc3ca919bbb3b50624d195c82d644025647ac8ba07206e5eb830799dfa896506743e81856edf8a31fef737fb4f44501dc71f019bdb12ed9cf0b9fba40ef98e5091b70484ba4f6af7711ec8b0ba4f4f2c4b11455a9e071f465817724159ddeea1170f4dd912c3a5a10ec6b046aa3c4a9febddfeeaa47e3ef06e1758694515562c958dc1b018149c7e4fcd91b9033ee216fea2ea498acd065e61fd436f26c31654bfd27c13ab67707384ad7a84a4b085e890e998e8a9655da954db3d279d598343a4706a2272fca526caeddb017627ecaf0138f1446c82e16d0926c0c510773e2b439c2c71414deb9b739fa370c010380d9ed5927fd7f4bb84ac22747f1bd405830b65d9e04c5efddc2c4dc89ba294c7568b9952193172d75ed8ea3e0fe57c8ad6636da54921ab52a8a0f54920d124f43b9fd3577690140cb46a28b6f55540f89444f63de0378e3d121be09e06cc9ded1c20e65876d36aa0c65e9645644786b620e2dd2ad648ddfcbf4a7e5b1a3a4ecfe7f64667a3f0b7e2f4418588ed35a2458cffeb39b93d26f18d2ab13bdce6aee58e7b99359ec2dfd95a9c16dc00d6ef18b7933a6f8dc65ccb55667138776f7dea101070dc8796e3774df84f40ae0c8229d0d6069e5c8f39a7c299677a09d367fc7b05e3bc380ee652cdc72595f74c7b1043d0e1ffbab734648c838dfb0527d971b602bc216c9619ef6834d8ef8faaf96b7b45235297538a266eb882b8b5680f621aab3417d43cdc2eb8cd74046ff337f0a7bf2c8e03e10f642c1886798d71806ab1e888d9e5ee87d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","step-input":"0xf8e0cb960000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000014200000000000000000000000000000000000000000000000000000000000000e2b8f068de604c85ea0e2acd437cdb47add074a2d70b81d018390c504b71fe26f4000000000000000000000000000000000000000000000000000000000000000000000000000a3900000a39040000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007fffd0000000000000000000000000000000000000000000000000000000000000000000000000000000070008028e3c0000000000000000000000003c01000a24210b7c00200008000000008fa40004240210960000000c0000003403e00008000000008fa100040000102571c0e460346a89963488f904199fc7b4dc3dce2ddadfe484510463ae5014a79df9d922ef2cb84325e4e13ad98828ed29937c1440d8ea9eb19cab7474243c2d0b1a83646e420529153298f3a914a2550658c930f5e519b1d8dd151cf828116697d27264e6fad331820ecf3855adcc68dc529acfc33ecfa45a3a33c9ac766edc1f437988f2abab9dce36d3bac27b0f7b58a06d125acd50a1bf14bb8c7f6c1618465a532f945043b5a9ebc800d7336673019654eb76f8c10cff4f794ee586dc9992c318cef3dfa57032e2dd2fc5cb2dcfebd05551301704dd37a7c169448ec02574f706e38c20963616dae4e03cc91f39a4c3f9608119212965b72948f0ee15feb48b758f050691197816dc3ca919bbb3b50624d195c82d644025647ac8ba07206e5eb830799dfa896506743e81856edf8a31fef737fb4f44501dc71f019bdb12ed9cf0b9fba40ef98e5091b70484ba4f6af7711ec8b0ba4f4f2c4b11455a9e071f465817724159ddeea1170f4dd912c3a5a10ec6b046aa3c4a9febddfeeaa47e3ef06e1758694515562c958dc1b018149c7e4fcd91b9033ee216fea2ea498acd065e61fd436f26c31654bfd27c13ab67707384ad7a84a4b085e890e998e8a9655da954db3d279d598343a4706a2272fca526caeddb017627ecaf0138f1446c82e16d0926c0c510773e2b439c2c71414deb9b739fa370c010380d9ed5927fd7f4bb84ac22747f1bd405830b65d9e04c5efddc2c4dc89ba294c7568b9952193172d75ed8ea3e0fe57c8ad6636da54921ab52a8a0f54920d124f43b9fd3577690140cb46a28b6f55540f89444f63de0378e3d121be09e06cc9ded1c20e65876d36aa0c65e9645644786b620e2dd2ad648ddfcbf4a7e5b1a3a4ecfe7f64667a3f0b7e2f4418588ed35a2458cffeb39b93d26f18d2ab13bdce6aee58e7b99359ec2dfd95a9c16dc00d6ef18b7933a6f8dc65ccb55667138776f7dea101070dc8796e3774df84f40ae0c8229d0d6069e5c8f39a7c299677a09d367fc7b05e3bc380ee652cdc72595f74c7b1043d0e1ffbab734648c838dfb0527d971b602bc216c9619ef6834d8ef8faaf96b7b45235297538a266eb882b8b5680f621aab3417d43cdc2eb8cd74046ff337f0a7bf2c8e03e10f642c1886798d71806ab1e888d9e5ee87d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","oracle-input":"0x"} {"foo":0,"bar":"0x71f9eb93ff904e5c03c3425228ef75766db0c906ad239df9a7a7f0d9c6a89705","post":"0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb","state-data":"0xcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc","proof-data":"0xdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd","step-input":"0xf8e0cb960000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000014200000000000000000000000000000000000000000000000000000000000000e2b8f068de604c85ea0e2acd437cdb47add074a2d70b81d018390c504b71fe26f4000000000000000000000000000000000000000000000000000000000000000000000000000a3900000a39040000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007fffd0000000000000000000000000000000000000000000000000000000000000000000000000000000070008028e3c0000000000000000000000003c01000a24210b7c00200008000000008fa40004240210960000000c0000003403e00008000000008fa100040000102571c0e460346a89963488f904199fc7b4dc3dce2ddadfe484510463ae5014a79df9d922ef2cb84325e4e13ad98828ed29937c1440d8ea9eb19cab7474243c2d0b1a83646e420529153298f3a914a2550658c930f5e519b1d8dd151cf828116697d27264e6fad331820ecf3855adcc68dc529acfc33ecfa45a3a33c9ac766edc1f437988f2abab9dce36d3bac27b0f7b58a06d125acd50a1bf14bb8c7f6c1618465a532f945043b5a9ebc800d7336673019654eb76f8c10cff4f794ee586dc9992c318cef3dfa57032e2dd2fc5cb2dcfebd05551301704dd37a7c169448ec02574f706e38c20963616dae4e03cc91f39a4c3f9608119212965b72948f0ee15feb48b758f050691197816dc3ca919bbb3b50624d195c82d644025647ac8ba07206e5eb830799dfa896506743e81856edf8a31fef737fb4f44501dc71f019bdb12ed9cf0b9fba40ef98e5091b70484ba4f6af7711ec8b0ba4f4f2c4b11455a9e071f465817724159ddeea1170f4dd912c3a5a10ec6b046aa3c4a9febddfeeaa47e3ef06e1758694515562c958dc1b018149c7e4fcd91b9033ee216fea2ea498acd065e61fd436f26c31654bfd27c13ab67707384ad7a84a4b085e890e998e8a9655da954db3d279d598343a4706a2272fca526caeddb017627ecaf0138f1446c82e16d0926c0c510773e2b439c2c71414deb9b739fa370c010380d9ed5927fd7f4bb84ac22747f1bd405830b65d9e04c5efddc2c4dc89ba294c7568b9952193172d75ed8ea3e0fe57c8ad6636da54921ab52a8a0f54920d124f43b9fd3577690140cb46a28b6f55540f89444f63de0378e3d121be09e06cc9ded1c20e65876d36aa0c65e9645644786b620e2dd2ad648ddfcbf4a7e5b1a3a4ecfe7f64667a3f0b7e2f4418588ed35a2458cffeb39b93d26f18d2ab13bdce6aee58e7b99359ec2dfd95a9c16dc00d6ef18b7933a6f8dc65ccb55667138776f7dea101070dc8796e3774df84f40ae0c8229d0d6069e5c8f39a7c299677a09d367fc7b05e3bc380ee652cdc72595f74c7b1043d0e1ffbab734648c838dfb0527d971b602bc216c9619ef6834d8ef8faaf96b7b45235297538a266eb882b8b5680f621aab3417d43cdc2eb8cd74046ff337f0a7bf2c8e03e10f642c1886798d71806ab1e888d9e5ee87d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","oracle-input":"0x"}
...@@ -7,6 +7,7 @@ import ( ...@@ -7,6 +7,7 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/bindings" "github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-service/txmgr" "github.com/ethereum-optimism/optimism/op-service/txmgr"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
...@@ -77,6 +78,20 @@ func (r *faultResponder) BuildTx(ctx context.Context, response Claim) ([]byte, e ...@@ -77,6 +78,20 @@ func (r *faultResponder) BuildTx(ctx context.Context, response Claim) ([]byte, e
} }
} }
// CanResolve determines if the resolve function on the fault dispute game contract
// would succeed. Returns true if the game can be resolved, otherwise false.
func (r *faultResponder) CanResolve(ctx context.Context) bool {
txData, err := r.buildResolveData()
if err != nil {
return false
}
_, err = r.txMgr.Call(ctx, ethereum.CallMsg{
To: &r.fdgAddr,
Data: txData,
}, nil)
return err == nil
}
// Resolve executes a resolve transaction to resolve a fault dispute game. // Resolve executes a resolve transaction to resolve a fault dispute game.
func (r *faultResponder) Resolve(ctx context.Context) error { func (r *faultResponder) Resolve(ctx context.Context) error {
txData, err := r.buildResolveData() txData, err := r.buildResolveData()
......
...@@ -10,6 +10,7 @@ import ( ...@@ -10,6 +10,7 @@ import (
"github.com/ethereum-optimism/optimism/op-node/testlog" "github.com/ethereum-optimism/optimism/op-node/testlog"
"github.com/ethereum-optimism/optimism/op-service/txmgr" "github.com/ethereum-optimism/optimism/op-service/txmgr"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
...@@ -25,6 +26,7 @@ var ( ...@@ -25,6 +26,7 @@ var (
type mockTxManager struct { type mockTxManager struct {
from common.Address from common.Address
sends int sends int
calls int
sendFails bool sendFails bool
} }
...@@ -40,6 +42,14 @@ func (m *mockTxManager) Send(ctx context.Context, candidate txmgr.TxCandidate) ( ...@@ -40,6 +42,14 @@ func (m *mockTxManager) Send(ctx context.Context, candidate txmgr.TxCandidate) (
), nil ), nil
} }
func (m *mockTxManager) Call(_ context.Context, _ ethereum.CallMsg, _ *big.Int) ([]byte, error) {
if m.sendFails {
return nil, mockSendError
}
m.calls++
return []byte{}, nil
}
func (m *mockTxManager) BlockNumber(ctx context.Context) (uint64, error) { func (m *mockTxManager) BlockNumber(ctx context.Context) (uint64, error) {
panic("not implemented") panic("not implemented")
} }
...@@ -57,6 +67,24 @@ func newTestFaultResponder(t *testing.T, sendFails bool) (*faultResponder, *mock ...@@ -57,6 +67,24 @@ func newTestFaultResponder(t *testing.T, sendFails bool) (*faultResponder, *mock
return responder, mockTxMgr return responder, mockTxMgr
} }
// TestResponder_CanResolve_CallFails tests the [Responder.CanResolve] method
// bubbles up the error returned by the [txmgr.Call] method.
func TestResponder_CanResolve_CallFails(t *testing.T) {
responder, mockTxMgr := newTestFaultResponder(t, true)
resolved := responder.CanResolve(context.Background())
require.False(t, resolved)
require.Equal(t, 0, mockTxMgr.sends)
}
// TestResponder_CanResolve_Success tests the [Responder.CanResolve] method
// succeeds when the call message is successfully sent through the txmgr.
func TestResponder_CanResolve_Success(t *testing.T) {
responder, mockTxMgr := newTestFaultResponder(t, false)
resolved := responder.CanResolve(context.Background())
require.True(t, resolved)
require.Equal(t, 1, mockTxMgr.calls)
}
// TestResponder_Resolve_SendFails tests the [Responder.Resolve] method // TestResponder_Resolve_SendFails tests the [Responder.Resolve] method
// bubbles up the error returned by the [txmgr.Send] method. // bubbles up the error returned by the [txmgr.Send] method.
func TestResponder_Resolve_SendFails(t *testing.T) { func TestResponder_Resolve_SendFails(t *testing.T) {
......
...@@ -67,6 +67,7 @@ type StepData struct { ...@@ -67,6 +67,7 @@ type StepData struct {
LeafClaim Claim LeafClaim Claim
IsAttack bool IsAttack bool
PreState []byte PreState []byte
ProofData []byte
} }
// AttemptStep determines what step should occur for a given leaf claim. // AttemptStep determines what step should occur for a given leaf claim.
...@@ -84,6 +85,7 @@ func (s *Solver) AttemptStep(claim Claim, agreeWithClaimLevel bool) (StepData, e ...@@ -84,6 +85,7 @@ func (s *Solver) AttemptStep(claim Claim, agreeWithClaimLevel bool) (StepData, e
} }
index := claim.TraceIndex(s.gameDepth) index := claim.TraceIndex(s.gameDepth)
var preState []byte var preState []byte
var proofData []byte
// If we are attacking index 0, we provide the absolute pre-state, not an intermediate state // If we are attacking index 0, we provide the absolute pre-state, not an intermediate state
if index == 0 && !claimCorrect { if index == 0 && !claimCorrect {
preState = s.AbsolutePreState() preState = s.AbsolutePreState()
...@@ -92,7 +94,7 @@ func (s *Solver) AttemptStep(claim Claim, agreeWithClaimLevel bool) (StepData, e ...@@ -92,7 +94,7 @@ func (s *Solver) AttemptStep(claim Claim, agreeWithClaimLevel bool) (StepData, e
if !claimCorrect { if !claimCorrect {
index = index - 1 index = index - 1
} }
preState, err = s.GetPreimage(index) preState, proofData, err = s.GetPreimage(index)
if err != nil { if err != nil {
return StepData{}, err return StepData{}, err
} }
...@@ -102,6 +104,7 @@ func (s *Solver) AttemptStep(claim Claim, agreeWithClaimLevel bool) (StepData, e ...@@ -102,6 +104,7 @@ func (s *Solver) AttemptStep(claim Claim, agreeWithClaimLevel bool) (StepData, e
LeafClaim: claim, LeafClaim: claim,
IsAttack: !claimCorrect, IsAttack: !claimCorrect,
PreState: preState, PreState: preState,
ProofData: proofData,
}, nil }, nil
} }
......
...@@ -100,7 +100,7 @@ func TestNoMoveAgainstOwnLevel(t *testing.T) { ...@@ -100,7 +100,7 @@ func TestNoMoveAgainstOwnLevel(t *testing.T) {
func TestAttemptStep(t *testing.T) { func TestAttemptStep(t *testing.T) {
maxDepth := 3 maxDepth := 3
canonicalProvider := NewAlphabetProvider("abcdefgh", uint64(maxDepth)) canonicalProvider := &alphabetWithProofProvider{NewAlphabetProvider("abcdefgh", uint64(maxDepth))}
solver := NewSolver(maxDepth, canonicalProvider) solver := NewSolver(maxDepth, canonicalProvider)
_, _, middle, bottom := createTestClaims() _, _, middle, bottom := createTestClaims()
...@@ -116,6 +116,7 @@ func TestAttemptStep(t *testing.T) { ...@@ -116,6 +116,7 @@ func TestAttemptStep(t *testing.T) {
require.Equal(t, bottom, step.LeafClaim) require.Equal(t, bottom, step.LeafClaim)
require.True(t, step.IsAttack) require.True(t, step.IsAttack)
require.Equal(t, step.PreState, BuildAlphabetPreimage(3, "d")) require.Equal(t, step.PreState, BuildAlphabetPreimage(3, "d"))
require.Equal(t, step.ProofData, []byte{3})
_, err = solver.AttemptStep(middle, false) _, err = solver.AttemptStep(middle, false)
require.Error(t, err) require.Error(t, err)
...@@ -137,3 +138,15 @@ func TestAttempStep_AgreeWithClaimLevel_Fails(t *testing.T) { ...@@ -137,3 +138,15 @@ func TestAttempStep_AgreeWithClaimLevel_Fails(t *testing.T) {
require.Error(t, err) require.Error(t, err)
require.Equal(t, StepData{}, step) require.Equal(t, StepData{}, step)
} }
type alphabetWithProofProvider struct {
*AlphabetProvider
}
func (a *alphabetWithProofProvider) GetPreimage(i uint64) ([]byte, []byte, error) {
preimage, _, err := a.AlphabetProvider.GetPreimage(i)
if err != nil {
return nil, nil, err
}
return preimage, []byte{byte(i)}, nil
}
...@@ -8,7 +8,6 @@ import ( ...@@ -8,7 +8,6 @@ import (
) )
var ( var (
ErrNegativeIndex = errors.New("index cannot be negative")
ErrIndexTooLarge = errors.New("index is larger than the maximum index") ErrIndexTooLarge = errors.New("index is larger than the maximum index")
) )
...@@ -20,13 +19,17 @@ type StepCallData struct { ...@@ -20,13 +19,17 @@ type StepCallData struct {
Proof []byte Proof []byte
} }
// TraceProvider is a generic way to get a claim value at a specific // TraceProvider is a generic way to get a claim value at a specific step in the trace.
// step in the trace.
// Get(i) = Keccak256(GetPreimage(i))
// AbsolutePreState is the value of the trace that transitions to the trace value at index 0
type TraceProvider interface { type TraceProvider interface {
// Get returns the claim value at the requested index.
// Get(i) = Keccak256(GetPreimage(i))
Get(i uint64) (common.Hash, error) Get(i uint64) (common.Hash, error)
GetPreimage(i uint64) ([]byte, error)
// GetPreimage returns the pre-image for a claim at the specified trace index, along
// with any associated proof data to assist in its verification.
GetPreimage(i uint64) (preimage []byte, proofData []byte, err error)
// AbsolutePreState is the pre-image value of the trace that transitions to the trace value at index 0
AbsolutePreState() []byte AbsolutePreState() []byte
} }
...@@ -76,6 +79,8 @@ func (c *Claim) DefendsParent() bool { ...@@ -76,6 +79,8 @@ func (c *Claim) DefendsParent() bool {
// Responder takes a response action & executes. // Responder takes a response action & executes.
// For full op-challenger this means executing the transaction on chain. // For full op-challenger this means executing the transaction on chain.
type Responder interface { type Responder interface {
CanResolve(ctx context.Context) bool
Resolve(ctx context.Context) error
Respond(ctx context.Context, response Claim) error Respond(ctx context.Context, response Claim) error
Step(ctx context.Context, stepData StepCallData) error Step(ctx context.Context, stepData StepCallData) error
} }
...@@ -44,6 +44,9 @@ type fakeTxMgr struct { ...@@ -44,6 +44,9 @@ type fakeTxMgr struct {
func (f fakeTxMgr) From() common.Address { func (f fakeTxMgr) From() common.Address {
return f.from return f.from
} }
func (f fakeTxMgr) Call(_ context.Context, _ ethereum.CallMsg, _ *big.Int) ([]byte, error) {
panic("unimplemented")
}
func (f fakeTxMgr) BlockNumber(_ context.Context) (uint64, error) { func (f fakeTxMgr) BlockNumber(_ context.Context) (uint64, error) {
panic("unimplemented") panic("unimplemented")
} }
......
package challenger
import (
"context"
"errors"
"testing"
"time"
op_challenger "github.com/ethereum-optimism/optimism/op-challenger"
"github.com/ethereum-optimism/optimism/op-challenger/config"
"github.com/ethereum-optimism/optimism/op-node/testlog"
"github.com/ethereum-optimism/optimism/op-service/txmgr"
"github.com/ethereum/go-ethereum/log"
"github.com/stretchr/testify/require"
)
type Helper struct {
log log.Logger
cancel func()
errors chan error
}
type Option func(config2 *config.Config)
func NewChallenger(t *testing.T, ctx context.Context, l1Endpoint string, name string, options ...Option) *Helper {
log := testlog.Logger(t, log.LvlInfo).New("role", name)
log.Info("Creating challenger", "l1", l1Endpoint)
txmgrCfg := txmgr.NewCLIConfig(l1Endpoint)
txmgrCfg.NumConfirmations = 1
txmgrCfg.ReceiptQueryInterval = 1 * time.Second
cfg := &config.Config{
L1EthRpc: l1Endpoint,
AlphabetTrace: "",
AgreeWithProposedOutput: true,
TxMgrConfig: txmgrCfg,
}
for _, option := range options {
option(cfg)
}
require.NotEmpty(t, cfg.TxMgrConfig.PrivateKey, "Missing private key for TxMgrConfig")
errCh := make(chan error, 1)
ctx, cancel := context.WithCancel(ctx)
go func() {
defer close(errCh)
errCh <- op_challenger.Main(ctx, log, cfg)
}()
return &Helper{
log: log,
cancel: cancel,
errors: errCh,
}
}
func (h *Helper) Close() error {
h.cancel()
select {
case <-time.After(1 * time.Minute):
return errors.New("timed out while stopping challenger")
case err := <-h.errors:
if !errors.Is(err, context.Canceled) {
return err
}
return nil
}
}
package disputegame
import (
"context"
"math/big"
"time"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-chain-ops/deployer"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/stretchr/testify/require"
)
// deployDisputeGameContracts deploys the DisputeGameFactory, AlphabetVM and FaultDisputeGame contracts
// It configures the alphabet fault game as game type 0 (faultGameType)
// If/when the dispute game factory becomes a predeployed contract this can be removed and just use the
// predeployed version
func deployDisputeGameContracts(require *require.Assertions, ctx context.Context, client *ethclient.Client, opts *bind.TransactOpts, gameDuration uint64) *bindings.DisputeGameFactory {
ctx, cancel := context.WithTimeout(ctx, 5*time.Minute)
defer cancel()
// Deploy the proxy
_, tx, proxy, err := bindings.DeployProxy(opts, client, deployer.TestAddress)
require.NoError(err)
proxyAddr, err := bind.WaitDeployed(ctx, client, tx)
require.NoError(err)
// Deploy the dispute game factory implementation
_, tx, _, err = bindings.DeployDisputeGameFactory(opts, client)
require.NoError(err)
factoryAddr, err := bind.WaitDeployed(ctx, client, tx)
require.NoError(err)
// Point the proxy at the implementation and create bindings going via the proxy
disputeGameFactoryAbi, err := bindings.DisputeGameFactoryMetaData.GetAbi()
require.NoError(err)
data, err := disputeGameFactoryAbi.Pack("initialize", deployer.TestAddress)
require.NoError(err)
_, err = proxy.UpgradeToAndCall(opts, factoryAddr, data)
require.NoError(err)
factory, err := bindings.NewDisputeGameFactory(proxyAddr, client)
require.NoError(err)
// Now setup the fault dispute game type
// Start by deploying the AlphabetVM
_, tx, _, err = bindings.DeployAlphabetVM(opts, client, alphabetVMAbsolutePrestateClaim)
require.NoError(err)
alphaVMAddr, err := bind.WaitDeployed(ctx, client, tx)
require.NoError(err)
// Deploy the fault dispute game implementation
_, tx, _, err = bindings.DeployFaultDisputeGame(opts, client, alphabetVMAbsolutePrestateClaim, big.NewInt(alphabetGameDepth), gameDuration, alphaVMAddr)
require.NoError(err)
faultDisputeGameAddr, err := bind.WaitDeployed(ctx, client, tx)
require.NoError(err)
// Set the fault game type implementation
_, err = factory.SetImplementation(opts, faultGameType, faultDisputeGameAddr)
require.NoError(err)
return factory
}
package disputegame
import (
"context"
"fmt"
"math/big"
"testing"
"time"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-chain-ops/deployer"
"github.com/ethereum-optimism/optimism/op-challenger/config"
"github.com/ethereum-optimism/optimism/op-challenger/fault"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/challenger"
"github.com/ethereum-optimism/optimism/op-service/client/utils"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/stretchr/testify/require"
)
const faultGameType uint8 = 0
const alphabetGameDepth = 4
const lastAlphabetTraceIndex = 1<<alphabetGameDepth - 1
type Status uint8
const (
StatusInProgress Status = iota
StatusChallengerWins
StatusDefenderWins
)
var alphaExtraData = common.Hex2Bytes("1000000000000000000000000000000000000000000000000000000000000000")
var alphabetVMAbsolutePrestate = common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000060")
var alphabetVMAbsolutePrestateClaim = crypto.Keccak256Hash(alphabetVMAbsolutePrestate)
var CorrectAlphabet = "abcdefghijklmnop"
type FactoryHelper struct {
t *testing.T
require *require.Assertions
client *ethclient.Client
opts *bind.TransactOpts
factory *bindings.DisputeGameFactory
}
func NewFactoryHelper(t *testing.T, ctx context.Context, client *ethclient.Client, gameDuration uint64) *FactoryHelper {
require := require.New(t)
chainID, err := client.ChainID(ctx)
require.NoError(err)
opts, err := bind.NewKeyedTransactorWithChainID(deployer.TestKey, chainID)
require.NoError(err)
factory := deployDisputeGameContracts(require, ctx, client, opts, gameDuration)
return &FactoryHelper{
t: t,
require: require,
client: client,
opts: opts,
factory: factory,
}
}
func (h *FactoryHelper) StartAlphabetGame(ctx context.Context, claimedAlphabet string) *FaultGameHelper {
ctx, cancel := context.WithTimeout(ctx, 1*time.Minute)
defer cancel()
trace := fault.NewAlphabetProvider(claimedAlphabet, 4)
rootClaim, err := trace.Get(lastAlphabetTraceIndex)
h.require.NoError(err)
tx, err := h.factory.Create(h.opts, faultGameType, rootClaim, alphaExtraData)
h.require.NoError(err)
rcpt, err := utils.WaitReceiptOK(ctx, h.client, tx.Hash())
h.require.NoError(err)
h.require.Len(rcpt.Logs, 1, "should have emitted a single DisputeGameCreated event")
createdEvent, err := h.factory.ParseDisputeGameCreated(*rcpt.Logs[0])
h.require.NoError(err)
game, err := bindings.NewFaultDisputeGame(createdEvent.DisputeProxy, h.client)
h.require.NoError(err)
return &FaultGameHelper{
t: h.t,
require: h.require,
client: h.client,
opts: h.opts,
game: game,
maxDepth: alphabetGameDepth,
addr: createdEvent.DisputeProxy,
claimedAlphabet: claimedAlphabet,
}
}
type FaultGameHelper struct {
t *testing.T
require *require.Assertions
client *ethclient.Client
opts *bind.TransactOpts
game *bindings.FaultDisputeGame
maxDepth int
addr common.Address
claimedAlphabet string
}
func (g *FaultGameHelper) StartChallenger(ctx context.Context, l1Endpoint string, name string, options ...challenger.Option) *challenger.Helper {
opts := []challenger.Option{
func(c *config.Config) {
c.GameAddress = g.addr
c.GameDepth = alphabetGameDepth
// By default the challenger agrees with the root claim (thus disagrees with the proposed output)
// This can be overridden by passing in options
c.AlphabetTrace = g.claimedAlphabet
c.AgreeWithProposedOutput = false
},
}
opts = append(opts, options...)
c := challenger.NewChallenger(g.t, ctx, l1Endpoint, name, opts...)
g.t.Cleanup(func() {
_ = c.Close()
})
return c
}
func (g *FaultGameHelper) WaitForClaimCount(ctx context.Context, count int64) {
ctx, cancel := context.WithTimeout(ctx, 1*time.Minute)
defer cancel()
err := utils.WaitFor(ctx, 1*time.Second, func() (bool, error) {
actual, err := g.game.ClaimDataLen(&bind.CallOpts{Context: ctx})
if err != nil {
return false, err
}
g.t.Log("Waiting for claim count", "current", actual, "expected", count, "game", g.addr)
return actual.Cmp(big.NewInt(count)) == 0, nil
})
g.require.NoError(err)
}
type ContractClaim struct {
ParentIndex uint32
Countered bool
Claim [32]byte
Position *big.Int
Clock *big.Int
}
func (g *FaultGameHelper) WaitForClaim(ctx context.Context, predicate func(claim ContractClaim) bool) {
ctx, cancel := context.WithTimeout(ctx, 1*time.Minute)
defer cancel()
err := utils.WaitFor(ctx, 1*time.Second, func() (bool, error) {
count, err := g.game.ClaimDataLen(&bind.CallOpts{Context: ctx})
if err != nil {
return false, fmt.Errorf("retrieve number of claims: %w", err)
}
// Search backwards because the new claims are at the end and more likely the ones we want.
for i := count.Int64() - 1; i >= 0; i-- {
claimData, err := g.game.ClaimData(&bind.CallOpts{Context: ctx}, big.NewInt(i))
if err != nil {
return false, fmt.Errorf("retrieve claim %v: %w", i, err)
}
if predicate(claimData) {
return true, nil
}
}
return false, nil
})
g.require.NoError(err)
}
func (g *FaultGameHelper) WaitForClaimAtMaxDepth(ctx context.Context, countered bool) {
g.WaitForClaim(ctx, func(claim ContractClaim) bool {
pos := fault.NewPositionFromGIndex(claim.Position.Uint64())
return pos.Depth() == g.maxDepth && claim.Countered == countered
})
}
func (g *FaultGameHelper) Resolve(ctx context.Context) {
ctx, cancel := context.WithTimeout(ctx, 1*time.Minute)
defer cancel()
tx, err := g.game.Resolve(g.opts)
g.require.NoError(err)
_, err = utils.WaitReceiptOK(ctx, g.client, tx.Hash())
g.require.NoError(err)
}
func (g *FaultGameHelper) WaitForGameStatus(ctx context.Context, expected Status) {
ctx, cancel := context.WithTimeout(ctx, 1*time.Minute)
defer cancel()
err := utils.WaitFor(ctx, 1*time.Second, func() (bool, error) {
ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
defer cancel()
status, err := g.game.Status(&bind.CallOpts{Context: ctx})
if err != nil {
return false, fmt.Errorf("game status unavailable: %w", err)
}
return expected == Status(status), nil
})
g.require.NoError(err, "wait for game status")
}
...@@ -137,6 +137,10 @@ func EncodePrivKey(priv *ecdsa.PrivateKey) hexutil.Bytes { ...@@ -137,6 +137,10 @@ func EncodePrivKey(priv *ecdsa.PrivateKey) hexutil.Bytes {
return privkey return privkey
} }
func EncodePrivKeyToString(priv *ecdsa.PrivateKey) string {
return hexutil.Encode(EncodePrivKey(priv))
}
// Addresses computes the ethereum address of each account, // Addresses computes the ethereum address of each account,
// which can then be kept around for fast precomputed address access. // which can then be kept around for fast precomputed address access.
func (s *Secrets) Addresses() *Addresses { func (s *Secrets) Addresses() *Addresses {
......
...@@ -5,37 +5,152 @@ import ( ...@@ -5,37 +5,152 @@ import (
"testing" "testing"
"time" "time"
"github.com/ethereum-optimism/optimism/op-challenger/config"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/disputegame"
"github.com/ethereum-optimism/optimism/op-service/client/utils" "github.com/ethereum-optimism/optimism/op-service/client/utils"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
func TestTimeTravel(t *testing.T) { func TestResolveDisputeGame(t *testing.T) {
InitParallel(t) InitParallel(t)
ctx := context.Background()
sys, l1Client := startL1OnlySystem(t)
t.Cleanup(sys.Close)
gameDuration := 24 * time.Hour
disputeGameFactory := disputegame.NewFactoryHelper(t, ctx, l1Client, uint64(gameDuration.Seconds()))
game := disputeGameFactory.StartAlphabetGame(ctx, "zyxwvut")
require.NotNil(t, game)
game.WaitForGameStatus(ctx, disputegame.StatusInProgress)
game.StartChallenger(ctx, sys.NodeEndpoint("l1"), "HonestAlice", func(c *config.Config) {
c.AgreeWithProposedOutput = true // Agree with the proposed output, so disagree with the root claim
c.AlphabetTrace = "abcdefg"
c.TxMgrConfig.PrivateKey = e2eutils.EncodePrivKeyToString(sys.cfg.Secrets.Alice)
})
game.WaitForClaimCount(ctx, 2)
sys.TimeTravelClock.AdvanceTime(gameDuration)
require.NoError(t, utils.WaitNextBlock(ctx, l1Client))
// Challenger should resolve the game now that the clocks have expired.
game.WaitForGameStatus(ctx, disputegame.StatusChallengerWins)
}
func TestChallengerCompleteDisputeGame(t *testing.T) {
InitParallel(t)
tests := []struct {
name string
rootClaimAlphabet string
otherAlphabet string
expectedResult disputegame.Status
expectStep bool
}{
{
name: "ChallengerWins_DefenseStep",
rootClaimAlphabet: "abcdexyz",
otherAlphabet: disputegame.CorrectAlphabet,
expectedResult: disputegame.StatusChallengerWins,
expectStep: true,
},
{
name: "DefenderWins_DefenseStep",
rootClaimAlphabet: disputegame.CorrectAlphabet,
otherAlphabet: "abcdexyz",
expectedResult: disputegame.StatusDefenderWins,
expectStep: false,
},
{
name: "ChallengerWins_AttackStep",
rootClaimAlphabet: "abcdefghzyx",
otherAlphabet: disputegame.CorrectAlphabet,
expectedResult: disputegame.StatusChallengerWins,
expectStep: true,
},
{
name: "DefenderWins_AttackStep",
rootClaimAlphabet: disputegame.CorrectAlphabet,
otherAlphabet: "abcdexyz",
expectedResult: disputegame.StatusDefenderWins,
expectStep: false,
},
{
name: "DefenderIncorrectAtTraceZero",
rootClaimAlphabet: "zyxwvut",
otherAlphabet: disputegame.CorrectAlphabet,
expectedResult: disputegame.StatusChallengerWins,
expectStep: true,
},
{
name: "ChallengerIncorrectAtTraceZero",
rootClaimAlphabet: disputegame.CorrectAlphabet,
otherAlphabet: "zyxwvut",
expectedResult: disputegame.StatusDefenderWins,
expectStep: false,
},
{
name: "DefenderIncorrectAtLastTraceIndex",
rootClaimAlphabet: "abcdefghijklmnoz",
otherAlphabet: disputegame.CorrectAlphabet,
expectedResult: disputegame.StatusChallengerWins,
expectStep: true,
},
{
name: "ChallengerIncorrectAtLastTraceIndex",
rootClaimAlphabet: disputegame.CorrectAlphabet,
otherAlphabet: "abcdefghijklmnoz",
expectedResult: disputegame.StatusDefenderWins,
expectStep: false,
},
}
for _, test := range tests {
test := test
t.Run(test.name, func(t *testing.T) {
InitParallel(t)
ctx := context.Background()
sys, l1Client := startL1OnlySystem(t)
t.Cleanup(sys.Close)
gameDuration := 24 * time.Hour
disputeGameFactory := disputegame.NewFactoryHelper(t, ctx, l1Client, uint64(gameDuration.Seconds()))
game := disputeGameFactory.StartAlphabetGame(ctx, test.rootClaimAlphabet)
require.NotNil(t, game)
game.StartChallenger(ctx, sys.NodeEndpoint("l1"), "Defender", func(c *config.Config) {
c.TxMgrConfig.PrivateKey = e2eutils.EncodePrivKeyToString(sys.cfg.Secrets.Mallory)
})
game.StartChallenger(ctx, sys.NodeEndpoint("l1"), "Challenger", func(c *config.Config) {
c.AgreeWithProposedOutput = true // Agree with the proposed output, so disagree with the root claim
c.AlphabetTrace = test.otherAlphabet
c.TxMgrConfig.PrivateKey = e2eutils.EncodePrivKeyToString(sys.cfg.Secrets.Alice)
})
// Wait for a claim at the maximum depth that has been countered to indicate we're ready to resolve the game
game.WaitForClaimAtMaxDepth(ctx, test.expectStep)
sys.TimeTravelClock.AdvanceTime(gameDuration)
require.NoError(t, utils.WaitNextBlock(ctx, l1Client))
game.WaitForGameStatus(ctx, test.expectedResult)
})
}
}
func startL1OnlySystem(t *testing.T) (*System, *ethclient.Client) {
cfg := DefaultSystemConfig(t) cfg := DefaultSystemConfig(t)
cfg.DeployConfig.L1BlockTime = 1
delete(cfg.Nodes, "verifier") delete(cfg.Nodes, "verifier")
delete(cfg.Nodes, "sequencer")
cfg.SupportL1TimeTravel = true cfg.SupportL1TimeTravel = true
sys, err := cfg.Start() sys, err := cfg.Start()
require.Nil(t, err, "Error starting up system") require.Nil(t, err, "Error starting up system")
defer sys.Close() return sys, sys.Clients["l1"]
l1Client := sys.Clients["l1"]
preTravel, err := l1Client.BlockByNumber(context.Background(), nil)
require.NoError(t, err)
sys.TimeTravelClock.AdvanceTime(24 * time.Hour)
// Check that the L1 chain reaches the new time reasonably quickly (ie without taking a week)
// It should be able to jump straight to the new time with just a single block
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Minute)
defer cancel()
err = utils.WaitFor(ctx, time.Second, func() (bool, error) {
postTravel, err := l1Client.BlockByNumber(context.Background(), nil)
if err != nil {
return false, err
}
diff := time.Duration(postTravel.Time()-preTravel.Time()) * time.Second
return diff.Hours() > 23, nil
})
require.NoError(t, err)
} }
...@@ -616,6 +616,10 @@ func (cfg SystemConfig) Start(_opts ...SystemConfigOption) (*System, error) { ...@@ -616,6 +616,10 @@ func (cfg SystemConfig) Start(_opts ...SystemConfigOption) (*System, error) {
} }
} }
// Don't start batch submitter and proposer if there's no sequencer.
if sys.RollupNodes["sequencer"] == nil {
return sys, nil
}
// L2Output Submitter // L2Output Submitter
sys.L2OutputSubmitter, err = l2os.NewL2OutputSubmitterFromCLIConfig(l2os.CLIConfig{ sys.L2OutputSubmitter, err = l2os.NewL2OutputSubmitterFromCLIConfig(l2os.CLIConfig{
L1EthRpc: sys.Nodes["l1"].WSEndpoint(), L1EthRpc: sys.Nodes["l1"].WSEndpoint(),
......
...@@ -30,7 +30,7 @@ func NewConfig(ctx *cli.Context, log log.Logger) (*node.Config, error) { ...@@ -30,7 +30,7 @@ func NewConfig(ctx *cli.Context, log log.Logger) (*node.Config, error) {
return nil, err return nil, err
} }
rollupConfig, err := NewRollupConfig(ctx) rollupConfig, err := NewRollupConfig(log, ctx)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -168,9 +168,16 @@ func NewDriverConfig(ctx *cli.Context) *driver.Config { ...@@ -168,9 +168,16 @@ func NewDriverConfig(ctx *cli.Context) *driver.Config {
} }
} }
func NewRollupConfig(ctx *cli.Context) (*rollup.Config, error) { func NewRollupConfig(log log.Logger, ctx *cli.Context) (*rollup.Config, error) {
network := ctx.String(flags.Network.Name) network := ctx.String(flags.Network.Name)
rollupConfigPath := ctx.String(flags.RollupConfig.Name)
if network != "" { if network != "" {
if rollupConfigPath != "" {
log.Error(`Cannot configure network and rollup-config at the same time.
Startup will proceed to use the network-parameter and ignore the rollup config.
Conflicting configuration is deprecated, and will stop the op-node from starting in the future.
`, "network", network, "rollup_config", rollupConfigPath)
}
config, err := chaincfg.GetRollupConfig(network) config, err := chaincfg.GetRollupConfig(network)
if err != nil { if err != nil {
return nil, err return nil, err
...@@ -179,7 +186,6 @@ func NewRollupConfig(ctx *cli.Context) (*rollup.Config, error) { ...@@ -179,7 +186,6 @@ func NewRollupConfig(ctx *cli.Context) (*rollup.Config, error) {
return &config, nil return &config, nil
} }
rollupConfigPath := ctx.String(flags.RollupConfig.Name)
file, err := os.Open(rollupConfigPath) file, err := os.Open(rollupConfigPath)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to read rollup config: %w", err) return nil, fmt.Errorf("failed to read rollup config: %w", err)
......
...@@ -63,7 +63,7 @@ func run(args []string, action ConfigAction) error { ...@@ -63,7 +63,7 @@ func run(args []string, action ConfigAction) error {
} }
logger.Info("Starting fault proof program", "version", VersionWithMeta) logger.Info("Starting fault proof program", "version", VersionWithMeta)
cfg, err := config.NewConfigFromCLI(ctx) cfg, err := config.NewConfigFromCLI(logger, ctx)
if err != nil { if err != nil {
return err return err
} }
......
...@@ -12,6 +12,7 @@ import ( ...@@ -12,6 +12,7 @@ import (
"github.com/ethereum-optimism/optimism/op-program/host/flags" "github.com/ethereum-optimism/optimism/op-program/host/flags"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
) )
...@@ -110,11 +111,11 @@ func NewConfig(rollupCfg *rollup.Config, l2Genesis *params.ChainConfig, l1Head c ...@@ -110,11 +111,11 @@ func NewConfig(rollupCfg *rollup.Config, l2Genesis *params.ChainConfig, l1Head c
} }
} }
func NewConfigFromCLI(ctx *cli.Context) (*Config, error) { func NewConfigFromCLI(log log.Logger, ctx *cli.Context) (*Config, error) {
if err := flags.CheckRequired(ctx); err != nil { if err := flags.CheckRequired(ctx); err != nil {
return nil, err return nil, err
} }
rollupCfg, err := opnode.NewRollupConfig(ctx) rollupCfg, err := opnode.NewRollupConfig(log, ctx)
if err != nil { if err != nil {
return nil, err return nil, err
} }
......
...@@ -59,6 +59,14 @@ func WaitBlock(ctx context.Context, client *ethclient.Client, n uint64) error { ...@@ -59,6 +59,14 @@ func WaitBlock(ctx context.Context, client *ethclient.Client, n uint64) error {
return nil return nil
} }
func WaitNextBlock(ctx context.Context, client *ethclient.Client) error {
current, err := client.BlockNumber(ctx)
if err != nil {
return fmt.Errorf("get starting block number: %w", err)
}
return WaitBlock(ctx, client, current+1)
}
func WaitFor(ctx context.Context, rate time.Duration, cb func() (bool, error)) error { func WaitFor(ctx context.Context, rate time.Duration, cb func() (bool, error)) error {
tick := time.NewTicker(rate) tick := time.NewTicker(rate)
defer tick.Stop() defer tick.Stop()
......
...@@ -4,9 +4,12 @@ package mocks ...@@ -4,9 +4,12 @@ package mocks
import ( import (
context "context" context "context"
big "math/big"
common "github.com/ethereum/go-ethereum/common" common "github.com/ethereum/go-ethereum/common"
ethereum "github.com/ethereum/go-ethereum"
mock "github.com/stretchr/testify/mock" mock "github.com/stretchr/testify/mock"
txmgr "github.com/ethereum-optimism/optimism/op-service/txmgr" txmgr "github.com/ethereum-optimism/optimism/op-service/txmgr"
...@@ -43,6 +46,32 @@ func (_m *TxManager) BlockNumber(ctx context.Context) (uint64, error) { ...@@ -43,6 +46,32 @@ func (_m *TxManager) BlockNumber(ctx context.Context) (uint64, error) {
return r0, r1 return r0, r1
} }
// Call provides a mock function with given fields: ctx, msg, blockNumber
func (_m *TxManager) Call(ctx context.Context, msg ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) {
ret := _m.Called(ctx, msg, blockNumber)
var r0 []byte
var r1 error
if rf, ok := ret.Get(0).(func(context.Context, ethereum.CallMsg, *big.Int) ([]byte, error)); ok {
return rf(ctx, msg, blockNumber)
}
if rf, ok := ret.Get(0).(func(context.Context, ethereum.CallMsg, *big.Int) []byte); ok {
r0 = rf(ctx, msg, blockNumber)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]byte)
}
}
if rf, ok := ret.Get(1).(func(context.Context, ethereum.CallMsg, *big.Int) error); ok {
r1 = rf(ctx, msg, blockNumber)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// From provides a mock function with given fields: // From provides a mock function with given fields:
func (_m *TxManager) From() common.Address { func (_m *TxManager) From() common.Address {
ret := _m.Called() ret := _m.Called()
......
...@@ -45,6 +45,10 @@ type TxManager interface { ...@@ -45,6 +45,10 @@ type TxManager interface {
// NOTE: Send can be called concurrently, the nonce will be managed internally. // NOTE: Send can be called concurrently, the nonce will be managed internally.
Send(ctx context.Context, candidate TxCandidate) (*types.Receipt, error) Send(ctx context.Context, candidate TxCandidate) (*types.Receipt, error)
// Call is used to call a contract.
// Internally, it uses the [ethclient.Client.CallContract] method.
Call(ctx context.Context, msg ethereum.CallMsg, blockNumber *big.Int) ([]byte, error)
// From returns the sending address associated with the instance of the transaction manager. // From returns the sending address associated with the instance of the transaction manager.
// It is static for a single instance of a TxManager. // It is static for a single instance of a TxManager.
From() common.Address From() common.Address
...@@ -59,6 +63,9 @@ type ETHBackend interface { ...@@ -59,6 +63,9 @@ type ETHBackend interface {
// BlockNumber returns the most recent block number. // BlockNumber returns the most recent block number.
BlockNumber(ctx context.Context) (uint64, error) BlockNumber(ctx context.Context) (uint64, error)
// CallContract executes an eth_call against the provided contract.
CallContract(ctx context.Context, msg ethereum.CallMsg, blockNumber *big.Int) ([]byte, error)
// TransactionReceipt queries the backend for a receipt associated with // TransactionReceipt queries the backend for a receipt associated with
// txHash. If lookup does not fail, but the transaction is not found, // txHash. If lookup does not fail, but the transaction is not found,
// nil should be returned for both values. // nil should be returned for both values.
...@@ -155,6 +162,12 @@ func (m *SimpleTxManager) Send(ctx context.Context, candidate TxCandidate) (*typ ...@@ -155,6 +162,12 @@ func (m *SimpleTxManager) Send(ctx context.Context, candidate TxCandidate) (*typ
return receipt, err return receipt, err
} }
// Call is used to call a contract.
// Internally, it uses the [ethclient.Client.CallContract] method.
func (m *SimpleTxManager) Call(ctx context.Context, msg ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) {
return m.backend.CallContract(ctx, msg, blockNumber)
}
// send performs the actual transaction creation and sending. // send performs the actual transaction creation and sending.
func (m *SimpleTxManager) send(ctx context.Context, candidate TxCandidate) (*types.Receipt, error) { func (m *SimpleTxManager) send(ctx context.Context, candidate TxCandidate) (*types.Receipt, error) {
if m.cfg.TxSendTimeout != 0 { if m.cfg.TxSendTimeout != 0 {
......
...@@ -194,6 +194,11 @@ func (b *mockBackend) BlockNumber(ctx context.Context) (uint64, error) { ...@@ -194,6 +194,11 @@ func (b *mockBackend) BlockNumber(ctx context.Context) (uint64, error) {
return b.blockHeight, nil return b.blockHeight, nil
} }
// Call mocks a call to the EVM.
func (b *mockBackend) CallContract(ctx context.Context, call ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) {
return nil, nil
}
func (b *mockBackend) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) { func (b *mockBackend) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) {
return &types.Header{ return &types.Header{
BaseFee: b.g.basefee(), BaseFee: b.g.basefee(),
...@@ -649,6 +654,10 @@ func (b *failingBackend) HeaderByNumber(_ context.Context, _ *big.Int) (*types.H ...@@ -649,6 +654,10 @@ func (b *failingBackend) HeaderByNumber(_ context.Context, _ *big.Int) (*types.H
}, nil }, nil
} }
func (b *failingBackend) CallContract(_ context.Context, _ ethereum.CallMsg, _ *big.Int) ([]byte, error) {
return nil, errors.New("unimplemented")
}
func (b *failingBackend) SendTransaction(_ context.Context, _ *types.Transaction) error { func (b *failingBackend) SendTransaction(_ context.Context, _ *types.Transaction) error {
return errors.New("unimplemented") return errors.New("unimplemented")
} }
......
...@@ -75,11 +75,6 @@ COPY ./packages ./packages ...@@ -75,11 +75,6 @@ COPY ./packages ./packages
RUN pnpm build RUN pnpm build
FROM base as fault-detector
WORKDIR /opt/optimism/packages/fault-detector
COPY ./ops/scripts/detector.sh .
CMD ["pnpm", "run", "start"]
FROM base as replica-healthcheck FROM base as replica-healthcheck
WORKDIR /opt/optimism/packages/replica-healthcheck WORKDIR /opt/optimism/packages/replica-healthcheck
ENTRYPOINT ["pnpm", "run", "start"] ENTRYPOINT ["pnpm", "run", "start"]
...@@ -92,7 +87,6 @@ FROM base as drippie-mon ...@@ -92,7 +87,6 @@ FROM base as drippie-mon
WORKDIR /opt/optimism/packages/chain-mon WORKDIR /opt/optimism/packages/chain-mon
ENTRYPOINT ["pnpm", "run", "start:drippie-mon"] ENTRYPOINT ["pnpm", "run", "start:drippie-mon"]
FROM base as wd-mon FROM base as wd-mon
WORKDIR /opt/optimism/packages/chain-mon WORKDIR /opt/optimism/packages/chain-mon
ENTRYPOINT ["pnpm", "run", "start:wd-mon"] ENTRYPOINT ["pnpm", "run", "start:wd-mon"]
...@@ -100,3 +94,7 @@ ENTRYPOINT ["pnpm", "run", "start:wd-mon"] ...@@ -100,3 +94,7 @@ ENTRYPOINT ["pnpm", "run", "start:wd-mon"]
FROM base as wallet-mon FROM base as wallet-mon
WORKDIR /opt/optimism/packages/chain-mon WORKDIR /opt/optimism/packages/chain-mon
ENTRYPOINT ["pnpm", "run", "start:wallet-mon"] ENTRYPOINT ["pnpm", "run", "start:wallet-mon"]
from base as fault-mon
WORKDIR /opt/optimism/packages/chain-mon
ENTRYPOINT ["pnpm", "run", "start:fault-mon"]
...@@ -6,7 +6,7 @@ DOCKER_REPO=$1 ...@@ -6,7 +6,7 @@ DOCKER_REPO=$1
GIT_TAG=$2 GIT_TAG=$2
GIT_SHA=$3 GIT_SHA=$3
IMAGE_NAME=$(echo "$GIT_TAG" | grep -Eow '^(ci-builder|fault-detector|proxyd|indexer|op-[a-z0-9\-]*)' || true) IMAGE_NAME=$(echo "$GIT_TAG" | grep -Eow '^(ci-builder|proxyd|indexer|op-[a-z0-9\-]*)' || true)
if [ -z "$IMAGE_NAME" ]; then if [ -z "$IMAGE_NAME" ]; then
echo "image name could not be parsed from git tag '$GIT_TAG'" echo "image name could not be parsed from git tag '$GIT_TAG'"
exit 1 exit 1
......
#!/bin/bash
set -e
RETRIES=${RETRIES:-60}
# waits for l2geth to be up
curl \
--fail \
--show-error \
--silent \
--output /dev/null \
--retry-connrefused \
--retry $RETRIES \
--retry-delay 1 \
$FAULT_DETECTOR__L2_RPC_PROVIDER
# go
exec pnpm start
...@@ -15,7 +15,6 @@ MIN_VERSIONS = { ...@@ -15,7 +15,6 @@ MIN_VERSIONS = {
'op-proposer': '0.10.14', 'op-proposer': '0.10.14',
'proxyd': '3.16.0', 'proxyd': '3.16.0',
'indexer': '0.5.0', 'indexer': '0.5.0',
'fault-detector': '0.6.3',
'ci-builder': '0.6.0' 'ci-builder': '0.6.0'
} }
......
...@@ -39,3 +39,31 @@ TWO_STEP_MONITOR__L2_RPC_PROVIDER= ...@@ -39,3 +39,31 @@ TWO_STEP_MONITOR__L2_RPC_PROVIDER=
# The block number to start monitoring from # The block number to start monitoring from
TWO_STEP_MONITOR__START_BLOCK_NUMBER= TWO_STEP_MONITOR__START_BLOCK_NUMBER=
###############################################################################
# ↓ fault-mon ↓ #
###############################################################################
# --l1rpcprovider Provider for interacting with L1 (env: FAULT_DETECTOR__L1_RPC_PROVIDER)
FAULT_DETECTOR__L1_RPC_PROVIDER=
# --l2rpcprovider Provider for interacting with L2 (env: FAULT_DETECTOR__L2_RPC_PROVIDER)
FAULT_DETECTOR__L2_RPC_PROVIDER=
# --bedrock Whether or not the service is running against a Bedrock chain (env: FAULT_DETECTOR__BEDROCK)
BEDROCK=true
# Optional Params
# --startbatchindex Batch index to start checking from. For bedrock chains, this is the L2 height to start from (env: FAULT_DETECTOR__START_BATCH_INDEX)
# FAULT_DETECTOR__START_BATCH_INDEX=
# --optimismportaladdress [Custom Bedrock Chains] Deployed OptimismPortal contract address. Used to retrieve necessary info for ouput verification (env: FAULT_DETECTOR__OPTIMISM_PORTAL_ADDRESS)
# FAULT_DETECTOR__OPTIMISM_PORTAL_ADDRESS=
# --statecommitmentchainaddress [Custom Legacy Chains] Deployed StateCommitmentChain contract address. Used to fetch necessary info for output verification. (env: FAULT_DETECTOR__STATE_COMMITMENT_CHAIN_ADDRESS)
# FAULT_DETECTOR__STATE_COMMITMENT_CHAIN_ADDRESS=
# --loopintervalms Loop interval in milliseconds, only applies if service is set to loop (env: FAULT_DETECTOR__LOOP_INTERVAL_MS)
# FAULT_DETECTOR__LOOP_INTERVAL_MS=
# --port Port for the app server (env: FAULT_DETECTOR__PORT)
# FAULT_DETECTOR__PORT=
# --hostname Hostname for the app server (env: FAULT_DETECTOR__HOSTNAME)
# FAULT_DETECTOR__HOSTNAME=
# --loglevel Log level (env: FAULT_DETECTOR__LOG_LEVEL)
# FAULT_DETECTOR__LOG_LEVEL=
# @eth-optimism/drippie-mon # @eth-optimism/drippie-mon
## 0.4.1
### Patch Changes
- [#6206](https://github.com/ethereum-optimism/optimism/pull/6206) [`3969730dc`](https://github.com/ethereum-optimism/optimism/commit/3969730dc938947a7105c27989e53d4b5cf788a9) Thanks [@tynes](https://github.com/tynes)! - Update import path for artifact
- Updated dependencies [[`a666c4f20`](https://github.com/ethereum-optimism/optimism/commit/a666c4f2082253abbb68c0678e5a0a1ed0c00f4b), [`ff577455f`](https://github.com/ethereum-optimism/optimism/commit/ff577455f196b5f5b8a889339b845561ca6c538a), [`89ca741a6`](https://github.com/ethereum-optimism/optimism/commit/89ca741a63c5e07f9d691bb6f7a89f7718fc49ca), [`c11039060`](https://github.com/ethereum-optimism/optimism/commit/c11039060bc037a88916c2cba602687b6d69ad1a), [`72d184854`](https://github.com/ethereum-optimism/optimism/commit/72d184854ebad8b2025641f126ed76573b1f0ac3), [`77da6edc6`](https://github.com/ethereum-optimism/optimism/commit/77da6edc643e0b5e39f7b6bb41c3c7ead418a876), [`3f13fd0bb`](https://github.com/ethereum-optimism/optimism/commit/3f13fd0bbea051a4550f1df6def1a53a616aa6f6), [`639163253`](https://github.com/ethereum-optimism/optimism/commit/639163253a5e2128f1c21c446b68d358d38cbd30)]:
- @eth-optimism/sdk@3.1.0
- @eth-optimism/contracts-bedrock@0.16.0
- @eth-optimism/core-utils@0.12.2
- @eth-optimism/common-ts@0.8.3
## 0.4.0 ## 0.4.0
### Minor Changes ### Minor Changes
......
{ {
"private": true, "private": true,
"name": "@eth-optimism/chain-mon", "name": "@eth-optimism/chain-mon",
"version": "0.4.0", "version": "0.4.1",
"description": "[Optimism] Chain monitoring services", "description": "[Optimism] Chain monitoring services",
"main": "dist/index", "main": "dist/index",
"types": "dist/index", "types": "dist/index",
...@@ -13,7 +13,9 @@ ...@@ -13,7 +13,9 @@
"start:wallet-mon": "ts-node ./src/wallet-mon/service.ts", "start:wallet-mon": "ts-node ./src/wallet-mon/service.ts",
"start:drippie-mon": "ts-node ./src/drippie-mon/service.ts", "start:drippie-mon": "ts-node ./src/drippie-mon/service.ts",
"start:wd-mon": "ts-node ./src/wd-mon/service.ts", "start:wd-mon": "ts-node ./src/wd-mon/service.ts",
"test:coverage": "echo 'No tests defined.'", "start:fault-mon": "ts-node ./src/fault-mon/service.ts",
"test": "hardhat test",
"test:coverage": "nyc hardhat test && nyc merge .nyc_output coverage.json",
"build": "tsc -p ./tsconfig.json", "build": "tsc -p ./tsconfig.json",
"clean": "rimraf dist/ ./tsconfig.tsbuildinfo", "clean": "rimraf dist/ ./tsconfig.tsbuildinfo",
"lint": "pnpm lint:fix && pnpm lint:check", "lint": "pnpm lint:fix && pnpm lint:check",
...@@ -34,18 +36,22 @@ ...@@ -34,18 +36,22 @@
"url": "https://github.com/ethereum-optimism/optimism.git" "url": "https://github.com/ethereum-optimism/optimism.git"
}, },
"dependencies": { "dependencies": {
"@eth-optimism/common-ts": "0.8.2", "@eth-optimism/common-ts": "0.8.3",
"@eth-optimism/contracts-periphery": "1.0.8", "@eth-optimism/contracts-periphery": "1.0.8",
"@eth-optimism/contracts-bedrock": "0.15.0", "@eth-optimism/contracts-bedrock": "0.16.0",
"@eth-optimism/core-utils": "0.12.1", "@eth-optimism/core-utils": "0.12.2",
"@eth-optimism/sdk": "3.0.0", "@eth-optimism/sdk": "3.1.0",
"ethers": "^5.7.0", "ethers": "^5.7.0",
"dotenv": "^16.1.4",
"@types/dateformat": "^5.0.0", "@types/dateformat": "^5.0.0",
"chai-as-promised": "^7.1.1", "chai-as-promised": "^7.1.1",
"dateformat": "^4.5.1" "dateformat": "^4.5.1"
}, },
"devDependencies": { "devDependencies": {
"@ethersproject/abstract-provider": "^5.7.0", "@ethersproject/abstract-provider": "^5.7.0",
"@nomiclabs/hardhat-ethers": "^2.0.6",
"@nomiclabs/hardhat-waffle": "^2.0.3",
"hardhat": "^2.9.6",
"ts-node": "^10.9.1" "ts-node": "^10.9.1"
} }
} }
# @eth-optimism/fault-detector # @eth-optimism/fault-mon
[![codecov](https://codecov.io/gh/ethereum-optimism/optimism/branch/develop/graph/badge.svg?token=0VTG7PG7YR&flag=fault-detector-tests)](https://codecov.io/gh/ethereum-optimism/optimism) [![codecov](https://codecov.io/gh/ethereum-optimism/optimism/branch/develop/graph/badge.svg?token=0VTG7PG7YR&flag=fault-detector-tests)](https://codecov.io/gh/ethereum-optimism/optimism)
The `fault-detector` is a simple service for detecting discrepancies between your local view of the Optimism network and the L2 output proposals published to Ethereum. The `fault-mon` is a simple service for detecting discrepancies between your local view of the Optimism network and the L2 output proposals published to Ethereum.
## Installation ## Installation
...@@ -34,7 +34,7 @@ pnpm start ...@@ -34,7 +34,7 @@ pnpm start
## What this service does ## What this service does
The `fault-detector` detects differences between the transaction results generated by your local Optimism node and the transaction results actually published to Ethereum. The `fault-mon` detects differences between the transaction results generated by your local Optimism node and the transaction results actually published to Ethereum.
Currently, transaction results take the form of [the root of the Optimism state trie](https://medium.com/@eiki1212/ethereum-state-trie-architecture-explained-a30237009d4e). Currently, transaction results take the form of [the root of the Optimism state trie](https://medium.com/@eiki1212/ethereum-state-trie-architecture-explained-a30237009d4e).
The state root of the block is published to the [`L2OutputOracle`](https://github.com/ethereum-optimism/optimism/blob/39b7262cc3ffd78cd314341b8512b2683c1d9af7/packages/contracts-bedrock/contracts/L1/L2OutputOracle.sol) contract on Ethereum. The state root of the block is published to the [`L2OutputOracle`](https://github.com/ethereum-optimism/optimism/blob/39b7262cc3ffd78cd314341b8512b2683c1d9af7/packages/contracts-bedrock/contracts/L1/L2OutputOracle.sol) contract on Ethereum.
......
...@@ -24,7 +24,7 @@ import { Provider } from '@ethersproject/abstract-provider' ...@@ -24,7 +24,7 @@ import { Provider } from '@ethersproject/abstract-provider'
import { Contract, ethers } from 'ethers' import { Contract, ethers } from 'ethers'
import dateformat from 'dateformat' import dateformat from 'dateformat'
import { version } from '../package.json' import { version } from '../../package.json'
import { import {
findFirstUnfinalizedStateBatchIndex, findFirstUnfinalizedStateBatchIndex,
findOutputForIndex, findOutputForIndex,
......
...@@ -2,3 +2,4 @@ export * from './balance-mon/service' ...@@ -2,3 +2,4 @@ export * from './balance-mon/service'
export * from './drippie-mon/service' export * from './drippie-mon/service'
export * from './wd-mon/service' export * from './wd-mon/service'
export * from './wallet-mon/service' export * from './wallet-mon/service'
export * from './fault-mon/index'
...@@ -6,7 +6,10 @@ import Artifact__L2OutputOracle from '@eth-optimism/contracts-bedrock/forge-arti ...@@ -6,7 +6,10 @@ import Artifact__L2OutputOracle from '@eth-optimism/contracts-bedrock/forge-arti
import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers'
import { expect } from './setup' import { expect } from './setup'
import { findOutputForIndex, findFirstUnfinalizedStateBatchIndex } from '../src' import {
findOutputForIndex,
findFirstUnfinalizedStateBatchIndex,
} from '../../src/fault-mon'
describe('helpers', () => { describe('helpers', () => {
const deployConfig = { const deployConfig = {
......
# @eth-optimism/common-ts # @eth-optimism/common-ts
## 0.8.3
### Patch Changes
- Updated dependencies [[`c11039060`](https://github.com/ethereum-optimism/optimism/commit/c11039060bc037a88916c2cba602687b6d69ad1a), [`77da6edc6`](https://github.com/ethereum-optimism/optimism/commit/77da6edc643e0b5e39f7b6bb41c3c7ead418a876)]:
- @eth-optimism/core-utils@0.12.2
## 0.8.2 ## 0.8.2
### Patch Changes ### Patch Changes
......
{ {
"name": "@eth-optimism/common-ts", "name": "@eth-optimism/common-ts",
"version": "0.8.2", "version": "0.8.3",
"description": "[Optimism] Advanced typescript tooling used by various services", "description": "[Optimism] Advanced typescript tooling used by various services",
"main": "dist/index", "main": "dist/index",
"types": "dist/index", "types": "dist/index",
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
"url": "https://github.com/ethereum-optimism/optimism.git" "url": "https://github.com/ethereum-optimism/optimism.git"
}, },
"dependencies": { "dependencies": {
"@eth-optimism/core-utils": "0.12.1", "@eth-optimism/core-utils": "0.12.2",
"@sentry/node": "^6.3.1", "@sentry/node": "^6.3.1",
"bcfg": "^0.1.7", "bcfg": "^0.1.7",
"body-parser": "^1.20.0", "body-parser": "^1.20.0",
......
...@@ -433,9 +433,9 @@ OptimistTest:test_supportsInterface_returnsCorrectInterfaceForERC721_succeeds() ...@@ -433,9 +433,9 @@ OptimistTest:test_supportsInterface_returnsCorrectInterfaceForERC721_succeeds()
OptimistTest:test_tokenIdOfAddress_returnsOwnerID_succeeds() (gas: 63730) OptimistTest:test_tokenIdOfAddress_returnsOwnerID_succeeds() (gas: 63730)
OptimistTest:test_tokenURI_returnsCorrectTokenURI_succeeds() (gas: 195908) OptimistTest:test_tokenURI_returnsCorrectTokenURI_succeeds() (gas: 195908)
OptimistTest:test_transferFrom_soulbound_reverts() (gas: 75512) OptimistTest:test_transferFrom_soulbound_reverts() (gas: 75512)
PreimageOracle_Test:test_computePreimageKey_succeeds() (gas: 6267) PreimageOracle_Test:test_computePreimageKey_succeeds() (gas: 6242)
PreimageOracle_Test:test_loadKeccak256PreimagePart_outOfBoundsOffset_reverts() (gas: 9025) PreimageOracle_Test:test_loadKeccak256PreimagePart_outOfBoundsOffset_reverts() (gas: 9005)
PreimageOracle_Test:test_loadKeccak256PreimagePart_succeeds() (gas: 77552) PreimageOracle_Test:test_loadKeccak256PreimagePart_succeeds() (gas: 77502)
ProxyAdmin_Test:test_chugsplashChangeProxyAdmin_succeeds() (gas: 35586) ProxyAdmin_Test:test_chugsplashChangeProxyAdmin_succeeds() (gas: 35586)
ProxyAdmin_Test:test_chugsplashGetProxyAdmin_succeeds() (gas: 15675) ProxyAdmin_Test:test_chugsplashGetProxyAdmin_succeeds() (gas: 15675)
ProxyAdmin_Test:test_chugsplashGetProxyImplementation_succeeds() (gas: 51084) ProxyAdmin_Test:test_chugsplashGetProxyImplementation_succeeds() (gas: 51084)
......
...@@ -19,3 +19,4 @@ deployments/hardhat ...@@ -19,3 +19,4 @@ deployments/hardhat
.envrc .envrc
!.envrc.example !.envrc.example
deployments/getting-started deployments/getting-started
deployments/*/.deploy
# @eth-optimism/contracts-bedrock # @eth-optimism/contracts-bedrock
## 0.16.0
### Minor Changes
- [#6206](https://github.com/ethereum-optimism/optimism/pull/6206) [`72d184854`](https://github.com/ethereum-optimism/optimism/commit/72d184854ebad8b2025641f126ed76573b1f0ac3) Thanks [@tynes](https://github.com/tynes)! - Migrate contracts periphery into bedrock
### Patch Changes
- [#6164](https://github.com/ethereum-optimism/optimism/pull/6164) [`c11039060`](https://github.com/ethereum-optimism/optimism/commit/c11039060bc037a88916c2cba602687b6d69ad1a) Thanks [@pengin7384](https://github.com/pengin7384)! - fix typo
- [#6198](https://github.com/ethereum-optimism/optimism/pull/6198) [`77da6edc6`](https://github.com/ethereum-optimism/optimism/commit/77da6edc643e0b5e39f7b6bb41c3c7ead418a876) Thanks [@tremarkley](https://github.com/tremarkley)! - Delete dead typescript https://github.com/ethereum-optimism/optimism/pull/6148.
## 0.15.0 ## 0.15.0
### Minor Changes ### Minor Changes
......
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
// A representation of an empty/uninitialized UID.
bytes32 constant EMPTY_UID = 0;
// A zero expiration represents an non-expiring attestation.
uint64 constant NO_EXPIRATION_TIME = 0;
error AccessDenied();
error InvalidEAS();
error InvalidLength();
error InvalidSignature();
error NotFound();
/**
* @dev A struct representing EIP712 signature data.
*/
struct EIP712Signature {
uint8 v; // The recovery ID.
bytes32 r; // The x-coordinate of the nonce R.
bytes32 s; // The signature data.
}
/**
* @dev A struct representing a single attestation.
*/
struct Attestation {
bytes32 uid; // A unique identifier of the attestation.
bytes32 schema; // The unique identifier of the schema.
uint64 time; // The time when the attestation was created (Unix timestamp).
uint64 expirationTime; // The time when the attestation expires (Unix timestamp).
uint64 revocationTime; // The time when the attestation was revoked (Unix timestamp).
bytes32 refUID; // The UID of the related attestation.
address recipient; // The recipient of the attestation.
address attester; // The attester/sender of the attestation.
bool revocable; // Whether the attestation is revocable.
bytes data; // Custom attestation data.
}
// Maximum upgrade forward-compatibility storage gap.
uint32 constant MAX_GAP = 50;
/**
* @dev A helper function to work with unchecked iterators in loops.
*
* @param i The index to increment.
*
* @return j The incremented index.
*/
function uncheckedInc(uint256 i) pure returns (uint256 j) {
unchecked {
j = i + 1;
}
}
/**
* @dev A helper function that converts a string to a bytes32.
*
* @param str The string to convert.
*
* @return The converted bytes32.
*/
function stringToBytes32(string memory str) pure returns (bytes32) {
bytes32 result;
assembly {
result := mload(add(str, 32))
}
return result;
}
/**
* @dev A helper function that converts a bytes32 to a string.
*
* @param data The bytes32 data to convert.
*
* @return The converted string.
*/
function bytes32ToString(bytes32 data) pure returns (string memory) {
bytes memory byteArray = new bytes(32);
uint256 length = 0;
for (uint256 i = 0; i < 32; i = uncheckedInc(i)) {
bytes1 char = data[i];
if (char == 0x00) {
break;
}
byteArray[length] = char;
length = uncheckedInc(length);
}
bytes memory terminatedBytes = new bytes(length);
for (uint256 j = 0; j < length; j = uncheckedInc(j)) {
terminatedBytes[j] = byteArray[j];
}
return string(terminatedBytes);
}
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;
import { Address } from "@openzeppelin/contracts/utils/Address.sol";
import { Semver } from "../universal/Semver.sol";
import { Predeploys } from "../libraries/Predeploys.sol";
import { EIP712Verifier } from "./eip712/EIP712Verifier.sol";
import { ISchemaResolver } from "./resolver/ISchemaResolver.sol";
// prettier-ignore
import {
AccessDenied,
EMPTY_UID,
EIP712Signature,
InvalidLength,
MAX_GAP,
NotFound,
NO_EXPIRATION_TIME,
uncheckedInc
} from "./Common.sol";
// prettier-ignore
import {
Attestation,
AttestationRequest,
AttestationRequestData,
DelegatedAttestationRequest,
DelegatedRevocationRequest,
IEAS,
MultiAttestationRequest,
MultiDelegatedAttestationRequest,
MultiDelegatedRevocationRequest,
MultiRevocationRequest,
RevocationRequest,
RevocationRequestData
} from "./IEAS.sol";
import { ISchemaRegistry, SchemaRecord } from "./ISchemaRegistry.sol";
struct AttestationsResult {
uint256 usedValue; // Total ETH amount that was sent to resolvers.
bytes32[] uids; // UIDs of the new attestations.
}
/// @custom:proxied
/// @custom:predeploy 0x4200000000000000000000000000000000000021
/// @title EAS
/// @notice The Ethereum Attestation Service protocol.
contract EAS is IEAS, Semver, EIP712Verifier {
using Address for address payable;
error AlreadyRevoked();
error AlreadyRevokedOffchain();
error AlreadyTimestamped();
error InsufficientValue();
error InvalidAttestation();
error InvalidAttestations();
error InvalidExpirationTime();
error InvalidOffset();
error InvalidRegistry();
error InvalidRevocation();
error InvalidRevocations();
error InvalidSchema();
error InvalidVerifier();
error Irrevocable();
error NotPayable();
error WrongSchema();
// The global schema registry.
ISchemaRegistry private constant _schemaRegistry = ISchemaRegistry(Predeploys.SCHEMA_REGISTRY);
// The global mapping between attestations and their UIDs.
mapping(bytes32 uid => Attestation attestation) private _db;
// The global mapping between data and their timestamps.
mapping(bytes32 data => uint64 timestamp) private _timestamps;
// The global mapping between data and their revocation timestamps.
mapping(address revoker => mapping(bytes32 data => uint64 timestamp)) private _revocationsOffchain;
// Upgrade forward-compatibility storage gap
uint256[MAX_GAP - 3] private __gap;
/**
* @dev Creates a new EAS instance.
*/
constructor() Semver(1, 0, 0) EIP712Verifier("EAS", "1.0.0") {
}
/**
* @inheritdoc IEAS
*/
function getSchemaRegistry() external pure returns (ISchemaRegistry) {
return _schemaRegistry;
}
/**
* @inheritdoc IEAS
*/
function attest(AttestationRequest calldata request) external payable returns (bytes32) {
AttestationRequestData[] memory requests = new AttestationRequestData[](1);
requests[0] = request.data;
return _attest(request.schema, requests, msg.sender, msg.value, true).uids[0];
}
/**
* @inheritdoc IEAS
*/
function attestByDelegation(
DelegatedAttestationRequest calldata delegatedRequest
) external payable returns (bytes32) {
_verifyAttest(delegatedRequest);
AttestationRequestData[] memory data = new AttestationRequestData[](1);
data[0] = delegatedRequest.data;
return _attest(delegatedRequest.schema, data, delegatedRequest.attester, msg.value, true).uids[0];
}
/**
* @inheritdoc IEAS
*/
function multiAttest(MultiAttestationRequest[] calldata multiRequests) external payable returns (bytes32[] memory) {
// Since a multi-attest call is going to make multiple attestations for multiple schemas, we'd need to collect
// all the returned UIDs into a single list.
bytes32[][] memory totalUids = new bytes32[][](multiRequests.length);
uint256 totalUidsCount = 0;
// We are keeping track of the total available ETH amount that can be sent to resolvers and will keep deducting
// from it to verify that there isn't any attempt to send too much ETH to resolvers. Please note that unless
// some ETH was stuck in the contract by accident (which shouldn't happen in normal conditions), it won't be
// possible to send too much ETH anyway.
uint availableValue = msg.value;
for (uint256 i = 0; i < multiRequests.length; i = uncheckedInc(i)) {
// The last batch is handled slightly differently: if the total available ETH wasn't spent in full and there
// is a remainder - it will be refunded back to the attester (something that we can only verify during the
// last and final batch).
bool last;
unchecked {
last = i == multiRequests.length - 1;
}
// Process the current batch of attestations.
MultiAttestationRequest calldata multiRequest = multiRequests[i];
AttestationsResult memory res = _attest(
multiRequest.schema,
multiRequest.data,
msg.sender,
availableValue,
last
);
// Ensure to deduct the ETH that was forwarded to the resolver during the processing of this batch.
availableValue -= res.usedValue;
// Collect UIDs (and merge them later).
totalUids[i] = res.uids;
unchecked {
totalUidsCount += res.uids.length;
}
}
// Merge all the collected UIDs and return them as a flatten array.
return _mergeUIDs(totalUids, totalUidsCount);
}
/**
* @inheritdoc IEAS
*/
function multiAttestByDelegation(
MultiDelegatedAttestationRequest[] calldata multiDelegatedRequests
) external payable returns (bytes32[] memory) {
// Since a multi-attest call is going to make multiple attestations for multiple schemas, we'd need to collect
// all the returned UIDs into a single list.
bytes32[][] memory totalUids = new bytes32[][](multiDelegatedRequests.length);
uint256 totalUidsCount = 0;
// We are keeping track of the total available ETH amount that can be sent to resolvers and will keep deducting
// from it to verify that there isn't any attempt to send too much ETH to resolvers. Please note that unless
// some ETH was stuck in the contract by accident (which shouldn't happen in normal conditions), it won't be
// possible to send too much ETH anyway.
uint availableValue = msg.value;
for (uint256 i = 0; i < multiDelegatedRequests.length; i = uncheckedInc(i)) {
// The last batch is handled slightly differently: if the total available ETH wasn't spent in full and there
// is a remainder - it will be refunded back to the attester (something that we can only verify during the
// last and final batch).
bool last;
unchecked {
last = i == multiDelegatedRequests.length - 1;
}
MultiDelegatedAttestationRequest calldata multiDelegatedRequest = multiDelegatedRequests[i];
AttestationRequestData[] calldata data = multiDelegatedRequest.data;
// Ensure that no inputs are missing.
if (data.length == 0 || data.length != multiDelegatedRequest.signatures.length) {
revert InvalidLength();
}
// Verify EIP712 signatures. Please note that the signatures are assumed to be signed with increasing nonces.
for (uint256 j = 0; j < data.length; j = uncheckedInc(j)) {
_verifyAttest(
DelegatedAttestationRequest({
schema: multiDelegatedRequest.schema,
data: data[j],
signature: multiDelegatedRequest.signatures[j],
attester: multiDelegatedRequest.attester
})
);
}
// Process the current batch of attestations.
AttestationsResult memory res = _attest(
multiDelegatedRequest.schema,
data,
multiDelegatedRequest.attester,
availableValue,
last
);
// Ensure to deduct the ETH that was forwarded to the resolver during the processing of this batch.
availableValue -= res.usedValue;
// Collect UIDs (and merge them later).
totalUids[i] = res.uids;
unchecked {
totalUidsCount += res.uids.length;
}
}
// Merge all the collected UIDs and return them as a flatten array.
return _mergeUIDs(totalUids, totalUidsCount);
}
/**
* @inheritdoc IEAS
*/
function revoke(RevocationRequest calldata request) external payable {
RevocationRequestData[] memory requests = new RevocationRequestData[](1);
requests[0] = request.data;
_revoke(request.schema, requests, msg.sender, msg.value, true);
}
/**
* @inheritdoc IEAS
*/
function revokeByDelegation(DelegatedRevocationRequest calldata delegatedRequest) external payable {
_verifyRevoke(delegatedRequest);
RevocationRequestData[] memory data = new RevocationRequestData[](1);
data[0] = delegatedRequest.data;
_revoke(delegatedRequest.schema, data, delegatedRequest.revoker, msg.value, true);
}
/**
* @inheritdoc IEAS
*/
function multiRevoke(MultiRevocationRequest[] calldata multiRequests) external payable {
// We are keeping track of the total available ETH amount that can be sent to resolvers and will keep deducting
// from it to verify that there isn't any attempt to send too much ETH to resolvers. Please note that unless
// some ETH was stuck in the contract by accident (which shouldn't happen in normal conditions), it won't be
// possible to send too much ETH anyway.
uint availableValue = msg.value;
for (uint256 i = 0; i < multiRequests.length; i = uncheckedInc(i)) {
// The last batch is handled slightly differently: if the total available ETH wasn't spent in full and there
// is a remainder - it will be refunded back to the attester (something that we can only verify during the
// last and final batch).
bool last;
unchecked {
last = i == multiRequests.length - 1;
}
MultiRevocationRequest calldata multiRequest = multiRequests[i];
// Ensure to deduct the ETH that was forwarded to the resolver during the processing of this batch.
availableValue -= _revoke(multiRequest.schema, multiRequest.data, msg.sender, availableValue, last);
}
}
/**
* @inheritdoc IEAS
*/
function multiRevokeByDelegation(
MultiDelegatedRevocationRequest[] calldata multiDelegatedRequests
) external payable {
// We are keeping track of the total available ETH amount that can be sent to resolvers and will keep deducting
// from it to verify that there isn't any attempt to send too much ETH to resolvers. Please note that unless
// some ETH was stuck in the contract by accident (which shouldn't happen in normal conditions), it won't be
// possible to send too much ETH anyway.
uint availableValue = msg.value;
for (uint256 i = 0; i < multiDelegatedRequests.length; i = uncheckedInc(i)) {
// The last batch is handled slightly differently: if the total available ETH wasn't spent in full and there
// is a remainder - it will be refunded back to the attester (something that we can only verify during the
// last and final batch).
bool last;
unchecked {
last = i == multiDelegatedRequests.length - 1;
}
MultiDelegatedRevocationRequest memory multiDelegatedRequest = multiDelegatedRequests[i];
RevocationRequestData[] memory data = multiDelegatedRequest.data;
// Ensure that no inputs are missing.
if (data.length == 0 || data.length != multiDelegatedRequest.signatures.length) {
revert InvalidLength();
}
// Verify EIP712 signatures. Please note that the signatures are assumed to be signed with increasing nonces.
for (uint256 j = 0; j < data.length; j = uncheckedInc(j)) {
_verifyRevoke(
DelegatedRevocationRequest({
schema: multiDelegatedRequest.schema,
data: data[j],
signature: multiDelegatedRequest.signatures[j],
revoker: multiDelegatedRequest.revoker
})
);
}
// Ensure to deduct the ETH that was forwarded to the resolver during the processing of this batch.
availableValue -= _revoke(
multiDelegatedRequest.schema,
data,
multiDelegatedRequest.revoker,
availableValue,
last
);
}
}
/**
* @inheritdoc IEAS
*/
function timestamp(bytes32 data) external returns (uint64) {
uint64 time = _time();
_timestamp(data, time);
return time;
}
/**
* @inheritdoc IEAS
*/
function revokeOffchain(bytes32 data) external returns (uint64) {
uint64 time = _time();
_revokeOffchain(msg.sender, data, time);
return time;
}
/**
* @inheritdoc IEAS
*/
function multiRevokeOffchain(bytes32[] calldata data) external returns (uint64) {
uint64 time = _time();
uint256 length = data.length;
for (uint256 i = 0; i < length; i = uncheckedInc(i)) {
_revokeOffchain(msg.sender, data[i], time);
}
return time;
}
/**
* @inheritdoc IEAS
*/
function multiTimestamp(bytes32[] calldata data) external returns (uint64) {
uint64 time = _time();
uint256 length = data.length;
for (uint256 i = 0; i < length; i = uncheckedInc(i)) {
_timestamp(data[i], time);
}
return time;
}
/**
* @inheritdoc IEAS
*/
function getAttestation(bytes32 uid) external view returns (Attestation memory) {
return _db[uid];
}
/**
* @inheritdoc IEAS
*/
function isAttestationValid(bytes32 uid) public view returns (bool) {
return _db[uid].uid != 0;
}
/**
* @inheritdoc IEAS
*/
function getTimestamp(bytes32 data) external view returns (uint64) {
return _timestamps[data];
}
/**
* @inheritdoc IEAS
*/
function getRevokeOffchain(address revoker, bytes32 data) external view returns (uint64) {
return _revocationsOffchain[revoker][data];
}
/**
* @dev Attests to a specific schema.
*
* @param schema // the unique identifier of the schema to attest to.
* @param data The arguments of the attestation requests.
* @param attester The attesting account.
* @param availableValue The total available ETH amount that can be sent to the resolver.
* @param last Whether this is the last attestations/revocations set.
*
* @return The UID of the new attestations and the total sent ETH amount.
*/
function _attest(
bytes32 schema,
AttestationRequestData[] memory data,
address attester,
uint256 availableValue,
bool last
) private returns (AttestationsResult memory) {
uint256 length = data.length;
AttestationsResult memory res;
res.uids = new bytes32[](length);
// Ensure that we aren't attempting to attest to a non-existing schema.
SchemaRecord memory schemaRecord = _schemaRegistry.getSchema(schema);
if (schemaRecord.uid == EMPTY_UID) {
revert InvalidSchema();
}
Attestation[] memory attestations = new Attestation[](length);
uint256[] memory values = new uint256[](length);
for (uint256 i = 0; i < length; i = uncheckedInc(i)) {
AttestationRequestData memory request = data[i];
// Ensure that either no expiration time was set or that it was set in the future.
if (request.expirationTime != NO_EXPIRATION_TIME && request.expirationTime <= _time()) {
revert InvalidExpirationTime();
}
// Ensure that we aren't trying to make a revocable attestation for a non-revocable schema.
if (!schemaRecord.revocable && request.revocable) {
revert Irrevocable();
}
Attestation memory attestation = Attestation({
uid: EMPTY_UID,
schema: schema,
refUID: request.refUID,
time: _time(),
expirationTime: request.expirationTime,
revocationTime: 0,
recipient: request.recipient,
attester: attester,
revocable: request.revocable,
data: request.data
});
// Look for the first non-existing UID (and use a bump seed/nonce in the rare case of a conflict).
bytes32 uid;
uint32 bump = 0;
while (true) {
uid = _getUID(attestation, bump);
if (_db[uid].uid == EMPTY_UID) {
break;
}
unchecked {
++bump;
}
}
attestation.uid = uid;
_db[uid] = attestation;
if (request.refUID != 0) {
// Ensure that we aren't trying to attest to a non-existing referenced UID.
if (!isAttestationValid(request.refUID)) {
revert NotFound();
}
}
attestations[i] = attestation;
values[i] = request.value;
res.uids[i] = uid;
emit Attested(request.recipient, attester, uid, schema);
}
res.usedValue = _resolveAttestations(schemaRecord, attestations, values, false, availableValue, last);
return res;
}
/**
* @dev Revokes an existing attestation to a specific schema.
*
* @param schema The unique identifier of the schema to attest to.
* @param data The arguments of the revocation requests.
* @param revoker The revoking account.
* @param availableValue The total available ETH amount that can be sent to the resolver.
* @param last Whether this is the last attestations/revocations set.
*
* @return Returns the total sent ETH amount.
*/
function _revoke(
bytes32 schema,
RevocationRequestData[] memory data,
address revoker,
uint256 availableValue,
bool last
) private returns (uint256) {
// Ensure that a non-existing schema ID wasn't passed by accident.
SchemaRecord memory schemaRecord = _schemaRegistry.getSchema(schema);
if (schemaRecord.uid == EMPTY_UID) {
revert InvalidSchema();
}
uint256 length = data.length;
Attestation[] memory attestations = new Attestation[](length);
uint256[] memory values = new uint256[](length);
for (uint256 i = 0; i < length; i = uncheckedInc(i)) {
RevocationRequestData memory request = data[i];
Attestation storage attestation = _db[request.uid];
// Ensure that we aren't attempting to revoke a non-existing attestation.
if (attestation.uid == EMPTY_UID) {
revert NotFound();
}
// Ensure that a wrong schema ID wasn't passed by accident.
if (attestation.schema != schema) {
revert InvalidSchema();
}
// Allow only original attesters to revoke their attestations.
if (attestation.attester != revoker) {
revert AccessDenied();
}
// Please note that also checking of the schema itself is revocable is unnecessary, since it's not possible to
// make revocable attestations to an irrevocable schema.
if (!attestation.revocable) {
revert Irrevocable();
}
// Ensure that we aren't trying to revoke the same attestation twice.
if (attestation.revocationTime != 0) {
revert AlreadyRevoked();
}
attestation.revocationTime = _time();
attestations[i] = attestation;
values[i] = request.value;
emit Revoked(attestation.recipient, revoker, request.uid, attestation.schema);
}
return _resolveAttestations(schemaRecord, attestations, values, true, availableValue, last);
}
/**
* @dev Resolves a new attestation or a revocation of an existing attestation.
*
* @param schemaRecord The schema of the attestation.
* @param attestation The data of the attestation to make/revoke.
* @param value An explicit ETH amount to send to the resolver.
* @param isRevocation Whether to resolve an attestation or its revocation.
* @param availableValue The total available ETH amount that can be sent to the resolver.
* @param last Whether this is the last attestations/revocations set.
*
* @return Returns the total sent ETH amount.
*/
function _resolveAttestation(
SchemaRecord memory schemaRecord,
Attestation memory attestation,
uint256 value,
bool isRevocation,
uint256 availableValue,
bool last
) private returns (uint256) {
ISchemaResolver resolver = schemaRecord.resolver;
if (address(resolver) == address(0)) {
// Ensure that we don't accept payments if there is no resolver.
if (value != 0) {
revert NotPayable();
}
return 0;
}
// Ensure that we don't accept payments which can't be forwarded to the resolver.
if (value != 0 && !resolver.isPayable()) {
revert NotPayable();
}
// Ensure that the attester/revoker doesn't try to spend more than available.
if (value > availableValue) {
revert InsufficientValue();
}
// Ensure to deduct the sent value explicitly.
unchecked {
availableValue -= value;
}
if (isRevocation) {
if (!resolver.revoke{ value: value }(attestation)) {
revert InvalidRevocation();
}
} else if (!resolver.attest{ value: value }(attestation)) {
revert InvalidAttestation();
}
if (last) {
_refund(availableValue);
}
return value;
}
/**
* @dev Resolves multiple attestations or revocations of existing attestations.
*
* @param schemaRecord The schema of the attestation.
* @param attestations The data of the attestations to make/revoke.
* @param values Explicit ETH amounts to send to the resolver.
* @param isRevocation Whether to resolve an attestation or its revocation.
* @param availableValue The total available ETH amount that can be sent to the resolver.
* @param last Whether this is the last attestations/revocations set.
*
* @return Returns the total sent ETH amount.
*/
function _resolveAttestations(
SchemaRecord memory schemaRecord,
Attestation[] memory attestations,
uint256[] memory values,
bool isRevocation,
uint256 availableValue,
bool last
) private returns (uint256) {
uint256 length = attestations.length;
if (length == 1) {
return _resolveAttestation(schemaRecord, attestations[0], values[0], isRevocation, availableValue, last);
}
ISchemaResolver resolver = schemaRecord.resolver;
if (address(resolver) == address(0)) {
// Ensure that we don't accept payments if there is no resolver.
for (uint256 i = 0; i < length; i = uncheckedInc(i)) {
if (values[i] != 0) {
revert NotPayable();
}
}
return 0;
}
uint256 totalUsedValue = 0;
for (uint256 i = 0; i < length; i = uncheckedInc(i)) {
uint256 value = values[i];
// Ensure that we don't accept payments which can't be forwarded to the resolver.
if (value != 0 && !resolver.isPayable()) {
revert NotPayable();
}
// Ensure that the attester/revoker doesn't try to spend more than available.
if (value > availableValue) {
revert InsufficientValue();
}
// Ensure to deduct the sent value explicitly and add it to the total used value by the batch.
unchecked {
availableValue -= value;
totalUsedValue += value;
}
}
if (isRevocation) {
if (!resolver.multiRevoke{ value: totalUsedValue }(attestations, values)) {
revert InvalidRevocations();
}
} else if (!resolver.multiAttest{ value: totalUsedValue }(attestations, values)) {
revert InvalidAttestations();
}
if (last) {
_refund(availableValue);
}
return totalUsedValue;
}
/**
* @dev Calculates a UID for a given attestation.
*
* @param attestation The input attestation.
* @param bump A bump value to use in case of a UID conflict.
*
* @return Attestation UID.
*/
function _getUID(Attestation memory attestation, uint32 bump) private pure returns (bytes32) {
return
keccak256(
abi.encodePacked(
attestation.schema,
attestation.recipient,
attestation.attester,
attestation.time,
attestation.expirationTime,
attestation.revocable,
attestation.refUID,
attestation.data,
bump
)
);
}
/**
* @dev Refunds remaining ETH amount to the attester.
*
* @param remainingValue The remaining ETH amount that was not sent to the resolver.
*/
function _refund(uint256 remainingValue) private {
if (remainingValue > 0) {
// Using a regular transfer here might revert, for some non-EOA attesters, due to exceeding of the 2300
// gas limit which is why we're using call instead (via sendValue), which the 2300 gas limit does not
// apply for.
payable(msg.sender).sendValue(remainingValue);
}
}
/**
* @dev Timestamps the specified bytes32 data.
*
* @param data The data to timestamp.
* @param time The timestamp.
*/
function _timestamp(bytes32 data, uint64 time) private {
if (_timestamps[data] != 0) {
revert AlreadyTimestamped();
}
_timestamps[data] = time;
emit Timestamped(data, time);
}
/**
* @dev Timestamps the specified bytes32 data.
*
* @param data The data to timestamp.
* @param time The timestamp.
*/
function _revokeOffchain(address revoker, bytes32 data, uint64 time) private {
mapping(bytes32 => uint64) storage revocations = _revocationsOffchain[revoker];
if (revocations[data] != 0) {
revert AlreadyRevokedOffchain();
}
revocations[data] = time;
emit RevokedOffchain(revoker, data, time);
}
/**
* @dev Returns the current's block timestamp. This method is overridden during tests and used to simulate the
* current block time.
*/
function _time() internal view virtual returns (uint64) {
return uint64(block.timestamp);
}
/**
* @dev Merges lists of UIDs.
*
* @param uidLists The provided lists of UIDs.
* @param uidsCount Total UIDs count.
*
* @return A merged and flatten list of all the UIDs.
*/
function _mergeUIDs(bytes32[][] memory uidLists, uint256 uidsCount) private pure returns (bytes32[] memory) {
bytes32[] memory uids = new bytes32[](uidsCount);
uint256 currentIndex = 0;
for (uint256 i = 0; i < uidLists.length; i = uncheckedInc(i)) {
bytes32[] memory currentUids = uidLists[i];
for (uint256 j = 0; j < currentUids.length; j = uncheckedInc(j)) {
uids[currentIndex] = currentUids[j];
unchecked {
++currentIndex;
}
}
}
return uids;
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { ISchemaRegistry } from "./ISchemaRegistry.sol";
import { Attestation, EIP712Signature } from "./Common.sol";
/**
* @dev A struct representing the arguments of the attestation request.
*/
struct AttestationRequestData {
address recipient; // The recipient of the attestation.
uint64 expirationTime; // The time when the attestation expires (Unix timestamp).
bool revocable; // Whether the attestation is revocable.
bytes32 refUID; // The UID of the related attestation.
bytes data; // Custom attestation data.
uint256 value; // An explicit ETH amount to send to the resolver. This is important to prevent accidental user errors.
}
/**
* @dev A struct representing the full arguments of the attestation request.
*/
struct AttestationRequest {
bytes32 schema; // The unique identifier of the schema.
AttestationRequestData data; // The arguments of the attestation request.
}
/**
* @dev A struct representing the full arguments of the full delegated attestation request.
*/
struct DelegatedAttestationRequest {
bytes32 schema; // The unique identifier of the schema.
AttestationRequestData data; // The arguments of the attestation request.
EIP712Signature signature; // The EIP712 signature data.
address attester; // The attesting account.
}
/**
* @dev A struct representing the full arguments of the multi attestation request.
*/
struct MultiAttestationRequest {
bytes32 schema; // The unique identifier of the schema.
AttestationRequestData[] data; // The arguments of the attestation request.
}
/**
* @dev A struct representing the full arguments of the delegated multi attestation request.
*/
struct MultiDelegatedAttestationRequest {
bytes32 schema; // The unique identifier of the schema.
AttestationRequestData[] data; // The arguments of the attestation requests.
EIP712Signature[] signatures; // The EIP712 signatures data. Please note that the signatures are assumed to be signed with increasing nonces.
address attester; // The attesting account.
}
/**
* @dev A struct representing the arguments of the revocation request.
*/
struct RevocationRequestData {
bytes32 uid; // The UID of the attestation to revoke.
uint256 value; // An explicit ETH amount to send to the resolver. This is important to prevent accidental user errors.
}
/**
* @dev A struct representing the full arguments of the revocation request.
*/
struct RevocationRequest {
bytes32 schema; // The unique identifier of the schema.
RevocationRequestData data; // The arguments of the revocation request.
}
/**
* @dev A struct representing the arguments of the full delegated revocation request.
*/
struct DelegatedRevocationRequest {
bytes32 schema; // The unique identifier of the schema.
RevocationRequestData data; // The arguments of the revocation request.
EIP712Signature signature; // The EIP712 signature data.
address revoker; // The revoking account.
}
/**
* @dev A struct representing the full arguments of the multi revocation request.
*/
struct MultiRevocationRequest {
bytes32 schema; // The unique identifier of the schema.
RevocationRequestData[] data; // The arguments of the revocation request.
}
/**
* @dev A struct representing the full arguments of the delegated multi revocation request.
*/
struct MultiDelegatedRevocationRequest {
bytes32 schema; // The unique identifier of the schema.
RevocationRequestData[] data; // The arguments of the revocation requests.
EIP712Signature[] signatures; // The EIP712 signatures data. Please note that the signatures are assumed to be signed with increasing nonces.
address revoker; // The revoking account.
}
/// @title IEAS
/// @notice The Ethereum Attestation Service interface.
interface IEAS {
/**
* @dev Emitted when an attestation has been made.
*
* @param recipient The recipient of the attestation.
* @param attester The attesting account.
* @param uid The UID the revoked attestation.
* @param schema The UID of the schema.
*/
event Attested(address indexed recipient, address indexed attester, bytes32 uid, bytes32 indexed schema);
/**
* @dev Emitted when an attestation has been revoked.
*
* @param recipient The recipient of the attestation.
* @param attester The attesting account.
* @param schema The UID of the schema.
* @param uid The UID the revoked attestation.
*/
event Revoked(address indexed recipient, address indexed attester, bytes32 uid, bytes32 indexed schema);
/**
* @dev Emitted when a data has been timestamped.
*
* @param data The data.
* @param timestamp The timestamp.
*/
event Timestamped(bytes32 indexed data, uint64 indexed timestamp);
/**
* @dev Emitted when a data has been revoked.
*
* @param revoker The address of the revoker.
* @param data The data.
* @param timestamp The timestamp.
*/
event RevokedOffchain(address indexed revoker, bytes32 indexed data, uint64 indexed timestamp);
/**
* @dev Returns the address of the global schema registry.
*
* @return The address of the global schema registry.
*/
function getSchemaRegistry() external view returns (ISchemaRegistry);
/**
* @dev Attests to a specific schema.
*
* @param request The arguments of the attestation request.
*
* Example:
*
* attest({
* schema: "0facc36681cbe2456019c1b0d1e7bedd6d1d40f6f324bf3dd3a4cef2999200a0",
* data: {
* recipient: "0xdEADBeAFdeAdbEafdeadbeafDeAdbEAFdeadbeaf",
* expirationTime: 0,
* revocable: true,
* refUID: "0x0000000000000000000000000000000000000000000000000000000000000000",
* data: "0xF00D",
* value: 0
* }
* })
*
* @return The UID of the new attestation.
*/
function attest(AttestationRequest calldata request) external payable returns (bytes32);
/**
* @dev Attests to a specific schema via the provided EIP712 signature.
*
* @param delegatedRequest The arguments of the delegated attestation request.
*
* Example:
*
* attestByDelegation({
* schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc',
* data: {
* recipient: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
* expirationTime: 1673891048,
* revocable: true,
* refUID: '0x0000000000000000000000000000000000000000000000000000000000000000',
* data: '0x1234',
* value: 0
* },
* signature: {
* v: 28,
* r: '0x148c...b25b',
* s: '0x5a72...be22'
* },
* attester: '0xc5E8740aD971409492b1A63Db8d83025e0Fc427e'
* })
*
* @return The UID of the new attestation.
*/
function attestByDelegation(
DelegatedAttestationRequest calldata delegatedRequest
) external payable returns (bytes32);
/**
* @dev Attests to multiple schemas.
*
* @param multiRequests The arguments of the multi attestation requests. The requests should be grouped by distinct
* schema ids to benefit from the best batching optimization.
*
* Example:
*
* multiAttest([{
* schema: '0x33e9094830a5cba5554d1954310e4fbed2ef5f859ec1404619adea4207f391fd',
* data: [{
* recipient: '0xdEADBeAFdeAdbEafdeadbeafDeAdbEAFdeadbeaf',
* expirationTime: 1673891048,
* revocable: true,
* refUID: '0x0000000000000000000000000000000000000000000000000000000000000000',
* data: '0x1234',
* value: 1000
* },
* {
* recipient: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
* expirationTime: 0,
* revocable: false,
* refUID: '0x480df4a039efc31b11bfdf491b383ca138b6bde160988222a2a3509c02cee174',
* data: '0x00',
* value: 0
* }],
* },
* {
* schema: '0x5ac273ce41e3c8bfa383efe7c03e54c5f0bff29c9f11ef6ffa930fc84ca32425',
* data: [{
* recipient: '0xdEADBeAFdeAdbEafdeadbeafDeAdbEAFdeadbeaf',
* expirationTime: 0,
* revocable: true,
* refUID: '0x75bf2ed8dca25a8190c50c52db136664de25b2449535839008ccfdab469b214f',
* data: '0x12345678',
* value: 0
* },
* }])
*
* @return The UIDs of the new attestations.
*/
function multiAttest(MultiAttestationRequest[] calldata multiRequests) external payable returns (bytes32[] memory);
/**
* @dev Attests to multiple schemas using via provided EIP712 signatures.
*
* @param multiDelegatedRequests The arguments of the delegated multi attestation requests. The requests should be
* grouped by distinct schema ids to benefit from the best batching optimization.
*
* Example:
*
* multiAttestByDelegation([{
* schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc',
* data: [{
* recipient: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
* expirationTime: 1673891048,
* revocable: true,
* refUID: '0x0000000000000000000000000000000000000000000000000000000000000000',
* data: '0x1234',
* value: 0
* },
* {
* recipient: '0xdEADBeAFdeAdbEafdeadbeafDeAdbEAFdeadbeaf',
* expirationTime: 0,
* revocable: false,
* refUID: '0x0000000000000000000000000000000000000000000000000000000000000000',
* data: '0x00',
* value: 0
* }],
* signatures: [{
* v: 28,
* r: '0x148c...b25b',
* s: '0x5a72...be22'
* },
* {
* v: 28,
* r: '0x487s...67bb',
* s: '0x12ad...2366'
* }],
* attester: '0x1D86495b2A7B524D747d2839b3C645Bed32e8CF4'
* }])
*
* @return The UIDs of the new attestations.
*/
function multiAttestByDelegation(
MultiDelegatedAttestationRequest[] calldata multiDelegatedRequests
) external payable returns (bytes32[] memory);
/**
* @dev Revokes an existing attestation to a specific schema.
*
* Example:
*
* revoke({
* schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc',
* data: {
* uid: '0x101032e487642ee04ee17049f99a70590c735b8614079fc9275f9dd57c00966d',
* value: 0
* }
* })
*
* @param request The arguments of the revocation request.
*/
function revoke(RevocationRequest calldata request) external payable;
/**
* @dev Revokes an existing attestation to a specific schema via the provided EIP712 signature.
*
* Example:
*
* revokeByDelegation({
* schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc',
* data: {
* uid: '0xcbbc12102578c642a0f7b34fe7111e41afa25683b6cd7b5a14caf90fa14d24ba',
* value: 0
* },
* signature: {
* v: 27,
* r: '0xb593...7142',
* s: '0x0f5b...2cce'
* },
* revoker: '0x244934dd3e31bE2c81f84ECf0b3E6329F5381992'
* })
*
* @param delegatedRequest The arguments of the delegated revocation request.
*/
function revokeByDelegation(DelegatedRevocationRequest calldata delegatedRequest) external payable;
/**
* @dev Revokes existing attestations to multiple schemas.
*
* @param multiRequests The arguments of the multi revocation requests. The requests should be grouped by distinct
* schema ids to benefit from the best batching optimization.
*
* Example:
*
* multiRevoke([{
* schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc',
* data: [{
* uid: '0x211296a1ca0d7f9f2cfebf0daaa575bea9b20e968d81aef4e743d699c6ac4b25',
* value: 1000
* },
* {
* uid: '0xe160ac1bd3606a287b4d53d5d1d6da5895f65b4b4bab6d93aaf5046e48167ade',
* value: 0
* }],
* },
* {
* schema: '0x5ac273ce41e3c8bfa383efe7c03e54c5f0bff29c9f11ef6ffa930fc84ca32425',
* data: [{
* uid: '0x053d42abce1fd7c8fcddfae21845ad34dae287b2c326220b03ba241bc5a8f019',
* value: 0
* },
* }])
*/
function multiRevoke(MultiRevocationRequest[] calldata multiRequests) external payable;
/**
* @dev Revokes existing attestations to multiple schemas via provided EIP712 signatures.
*
* @param multiDelegatedRequests The arguments of the delegated multi revocation attestation requests. The requests should be
* grouped by distinct schema ids to benefit from the best batching optimization.
*
* Example:
*
* multiRevokeByDelegation([{
* schema: '0x8e72f5bc0a8d4be6aa98360baa889040c50a0e51f32dbf0baa5199bd93472ebc',
* data: [{
* uid: '0x211296a1ca0d7f9f2cfebf0daaa575bea9b20e968d81aef4e743d699c6ac4b25',
* value: 1000
* },
* {
* uid: '0xe160ac1bd3606a287b4d53d5d1d6da5895f65b4b4bab6d93aaf5046e48167ade',
* value: 0
* }],
* signatures: [{
* v: 28,
* r: '0x148c...b25b',
* s: '0x5a72...be22'
* },
* {
* v: 28,
* r: '0x487s...67bb',
* s: '0x12ad...2366'
* }],
* revoker: '0x244934dd3e31bE2c81f84ECf0b3E6329F5381992'
* }])
*
*/
function multiRevokeByDelegation(
MultiDelegatedRevocationRequest[] calldata multiDelegatedRequests
) external payable;
/**
* @dev Timestamps the specified bytes32 data.
*
* @param data The data to timestamp.
*
* @return The timestamp the data was timestamped with.
*/
function timestamp(bytes32 data) external returns (uint64);
/**
* @dev Timestamps the specified multiple bytes32 data.
*
* @param data The data to timestamp.
*
* @return The timestamp the data was timestamped with.
*/
function multiTimestamp(bytes32[] calldata data) external returns (uint64);
/**
* @dev Revokes the specified bytes32 data.
*
* @param data The data to timestamp.
*
* @return The timestamp the data was revoked with.
*/
function revokeOffchain(bytes32 data) external returns (uint64);
/**
* @dev Revokes the specified multiple bytes32 data.
*
* @param data The data to timestamp.
*
* @return The timestamp the data was revoked with.
*/
function multiRevokeOffchain(bytes32[] calldata data) external returns (uint64);
/**
* @dev Returns an existing attestation by UID.
*
* @param uid The UID of the attestation to retrieve.
*
* @return The attestation data members.
*/
function getAttestation(bytes32 uid) external view returns (Attestation memory);
/**
* @dev Checks whether an attestation exists.
*
* @param uid The UID of the attestation to retrieve.
*
* @return Whether an attestation exists.
*/
function isAttestationValid(bytes32 uid) external view returns (bool);
/**
* @dev Returns the timestamp that the specified data was timestamped with.
*
* @param data The data to query.
*
* @return The timestamp the data was timestamped with.
*/
function getTimestamp(bytes32 data) external view returns (uint64);
/**
* @dev Returns the timestamp that the specified data was timestamped with.
*
* @param data The data to query.
*
* @return The timestamp the data was timestamped with.
*/
function getRevokeOffchain(address revoker, bytes32 data) external view returns (uint64);
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { ISchemaResolver } from "./resolver/ISchemaResolver.sol";
/**
* @title A struct representing a record for a submitted schema.
*/
struct SchemaRecord {
bytes32 uid; // The unique identifier of the schema.
ISchemaResolver resolver; // Optional schema resolver.
bool revocable; // Whether the schema allows revocations explicitly.
string schema; // Custom specification of the schema (e.g., an ABI).
}
/// @title ISchemaRegistry
/// @notice The interface of global attestation schemas for the Ethereum Attestation Service protocol.
interface ISchemaRegistry {
/**
* @dev Emitted when a new schema has been registered
*
* @param uid The schema UID.
* @param registerer The address of the account used to register the schema.
*/
event Registered(bytes32 indexed uid, address registerer);
/**
* @dev Submits and reserves a new schema
*
* @param schema The schema data schema.
* @param resolver An optional schema resolver.
* @param revocable Whether the schema allows revocations explicitly.
*
* @return The UID of the new schema.
*/
function register(string calldata schema, ISchemaResolver resolver, bool revocable) external returns (bytes32);
/**
* @dev Returns an existing schema by UID
*
* @param uid The UID of the schema to retrieve.
*
* @return The schema data members.
*/
function getSchema(bytes32 uid) external view returns (SchemaRecord memory);
}
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;
import { Semver } from "../universal/Semver.sol";
import { ISchemaResolver } from "./resolver/ISchemaResolver.sol";
import { EMPTY_UID, MAX_GAP } from "./Common.sol";
import { ISchemaRegistry, SchemaRecord } from "./ISchemaRegistry.sol";
/// @custom:proxied
/// @custom:predeploy 0x4200000000000000000000000000000000000020
/// @title SchemaRegistry
/// @notice The global attestation schemas for the Ethereum Attestation Service protocol.
contract SchemaRegistry is ISchemaRegistry, Semver {
error AlreadyExists();
// The global mapping between schema records and their IDs.
mapping(bytes32 uid => SchemaRecord schemaRecord) private _registry;
// Upgrade forward-compatibility storage gap
uint256[MAX_GAP - 1] private __gap;
/**
* @dev Creates a new SchemaRegistry instance.
*/
constructor() Semver(1, 0, 0) {}
/**
* @inheritdoc ISchemaRegistry
*/
function register(string calldata schema, ISchemaResolver resolver, bool revocable) external returns (bytes32) {
SchemaRecord memory schemaRecord = SchemaRecord({
uid: EMPTY_UID,
schema: schema,
resolver: resolver,
revocable: revocable
});
bytes32 uid = _getUID(schemaRecord);
if (_registry[uid].uid != EMPTY_UID) {
revert AlreadyExists();
}
schemaRecord.uid = uid;
_registry[uid] = schemaRecord;
emit Registered(uid, msg.sender);
return uid;
}
/**
* @inheritdoc ISchemaRegistry
*/
function getSchema(bytes32 uid) external view returns (SchemaRecord memory) {
return _registry[uid];
}
/**
* @dev Calculates a UID for a given schema.
*
* @param schemaRecord The input schema.
*
* @return schema UID.
*/
function _getUID(SchemaRecord memory schemaRecord) private pure returns (bytes32) {
return keccak256(abi.encodePacked(schemaRecord.schema, schemaRecord.resolver, schemaRecord.revocable));
}
}
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;
import { EIP712 } from "@openzeppelin/contracts/utils/cryptography/draft-EIP712.sol";
import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
// prettier-ignore
import {
AttestationRequest,
AttestationRequestData,
DelegatedAttestationRequest,
DelegatedRevocationRequest,
RevocationRequest,
RevocationRequestData
} from "../IEAS.sol";
import { EIP712Signature, InvalidSignature, MAX_GAP, stringToBytes32, bytes32ToString } from "../Common.sol";
/// @title EIP712
/// @notice The EIP712 typed signatures verifier for EAS delegated attestations.
abstract contract EIP712Verifier is EIP712 {
// The hash of the data type used to relay calls to the attest function. It's the value of
// keccak256("Attest(bytes32 schema,address recipient,uint64 expirationTime,bool revocable,bytes32 refUID,bytes data,uint256 nonce)").
bytes32 private constant ATTEST_TYPEHASH = 0xdbfdf8dc2b135c26253e00d5b6cbe6f20457e003fd526d97cea183883570de61;
// The hash of the data type used to relay calls to the revoke function. It's the value of
// keccak256("Revoke(bytes32 schema,bytes32 uid,uint256 nonce)").
bytes32 private constant REVOKE_TYPEHASH = 0xa98d02348410c9c76735e0d0bb1396f4015ac2bb9615f9c2611d19d7a8a99650;
// The user readable name of the signing domain.
bytes32 private immutable _name;
// Replay protection nonces.
mapping(address => uint256) private _nonces;
// Upgrade forward-compatibility storage gap
uint256[MAX_GAP - 1] private __gap;
/**
* @dev Creates a new EIP712Verifier instance.
*
* @param version The current major version of the signing domain
*/
constructor(string memory name, string memory version) EIP712(name, version) {
_name = stringToBytes32(name);
}
/**
* @dev Returns the domain separator used in the encoding of the signatures for attest, and revoke.
*/
function getDomainSeparator() external view returns (bytes32) {
return _domainSeparatorV4();
}
/**
* @dev Returns the current nonce per-account.
*
* @param account The requested account.
*
* @return The current nonce.
*/
function getNonce(address account) external view returns (uint256) {
return _nonces[account];
}
/**
* Returns the EIP712 type hash for the attest function.
*/
function getAttestTypeHash() external pure returns (bytes32) {
return ATTEST_TYPEHASH;
}
/**
* Returns the EIP712 type hash for the revoke function.
*/
function getRevokeTypeHash() external pure returns (bytes32) {
return REVOKE_TYPEHASH;
}
/**
* Returns the EIP712 name.
*/
function getName() external view returns (string memory) {
return bytes32ToString(_name);
}
/**
* @dev Verifies delegated attestation request.
*
* @param request The arguments of the delegated attestation request.
*/
function _verifyAttest(DelegatedAttestationRequest memory request) internal {
AttestationRequestData memory data = request.data;
EIP712Signature memory signature = request.signature;
uint256 nonce;
unchecked {
nonce = _nonces[request.attester]++;
}
bytes32 digest = _hashTypedDataV4(
keccak256(
abi.encode(
ATTEST_TYPEHASH,
request.schema,
data.recipient,
data.expirationTime,
data.revocable,
data.refUID,
keccak256(data.data),
nonce
)
)
);
if (ECDSA.recover(digest, signature.v, signature.r, signature.s) != request.attester) {
revert InvalidSignature();
}
}
/**
* @dev Verifies delegated revocation request.
*
* @param request The arguments of the delegated revocation request.
*/
function _verifyRevoke(DelegatedRevocationRequest memory request) internal {
RevocationRequestData memory data = request.data;
EIP712Signature memory signature = request.signature;
uint256 nonce;
unchecked {
nonce = _nonces[request.revoker]++;
}
bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(REVOKE_TYPEHASH, request.schema, data.uid, nonce)));
if (ECDSA.recover(digest, signature.v, signature.r, signature.s) != request.revoker) {
revert InvalidSignature();
}
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { Attestation } from "../Common.sol";
/// @title ISchemaResolver
/// @notice The interface of an optional schema resolver.
interface ISchemaResolver {
/**
* @dev Returns whether the resolver supports ETH transfers.
*/
function isPayable() external pure returns (bool);
/**
* @dev Processes an attestation and verifies whether it's valid.
*
* @param attestation The new attestation.
*
* @return Whether the attestation is valid.
*/
function attest(Attestation calldata attestation) external payable returns (bool);
/**
* @dev Processes multiple attestations and verifies whether they are valid.
*
* @param attestations The new attestations.
* @param values Explicit ETH amounts which were sent with each attestation.
*
* @return Whether all the attestations are valid.
*/
function multiAttest(
Attestation[] calldata attestations,
uint256[] calldata values
) external payable returns (bool);
/**
* @dev Processes an attestation revocation and verifies if it can be revoked.
*
* @param attestation The existing attestation to be revoked.
*
* @return Whether the attestation can be revoked.
*/
function revoke(Attestation calldata attestation) external payable returns (bool);
/**
* @dev Processes revocation of multiple attestation and verifies they can be revoked.
*
* @param attestations The existing attestations to be revoked.
* @param values Explicit ETH amounts which were sent with each revocation.
*
* @return Whether the attestations can be revoked.
*/
function multiRevoke(
Attestation[] calldata attestations,
uint256[] calldata values
) external payable returns (bool);
}
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;
import { Semver } from "../../universal/Semver.sol";
import { IEAS, Attestation } from "../IEAS.sol";
import { InvalidEAS, uncheckedInc } from "../Common.sol";
import { ISchemaResolver } from "./ISchemaResolver.sol";
/// @title SchemaResolver
/// @notice The base schema resolver contract.
abstract contract SchemaResolver is ISchemaResolver, Semver {
error AccessDenied();
error InsufficientValue();
error NotPayable();
// The global EAS contract.
IEAS internal immutable _eas;
/**
* @dev Creates a new resolver.
*
* @param eas The address of the global EAS contract.
*/
constructor(IEAS eas) Semver(1, 0, 0) {
if (address(eas) == address(0)) {
revert InvalidEAS();
}
_eas = eas;
}
/**
* @dev Ensures that only the EAS contract can make this call.
*/
modifier onlyEAS() {
_onlyEAS();
_;
}
/**
* @inheritdoc ISchemaResolver
*/
function isPayable() public pure virtual returns (bool) {
return false;
}
/**
* @dev ETH callback.
*/
receive() external payable virtual {
if (!isPayable()) {
revert NotPayable();
}
}
/**
* @inheritdoc ISchemaResolver
*/
function attest(Attestation calldata attestation) external payable onlyEAS returns (bool) {
return onAttest(attestation, msg.value);
}
/**
* @inheritdoc ISchemaResolver
*/
function multiAttest(
Attestation[] calldata attestations,
uint256[] calldata values
) external payable onlyEAS returns (bool) {
uint256 length = attestations.length;
// We are keeping track of the remaining ETH amount that can be sent to resolvers and will keep deducting
// from it to verify that there isn't any attempt to send too much ETH to resolvers. Please note that unless
// some ETH was stuck in the contract by accident (which shouldn't happen in normal conditions), it won't be
// possible to send too much ETH anyway.
uint256 remainingValue = msg.value;
for (uint256 i = 0; i < length; i = uncheckedInc(i)) {
// Ensure that the attester/revoker doesn't try to spend more than available.
uint256 value = values[i];
if (value > remainingValue) {
revert InsufficientValue();
}
// Forward the attestation to the underlying resolver and revert in case it isn't approved.
if (!onAttest(attestations[i], value)) {
return false;
}
unchecked {
// Subtract the ETH amount, that was provided to this attestation, from the global remaining ETH amount.
remainingValue -= value;
}
}
return true;
}
/**
* @inheritdoc ISchemaResolver
*/
function revoke(Attestation calldata attestation) external payable onlyEAS returns (bool) {
return onRevoke(attestation, msg.value);
}
/**
* @inheritdoc ISchemaResolver
*/
function multiRevoke(
Attestation[] calldata attestations,
uint256[] calldata values
) external payable onlyEAS returns (bool) {
uint256 length = attestations.length;
// We are keeping track of the remaining ETH amount that can be sent to resolvers and will keep deducting
// from it to verify that there isn't any attempt to send too much ETH to resolvers. Please note that unless
// some ETH was stuck in the contract by accident (which shouldn't happen in normal conditions), it won't be
// possible to send too much ETH anyway.
uint256 remainingValue = msg.value;
for (uint256 i = 0; i < length; i = uncheckedInc(i)) {
// Ensure that the attester/revoker doesn't try to spend more than available.
uint256 value = values[i];
if (value > remainingValue) {
revert InsufficientValue();
}
// Forward the revocation to the underlying resolver and revert in case it isn't approved.
if (!onRevoke(attestations[i], value)) {
return false;
}
unchecked {
// Subtract the ETH amount, that was provided to this attestation, from the global remaining ETH amount.
remainingValue -= value;
}
}
return true;
}
/**
* @dev A resolver callback that should be implemented by child contracts.
*
* @param attestation The new attestation.
* @param value An explicit ETH amount that was sent to the resolver. Please note that this value is verified in
* both attest() and multiAttest() callbacks EAS-only callbacks and that in case of multi attestations, it'll
* usually hold that msg.value != value, since msg.value aggregated the sent ETH amounts for all the attestations
* in the batch.
*
* @return Whether the attestation is valid.
*/
function onAttest(Attestation calldata attestation, uint256 value) internal virtual returns (bool);
/**
* @dev Processes an attestation revocation and verifies if it can be revoked.
*
* @param attestation The existing attestation to be revoked.
* @param value An explicit ETH amount that was sent to the resolver. Please note that this value is verified in
* both revoke() and multiRevoke() callbacks EAS-only callbacks and that in case of multi attestations, it'll
* usually hold that msg.value != value, since msg.value aggregated the sent ETH amounts for all the attestations
* in the batch.
*
* @return Whether the attestation can be revoked.
*/
function onRevoke(Attestation calldata attestation, uint256 value) internal virtual returns (bool);
/**
* @dev Ensures that only the EAS contract can make this call.
*/
function _onlyEAS() private view {
if (msg.sender != address(_eas)) {
revert AccessDenied();
}
}
}
...@@ -71,4 +71,10 @@ library Predeploys { ...@@ -71,4 +71,10 @@ library Predeploys {
/// @notice Address of the GovernanceToken predeploy. /// @notice Address of the GovernanceToken predeploy.
address internal constant GOVERNANCE_TOKEN = 0x4200000000000000000000000000000000000042; address internal constant GOVERNANCE_TOKEN = 0x4200000000000000000000000000000000000042;
/// @notice Address of the SchemaRegistry predeploy.
address internal constant SCHEMA_REGISTRY = 0x4200000000000000000000000000000000000020;
/// @notice Address of the EAS predeploy.
address internal constant EAS = 0x4200000000000000000000000000000000000021;
} }
...@@ -46,5 +46,5 @@ ...@@ -46,5 +46,5 @@
"l2GenesisRegolithTimeOffset": "0x0", "l2GenesisRegolithTimeOffset": "0x0",
"faultGameAbsolutePrestate": 96, "faultGameAbsolutePrestate": 96,
"faultGameMaxDepth": 4, "faultGameMaxDepth": 4,
"faultGameMaxDuration": 604800 "faultGameMaxDuration": 120
} }
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
{
"abi": [
{
"inputs": [],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"inputs": [],
"name": "AlreadyExists",
"type": "error"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "bytes32",
"name": "uid",
"type": "bytes32"
},
{
"indexed": false,
"internalType": "address",
"name": "registerer",
"type": "address"
}
],
"name": "Registered",
"type": "event"
},
{
"inputs": [
{
"internalType": "bytes32",
"name": "uid",
"type": "bytes32"
}
],
"name": "getSchema",
"outputs": [
{
"components": [
{
"internalType": "bytes32",
"name": "uid",
"type": "bytes32"
},
{
"internalType": "contract ISchemaResolver",
"name": "resolver",
"type": "address"
},
{
"internalType": "bool",
"name": "revocable",
"type": "bool"
},
{
"internalType": "string",
"name": "schema",
"type": "string"
}
],
"internalType": "struct SchemaRecord",
"name": "",
"type": "tuple"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "string",
"name": "schema",
"type": "string"
},
{
"internalType": "contract ISchemaResolver",
"name": "resolver",
"type": "address"
},
{
"internalType": "bool",
"name": "revocable",
"type": "bool"
}
],
"name": "register",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "version",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
}
],
"address": "0x2545fa928d5d278cA75Fd47306e4a89096ff6403",
"args": [],
"bytecode": "0x60e060405234801561001057600080fd5b5060016080819052600060a081905260c081905280610b166100478239600060fe0152600060d50152600060ac0152610b166000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c806354fd4d501461004657806360d7a27814610064578063a2ea7c6e14610085575b600080fd5b61004e6100a5565b60405161005b9190610604565b60405180910390f35b61007761007236600461061e565b610148565b60405190815260200161005b565b6100986100933660046106d0565b6102f1565b60405161005b91906106e9565b60606100d07f0000000000000000000000000000000000000000000000000000000000000000610419565b6100f97f0000000000000000000000000000000000000000000000000000000000000000610419565b6101227f0000000000000000000000000000000000000000000000000000000000000000610419565b6040516020016101349392919061073a565b604051602081830303815290604052905090565b60008060405180608001604052806000801b81526020018573ffffffffffffffffffffffffffffffffffffffff168152602001841515815260200187878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920182905250939094525092935091506101ca905082610556565b60008181526020819052604090205490915015610213576040517f23369fa600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80825260008181526020818152604091829020845181559084015160018201805493860151151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00000000000000000000000000000000000000000090941673ffffffffffffffffffffffffffffffffffffffff9092169190911792909217909155606083015183919060028201906102af9082610881565b50506040513381528291507f7d917fcbc9a29a9705ff9936ffa599500e4fd902e4486bae317414fe967b307c9060200160405180910390a29695505050505050565b604080516080810182526000808252602082018190529181019190915260608082015260008281526020818152604091829020825160808101845281548152600182015473ffffffffffffffffffffffffffffffffffffffff8116938201939093527401000000000000000000000000000000000000000090920460ff16151592820192909252600282018054919291606084019190610390906107df565b80601f01602080910402602001604051908101604052809291908181526020018280546103bc906107df565b80156104095780601f106103de57610100808354040283529160200191610409565b820191906000526020600020905b8154815290600101906020018083116103ec57829003601f168201915b5050505050815250509050919050565b60608160000361045c57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156104865780610470816109ca565b915061047f9050600a83610a31565b9150610460565b60008167ffffffffffffffff8111156104a1576104a16107b0565b6040519080825280601f01601f1916602001820160405280156104cb576020820181803683370190505b5090505b841561054e576104e0600183610a45565b91506104ed600a86610a5e565b6104f8906030610a72565b60f81b81838151811061050d5761050d610a85565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610547600a86610a31565b94506104cf565b949350505050565b600081606001518260200151836040015160405160200161057993929190610ab4565b604051602081830303815290604052805190602001209050919050565b60005b838110156105b1578181015183820152602001610599565b50506000910152565b600081518084526105d2816020860160208601610596565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061061760208301846105ba565b9392505050565b6000806000806060858703121561063457600080fd5b843567ffffffffffffffff8082111561064c57600080fd5b818701915087601f83011261066057600080fd5b81358181111561066f57600080fd5b88602082850101111561068157600080fd5b6020928301965094505085013573ffffffffffffffffffffffffffffffffffffffff811681146106b057600080fd5b9150604085013580151581146106c557600080fd5b939692955090935050565b6000602082840312156106e257600080fd5b5035919050565b602081528151602082015273ffffffffffffffffffffffffffffffffffffffff60208301511660408201526040820151151560608201526000606083015160808084015261054e60a08401826105ba565b6000845161074c818460208901610596565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551610788816001850160208a01610596565b600192019182015283516107a3816002840160208801610596565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600181811c908216806107f357607f821691505b60208210810361082c577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f82111561087c57600081815260208120601f850160051c810160208610156108595750805b601f850160051c820191505b8181101561087857828155600101610865565b5050505b505050565b815167ffffffffffffffff81111561089b5761089b6107b0565b6108af816108a984546107df565b84610832565b602080601f83116001811461090257600084156108cc5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610878565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561094f57888601518255948401946001909101908401610930565b508582101561098b57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036109fb576109fb61099b565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082610a4057610a40610a02565b500490565b81810381811115610a5857610a5861099b565b92915050565b600082610a6d57610a6d610a02565b500690565b80820180821115610a5857610a5861099b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008451610ac6818460208901610596565b60609490941b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000169190930190815290151560f81b60148201526015019291505056fea164736f6c6343000813000a",
"deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100415760003560e01c806354fd4d501461004657806360d7a27814610064578063a2ea7c6e14610085575b600080fd5b61004e6100a5565b60405161005b9190610604565b60405180910390f35b61007761007236600461061e565b610148565b60405190815260200161005b565b6100986100933660046106d0565b6102f1565b60405161005b91906106e9565b60606100d07f0000000000000000000000000000000000000000000000000000000000000000610419565b6100f97f0000000000000000000000000000000000000000000000000000000000000000610419565b6101227f0000000000000000000000000000000000000000000000000000000000000000610419565b6040516020016101349392919061073a565b604051602081830303815290604052905090565b60008060405180608001604052806000801b81526020018573ffffffffffffffffffffffffffffffffffffffff168152602001841515815260200187878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920182905250939094525092935091506101ca905082610556565b60008181526020819052604090205490915015610213576040517f23369fa600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80825260008181526020818152604091829020845181559084015160018201805493860151151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00000000000000000000000000000000000000000090941673ffffffffffffffffffffffffffffffffffffffff9092169190911792909217909155606083015183919060028201906102af9082610881565b50506040513381528291507f7d917fcbc9a29a9705ff9936ffa599500e4fd902e4486bae317414fe967b307c9060200160405180910390a29695505050505050565b604080516080810182526000808252602082018190529181019190915260608082015260008281526020818152604091829020825160808101845281548152600182015473ffffffffffffffffffffffffffffffffffffffff8116938201939093527401000000000000000000000000000000000000000090920460ff16151592820192909252600282018054919291606084019190610390906107df565b80601f01602080910402602001604051908101604052809291908181526020018280546103bc906107df565b80156104095780601f106103de57610100808354040283529160200191610409565b820191906000526020600020905b8154815290600101906020018083116103ec57829003601f168201915b5050505050815250509050919050565b60608160000361045c57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156104865780610470816109ca565b915061047f9050600a83610a31565b9150610460565b60008167ffffffffffffffff8111156104a1576104a16107b0565b6040519080825280601f01601f1916602001820160405280156104cb576020820181803683370190505b5090505b841561054e576104e0600183610a45565b91506104ed600a86610a5e565b6104f8906030610a72565b60f81b81838151811061050d5761050d610a85565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610547600a86610a31565b94506104cf565b949350505050565b600081606001518260200151836040015160405160200161057993929190610ab4565b604051602081830303815290604052805190602001209050919050565b60005b838110156105b1578181015183820152602001610599565b50506000910152565b600081518084526105d2816020860160208601610596565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061061760208301846105ba565b9392505050565b6000806000806060858703121561063457600080fd5b843567ffffffffffffffff8082111561064c57600080fd5b818701915087601f83011261066057600080fd5b81358181111561066f57600080fd5b88602082850101111561068157600080fd5b6020928301965094505085013573ffffffffffffffffffffffffffffffffffffffff811681146106b057600080fd5b9150604085013580151581146106c557600080fd5b939692955090935050565b6000602082840312156106e257600080fd5b5035919050565b602081528151602082015273ffffffffffffffffffffffffffffffffffffffff60208301511660408201526040820151151560608201526000606083015160808084015261054e60a08401826105ba565b6000845161074c818460208901610596565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551610788816001850160208a01610596565b600192019182015283516107a3816002840160208801610596565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600181811c908216806107f357607f821691505b60208210810361082c577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f82111561087c57600081815260208120601f850160051c810160208610156108595750805b601f850160051c820191505b8181101561087857828155600101610865565b5050505b505050565b815167ffffffffffffffff81111561089b5761089b6107b0565b6108af816108a984546107df565b84610832565b602080601f83116001811461090257600084156108cc5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610878565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561094f57888601518255948401946001909101908401610930565b508582101561098b57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036109fb576109fb61099b565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082610a4057610a40610a02565b500490565b81810381811115610a5857610a5861099b565b92915050565b600082610a6d57610a6d610a02565b500690565b80820180821115610a5857610a5861099b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008451610ac6818460208901610596565b60609490941b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000169190930190815290151560f81b60148201526015019291505056fea164736f6c6343000813000a",
"devdoc": {
"version": 1,
"kind": "dev",
"methods": {
"constructor": {
"details": "Creates a new SchemaRegistry instance."
},
"getSchema(bytes32)": {
"details": "Returns an existing schema by UID",
"params": {
"uid": "The UID of the schema to retrieve."
},
"returns": {
"_0": "The schema data members."
}
},
"register(string,address,bool)": {
"details": "Submits and reserves a new schema",
"params": {
"resolver": "An optional schema resolver.",
"revocable": "Whether the schema allows revocations explicitly.",
"schema": "The schema data schema."
},
"returns": {
"_0": "The UID of the new schema."
}
},
"version()": {
"returns": {
"_0": "Semver contract version as a string."
}
}
},
"events": {
"Registered(bytes32,address)": {
"details": "Emitted when a new schema has been registered",
"params": {
"registerer": "The address of the account used to register the schema.",
"uid": "The schema UID."
}
}
},
"title": "SchemaRegistry"
},
"metadata": "{\"compiler\":{\"version\":\"0.8.19+commit.7dd6d404\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"type\":\"error\",\"name\":\"AlreadyExists\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\",\"indexed\":true},{\"internalType\":\"address\",\"name\":\"registerer\",\"type\":\"address\",\"indexed\":false}],\"type\":\"event\",\"name\":\"Registered\",\"anonymous\":false},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"getSchema\",\"outputs\":[{\"internalType\":\"struct SchemaRecord\",\"name\":\"\",\"type\":\"tuple\",\"components\":[{\"internalType\":\"bytes32\",\"name\":\"uid\",\"type\":\"bytes32\"},{\"internalType\":\"contract ISchemaResolver\",\"name\":\"resolver\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"revocable\",\"type\":\"bool\"},{\"internalType\":\"string\",\"name\":\"schema\",\"type\":\"string\"}]}]},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"schema\",\"type\":\"string\"},{\"internalType\":\"contract ISchemaResolver\",\"name\":\"resolver\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"revocable\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\",\"name\":\"register\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}]},{\"inputs\":[],\"stateMutability\":\"view\",\"type\":\"function\",\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}]}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"constructor\":{\"details\":\"Creates a new SchemaRegistry instance.\"},\"getSchema(bytes32)\":{\"details\":\"Returns an existing schema by UID\",\"params\":{\"uid\":\"The UID of the schema to retrieve.\"},\"returns\":{\"_0\":\"The schema data members.\"}},\"register(string,address,bool)\":{\"details\":\"Submits and reserves a new schema\",\"params\":{\"resolver\":\"An optional schema resolver.\",\"revocable\":\"Whether the schema allows revocations explicitly.\",\"schema\":\"The schema data schema.\"},\"returns\":{\"_0\":\"The UID of the new schema.\"}},\"version()\":{\"returns\":{\"_0\":\"Semver contract version as a string.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"version()\":{\"notice\":\"Returns the full semver contract version.\"}},\"version\":1}},\"settings\":{\"remappings\":[\":.ignored_clones-with-immutable-args/=node_modules/.ignored_clones-with-immutable-args/src/\",\":.ignored_forge-std/=node_modules/.ignored_forge-std/src/\",\":@cwia/=node_modules/clones-with-immutable-args/src/\",\":@openzeppelin/=node_modules/@openzeppelin/\",\":@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/\",\":@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/\",\":@rari-capital/=node_modules/@rari-capital/\",\":@rari-capital/solmate/=node_modules/@rari-capital/solmate/\",\":clones-with-immutable-args/=node_modules/clones-with-immutable-args/\",\":ds-test/=node_modules/ds-test/src/\",\":forge-std/=node_modules/forge-std/src/\"],\"optimizer\":{\"enabled\":true,\"runs\":999999},\"metadata\":{\"bytecodeHash\":\"none\"},\"compilationTarget\":{\"contracts/EAS/SchemaRegistry.sol\":\"SchemaRegistry\"},\"libraries\":{}},\"sources\":{\"contracts/EAS/Common.sol\":{\"keccak256\":\"0x922fda236f56fa813171ac1ae04d70d58763142ed084e36d29b369160f99acef\",\"urls\":[\"bzz-raw://82c6eb5ce50a0cfa28ad70fcd33fcd7f7704d538666127dc7aca32960423851b\",\"dweb:/ipfs/QmVQXmi9d7R4iks3rKNQKsq9HeuHZwpCg68jFbYGTw3VUs\"],\"license\":\"MIT\"},\"contracts/EAS/ISchemaRegistry.sol\":{\"keccak256\":\"0x456637ee808bb949d3941cd8b11581a7e7e0a92f304dbbf06fba320f27f57664\",\"urls\":[\"bzz-raw://372bc7f2fc72460daa5273200ac0d6b81427a23a65c8f5152a0f0fe2a47567d7\",\"dweb:/ipfs/QmSDDuVvp5nXaNDPzZbDMH1YE2nN4nrK8hEDctWds4wRah\"],\"license\":\"MIT\"},\"contracts/EAS/SchemaRegistry.sol\":{\"keccak256\":\"0x0cba1207d8986681585b65863a7cefd5cfc23e9e414d02baef027fca5cc8113d\",\"urls\":[\"bzz-raw://a5f62f15f3e977d1416af1cc4742e312d6f7c75a5ab533180695e02eb603d172\",\"dweb:/ipfs/QmPsyWTzKet3v4bfM7H8Eyz2uRRafz25Jxeqg9c6rKUDPH\"],\"license\":\"MIT\"},\"contracts/EAS/resolver/ISchemaResolver.sol\":{\"keccak256\":\"0x222f41e52e73c3edf2adcddd65c1c6911287b701b07413959a2f720778136135\",\"urls\":[\"bzz-raw://5b3fc66b38c358c3aa704aa3c22bfe7d48063f18529dbc6b61666d0609ffd658\",\"dweb:/ipfs/QmcHBVQzH4mTV1afqQrYw83kgknNETQ1brgWryBwN6u3mf\"],\"license\":\"MIT\"},\"contracts/universal/Semver.sol\":{\"keccak256\":\"0xc455c84bb1f17e994dea0451fd363f81f83965bfa86e81ac6c8b3a327b9a0ff0\",\"urls\":[\"bzz-raw://fab499f3c0d7df8eb763b50621848d5d2147fb9c42a8eb9b65a11093090bb482\",\"dweb:/ipfs/QmUKsG4ztwtUZFjuRYAxgUFTgH5YxWSGF1BFFaB7vdM2K3\"],\"license\":\"MIT\"},\"node_modules/@openzeppelin/contracts/utils/Strings.sol\":{\"keccak256\":\"0xaf159a8b1923ad2a26d516089bceca9bdeaeacd04be50983ea00ba63070f08a3\",\"urls\":[\"bzz-raw://6f2cf1c531122bc7ca96b8c8db6a60deae60441e5223065e792553d4849b5638\",\"dweb:/ipfs/QmPBdJmBBABMDCfyDjCbdxgiqRavgiSL88SYPGibgbPas9\"],\"license\":\"MIT\"}},\"version\":1}",
"numDeployments": 1,
"receipt": {
"transactionHash": "0xfcee65e070a73f09d30aeae275abb7ff11f0e6d7a950c6032b0fb7e0950a382c",
"transactionIndex": "0x1",
"blockHash": "0x9c59cce84fd9fdd418fa3b99cc22fc52b775eed30b3671ab644dbec7630ce162",
"blockNumber": "0xbaabdb",
"from": "0x18394B52d3Cb931dfA76F63251919D051953413d",
"to": null,
"cumulativeGasUsed": "0xad18a",
"gasUsed": "0xa1a55",
"contractAddress": "0x2545fa928d5d278cA75Fd47306e4a89096ff6403",
"logs": [],
"status": "0x1",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"type": "0x2",
"effectiveGasPrice": "0xb2d05e32"
},
"solcInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"storageLayout": {
"storage": [
{
"astId": 27112,
"contract": "contracts/EAS/SchemaRegistry.sol:SchemaRegistry",
"label": "_registry",
"offset": 0,
"slot": "0",
"type": "t_mapping(t_bytes32,t_struct(SchemaRecord)27057_storage)"
},
{
"astId": 27118,
"contract": "contracts/EAS/SchemaRegistry.sol:SchemaRegistry",
"label": "__gap",
"offset": 0,
"slot": "1",
"type": "t_array(t_uint256)49_storage"
}
],
"types": {
"t_array(t_uint256)49_storage": {
"encoding": "inplace",
"label": "uint256[49]",
"numberOfBytes": "1568",
"base": "t_uint256"
},
"t_bool": {
"encoding": "inplace",
"label": "bool",
"numberOfBytes": "1"
},
"t_bytes32": {
"encoding": "inplace",
"label": "bytes32",
"numberOfBytes": "32"
},
"t_contract(ISchemaResolver)27536": {
"encoding": "inplace",
"label": "contract ISchemaResolver",
"numberOfBytes": "20"
},
"t_mapping(t_bytes32,t_struct(SchemaRecord)27057_storage)": {
"encoding": "mapping",
"key": "t_bytes32",
"label": "mapping(bytes32 => struct SchemaRecord)",
"numberOfBytes": "32",
"value": "t_struct(SchemaRecord)27057_storage"
},
"t_string_storage": {
"encoding": "bytes",
"label": "string",
"numberOfBytes": "32"
},
"t_struct(SchemaRecord)27057_storage": {
"encoding": "inplace",
"label": "struct SchemaRecord",
"numberOfBytes": "96",
"members": [
{
"astId": 27049,
"contract": "contracts/EAS/SchemaRegistry.sol:SchemaRegistry",
"label": "uid",
"offset": 0,
"slot": "0",
"type": "t_bytes32"
},
{
"astId": 27052,
"contract": "contracts/EAS/SchemaRegistry.sol:SchemaRegistry",
"label": "resolver",
"offset": 0,
"slot": "1",
"type": "t_contract(ISchemaResolver)27536"
},
{
"astId": 27054,
"contract": "contracts/EAS/SchemaRegistry.sol:SchemaRegistry",
"label": "revocable",
"offset": 20,
"slot": "1",
"type": "t_bool"
},
{
"astId": 27056,
"contract": "contracts/EAS/SchemaRegistry.sol:SchemaRegistry",
"label": "schema",
"offset": 0,
"slot": "2",
"type": "t_string_storage"
}
]
},
"t_uint256": {
"encoding": "inplace",
"label": "uint256",
"numberOfBytes": "32"
}
}
},
"transactionHash": "0xfcee65e070a73f09d30aeae275abb7ff11f0e6d7a950c6032b0fb7e0950a382c",
"userdoc": {
"version": 1,
"kind": "user",
"methods": {
"version()": {
"notice": "Returns the full semver contract version."
}
},
"notice": "The global attestation schemas for the Ethereum Attestation Service protocol."
}
}
\ No newline at end of file
{ {
"name": "@eth-optimism/contracts-bedrock", "name": "@eth-optimism/contracts-bedrock",
"version": "0.15.0", "version": "0.16.0",
"description": "Contracts for Optimism Specs", "description": "Contracts for Optimism Specs",
"license": "MIT", "license": "MIT",
"files": [ "files": [
...@@ -31,10 +31,10 @@ ...@@ -31,10 +31,10 @@
"clean": "rm -rf ./dist ./artifacts ./forge-artifacts ./cache ./tsconfig.tsbuildinfo ./tsconfig.build.tsbuildinfo ./src/contract-artifacts.ts ./test-case-generator/fuzz", "clean": "rm -rf ./dist ./artifacts ./forge-artifacts ./cache ./tsconfig.tsbuildinfo ./tsconfig.build.tsbuildinfo ./src/contract-artifacts.ts ./test-case-generator/fuzz",
"lint:ts:check": "eslint . --max-warnings=0", "lint:ts:check": "eslint . --max-warnings=0",
"lint:forge-tests:check": "ts-node scripts/forge-test-names.ts", "lint:forge-tests:check": "ts-node scripts/forge-test-names.ts",
"lint:contracts:check": "pnpm solhint -f table 'contracts/**/!(DisputeTypes|RLPReader).sol' && pnpm prettier --check 'contracts/**/!(DisputeTypes|RLPReader).sol' && pnpm lint:forge-tests:check", "lint:contracts:check": "pnpm solhint -f table 'contracts/**/!(DisputeTypes|RLPReader|EAS|SchemaRegistry|IEAS|ISchemaRegistry|SchemaResolver|EIP712Verifier|ISchemaResolver).sol' && pnpm prettier --check 'contracts/**/!(DisputeTypes|RLPReader|EAS|SchemaRegistry|IEAS|ISchemaRegistry|SchemaResolver|EIP712Verifier|ISchemaResolver).sol' && pnpm lint:forge-tests:check",
"lint:check": "pnpm lint:contracts:check && pnpm lint:ts:check", "lint:check": "pnpm lint:contracts:check && pnpm lint:ts:check",
"lint:ts:fix": "eslint --fix .", "lint:ts:fix": "eslint --fix .",
"lint:contracts:fix": "pnpm solhint --fix 'contracts/**/!(DisputeTypes|RLPReader).sol' && pnpm prettier --write 'contracts/**/!(DisputeTypes|RLPReader).sol'", "lint:contracts:fix": "pnpm solhint --fix 'contracts/**/!(DisputeTypes|RLPReader|EAS|SchemaRegistry|IEAS|ISchemaRegistry|SchemaResolver|EIP712Verifier|ISchemaResolver).sol' && pnpm prettier --write 'contracts/**/!(DisputeTypes|RLPReader|EAS|SchemaRegistry|IEAS|ISchemaRegistry|SchemaResolver|EIP712Verifier|ISchemaResolver).sol'",
"lint:fix": "pnpm lint:contracts:fix && pnpm lint:ts:fix", "lint:fix": "pnpm lint:contracts:fix && pnpm lint:ts:fix",
"lint": "pnpm lint:fix && pnpm lint:check" "lint": "pnpm lint:fix && pnpm lint:check"
}, },
......
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
pragma solidity 0.8.15; pragma solidity ^0.8.0;
import { Script } from "forge-std/Script.sol"; import { Script } from "forge-std/Script.sol";
import { Test } from "forge-std/Test.sol"; import { Test } from "forge-std/Test.sol";
......
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
pragma solidity 0.8.15; pragma solidity ^0.8.0;
import { Script } from "forge-std/Script.sol"; import { Script } from "forge-std/Script.sol";
import { console2 as console } from "forge-std/console2.sol"; import { console2 as console } from "forge-std/console2.sol";
...@@ -44,14 +44,18 @@ contract DeployConfig is Script { ...@@ -44,14 +44,18 @@ contract DeployConfig is Script {
uint256 public gasPriceOracleScalar; uint256 public gasPriceOracleScalar;
uint256 public eip1559Denominator; uint256 public eip1559Denominator;
uint256 public eip1559Elasticity; uint256 public eip1559Elasticity;
uint256 public l2GenesisRegolithTimeOffset;
uint256 public faultGameAbsolutePrestate; uint256 public faultGameAbsolutePrestate;
uint256 public faultGameMaxDepth; uint256 public faultGameMaxDepth;
uint256 public faultGameMaxDuration; uint256 public faultGameMaxDuration;
constructor(string memory _path) { constructor(string memory _path) {
console.log("DeployConfig: reading file %s", _path); console.log("DeployConfig: reading file %s", _path);
_json = vm.readFile(_path); try vm.readFile(_path) returns (string memory data) {
_json = data;
} catch {
console.log("Warning: unable to read config. Do not deploy unless you are not using config.");
return;
}
finalSystemOwner = stdJson.readAddress(_json, "$.finalSystemOwner"); finalSystemOwner = stdJson.readAddress(_json, "$.finalSystemOwner");
controller = stdJson.readAddress(_json, "$.controller"); controller = stdJson.readAddress(_json, "$.controller");
...@@ -84,7 +88,6 @@ contract DeployConfig is Script { ...@@ -84,7 +88,6 @@ contract DeployConfig is Script {
gasPriceOracleScalar = stdJson.readUint(_json, "$.gasPriceOracleScalar"); gasPriceOracleScalar = stdJson.readUint(_json, "$.gasPriceOracleScalar");
eip1559Denominator = stdJson.readUint(_json, "$.eip1559Denominator"); eip1559Denominator = stdJson.readUint(_json, "$.eip1559Denominator");
eip1559Elasticity = stdJson.readUint(_json, "$.eip1559Elasticity"); eip1559Elasticity = stdJson.readUint(_json, "$.eip1559Elasticity");
l2GenesisRegolithTimeOffset = stdJson.readUint(_json, "$.l2GenesisRegolithTimeOffset");
if (block.chainid == 900) { if (block.chainid == 900) {
faultGameAbsolutePrestate = stdJson.readUint(_json, "$.faultGameAbsolutePrestate"); faultGameAbsolutePrestate = stdJson.readUint(_json, "$.faultGameAbsolutePrestate");
......
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { Deployer } from "./Deployer.sol";
import { DeployConfig } from "./DeployConfig.s.sol";
import { console2 as console } from "forge-std/console2.sol";
import { EAS } from "../contracts/EAS/EAS.sol";
import { SchemaRegistry } from "../contracts/EAS/SchemaRegistry.sol";
import { ISchemaRegistry } from "../contracts/EAS/ISchemaRegistry.sol";
import { Predeploys } from "../contracts/libraries/Predeploys.sol";
/// @title DeployL2
/// @notice Script used to deploy predeploy implementations to L2.
contract DeployL2 is Deployer {
DeployConfig cfg;
/// @notice The name of the script, used to ensure the right deploy artifacts
/// are used.
function name() public pure override returns (string memory) {
return "DeployL2";
}
function setUp() public override {
super.setUp();
string memory path = string.concat(vm.projectRoot(), "/deploy-config/", deploymentContext, ".json");
cfg = new DeployConfig(path);
console.log("Deploying from %s", deployScript);
console.log("Deployment context: %s", deploymentContext);
}
/// @notice Modifier that wraps a function in broadcasting.
modifier broadcast() {
vm.startBroadcast();
_;
vm.stopBroadcast();
}
/// @notice Deploy the EAS implementation.
function deployEAS() broadcast() public returns (address) {
EAS eas = new EAS();
ISchemaRegistry registry = eas.getSchemaRegistry();
require(address(registry) == Predeploys.SCHEMA_REGISTRY, "EAS: invalid SchemaRegistry address");
save("EAS", address(eas));
console.log("EAS deployed at %s", address(eas));
string memory version = eas.version();
console.log("EAS version: %s", version);
return address(eas);
}
/// @notice Deploy the SchemaManager implementation.
function deploySchemaRegistry() broadcast() public returns (address) {
SchemaRegistry registry = new SchemaRegistry();
save("SchemaRegistry", address(registry));
console.log("SchemaRegistry deployed at %s", address(registry));
string memory version = registry.version();
console.log("SchemaRegistry version: %s", version);
return address(registry);
}
}
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
pragma solidity 0.8.15; pragma solidity ^0.8.0;
import { Script } from "forge-std/Script.sol"; import { Script } from "forge-std/Script.sol";
import { stdJson } from "forge-std/StdJson.sol"; import { stdJson } from "forge-std/StdJson.sol";
...@@ -97,19 +97,19 @@ abstract contract Deployer is Script { ...@@ -97,19 +97,19 @@ abstract contract Deployer is Script {
function sync() public { function sync() public {
Deployment[] memory deployments = _getTempDeployments(); Deployment[] memory deployments = _getTempDeployments();
console.log("Syncing %s deployments", deployments.length); console.log("Syncing %s deployments", deployments.length);
console.log("Using deployment artifact %s", deployPath);
for (uint256 i; i < deployments.length; i++) { for (uint256 i; i < deployments.length; i++) {
address addr = deployments[i].addr; address addr = deployments[i].addr;
string memory deploymentName = deployments[i].name; string memory deploymentName = deployments[i].name;
string memory deployTx = _getDeployTransactionByContractAddress(addr); string memory deployTx = _getDeployTransactionByContractAddress(addr);
string memory contractName = stdJson.readString(deployTx, ".contractName"); string memory contractName = _getContractNameFromDeployTransaction(deployTx);
console.log("Syncing %s", deploymentName); console.log("Syncing deployment %s: contract %s", deploymentName, contractName);
string memory fqn = getFullyQualifiedName(contractName);
string[] memory args = getDeployTransactionConstructorArguments(deployTx); string[] memory args = getDeployTransactionConstructorArguments(deployTx);
bytes memory code = vm.getCode(fqn); bytes memory code = _getCode(contractName);
bytes memory deployedCode = vm.getDeployedCode(fqn); bytes memory deployedCode = _getDeployedCode(contractName);
string memory receipt = _getDeployReceiptByContractAddress(addr); string memory receipt = _getDeployReceiptByContractAddress(addr);
string memory artifactPath = string.concat(deploymentsDir, "/", deploymentName, ".json"); string memory artifactPath = string.concat(deploymentsDir, "/", deploymentName, ".json");
...@@ -119,6 +119,7 @@ abstract contract Deployer is Script { ...@@ -119,6 +119,7 @@ abstract contract Deployer is Script {
numDeployments = stdJson.readUint(string(res), "$.numDeployments"); numDeployments = stdJson.readUint(string(res), "$.numDeployments");
vm.removeFile(artifactPath); vm.removeFile(artifactPath);
} catch {} } catch {}
numDeployments++;
Artifact memory artifact = Artifact({ Artifact memory artifact = Artifact({
abi: getAbi(contractName), abi: getAbi(contractName),
...@@ -261,6 +262,36 @@ abstract contract Deployer is Script { ...@@ -261,6 +262,36 @@ abstract contract Deployer is Script {
return string(res); return string(res);
} }
/// @notice Returns the contract name from a deploy transaction.
function _getContractNameFromDeployTransaction(string memory _deployTx) internal returns (string memory) {
return stdJson.readString(_deployTx, ".contractName");
}
/// @notice Wrapper for vm.getCode that handles semver in the name.
function _getCode(string memory _name) internal returns (bytes memory) {
string memory fqn = _getFullyQualifiedName(_name);
bytes memory code = vm.getCode(fqn);
return code;
}
/// @notice Wrapper for vm.getDeployedCode that handles semver in the name.
function _getDeployedCode(string memory _name) internal returns (bytes memory) {
string memory fqn = _getFullyQualifiedName(_name);
bytes memory code = vm.getDeployedCode(fqn);
return code;
}
/// @notice Removes the semantic versioning from a contract name. The semver will exist if the contract is compiled more than
/// once with different versions of the compiler.
function _stripSemver(string memory _name) internal returns (string memory) {
string[] memory cmd = new string[](3);
cmd[0] = Executables.bash;
cmd[1] = "-c";
cmd[2] = string.concat(Executables.echo, " ", _name, " | ", Executables.sed, " -E 's/[.][0-9]+\\.[0-9]+\\.[0-9]+//g'");
bytes memory res = vm.ffi(cmd);
return string(res);
}
/// @notice Returns the constructor arguent of a deployment transaction given a transaction json. /// @notice Returns the constructor arguent of a deployment transaction given a transaction json.
function getDeployTransactionConstructorArguments(string memory _transaction) internal returns (string[] memory) { function getDeployTransactionConstructorArguments(string memory _transaction) internal returns (string[] memory) {
string[] memory cmd = new string[](3); string[] memory cmd = new string[](3);
...@@ -277,9 +308,10 @@ abstract contract Deployer is Script { ...@@ -277,9 +308,10 @@ abstract contract Deployer is Script {
} }
/// @notice Builds the fully qualified name of a contract. Assumes that the /// @notice Builds the fully qualified name of a contract. Assumes that the
/// file name is the same as the contract name. /// file name is the same as the contract name but strips semver for the file name.
function getFullyQualifiedName(string memory _name) internal pure returns (string memory) { function _getFullyQualifiedName(string memory _name) internal returns (string memory) {
return string.concat(_name, ".sol:", _name); string memory sanitized = _stripSemver(_name);
return string.concat(sanitized, ".sol:", _name);
} }
/// @notice Returns the filesystem path to the artifact path. Assumes that the name of the /// @notice Returns the filesystem path to the artifact path. Assumes that the name of the
...@@ -290,7 +322,8 @@ abstract contract Deployer is Script { ...@@ -290,7 +322,8 @@ abstract contract Deployer is Script {
cmd[1] = "-c"; cmd[1] = "-c";
cmd[2] = string.concat(Executables.forge, " config --json | ", Executables.jq, " -r .out"); cmd[2] = string.concat(Executables.forge, " config --json | ", Executables.jq, " -r .out");
bytes memory res = vm.ffi(cmd); bytes memory res = vm.ffi(cmd);
string memory forgeArtifactPath = string.concat(vm.projectRoot(), "/", string(res), "/", _name, ".sol/", _name, ".json"); string memory contractName = _stripSemver(_name);
string memory forgeArtifactPath = string.concat(vm.projectRoot(), "/", string(res), "/", contractName, ".sol/", _name, ".json");
return forgeArtifactPath; return forgeArtifactPath;
} }
......
...@@ -8,4 +8,6 @@ library Executables { ...@@ -8,4 +8,6 @@ library Executables {
string internal constant bash = "bash"; string internal constant bash = "bash";
string internal constant jq = "jq"; string internal constant jq = "jq";
string internal constant forge = "forge"; string internal constant forge = "forge";
string internal constant echo = "echo";
string internal constant sed = "sed";
} }
...@@ -52,9 +52,24 @@ abstract contract SafeBuilder is EnhancedScript, GlobalConstants { ...@@ -52,9 +52,24 @@ abstract contract SafeBuilder is EnhancedScript, GlobalConstants {
// Core Logic // // Core Logic //
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
function run() public returns (bool) {
address safe;
address proxyAdmin;
if (block.chainid == OP_GOERLI) {
safe = 0xE534ccA2753aCFbcDBCeB2291F596fc60495257e;
proxyAdmin = 0x4200000000000000000000000000000000000018;
}
return run(safe, proxyAdmin);
}
/// @notice The entrypoint to this script. /// @notice The entrypoint to this script.
function run(address _safe, address _proxyAdmin) public returns (bool) { function run(address _safe, address _proxyAdmin) public returns (bool) {
require(_safe != address(0), "Safe address undefined");
require(_proxyAdmin != address(0), "ProxyAdminAddress undefined");
console.log("Using Safe: %s", _safe);
console.log("Using ProxyAdmin: %s", _proxyAdmin);
vm.startBroadcast(); vm.startBroadcast();
bool success = _run(_safe, _proxyAdmin); bool success = _run(_safe, _proxyAdmin);
if (success) _postCheck(); if (success) _postCheck();
......
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { console2 as console } from "forge-std/console2.sol";
import { SafeBuilder } from "../universal/SafeBuilder.sol";
import { IGnosisSafe, Enum } from "../interfaces/IGnosisSafe.sol";
import { IMulticall3 } from "forge-std/interfaces/IMulticall3.sol";
import { Predeploys } from "../../contracts/libraries/Predeploys.sol";
import { ProxyAdmin } from "../../contracts/universal/ProxyAdmin.sol";
import { Deployer } from "../Deployer.sol";
/// @title EASUpgrader
/// @notice Upgrades the EAS predeploys.
contract EASUpgrader is SafeBuilder, Deployer {
/// @notice The proxy admin predeploy on L2.
ProxyAdmin immutable PROXY_ADMIN = ProxyAdmin(Predeploys.PROXY_ADMIN);
/// @notice Represents the EAS contracts predeploys
struct ContractSet {
address EAS;
address SchemaRegistry;
}
/// @notice A mapping of chainid to a ContractSet of implementations.
mapping(uint256 => ContractSet) internal implementations;
/// @notice A mapping of chainid to ContractSet of proxy addresses.
mapping(uint256 => ContractSet) internal proxies;
/// @notice The expected versions for the contracts to be upgraded to.
string constant internal EAS_Version = "1.0.0";
string constant internal SchemaRegistry_Version = "1.0.0";
/// @notice Place the contract addresses in storage so they can be used when building calldata.
function setUp() public override {
super.setUp();
implementations[OP_GOERLI] = ContractSet({
EAS: getAddress("EAS"),
SchemaRegistry: getAddress("SchemaRegistry")
});
proxies[OP_GOERLI] = ContractSet({
EAS: Predeploys.EAS,
SchemaRegistry: Predeploys.SCHEMA_REGISTRY
});
}
/// @notice
function name() public override pure returns (string memory) {
return "EASUpgrader";
}
/// @notice Follow up assertions to ensure that the script ran to completion.
function _postCheck() internal override view {
ContractSet memory prox = getProxies();
require(_versionHash(prox.EAS) == keccak256(bytes(EAS_Version)), "EAS");
require(_versionHash(prox.SchemaRegistry) == keccak256(bytes(SchemaRegistry_Version)), "SchemaRegistry");
// Check that the codehashes of all implementations match the proxies set implementations.
ContractSet memory impl = getImplementations();
require(PROXY_ADMIN.getProxyImplementation(prox.EAS).codehash == impl.EAS.codehash);
require(PROXY_ADMIN.getProxyImplementation(prox.SchemaRegistry).codehash == impl.SchemaRegistry.codehash);
}
/// @notice Test coverage of the logic. Should only run on goerli but other chains
/// could be added.
function test_script_succeeds() skipWhenNotForking external {
address _safe;
address _proxyAdmin;
if (block.chainid == OP_GOERLI) {
_safe = 0xE534ccA2753aCFbcDBCeB2291F596fc60495257e;
_proxyAdmin = 0x4200000000000000000000000000000000000018;
}
require(_safe != address(0) && _proxyAdmin != address(0));
address[] memory owners = IGnosisSafe(payable(_safe)).getOwners();
for (uint256 i; i < owners.length; i++) {
address owner = owners[i];
vm.startBroadcast(owner);
bool success = _run(_safe, _proxyAdmin);
vm.stopBroadcast();
if (success) {
console.log("tx success");
break;
}
}
_postCheck();
}
/// @notice Builds the calldata that the multisig needs to make for the upgrade to happen.
/// A total of 9 calls are made to the proxy admin to upgrade the implementations
/// of the predeploys.
function buildCalldata(address _proxyAdmin) internal override view returns (bytes memory) {
IMulticall3.Call3[] memory calls = new IMulticall3.Call3[](2);
ContractSet memory impl = getImplementations();
ContractSet memory prox = getProxies();
// Upgrade EAS
calls[0] = IMulticall3.Call3({
target: _proxyAdmin,
allowFailure: false,
callData: abi.encodeCall(
ProxyAdmin.upgrade,
(payable(prox.EAS), impl.EAS)
)
});
// Upgrade SchemaRegistry
calls[1] = IMulticall3.Call3({
target: _proxyAdmin,
allowFailure: false,
callData: abi.encodeCall(
ProxyAdmin.upgrade,
(payable(prox.SchemaRegistry), impl.SchemaRegistry)
)
});
return abi.encodeCall(IMulticall3.aggregate3, (calls));
}
/// @notice Returns the ContractSet that represents the implementations for a given network.
function getImplementations() internal view returns (ContractSet memory) {
ContractSet memory set = implementations[block.chainid];
require(set.EAS != address(0), "no implementations for this network");
return set;
}
/// @notice Returns the ContractSet that represents the proxies for a given network.
function getProxies() internal view returns (ContractSet memory) {
ContractSet memory set = proxies[block.chainid];
require(set.EAS != address(0), "no proxies for this network");
return set;
}
}
# @eth-optimism/core-utils # @eth-optimism/core-utils
## 0.12.2
### Patch Changes
- [#6164](https://github.com/ethereum-optimism/optimism/pull/6164) [`c11039060`](https://github.com/ethereum-optimism/optimism/commit/c11039060bc037a88916c2cba602687b6d69ad1a) Thanks [@pengin7384](https://github.com/pengin7384)! - fix typo
- [#6198](https://github.com/ethereum-optimism/optimism/pull/6198) [`77da6edc6`](https://github.com/ethereum-optimism/optimism/commit/77da6edc643e0b5e39f7b6bb41c3c7ead418a876) Thanks [@tremarkley](https://github.com/tremarkley)! - Delete dead typescript https://github.com/ethereum-optimism/optimism/pull/6148.
## 0.12.1 ## 0.12.1
### Patch Changes ### Patch Changes
......
{ {
"name": "@eth-optimism/core-utils", "name": "@eth-optimism/core-utils",
"version": "0.12.1", "version": "0.12.2",
"description": "[Optimism] Core typescript utilities", "description": "[Optimism] Core typescript utilities",
"main": "dist/index", "main": "dist/index",
"types": "dist/index", "types": "dist/index",
......
ignores: [
"@babel/eslint-parser",
"@typescript-eslint/parser",
"eslint-plugin-import",
"eslint-plugin-unicorn",
"eslint-plugin-jsdoc",
"eslint-plugin-prefer-arrow",
"eslint-plugin-react",
"@typescript-eslint/eslint-plugin",
"eslint-config-prettier",
"eslint-plugin-prettier",
"chai"
]
# URL for an L1 RPC provider, used to query L2 output proposals
FAULT_DETECTOR__L1_RPC_PROVIDER=
# URL for an L2 RPC provider, used to query canonical L2 state
FAULT_DETECTOR__L2_RPC_PROVIDER=
module.exports = {
extends: '../../.eslintrc.js',
}
module.exports = {
...require('../../.prettierrc.js'),
};
# @eth-optimism/fault-detector
## 1.0.0
### Major Changes
- 119754c2f: Make optimism/sdk default to bedrock mode
### Patch Changes
- 16ccbee24: Fix false error to warning
- 685addec2: Add better source maps and developer support
- Updated dependencies [8d7dcc70c]
- Updated dependencies [119754c2f]
- Updated dependencies [d6388be4a]
- @eth-optimism/core-utils@0.12.1
- @eth-optimism/sdk@3.0.0
- @eth-optimism/common-ts@0.8.2
## 0.6.4
### Patch Changes
- Updated dependencies [a1b7ff9e3]
- Updated dependencies [8133872ed]
- Updated dependencies [afc2ab8c9]
- Updated dependencies [5063a69fb]
- Updated dependencies [aa854bdd8]
- @eth-optimism/sdk@2.1.0
- @eth-optimism/contracts@0.6.0
## 0.6.3
### Patch Changes
- dbe5eb308: Empty patch release to re-release packages that failed to be released by a bug in the release process.
- Updated dependencies [be3315689]
- @eth-optimism/sdk@2.0.2
## 0.6.2
### Patch Changes
- f9b579d55: Fixes a bug that would cause the fault detector to error out if no outputs had been proposed yet.
- Updated dependencies [fecd42d67]
- Updated dependencies [66cafc00a]
- @eth-optimism/common-ts@0.8.1
- @eth-optimism/sdk@2.0.1
## 0.6.1
### Patch Changes
- Updated dependencies [cb19e2f9c]
- @eth-optimism/sdk@2.0.0
## 0.6.0
### Minor Changes
- b004d1ad4: Updates the fault detector to support Bedrock networks.
### Patch Changes
- Updated dependencies [0e179781b]
- Updated dependencies [5372c9f5b]
- Updated dependencies [4ae94b412]
- @eth-optimism/common-ts@0.8.0
- @eth-optimism/sdk@1.10.2
## 0.5.0
### Minor Changes
- 9b2891852: Refactors BaseServiceV2 slightly, merges standard options with regular options
### Patch Changes
- ab8ec365c: Updates BaseServiceV2 so that options are secret by default. Services will have to explicitly mark options as "public" for those options to be logged and included in the metadata metric.
- c6c9c7dbf: Fault detector will now wait for providers to be connected
- Updated dependencies [e23f60f63]
- Updated dependencies [ab8ec365c]
- Updated dependencies [ba8b94a60]
- Updated dependencies [9b2891852]
- Updated dependencies [d1f9098f9]
- Updated dependencies [c6c9c7dbf]
- Updated dependencies [ffcee1013]
- Updated dependencies [eceb0de1d]
- @eth-optimism/common-ts@0.7.0
- @eth-optimism/sdk@1.9.0
- @eth-optimism/contracts@0.5.40
## 0.4.0
### Minor Changes
- ab5c1b897: Includes a new event caching mechanism for running the fault detector against Geth.
### Patch Changes
- 1d3c749a2: Bumps the version of ts-node used
- Updated dependencies [1d3c749a2]
- Updated dependencies [767585b07]
- Updated dependencies [c975c9620]
- Updated dependencies [1d3c749a2]
- Updated dependencies [136ea1785]
- @eth-optimism/contracts@0.5.39
- @eth-optimism/sdk@1.8.0
- @eth-optimism/core-utils@0.12.0
- @eth-optimism/common-ts@0.6.8
## 0.3.2
### Patch Changes
- 97b5f578c: Fixes how versions are imported for BaseServiceV2 services
- @eth-optimism/sdk@1.6.11
## 0.3.1
### Patch Changes
- Updated dependencies [1e76cdb86]
- @eth-optimism/core-utils@0.11.0
- @eth-optimism/common-ts@0.6.7
- @eth-optimism/contracts@0.5.38
- @eth-optimism/sdk@1.6.10
## 0.3.0
### Minor Changes
- 4a5e1832: Updates metrics to use better labels.
### Patch Changes
- Updated dependencies [e2faaa8b]
- @eth-optimism/sdk@1.6.5
## 0.2.7
### Patch Changes
- 7215f4ce: Bump ethers to 5.7.0 globally
- 17999a54: Adds a fault status API to the Fault Detector.
- 2f058b84: Fixes a small bug in the fault detector that would cause errors for testnets where the fault proof window is extremely short.
- Updated dependencies [7215f4ce]
- Updated dependencies [206f6033]
- Updated dependencies [d7679ca4]
- @eth-optimism/common-ts@0.6.5
- @eth-optimism/contracts@0.5.36
- @eth-optimism/core-utils@0.10.1
- @eth-optimism/sdk@1.6.4
## 0.2.6
### Patch Changes
- Updated dependencies [b27d0fa7]
- Updated dependencies [dbfea116]
- Updated dependencies [299157e7]
- @eth-optimism/sdk@1.6.1
- @eth-optimism/core-utils@0.10.0
- @eth-optimism/contracts@0.5.34
- @eth-optimism/common-ts@0.6.4
## 0.2.5
### Patch Changes
- 98206b7e: Properly handle connection failures for L2 node
## 0.2.4
### Patch Changes
- 89d01f2e: Update dev deps
- Updated dependencies [6e3449ba]
- Updated dependencies [f9fee446]
- @eth-optimism/contracts@0.5.30
- @eth-optimism/core-utils@0.9.1
- @eth-optimism/sdk@1.2.1
- @eth-optimism/common-ts@0.6.1
## 0.2.3
### Patch Changes
- 977493bc: Update SDK version and usage to account for new constructor
- 2296cf81: Fix bug where FD would try to sync beyond local tip
- Updated dependencies [977493bc]
- Updated dependencies [700dcbb0]
- Updated dependencies [3d1cb720]
- @eth-optimism/sdk@1.2.0
- @eth-optimism/core-utils@0.9.0
- @eth-optimism/common-ts@0.6.0
- @eth-optimism/contracts@0.5.29
## 0.2.2
### Patch Changes
- Updated dependencies [cb71fcde]
- Updated dependencies [10e41522]
- @eth-optimism/common-ts@0.5.0
## 0.2.1
### Patch Changes
- 29ff7462: Revert es target back to 2017
- Updated dependencies [27234f68]
- Updated dependencies [c201f3f1]
- Updated dependencies [29ff7462]
- Updated dependencies [52b26878]
- @eth-optimism/contracts@0.5.28
- @eth-optimism/common-ts@0.4.0
- @eth-optimism/core-utils@0.8.7
- @eth-optimism/sdk@1.1.9
## 0.2.0
### Minor Changes
- 84a8934c: BaseServiceV2 exposes service name and version as standard synthetic metric
### Patch Changes
- 37dfe4f6: Smarter starting height for fault-detector
- 6fe58eb2: Fix order in which a metric was bumped then emitted to fix off by one issue
- Updated dependencies [d9e39931]
- Updated dependencies [84a8934c]
- @eth-optimism/common-ts@0.3.0
## 0.1.1
### Patch Changes
- d18ae135: Updates all ethers versions in response to BN.js bug
- Updated dependencies [f16383f2]
- Updated dependencies [d18ae135]
- @eth-optimism/common-ts@0.2.8
- @eth-optimism/core-utils@0.8.5
- @eth-optimism/sdk@1.1.6
## 0.1.0
### Minor Changes
- 2177c8ef: Releases the first public version of the fault detector
### Patch Changes
- @eth-optimism/sdk@1.1.4
(The MIT License)
Copyright 2020-2021 Optimism
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# --l1rpcprovider Provider for interacting with L1 (env: FAULT_DETECTOR__L1_RPC_PROVIDER)
FAULT_DETECTOR__L1_RPC_PROVIDER=
# --l2rpcprovider Provider for interacting with L2 (env: FAULT_DETECTOR__L2_RPC_PROVIDER)
FAULT_DETECTOR__L2_RPC_PROVIDER=
# --bedrock Whether or not the service is running against a Bedrock chain (env: FAULT_DETECTOR__BEDROCK)
BEDROCK=true
# Optional Params
# --startbatchindex Batch index to start checking from. For bedrock chains, this is the L2 height to start from (env: FAULT_DETECTOR__START_BATCH_INDEX)
# FAULT_DETECTOR__START_BATCH_INDEX=
# --optimismportaladdress [Custom Bedrock Chains] Deployed OptimismPortal contract address. Used to retrieve necessary info for ouput verification (env: FAULT_DETECTOR__OPTIMISM_PORTAL_ADDRESS)
# FAULT_DETECTOR__OPTIMISM_PORTAL_ADDRESS=
# --statecommitmentchainaddress [Custom Legacy Chains] Deployed StateCommitmentChain contract address. Used to fetch necessary info for output verification. (env: FAULT_DETECTOR__STATE_COMMITMENT_CHAIN_ADDRESS)
# FAULT_DETECTOR__STATE_COMMITMENT_CHAIN_ADDRESS=
# --loopintervalms Loop interval in milliseconds, only applies if service is set to loop (env: FAULT_DETECTOR__LOOP_INTERVAL_MS)
# FAULT_DETECTOR__LOOP_INTERVAL_MS=
# --port Port for the app server (env: FAULT_DETECTOR__PORT)
# FAULT_DETECTOR__PORT=
# --hostname Hostname for the app server (env: FAULT_DETECTOR__HOSTNAME)
# FAULT_DETECTOR__HOSTNAME=
# --loglevel Log level (env: FAULT_DETECTOR__LOG_LEVEL)
# FAULT_DETECTOR__LOG_LEVEL=
{
"private": true,
"name": "@eth-optimism/fault-detector",
"version": "1.0.0",
"description": "[Optimism] Service for detecting faulty L2 output proposals",
"main": "dist/index",
"types": "dist/index",
"files": [
"dist/*"
],
"scripts": {
"start": "node --enable-source-maps dist/src/service.js",
"dev": "tsx watch ./src/service.ts",
"test": "hardhat test",
"test:coverage": "nyc hardhat test && nyc merge .nyc_output coverage.json",
"build": "tsc -p tsconfig.json",
"preview": "pnpm build && pnpm start",
"clean": "rimraf dist/ ./tsconfig.tsbuildinfo",
"lint": "pnpm lint:fix && pnpm lint:check",
"pre-commit": "lint-staged",
"lint:fix": "pnpm lint:check --fix",
"lint:check": "eslint . --max-warnings=0"
},
"keywords": [
"optimism",
"ethereum",
"fault",
"detector"
],
"homepage": "https://github.com/ethereum-optimism/optimism/tree/develop/packages/fault-detector#readme",
"license": "MIT",
"author": "Optimism PBC",
"repository": {
"type": "git",
"url": "https://github.com/ethereum-optimism/optimism.git"
},
"devDependencies": {
"@defi-wonderland/smock": "^2.0.7",
"@nomiclabs/hardhat-ethers": "^2.0.6",
"@nomiclabs/hardhat-waffle": "^2.0.3",
"@types/chai": "^4.3.1",
"@types/dateformat": "^5.0.0",
"chai-as-promised": "^7.1.1",
"dateformat": "^4.5.1",
"dotenv": "^16.1.4",
"ethereum-waffle": "^3.4.4",
"ethers": "^5.7.0",
"hardhat": "^2.9.6",
"lodash": "^4.17.21",
"tsx": "^3.12.7"
},
"dependencies": {
"@eth-optimism/common-ts": "^0.8.2",
"@eth-optimism/contracts-bedrock": "0.15.0",
"@eth-optimism/core-utils": "^0.12.1",
"@eth-optimism/sdk": "^3.0.0",
"@ethersproject/abstract-provider": "^5.7.0"
}
}
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "./dist",
"sourceMap": true
},
"include": [
"package.json",
"src/**/*"
]
}
# @eth-optimism/replica-healthcheck # @eth-optimism/replica-healthcheck
## 1.2.6
### Patch Changes
- Updated dependencies [[`c11039060`](https://github.com/ethereum-optimism/optimism/commit/c11039060bc037a88916c2cba602687b6d69ad1a), [`77da6edc6`](https://github.com/ethereum-optimism/optimism/commit/77da6edc643e0b5e39f7b6bb41c3c7ead418a876)]:
- @eth-optimism/core-utils@0.12.2
- @eth-optimism/common-ts@0.8.3
## 1.2.5 ## 1.2.5
### Patch Changes ### Patch Changes
......
{ {
"private": true, "private": true,
"name": "@eth-optimism/replica-healthcheck", "name": "@eth-optimism/replica-healthcheck",
"version": "1.2.5", "version": "1.2.6",
"description": "[Optimism] Service for monitoring the health of replica nodes", "description": "[Optimism] Service for monitoring the health of replica nodes",
"main": "dist/index", "main": "dist/index",
"types": "dist/index", "types": "dist/index",
...@@ -32,8 +32,8 @@ ...@@ -32,8 +32,8 @@
"url": "https://github.com/ethereum-optimism/optimism.git" "url": "https://github.com/ethereum-optimism/optimism.git"
}, },
"dependencies": { "dependencies": {
"@eth-optimism/common-ts": "0.8.2", "@eth-optimism/common-ts": "0.8.3",
"@eth-optimism/core-utils": "0.12.1", "@eth-optimism/core-utils": "0.12.2",
"@ethersproject/abstract-provider": "^5.7.0" "@ethersproject/abstract-provider": "^5.7.0"
}, },
"devDependencies": { "devDependencies": {
......
# @eth-optimism/sdk # @eth-optimism/sdk
## 3.1.0
### Minor Changes
- [#6053](https://github.com/ethereum-optimism/optimism/pull/6053) [`ff577455f`](https://github.com/ethereum-optimism/optimism/commit/ff577455f196b5f5b8a889339b845561ca6c538a) Thanks [@roninjin10](https://github.com/roninjin10)! - Add support for claiming multicall3 withdrawals
- [#6042](https://github.com/ethereum-optimism/optimism/pull/6042) [`89ca741a6`](https://github.com/ethereum-optimism/optimism/commit/89ca741a63c5e07f9d691bb6f7a89f7718fc49ca) Thanks [@roninjin10](https://github.com/roninjin10)! - Fixes issue with legacy withdrawal message status detection
- [#6332](https://github.com/ethereum-optimism/optimism/pull/6332) [`639163253`](https://github.com/ethereum-optimism/optimism/commit/639163253a5e2128f1c21c446b68d358d38cbd30) Thanks [@wilsoncusack](https://github.com/wilsoncusack)! - Added to and from block filters to several methods in CrossChainMessenger
### Patch Changes
- [#6254](https://github.com/ethereum-optimism/optimism/pull/6254) [`a666c4f20`](https://github.com/ethereum-optimism/optimism/commit/a666c4f2082253abbb68c0678e5a0a1ed0c00f4b) Thanks [@roninjin10](https://github.com/roninjin10)! - Fixed missing indexes for multicall support
- [#6164](https://github.com/ethereum-optimism/optimism/pull/6164) [`c11039060`](https://github.com/ethereum-optimism/optimism/commit/c11039060bc037a88916c2cba602687b6d69ad1a) Thanks [@pengin7384](https://github.com/pengin7384)! - fix typo
- [#6198](https://github.com/ethereum-optimism/optimism/pull/6198) [`77da6edc6`](https://github.com/ethereum-optimism/optimism/commit/77da6edc643e0b5e39f7b6bb41c3c7ead418a876) Thanks [@tremarkley](https://github.com/tremarkley)! - Delete dead typescript https://github.com/ethereum-optimism/optimism/pull/6148.
- [#6182](https://github.com/ethereum-optimism/optimism/pull/6182) [`3f13fd0bb`](https://github.com/ethereum-optimism/optimism/commit/3f13fd0bbea051a4550f1df6def1a53a616aa6f6) Thanks [@tremarkley](https://github.com/tremarkley)! - Update the addresses of the bridges on optimism and optimism goerli for the ECO bridge adapter
- Updated dependencies [[`c11039060`](https://github.com/ethereum-optimism/optimism/commit/c11039060bc037a88916c2cba602687b6d69ad1a), [`72d184854`](https://github.com/ethereum-optimism/optimism/commit/72d184854ebad8b2025641f126ed76573b1f0ac3), [`77da6edc6`](https://github.com/ethereum-optimism/optimism/commit/77da6edc643e0b5e39f7b6bb41c3c7ead418a876)]:
- @eth-optimism/contracts-bedrock@0.16.0
- @eth-optimism/core-utils@0.12.2
## 3.0.0 ## 3.0.0
### Major Changes ### Major Changes
......
{ {
"name": "@eth-optimism/sdk", "name": "@eth-optimism/sdk",
"version": "3.0.0", "version": "3.1.0",
"description": "[Optimism] Tools for working with Optimism", "description": "[Optimism] Tools for working with Optimism",
"main": "dist/index", "main": "dist/index",
"types": "dist/index", "types": "dist/index",
...@@ -55,8 +55,8 @@ ...@@ -55,8 +55,8 @@
}, },
"dependencies": { "dependencies": {
"@eth-optimism/contracts": "0.6.0", "@eth-optimism/contracts": "0.6.0",
"@eth-optimism/core-utils": "0.12.1", "@eth-optimism/core-utils": "0.12.2",
"@eth-optimism/contracts-bedrock": "0.15.0", "@eth-optimism/contracts-bedrock": "0.16.0",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"merkletreejs": "^0.2.27", "merkletreejs": "^0.2.27",
"rlp": "^2.2.7" "rlp": "^2.2.7"
......
...@@ -23,7 +23,7 @@ importers: ...@@ -23,7 +23,7 @@ importers:
version: 0.4.8 version: 0.4.8
'@nrwl/nx-cloud': '@nrwl/nx-cloud':
specifier: latest specifier: latest
version: 16.1.0 version: 16.0.5
'@types/chai': '@types/chai':
specifier: ^4.2.18 specifier: ^4.2.18
version: 4.2.21 version: 4.2.21
...@@ -140,19 +140,19 @@ importers: ...@@ -140,19 +140,19 @@ importers:
packages/chain-mon: packages/chain-mon:
dependencies: dependencies:
'@eth-optimism/common-ts': '@eth-optimism/common-ts':
specifier: 0.8.2 specifier: 0.8.3
version: link:../common-ts version: link:../common-ts
'@eth-optimism/contracts-bedrock': '@eth-optimism/contracts-bedrock':
specifier: 0.15.0 specifier: 0.16.0
version: link:../contracts-bedrock version: link:../contracts-bedrock
'@eth-optimism/contracts-periphery': '@eth-optimism/contracts-periphery':
specifier: 1.0.8 specifier: 1.0.8
version: 1.0.8 version: 1.0.8
'@eth-optimism/core-utils': '@eth-optimism/core-utils':
specifier: 0.12.1 specifier: 0.12.2
version: link:../core-utils version: link:../core-utils
'@eth-optimism/sdk': '@eth-optimism/sdk':
specifier: 3.0.0 specifier: 3.1.0
version: link:../sdk version: link:../sdk
'@types/dateformat': '@types/dateformat':
specifier: ^5.0.0 specifier: ^5.0.0
...@@ -163,6 +163,9 @@ importers: ...@@ -163,6 +163,9 @@ importers:
dateformat: dateformat:
specifier: ^4.5.1 specifier: ^4.5.1
version: 4.5.1 version: 4.5.1
dotenv:
specifier: ^16.1.4
version: 16.1.4
ethers: ethers:
specifier: ^5.7.0 specifier: ^5.7.0
version: 5.7.1 version: 5.7.1
...@@ -170,6 +173,15 @@ importers: ...@@ -170,6 +173,15 @@ importers:
'@ethersproject/abstract-provider': '@ethersproject/abstract-provider':
specifier: ^5.7.0 specifier: ^5.7.0
version: 5.7.0 version: 5.7.0
'@nomiclabs/hardhat-ethers':
specifier: ^2.0.6
version: 2.0.6(ethers@5.7.1)(hardhat@2.9.6)
'@nomiclabs/hardhat-waffle':
specifier: ^2.0.3
version: 2.0.3(@nomiclabs/hardhat-ethers@2.0.6)(ethereum-waffle@3.4.4)(ethers@5.7.1)(hardhat@2.9.6)
hardhat:
specifier: ^2.9.6
version: 2.9.6(chai@4.3.7)
ts-node: ts-node:
specifier: ^10.9.1 specifier: ^10.9.1
version: 10.9.1(@types/node@12.20.55)(typescript@5.1.6) version: 10.9.1(@types/node@12.20.55)(typescript@5.1.6)
...@@ -177,7 +189,7 @@ importers: ...@@ -177,7 +189,7 @@ importers:
packages/common-ts: packages/common-ts:
dependencies: dependencies:
'@eth-optimism/core-utils': '@eth-optimism/core-utils':
specifier: 0.12.1 specifier: 0.12.2
version: link:../core-utils version: link:../core-utils
'@sentry/node': '@sentry/node':
specifier: ^6.3.1 specifier: ^6.3.1
...@@ -409,71 +421,13 @@ importers: ...@@ -409,71 +421,13 @@ importers:
specifier: ^10.0.0 specifier: ^10.0.0
version: 10.0.0 version: 10.0.0
packages/fault-detector:
dependencies:
'@eth-optimism/common-ts':
specifier: ^0.8.2
version: link:../common-ts
'@eth-optimism/contracts-bedrock':
specifier: 0.15.0
version: link:../contracts-bedrock
'@eth-optimism/core-utils':
specifier: ^0.12.1
version: link:../core-utils
'@eth-optimism/sdk':
specifier: ^3.0.0
version: link:../sdk
'@ethersproject/abstract-provider':
specifier: ^5.7.0
version: 5.7.0
devDependencies:
'@defi-wonderland/smock':
specifier: ^2.0.7
version: 2.0.7(@ethersproject/abi@5.7.0)(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@nomiclabs/hardhat-ethers@2.0.6)(ethers@5.7.1)(hardhat@2.9.6)
'@nomiclabs/hardhat-ethers':
specifier: ^2.0.6
version: 2.0.6(ethers@5.7.1)(hardhat@2.9.6)
'@nomiclabs/hardhat-waffle':
specifier: ^2.0.3
version: 2.0.3(@nomiclabs/hardhat-ethers@2.0.6)(ethereum-waffle@3.4.4)(ethers@5.7.1)(hardhat@2.9.6)
'@types/chai':
specifier: ^4.3.1
version: 4.3.1
'@types/dateformat':
specifier: ^5.0.0
version: 5.0.0
chai-as-promised:
specifier: ^7.1.1
version: 7.1.1(chai@4.3.7)
dateformat:
specifier: ^4.5.1
version: 4.5.1
dotenv:
specifier: ^16.1.4
version: 16.1.4
ethereum-waffle:
specifier: ^3.4.4
version: 3.4.4(typescript@5.1.6)
ethers:
specifier: ^5.7.0
version: 5.7.1
hardhat:
specifier: ^2.9.6
version: 2.9.6(chai@4.3.7)
lodash:
specifier: ^4.17.21
version: 4.17.21
tsx:
specifier: ^3.12.7
version: 3.12.7
packages/replica-healthcheck: packages/replica-healthcheck:
dependencies: dependencies:
'@eth-optimism/common-ts': '@eth-optimism/common-ts':
specifier: 0.8.2 specifier: 0.8.3
version: link:../common-ts version: link:../common-ts
'@eth-optimism/core-utils': '@eth-optimism/core-utils':
specifier: 0.12.1 specifier: 0.12.2
version: link:../core-utils version: link:../core-utils
'@ethersproject/abstract-provider': '@ethersproject/abstract-provider':
specifier: ^5.7.0 specifier: ^5.7.0
...@@ -489,10 +443,10 @@ importers: ...@@ -489,10 +443,10 @@ importers:
specifier: 0.6.0 specifier: 0.6.0
version: 0.6.0(ethers@5.7.1) version: 0.6.0(ethers@5.7.1)
'@eth-optimism/contracts-bedrock': '@eth-optimism/contracts-bedrock':
specifier: 0.15.0 specifier: 0.16.0
version: link:../contracts-bedrock version: link:../contracts-bedrock
'@eth-optimism/core-utils': '@eth-optimism/core-utils':
specifier: 0.12.1 specifier: 0.12.2
version: link:../core-utils version: link:../core-utils
lodash: lodash:
specifier: ^4.17.21 specifier: ^4.17.21
...@@ -1121,30 +1075,6 @@ packages: ...@@ -1121,30 +1075,6 @@ packages:
'@jridgewell/trace-mapping': 0.3.9 '@jridgewell/trace-mapping': 0.3.9
dev: true dev: true
/@defi-wonderland/smock@2.0.7(@ethersproject/abi@5.7.0)(@ethersproject/abstract-provider@5.7.0)(@ethersproject/abstract-signer@5.7.0)(@nomiclabs/hardhat-ethers@2.0.6)(ethers@5.7.1)(hardhat@2.9.6):
resolution: {integrity: sha512-RVpODLKZ/Cr0C1bCbhJ2aXbAr2Ll/K2WO7hDL96tqhMzCsA7ToWdDIgiNpV5Vtqqvpftu5ddO7v3TAurQNSU0w==}
peerDependencies:
'@ethersproject/abi': ^5
'@ethersproject/abstract-provider': ^5
'@ethersproject/abstract-signer': ^5
'@nomiclabs/hardhat-ethers': ^2
ethers: ^5
hardhat: ^2
dependencies:
'@ethersproject/abi': 5.7.0
'@ethersproject/abstract-provider': 5.7.0
'@ethersproject/abstract-signer': 5.7.0
'@nomiclabs/ethereumjs-vm': 4.2.2
'@nomiclabs/hardhat-ethers': 2.0.6(ethers@5.7.1)(hardhat@2.9.6)
diff: 5.1.0
ethers: 5.7.1
hardhat: 2.9.6(chai@4.3.7)
lodash.isequal: 4.5.0
lodash.isequalwith: 4.4.0
rxjs: 7.8.1
semver: 7.5.3
dev: true
/@ensdomains/ens@0.4.5: /@ensdomains/ens@0.4.5:
resolution: {integrity: sha512-JSvpj1iNMFjK6K+uVl4unqMoa9rf5jopb8cya5UGBWz23Nw8hSNT7efgUx4BTlAPAgpNlEioUfeTyQ6J9ZvTVw==} resolution: {integrity: sha512-JSvpj1iNMFjK6K+uVl4unqMoa9rf5jopb8cya5UGBWz23Nw8hSNT7efgUx4BTlAPAgpNlEioUfeTyQ6J9ZvTVw==}
deprecated: Please use @ensdomains/ens-contracts deprecated: Please use @ensdomains/ens-contracts
...@@ -1170,27 +1100,6 @@ packages: ...@@ -1170,27 +1100,6 @@ packages:
jsdoc-type-pratt-parser: 1.0.4 jsdoc-type-pratt-parser: 1.0.4
dev: true dev: true
/@esbuild-kit/cjs-loader@2.4.2:
resolution: {integrity: sha512-BDXFbYOJzT/NBEtp71cvsrGPwGAMGRB/349rwKuoxNSiKjPraNNnlK6MIIabViCjqZugu6j+xeMDlEkWdHHJSg==}
dependencies:
'@esbuild-kit/core-utils': 3.0.0
get-tsconfig: 4.4.0
dev: true
/@esbuild-kit/core-utils@3.0.0:
resolution: {integrity: sha512-TXmwH9EFS3DC2sI2YJWJBgHGhlteK0Xyu1VabwetMULfm3oYhbrsWV5yaSr2NTWZIgDGVLHbRf0inxbjXqAcmQ==}
dependencies:
esbuild: 0.15.18
source-map-support: 0.5.21
dev: true
/@esbuild-kit/esm-loader@2.5.5:
resolution: {integrity: sha512-Qwfvj/qoPbClxCRNuac1Du01r9gvNOT+pMYtJDapfB1eoGN1YlJ1BixLyL9WVENRx5RXgNLdfYdx/CuswlGhMw==}
dependencies:
'@esbuild-kit/core-utils': 3.0.0
get-tsconfig: 4.4.0
dev: true
/@esbuild/android-arm64@0.18.13: /@esbuild/android-arm64@0.18.13:
resolution: {integrity: sha512-j7NhycJUoUAG5kAzGf4fPWfd17N6SM3o1X6MlXVqfHvs2buFraCJzos9vbeWjLxOyBKHyPOnuCuipbhvbYtTAg==} resolution: {integrity: sha512-j7NhycJUoUAG5kAzGf4fPWfd17N6SM3o1X6MlXVqfHvs2buFraCJzos9vbeWjLxOyBKHyPOnuCuipbhvbYtTAg==}
engines: {node: '>=12'} engines: {node: '>=12'}
...@@ -1209,15 +1118,6 @@ packages: ...@@ -1209,15 +1118,6 @@ packages:
dev: true dev: true
optional: true optional: true
/@esbuild/android-arm@0.15.18:
resolution: {integrity: sha512-5GT+kcs2WVGjVs7+boataCkO5Fg0y4kCjzkB5bAip7H4jfnOS3dA6KPiww9W1OEKTKeAcUVhdZGvgI65OXmUnw==}
engines: {node: '>=12'}
cpu: [arm]
os: [android]
requiresBuild: true
dev: true
optional: true
/@esbuild/android-arm@0.18.13: /@esbuild/android-arm@0.18.13:
resolution: {integrity: sha512-KwqFhxRFMKZINHzCqf8eKxE0XqWlAVPRxwy6rc7CbVFxzUWB2sA/s3hbMZeemPdhN3fKBkqOaFhTbS8xJXYIWQ==} resolution: {integrity: sha512-KwqFhxRFMKZINHzCqf8eKxE0XqWlAVPRxwy6rc7CbVFxzUWB2sA/s3hbMZeemPdhN3fKBkqOaFhTbS8xJXYIWQ==}
engines: {node: '>=12'} engines: {node: '>=12'}
...@@ -1308,15 +1208,6 @@ packages: ...@@ -1308,15 +1208,6 @@ packages:
dev: true dev: true
optional: true optional: true
/@esbuild/linux-loong64@0.15.18:
resolution: {integrity: sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==}
engines: {node: '>=12'}
cpu: [loong64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@esbuild/linux-loong64@0.18.13: /@esbuild/linux-loong64@0.18.13:
resolution: {integrity: sha512-8pcKDApAsKc6WW51ZEVidSGwGbebYw2qKnO1VyD8xd6JN0RN6EUXfhXmDk9Vc4/U3Y4AoFTexQewQDJGsBXBpg==} resolution: {integrity: sha512-8pcKDApAsKc6WW51ZEVidSGwGbebYw2qKnO1VyD8xd6JN0RN6EUXfhXmDk9Vc4/U3Y4AoFTexQewQDJGsBXBpg==}
engines: {node: '>=12'} engines: {node: '>=12'}
...@@ -2399,26 +2290,6 @@ packages: ...@@ -2399,26 +2290,6 @@ packages:
'@nodelib/fs.scandir': 2.1.5 '@nodelib/fs.scandir': 2.1.5
fastq: 1.15.0 fastq: 1.15.0
/@nomiclabs/ethereumjs-vm@4.2.2:
resolution: {integrity: sha512-8WmX94mMcJaZ7/m7yBbyuS6B+wuOul+eF+RY9fBpGhNaUpyMR/vFIcDojqcWQ4Yafe1tMKY5LDu2yfT4NZgV4Q==}
dependencies:
async: 2.6.4
async-eventemitter: 0.2.4
core-js-pure: 3.16.2
ethereumjs-account: 3.0.0
ethereumjs-block: 2.2.2
ethereumjs-blockchain: 4.0.4
ethereumjs-common: 1.5.2
ethereumjs-tx: 2.1.2
ethereumjs-util: 6.2.1
fake-merkle-patricia-tree: 1.0.1
functional-red-black-tree: 1.0.1
merkle-patricia-tree: 3.0.0
rustbn.js: 0.2.0
safe-buffer: 5.2.1
util.promisify: 1.1.2
dev: true
/@nomiclabs/hardhat-ethers@2.0.2(ethers@5.7.1)(hardhat@2.9.6): /@nomiclabs/hardhat-ethers@2.0.2(ethers@5.7.1)(hardhat@2.9.6):
resolution: {integrity: sha512-6quxWe8wwS4X5v3Au8q1jOvXYEPkS1Fh+cME5u6AwNdnI4uERvPlVjlgRWzpnb+Rrt1l/cEqiNRH9GlsBMSDQg==} resolution: {integrity: sha512-6quxWe8wwS4X5v3Au8q1jOvXYEPkS1Fh+cME5u6AwNdnI4uERvPlVjlgRWzpnb+Rrt1l/cEqiNRH9GlsBMSDQg==}
peerDependencies: peerDependencies:
...@@ -2695,10 +2566,10 @@ packages: ...@@ -2695,10 +2566,10 @@ packages:
tslib: 2.6.0 tslib: 2.6.0
dev: true dev: true
/@nrwl/nx-cloud@16.1.0: /@nrwl/nx-cloud@16.0.5:
resolution: {integrity: sha512-OFjbSqdCuZq9KRYU/mOlIN8SYLZREsLlZYqYpObZqXJ5meUgBDJbUSwRweUSUvt73fgRixLEau2jPysiLHKxSQ==} resolution: {integrity: sha512-1p82ym8WE9ziejwgPslstn19iV/VkHfHfKr/5YOnfCHQS+NxUf92ogcYhHXtqWLblVZ9Zs4W4pkSXK4e04wCmQ==}
dependencies: dependencies:
nx-cloud: 16.1.0 nx-cloud: 16.0.5
transitivePeerDependencies: transitivePeerDependencies:
- debug - debug
dev: true dev: true
...@@ -3632,10 +3503,6 @@ packages: ...@@ -3632,10 +3503,6 @@ packages:
resolution: {integrity: sha512-yd+9qKmJxm496BOV9CMNaey8TWsikaZOwMRwPHQIjcOJM9oV+fi9ZMNw3JsVnbEEbo2gRTDnGEBv8pjyn67hNg==} resolution: {integrity: sha512-yd+9qKmJxm496BOV9CMNaey8TWsikaZOwMRwPHQIjcOJM9oV+fi9ZMNw3JsVnbEEbo2gRTDnGEBv8pjyn67hNg==}
dev: true dev: true
/@types/chai@4.3.1:
resolution: {integrity: sha512-/zPMqDkzSZ8t3VtxOa4KPq7uzzW978M9Tvh+j7GHKuo6k6GTLxPJ4J5gE5cjfJ26pnXst0N5Hax8Sr0T2Mi9zQ==}
dev: true
/@types/chai@4.3.5: /@types/chai@4.3.5:
resolution: {integrity: sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng==} resolution: {integrity: sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng==}
dev: true dev: true
...@@ -3647,6 +3514,7 @@ packages: ...@@ -3647,6 +3514,7 @@ packages:
/@types/dateformat@5.0.0: /@types/dateformat@5.0.0:
resolution: {integrity: sha512-SZg4JdHIWHQGEokbYGZSDvo5wA4TLYPXaqhigs/wH+REDOejcJzgH+qyY+HtEUtWOZxEUkbhbdYPqQDiEgrXeA==} resolution: {integrity: sha512-SZg4JdHIWHQGEokbYGZSDvo5wA4TLYPXaqhigs/wH+REDOejcJzgH+qyY+HtEUtWOZxEUkbhbdYPqQDiEgrXeA==}
dev: false
/@types/debug@4.1.8: /@types/debug@4.1.8:
resolution: {integrity: sha512-/vPO1EPOs306Cvhwv7KfVfYvOJqA/S/AXjaHQiJboCZzcNDb+TIJFN9/2C9DZ//ijSKWioNyUxD792QmDJ+HKQ==} resolution: {integrity: sha512-/vPO1EPOs306Cvhwv7KfVfYvOJqA/S/AXjaHQiJboCZzcNDb+TIJFN9/2C9DZ//ijSKWioNyUxD792QmDJ+HKQ==}
...@@ -5418,7 +5286,7 @@ packages: ...@@ -5418,7 +5286,7 @@ packages:
call-bind: 1.0.2 call-bind: 1.0.2
define-properties: 1.1.4 define-properties: 1.1.4
es-abstract: 1.21.1 es-abstract: 1.21.1
get-intrinsic: 1.1.3 get-intrinsic: 1.2.1
is-string: 1.0.7 is-string: 1.0.7
dev: true dev: true
...@@ -7712,6 +7580,7 @@ packages: ...@@ -7712,6 +7580,7 @@ packages:
/dateformat@4.5.1: /dateformat@4.5.1:
resolution: {integrity: sha512-OD0TZ+B7yP7ZgpJf5K2DIbj3FZvFvxgFUuaqA/V5zTjAtAAXZ1E8bktHxmAGs4x5b7PflqA9LeQ84Og7wYtF7Q==} resolution: {integrity: sha512-OD0TZ+B7yP7ZgpJf5K2DIbj3FZvFvxgFUuaqA/V5zTjAtAAXZ1E8bktHxmAGs4x5b7PflqA9LeQ84Og7wYtF7Q==}
dev: false
/debug@2.6.9: /debug@2.6.9:
resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==}
...@@ -8224,7 +8093,6 @@ packages: ...@@ -8224,7 +8093,6 @@ packages:
/dotenv@16.1.4: /dotenv@16.1.4:
resolution: {integrity: sha512-m55RtE8AsPeJBpOIFKihEmqUcoVncQIwo7x9U8ZwLEZw9ZpXboz2c+rvog+jUaJvVrZ5kBOeYQBX5+8Aa/OZQw==} resolution: {integrity: sha512-m55RtE8AsPeJBpOIFKihEmqUcoVncQIwo7x9U8ZwLEZw9ZpXboz2c+rvog+jUaJvVrZ5kBOeYQBX5+8Aa/OZQw==}
engines: {node: '>=12'} engines: {node: '>=12'}
dev: true
/dotenv@8.6.0: /dotenv@8.6.0:
resolution: {integrity: sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==} resolution: {integrity: sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==}
...@@ -8569,15 +8437,6 @@ packages: ...@@ -8569,15 +8437,6 @@ packages:
dev: true dev: true
optional: true optional: true
/esbuild-android-64@0.15.18:
resolution: {integrity: sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==}
engines: {node: '>=12'}
cpu: [x64]
os: [android]
requiresBuild: true
dev: true
optional: true
/esbuild-android-arm64@0.15.13: /esbuild-android-arm64@0.15.13:
resolution: {integrity: sha512-TKzyymLD6PiVeyYa4c5wdPw87BeAiTXNtK6amWUcXZxkV51gOk5u5qzmDaYSwiWeecSNHamFsaFjLoi32QR5/w==} resolution: {integrity: sha512-TKzyymLD6PiVeyYa4c5wdPw87BeAiTXNtK6amWUcXZxkV51gOk5u5qzmDaYSwiWeecSNHamFsaFjLoi32QR5/w==}
engines: {node: '>=12'} engines: {node: '>=12'}
...@@ -8587,15 +8446,6 @@ packages: ...@@ -8587,15 +8446,6 @@ packages:
dev: true dev: true
optional: true optional: true
/esbuild-android-arm64@0.15.18:
resolution: {integrity: sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==}
engines: {node: '>=12'}
cpu: [arm64]
os: [android]
requiresBuild: true
dev: true
optional: true
/esbuild-darwin-64@0.15.13: /esbuild-darwin-64@0.15.13:
resolution: {integrity: sha512-WAx7c2DaOS6CrRcoYCgXgkXDliLnFv3pQLV6GeW1YcGEZq2Gnl8s9Pg7ahValZkpOa0iE/ojRVQ87sbUhF1Cbg==} resolution: {integrity: sha512-WAx7c2DaOS6CrRcoYCgXgkXDliLnFv3pQLV6GeW1YcGEZq2Gnl8s9Pg7ahValZkpOa0iE/ojRVQ87sbUhF1Cbg==}
engines: {node: '>=12'} engines: {node: '>=12'}
...@@ -8605,15 +8455,6 @@ packages: ...@@ -8605,15 +8455,6 @@ packages:
dev: true dev: true
optional: true optional: true
/esbuild-darwin-64@0.15.18:
resolution: {integrity: sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==}
engines: {node: '>=12'}
cpu: [x64]
os: [darwin]
requiresBuild: true
dev: true
optional: true
/esbuild-darwin-arm64@0.15.13: /esbuild-darwin-arm64@0.15.13:
resolution: {integrity: sha512-U6jFsPfSSxC3V1CLiQqwvDuj3GGrtQNB3P3nNC3+q99EKf94UGpsG9l4CQ83zBs1NHrk1rtCSYT0+KfK5LsD8A==} resolution: {integrity: sha512-U6jFsPfSSxC3V1CLiQqwvDuj3GGrtQNB3P3nNC3+q99EKf94UGpsG9l4CQ83zBs1NHrk1rtCSYT0+KfK5LsD8A==}
engines: {node: '>=12'} engines: {node: '>=12'}
...@@ -8623,15 +8464,6 @@ packages: ...@@ -8623,15 +8464,6 @@ packages:
dev: true dev: true
optional: true optional: true
/esbuild-darwin-arm64@0.15.18:
resolution: {integrity: sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA==}
engines: {node: '>=12'}
cpu: [arm64]
os: [darwin]
requiresBuild: true
dev: true
optional: true
/esbuild-freebsd-64@0.15.13: /esbuild-freebsd-64@0.15.13:
resolution: {integrity: sha512-whItJgDiOXaDG/idy75qqevIpZjnReZkMGCgQaBWZuKHoElDJC1rh7MpoUgupMcdfOd+PgdEwNQW9DAE6i8wyA==} resolution: {integrity: sha512-whItJgDiOXaDG/idy75qqevIpZjnReZkMGCgQaBWZuKHoElDJC1rh7MpoUgupMcdfOd+PgdEwNQW9DAE6i8wyA==}
engines: {node: '>=12'} engines: {node: '>=12'}
...@@ -8641,15 +8473,6 @@ packages: ...@@ -8641,15 +8473,6 @@ packages:
dev: true dev: true
optional: true optional: true
/esbuild-freebsd-64@0.15.18:
resolution: {integrity: sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==}
engines: {node: '>=12'}
cpu: [x64]
os: [freebsd]
requiresBuild: true
dev: true
optional: true
/esbuild-freebsd-arm64@0.15.13: /esbuild-freebsd-arm64@0.15.13:
resolution: {integrity: sha512-6pCSWt8mLUbPtygv7cufV0sZLeylaMwS5Fznj6Rsx9G2AJJsAjQ9ifA+0rQEIg7DwJmi9it+WjzNTEAzzdoM3Q==} resolution: {integrity: sha512-6pCSWt8mLUbPtygv7cufV0sZLeylaMwS5Fznj6Rsx9G2AJJsAjQ9ifA+0rQEIg7DwJmi9it+WjzNTEAzzdoM3Q==}
engines: {node: '>=12'} engines: {node: '>=12'}
...@@ -8659,15 +8482,6 @@ packages: ...@@ -8659,15 +8482,6 @@ packages:
dev: true dev: true
optional: true optional: true
/esbuild-freebsd-arm64@0.15.18:
resolution: {integrity: sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==}
engines: {node: '>=12'}
cpu: [arm64]
os: [freebsd]
requiresBuild: true
dev: true
optional: true
/esbuild-linux-32@0.15.13: /esbuild-linux-32@0.15.13:
resolution: {integrity: sha512-VbZdWOEdrJiYApm2kkxoTOgsoCO1krBZ3quHdYk3g3ivWaMwNIVPIfEE0f0XQQ0u5pJtBsnk2/7OPiCFIPOe/w==} resolution: {integrity: sha512-VbZdWOEdrJiYApm2kkxoTOgsoCO1krBZ3quHdYk3g3ivWaMwNIVPIfEE0f0XQQ0u5pJtBsnk2/7OPiCFIPOe/w==}
engines: {node: '>=12'} engines: {node: '>=12'}
...@@ -8677,15 +8491,6 @@ packages: ...@@ -8677,15 +8491,6 @@ packages:
dev: true dev: true
optional: true optional: true
/esbuild-linux-32@0.15.18:
resolution: {integrity: sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==}
engines: {node: '>=12'}
cpu: [ia32]
os: [linux]
requiresBuild: true
dev: true
optional: true
/esbuild-linux-64@0.15.13: /esbuild-linux-64@0.15.13:
resolution: {integrity: sha512-rXmnArVNio6yANSqDQlIO4WiP+Cv7+9EuAHNnag7rByAqFVuRusLbGi2697A5dFPNXoO//IiogVwi3AdcfPC6A==} resolution: {integrity: sha512-rXmnArVNio6yANSqDQlIO4WiP+Cv7+9EuAHNnag7rByAqFVuRusLbGi2697A5dFPNXoO//IiogVwi3AdcfPC6A==}
engines: {node: '>=12'} engines: {node: '>=12'}
...@@ -8695,15 +8500,6 @@ packages: ...@@ -8695,15 +8500,6 @@ packages:
dev: true dev: true
optional: true optional: true
/esbuild-linux-64@0.15.18:
resolution: {integrity: sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==}
engines: {node: '>=12'}
cpu: [x64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/esbuild-linux-arm64@0.15.13: /esbuild-linux-arm64@0.15.13:
resolution: {integrity: sha512-alEMGU4Z+d17U7KQQw2IV8tQycO6T+rOrgW8OS22Ua25x6kHxoG6Ngry6Aq6uranC+pNWNMB6aHFPh7aTQdORQ==} resolution: {integrity: sha512-alEMGU4Z+d17U7KQQw2IV8tQycO6T+rOrgW8OS22Ua25x6kHxoG6Ngry6Aq6uranC+pNWNMB6aHFPh7aTQdORQ==}
engines: {node: '>=12'} engines: {node: '>=12'}
...@@ -8713,15 +8509,6 @@ packages: ...@@ -8713,15 +8509,6 @@ packages:
dev: true dev: true
optional: true optional: true
/esbuild-linux-arm64@0.15.18:
resolution: {integrity: sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==}
engines: {node: '>=12'}
cpu: [arm64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/esbuild-linux-arm@0.15.13: /esbuild-linux-arm@0.15.13:
resolution: {integrity: sha512-Ac6LpfmJO8WhCMQmO253xX2IU2B3wPDbl4IvR0hnqcPrdfCaUa2j/lLMGTjmQ4W5JsJIdHEdW12dG8lFS0MbxQ==} resolution: {integrity: sha512-Ac6LpfmJO8WhCMQmO253xX2IU2B3wPDbl4IvR0hnqcPrdfCaUa2j/lLMGTjmQ4W5JsJIdHEdW12dG8lFS0MbxQ==}
engines: {node: '>=12'} engines: {node: '>=12'}
...@@ -8731,15 +8518,6 @@ packages: ...@@ -8731,15 +8518,6 @@ packages:
dev: true dev: true
optional: true optional: true
/esbuild-linux-arm@0.15.18:
resolution: {integrity: sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==}
engines: {node: '>=12'}
cpu: [arm]
os: [linux]
requiresBuild: true
dev: true
optional: true
/esbuild-linux-mips64le@0.15.13: /esbuild-linux-mips64le@0.15.13:
resolution: {integrity: sha512-47PgmyYEu+yN5rD/MbwS6DxP2FSGPo4Uxg5LwIdxTiyGC2XKwHhHyW7YYEDlSuXLQXEdTO7mYe8zQ74czP7W8A==} resolution: {integrity: sha512-47PgmyYEu+yN5rD/MbwS6DxP2FSGPo4Uxg5LwIdxTiyGC2XKwHhHyW7YYEDlSuXLQXEdTO7mYe8zQ74czP7W8A==}
engines: {node: '>=12'} engines: {node: '>=12'}
...@@ -8749,15 +8527,6 @@ packages: ...@@ -8749,15 +8527,6 @@ packages:
dev: true dev: true
optional: true optional: true
/esbuild-linux-mips64le@0.15.18:
resolution: {integrity: sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==}
engines: {node: '>=12'}
cpu: [mips64el]
os: [linux]
requiresBuild: true
dev: true
optional: true
/esbuild-linux-ppc64le@0.15.13: /esbuild-linux-ppc64le@0.15.13:
resolution: {integrity: sha512-z6n28h2+PC1Ayle9DjKoBRcx/4cxHoOa2e689e2aDJSaKug3jXcQw7mM+GLg+9ydYoNzj8QxNL8ihOv/OnezhA==} resolution: {integrity: sha512-z6n28h2+PC1Ayle9DjKoBRcx/4cxHoOa2e689e2aDJSaKug3jXcQw7mM+GLg+9ydYoNzj8QxNL8ihOv/OnezhA==}
engines: {node: '>=12'} engines: {node: '>=12'}
...@@ -8767,15 +8536,6 @@ packages: ...@@ -8767,15 +8536,6 @@ packages:
dev: true dev: true
optional: true optional: true
/esbuild-linux-ppc64le@0.15.18:
resolution: {integrity: sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==}
engines: {node: '>=12'}
cpu: [ppc64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/esbuild-linux-riscv64@0.15.13: /esbuild-linux-riscv64@0.15.13:
resolution: {integrity: sha512-+Lu4zuuXuQhgLUGyZloWCqTslcCAjMZH1k3Xc9MSEJEpEFdpsSU0sRDXAnk18FKOfEjhu4YMGaykx9xjtpA6ow==} resolution: {integrity: sha512-+Lu4zuuXuQhgLUGyZloWCqTslcCAjMZH1k3Xc9MSEJEpEFdpsSU0sRDXAnk18FKOfEjhu4YMGaykx9xjtpA6ow==}
engines: {node: '>=12'} engines: {node: '>=12'}
...@@ -8785,15 +8545,6 @@ packages: ...@@ -8785,15 +8545,6 @@ packages:
dev: true dev: true
optional: true optional: true
/esbuild-linux-riscv64@0.15.18:
resolution: {integrity: sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==}
engines: {node: '>=12'}
cpu: [riscv64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/esbuild-linux-s390x@0.15.13: /esbuild-linux-s390x@0.15.13:
resolution: {integrity: sha512-BMeXRljruf7J0TMxD5CIXS65y7puiZkAh+s4XFV9qy16SxOuMhxhVIXYLnbdfLrsYGFzx7U9mcdpFWkkvy/Uag==} resolution: {integrity: sha512-BMeXRljruf7J0TMxD5CIXS65y7puiZkAh+s4XFV9qy16SxOuMhxhVIXYLnbdfLrsYGFzx7U9mcdpFWkkvy/Uag==}
engines: {node: '>=12'} engines: {node: '>=12'}
...@@ -8803,15 +8554,6 @@ packages: ...@@ -8803,15 +8554,6 @@ packages:
dev: true dev: true
optional: true optional: true
/esbuild-linux-s390x@0.15.18:
resolution: {integrity: sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==}
engines: {node: '>=12'}
cpu: [s390x]
os: [linux]
requiresBuild: true
dev: true
optional: true
/esbuild-netbsd-64@0.15.13: /esbuild-netbsd-64@0.15.13:
resolution: {integrity: sha512-EHj9QZOTel581JPj7UO3xYbltFTYnHy+SIqJVq6yd3KkCrsHRbapiPb0Lx3EOOtybBEE9EyqbmfW1NlSDsSzvQ==} resolution: {integrity: sha512-EHj9QZOTel581JPj7UO3xYbltFTYnHy+SIqJVq6yd3KkCrsHRbapiPb0Lx3EOOtybBEE9EyqbmfW1NlSDsSzvQ==}
engines: {node: '>=12'} engines: {node: '>=12'}
...@@ -8821,15 +8563,6 @@ packages: ...@@ -8821,15 +8563,6 @@ packages:
dev: true dev: true
optional: true optional: true
/esbuild-netbsd-64@0.15.18:
resolution: {integrity: sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==}
engines: {node: '>=12'}
cpu: [x64]
os: [netbsd]
requiresBuild: true
dev: true
optional: true
/esbuild-openbsd-64@0.15.13: /esbuild-openbsd-64@0.15.13:
resolution: {integrity: sha512-nkuDlIjF/sfUhfx8SKq0+U+Fgx5K9JcPq1mUodnxI0x4kBdCv46rOGWbuJ6eof2n3wdoCLccOoJAbg9ba/bT2w==} resolution: {integrity: sha512-nkuDlIjF/sfUhfx8SKq0+U+Fgx5K9JcPq1mUodnxI0x4kBdCv46rOGWbuJ6eof2n3wdoCLccOoJAbg9ba/bT2w==}
engines: {node: '>=12'} engines: {node: '>=12'}
...@@ -8839,15 +8572,6 @@ packages: ...@@ -8839,15 +8572,6 @@ packages:
dev: true dev: true
optional: true optional: true
/esbuild-openbsd-64@0.15.18:
resolution: {integrity: sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==}
engines: {node: '>=12'}
cpu: [x64]
os: [openbsd]
requiresBuild: true
dev: true
optional: true
/esbuild-sunos-64@0.15.13: /esbuild-sunos-64@0.15.13:
resolution: {integrity: sha512-jVeu2GfxZQ++6lRdY43CS0Tm/r4WuQQ0Pdsrxbw+aOrHQPHV0+LNOLnvbN28M7BSUGnJnHkHm2HozGgNGyeIRw==} resolution: {integrity: sha512-jVeu2GfxZQ++6lRdY43CS0Tm/r4WuQQ0Pdsrxbw+aOrHQPHV0+LNOLnvbN28M7BSUGnJnHkHm2HozGgNGyeIRw==}
engines: {node: '>=12'} engines: {node: '>=12'}
...@@ -8857,15 +8581,6 @@ packages: ...@@ -8857,15 +8581,6 @@ packages:
dev: true dev: true
optional: true optional: true
/esbuild-sunos-64@0.15.18:
resolution: {integrity: sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==}
engines: {node: '>=12'}
cpu: [x64]
os: [sunos]
requiresBuild: true
dev: true
optional: true
/esbuild-windows-32@0.15.13: /esbuild-windows-32@0.15.13:
resolution: {integrity: sha512-XoF2iBf0wnqo16SDq+aDGi/+QbaLFpkiRarPVssMh9KYbFNCqPLlGAWwDvxEVz+ywX6Si37J2AKm+AXq1kC0JA==} resolution: {integrity: sha512-XoF2iBf0wnqo16SDq+aDGi/+QbaLFpkiRarPVssMh9KYbFNCqPLlGAWwDvxEVz+ywX6Si37J2AKm+AXq1kC0JA==}
engines: {node: '>=12'} engines: {node: '>=12'}
...@@ -8875,15 +8590,6 @@ packages: ...@@ -8875,15 +8590,6 @@ packages:
dev: true dev: true
optional: true optional: true
/esbuild-windows-32@0.15.18:
resolution: {integrity: sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==}
engines: {node: '>=12'}
cpu: [ia32]
os: [win32]
requiresBuild: true
dev: true
optional: true
/esbuild-windows-64@0.15.13: /esbuild-windows-64@0.15.13:
resolution: {integrity: sha512-Et6htEfGycjDrtqb2ng6nT+baesZPYQIW+HUEHK4D1ncggNrDNk3yoboYQ5KtiVrw/JaDMNttz8rrPubV/fvPQ==} resolution: {integrity: sha512-Et6htEfGycjDrtqb2ng6nT+baesZPYQIW+HUEHK4D1ncggNrDNk3yoboYQ5KtiVrw/JaDMNttz8rrPubV/fvPQ==}
engines: {node: '>=12'} engines: {node: '>=12'}
...@@ -8893,15 +8599,6 @@ packages: ...@@ -8893,15 +8599,6 @@ packages:
dev: true dev: true
optional: true optional: true
/esbuild-windows-64@0.15.18:
resolution: {integrity: sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==}
engines: {node: '>=12'}
cpu: [x64]
os: [win32]
requiresBuild: true
dev: true
optional: true
/esbuild-windows-arm64@0.15.13: /esbuild-windows-arm64@0.15.13:
resolution: {integrity: sha512-3bv7tqntThQC9SWLRouMDmZnlOukBhOCTlkzNqzGCmrkCJI7io5LLjwJBOVY6kOUlIvdxbooNZwjtBvj+7uuVg==} resolution: {integrity: sha512-3bv7tqntThQC9SWLRouMDmZnlOukBhOCTlkzNqzGCmrkCJI7io5LLjwJBOVY6kOUlIvdxbooNZwjtBvj+7uuVg==}
engines: {node: '>=12'} engines: {node: '>=12'}
...@@ -8911,15 +8608,6 @@ packages: ...@@ -8911,15 +8608,6 @@ packages:
dev: true dev: true
optional: true optional: true
/esbuild-windows-arm64@0.15.18:
resolution: {integrity: sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==}
engines: {node: '>=12'}
cpu: [arm64]
os: [win32]
requiresBuild: true
dev: true
optional: true
/esbuild@0.15.13: /esbuild@0.15.13:
resolution: {integrity: sha512-Cu3SC84oyzzhrK/YyN4iEVy2jZu5t2fz66HEOShHURcjSkOSAVL8C/gfUT+lDJxkVHpg8GZ10DD0rMHRPqMFaQ==} resolution: {integrity: sha512-Cu3SC84oyzzhrK/YyN4iEVy2jZu5t2fz66HEOShHURcjSkOSAVL8C/gfUT+lDJxkVHpg8GZ10DD0rMHRPqMFaQ==}
engines: {node: '>=12'} engines: {node: '>=12'}
...@@ -8950,36 +8638,6 @@ packages: ...@@ -8950,36 +8638,6 @@ packages:
esbuild-windows-arm64: 0.15.13 esbuild-windows-arm64: 0.15.13
dev: true dev: true
/esbuild@0.15.18:
resolution: {integrity: sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q==}
engines: {node: '>=12'}
hasBin: true
requiresBuild: true
optionalDependencies:
'@esbuild/android-arm': 0.15.18
'@esbuild/linux-loong64': 0.15.18
esbuild-android-64: 0.15.18
esbuild-android-arm64: 0.15.18
esbuild-darwin-64: 0.15.18
esbuild-darwin-arm64: 0.15.18
esbuild-freebsd-64: 0.15.18
esbuild-freebsd-arm64: 0.15.18
esbuild-linux-32: 0.15.18
esbuild-linux-64: 0.15.18
esbuild-linux-arm: 0.15.18
esbuild-linux-arm64: 0.15.18
esbuild-linux-mips64le: 0.15.18
esbuild-linux-ppc64le: 0.15.18
esbuild-linux-riscv64: 0.15.18
esbuild-linux-s390x: 0.15.18
esbuild-netbsd-64: 0.15.18
esbuild-openbsd-64: 0.15.18
esbuild-sunos-64: 0.15.18
esbuild-windows-32: 0.15.18
esbuild-windows-64: 0.15.18
esbuild-windows-arm64: 0.15.18
dev: true
/esbuild@0.18.13: /esbuild@0.18.13:
resolution: {integrity: sha512-vhg/WR/Oiu4oUIkVhmfcc23G6/zWuEQKFS+yiosSHe4aN6+DQRXIfeloYGibIfVhkr4wyfuVsGNLr+sQU1rWWw==} resolution: {integrity: sha512-vhg/WR/Oiu4oUIkVhmfcc23G6/zWuEQKFS+yiosSHe4aN6+DQRXIfeloYGibIfVhkr4wyfuVsGNLr+sQU1rWWw==}
engines: {node: '>=12'} engines: {node: '>=12'}
...@@ -9611,7 +9269,7 @@ packages: ...@@ -9611,7 +9269,7 @@ packages:
'@ethereum-waffle/compiler': 3.4.4(typescript@5.1.6) '@ethereum-waffle/compiler': 3.4.4(typescript@5.1.6)
'@ethereum-waffle/mock-contract': 3.4.4 '@ethereum-waffle/mock-contract': 3.4.4
'@ethereum-waffle/provider': 3.4.4 '@ethereum-waffle/provider': 3.4.4
ethers: 5.7.1 ethers: 5.7.2
transitivePeerDependencies: transitivePeerDependencies:
- bufferutil - bufferutil
- encoding - encoding
...@@ -10766,14 +10424,6 @@ packages: ...@@ -10766,14 +10424,6 @@ packages:
/get-func-name@2.0.0: /get-func-name@2.0.0:
resolution: {integrity: sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==} resolution: {integrity: sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==}
/get-intrinsic@1.1.3:
resolution: {integrity: sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==}
dependencies:
function-bind: 1.1.1
has: 1.0.3
has-symbols: 1.0.3
dev: true
/get-intrinsic@1.2.1: /get-intrinsic@1.2.1:
resolution: {integrity: sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==} resolution: {integrity: sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==}
dependencies: dependencies:
...@@ -10844,10 +10494,6 @@ packages: ...@@ -10844,10 +10494,6 @@ packages:
call-bind: 1.0.2 call-bind: 1.0.2
get-intrinsic: 1.2.1 get-intrinsic: 1.2.1
/get-tsconfig@4.4.0:
resolution: {integrity: sha512-0Gdjo/9+FzsYhXCEFueo2aY1z1tpXrxWZzP7k8ul9qt1U5o8rYJwTJYmaeHdrVosYIVYkOy2iwCJ9FdpocJhPQ==}
dev: true
/get-value@2.0.6: /get-value@2.0.6:
resolution: {integrity: sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==} resolution: {integrity: sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
...@@ -11230,8 +10876,8 @@ packages: ...@@ -11230,8 +10876,8 @@ packages:
mnemonist: 0.38.3 mnemonist: 0.38.3
mocha: 9.2.1 mocha: 9.2.1
p-map: 4.0.0 p-map: 4.0.0
qs: 6.11.0 qs: 6.11.2
raw-body: 2.5.1 raw-body: 2.5.2
resolve: 1.17.0 resolve: 1.17.0
semver: 6.3.0 semver: 6.3.0
slash: 3.0.0 slash: 3.0.0
...@@ -13258,10 +12904,6 @@ packages: ...@@ -13258,10 +12904,6 @@ packages:
/lodash.isequal@4.5.0: /lodash.isequal@4.5.0:
resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==}
/lodash.isequalwith@4.4.0:
resolution: {integrity: sha512-dcZON0IalGBpRmJBmMkaoV7d3I80R2O+FrzsZyHdNSFrANq/cgDqKQNmAHE8UEj4+QYWwwhkQOVdLHiAopzlsQ==}
dev: true
/lodash.ismatch@4.4.0: /lodash.ismatch@4.4.0:
resolution: {integrity: sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g==} resolution: {integrity: sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g==}
dev: true dev: true
...@@ -14927,11 +14569,11 @@ packages: ...@@ -14927,11 +14569,11 @@ packages:
resolution: {integrity: sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==} resolution: {integrity: sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==}
dev: true dev: true
/nx-cloud@16.1.0: /nx-cloud@16.0.5:
resolution: {integrity: sha512-2K5OuJ4MEDrn2solje2X+a3UxSCdfR5PIscCRQbBANyvJfl3hGJSTxz0n5xeJJX4cKcQlfAxDQFRH6DHNdTGPQ==} resolution: {integrity: sha512-13P7r0aKikjBtmdZrNorwXzVPeVIV4MLEwqGY+DEG6doLBtI5KqEQk/d5B5l2dCF2BEi/LXEmLYCmf9gwbOJ+Q==}
hasBin: true hasBin: true
dependencies: dependencies:
'@nrwl/nx-cloud': 16.1.0 '@nrwl/nx-cloud': 16.0.5
axios: 1.1.3 axios: 1.1.3
chalk: 4.1.2 chalk: 4.1.2
dotenv: 10.0.0 dotenv: 10.0.0
...@@ -15804,11 +15446,6 @@ packages: ...@@ -15804,11 +15446,6 @@ packages:
resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==}
dev: true dev: true
/picomatch@2.3.0:
resolution: {integrity: sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==}
engines: {node: '>=8.6'}
dev: true
/picomatch@2.3.1: /picomatch@2.3.1:
resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
engines: {node: '>=8.6'} engines: {node: '>=8.6'}
...@@ -16435,7 +16072,6 @@ packages: ...@@ -16435,7 +16072,6 @@ packages:
iconv-lite: 0.4.24 iconv-lite: 0.4.24
unpipe: 1.0.0 unpipe: 1.0.0
dev: true dev: true
optional: true
/react-dom@18.2.0(react@18.2.0): /react-dom@18.2.0(react@18.2.0):
resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==} resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==}
...@@ -16606,18 +16242,6 @@ packages: ...@@ -16606,18 +16242,6 @@ packages:
string_decoder: 0.10.31 string_decoder: 0.10.31
dev: true dev: true
/readable-stream@2.3.7:
resolution: {integrity: sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==}
dependencies:
core-util-is: 1.0.3
inherits: 2.0.4
isarray: 1.0.0
process-nextick-args: 2.0.1
safe-buffer: 5.1.2
string_decoder: 1.1.1
util-deprecate: 1.0.2
dev: true
/readable-stream@2.3.8: /readable-stream@2.3.8:
resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==}
dependencies: dependencies:
...@@ -16659,7 +16283,7 @@ packages: ...@@ -16659,7 +16283,7 @@ packages:
resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
engines: {node: '>=8.10.0'} engines: {node: '>=8.10.0'}
dependencies: dependencies:
picomatch: 2.3.0 picomatch: 2.3.1
dev: true dev: true
/real-require@0.1.0: /real-require@0.1.0:
...@@ -17978,7 +17602,7 @@ packages: ...@@ -17978,7 +17602,7 @@ packages:
call-bind: 1.0.2 call-bind: 1.0.2
define-properties: 1.1.4 define-properties: 1.1.4
es-abstract: 1.21.1 es-abstract: 1.21.1
get-intrinsic: 1.1.3 get-intrinsic: 1.2.1
has-symbols: 1.0.3 has-symbols: 1.0.3
internal-slot: 1.0.4 internal-slot: 1.0.4
regexp.prototype.flags: 1.4.3 regexp.prototype.flags: 1.4.3
...@@ -18090,7 +17714,7 @@ packages: ...@@ -18090,7 +17714,7 @@ packages:
dev: true dev: true
/strip-hex-prefix@1.0.0: /strip-hex-prefix@1.0.0:
resolution: {integrity: sha512-q8d4ue7JGEiVcypji1bALTos+0pWtyGlivAWyPuTkHzuTCJqrK9sWxYQZUq6Nq3cuyv3bm734IhHvHtGGURU6A==} resolution: {integrity: sha1-DF8VX+8RUTczd96du1iNoFUA428=}
engines: {node: '>=6.5.0', npm: '>=3'} engines: {node: '>=6.5.0', npm: '>=3'}
dependencies: dependencies:
is-hex-prefixed: 1.0.0 is-hex-prefixed: 1.0.0
...@@ -18154,7 +17778,7 @@ packages: ...@@ -18154,7 +17778,7 @@ packages:
formidable: 1.2.2 formidable: 1.2.2
methods: 1.1.2 methods: 1.1.2
mime: 2.6.0 mime: 2.6.0
qs: 6.11.0 qs: 6.11.2
readable-stream: 3.6.2 readable-stream: 3.6.2
semver: 7.5.3 semver: 7.5.3
transitivePeerDependencies: transitivePeerDependencies:
...@@ -18394,7 +18018,7 @@ packages: ...@@ -18394,7 +18018,7 @@ packages:
/through2@2.0.5: /through2@2.0.5:
resolution: {integrity: sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==} resolution: {integrity: sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==}
dependencies: dependencies:
readable-stream: 2.3.7 readable-stream: 2.3.8
xtend: 4.0.2 xtend: 4.0.2
dev: true dev: true
...@@ -18790,7 +18414,7 @@ packages: ...@@ -18790,7 +18414,7 @@ packages:
resolution: {integrity: sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==} resolution: {integrity: sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==}
/tsort@0.0.1: /tsort@0.0.1:
resolution: {integrity: sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw==} resolution: {integrity: sha1-4igPXoF/i/QnVlf9D5rr1E9aJ4Y=}
dev: true dev: true
/tsup@7.1.0(typescript@5.1.6): /tsup@7.1.0(typescript@5.1.6):
...@@ -18839,17 +18463,6 @@ packages: ...@@ -18839,17 +18463,6 @@ packages:
typescript: 4.9.3 typescript: 4.9.3
dev: true dev: true
/tsx@3.12.7:
resolution: {integrity: sha512-C2Ip+jPmqKd1GWVQDvz/Eyc6QJbGfE7NrR3fx5BpEHMZsEHoIxHL1j+lKdGobr8ovEyqeNkPLSKp6SCSOt7gmw==}
hasBin: true
dependencies:
'@esbuild-kit/cjs-loader': 2.4.2
'@esbuild-kit/core-utils': 3.0.0
'@esbuild-kit/esm-loader': 2.5.5
optionalDependencies:
fsevents: 2.3.2
dev: true
/tty-table@4.1.6: /tty-table@4.1.6:
resolution: {integrity: sha512-kRj5CBzOrakV4VRRY5kUWbNYvo/FpOsz65DzI5op9P+cHov3+IqPbo1JE1ZnQGkHdZgNFDsrEjrfqqy/Ply9fw==} resolution: {integrity: sha512-kRj5CBzOrakV4VRRY5kUWbNYvo/FpOsz65DzI5op9P+cHov3+IqPbo1JE1ZnQGkHdZgNFDsrEjrfqqy/Ply9fw==}
engines: {node: '>=8.0.0'} engines: {node: '>=8.0.0'}
......
...@@ -66,7 +66,9 @@ location as the entire address space is unprotected. ...@@ -66,7 +66,9 @@ location as the entire address space is unprotected.
### Heap ### Heap
FPVM state contains a `heap` that tracks the base address of the most recent memory allocation. FPVM state contains a `heap` that tracks the base address of the most recent memory allocation.
Heap pages are bump allocated at the page boundary, per `mmap` syscall. The page size is 4096. Heap pages are bump allocated at the page boundary, per `mmap` syscall.
mmap-ing is purely to satisfy program runtimes that need the memory-pointer
result of the syscall to locate free memory. The page size is 4096.
The FPVM has a fixed program break at `0x40000000`. However, the FPVM is permitted to extend the The FPVM has a fixed program break at `0x40000000`. However, the FPVM is permitted to extend the
heap beyond this limit via mmap syscalls. heap beyond this limit via mmap syscalls.
...@@ -105,8 +107,9 @@ The following table list summarizes the supported syscalls and their behaviors. ...@@ -105,8 +107,9 @@ The following table list summarizes the supported syscalls and their behaviors.
| 4004 | write | uint32 fd | char *buf | uint32 count | Similar behavior as Linux/MIPS with support for unaligned writes. See [I/O](#io) for more details. | | 4004 | write | uint32 fd | char *buf | uint32 count | Similar behavior as Linux/MIPS with support for unaligned writes. See [I/O](#io) for more details. |
| 4055 | fcntl | uint32 fd | int32 cmd | | Similar behavior as Linux/MIPS. Only the `F_GETFL` (3) cmd is supported. Sets errno to `0x16` for all other commands | | 4055 | fcntl | uint32 fd | int32 cmd | | Similar behavior as Linux/MIPS. Only the `F_GETFL` (3) cmd is supported. Sets errno to `0x16` for all other commands |
For all of the above syscalls, an error is indicated by setting the return register (`$v0`) to For all of the above syscalls, an error is indicated by setting the return
`0xFFFFFFFF` (-1) and `errno` (`$a3`) is set accordingly. register (`$v0`) to `0xFFFFFFFF` (-1) and `errno` (`$a3`) is set accordingly.
The VM must not modify any register other than `$v0` and `$a3` during syscall handling.
For unsupported syscalls, the VM must do nothing except to zero out the syscall return (`$v0`) For unsupported syscalls, the VM must do nothing except to zero out the syscall return (`$v0`)
and errno (`$a3`) registers. and errno (`$a3`) registers.
......
...@@ -21,6 +21,8 @@ ...@@ -21,6 +21,8 @@
- [OptimismMintableERC721Factory](#optimismmintableerc721factory) - [OptimismMintableERC721Factory](#optimismmintableerc721factory)
- [BaseFeeVault](#basefeevault) - [BaseFeeVault](#basefeevault)
- [L1FeeVault](#l1feevault) - [L1FeeVault](#l1feevault)
- [SchemaRegistry](#schemaregistry)
- [EAS](#eas)
<!-- END doctoc generated TOC please keep comment here to allow auto update --> <!-- END doctoc generated TOC please keep comment here to allow auto update -->
...@@ -311,3 +313,20 @@ Address: `0x420000000000000000000000000000000000001a` ...@@ -311,3 +313,20 @@ Address: `0x420000000000000000000000000000000000001a`
The `L1FeeVault` predeploy receives the L1 portion of the transaction fees. The `L1FeeVault` predeploy receives the L1 portion of the transaction fees.
Once the contract has received a certain amount of fees, the ETH can be Once the contract has received a certain amount of fees, the ETH can be
withdrawn to an immutable address on L1. withdrawn to an immutable address on L1.
## SchemaRegistry
[Implementation](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/contracts/EAS/SchemaRegistry.sol)
Address: `0x4200000000000000000000000000000000000020`
The `SchemaRegistry` predeploy implements the global attestation schemas for the `Ethereum Attestation Service`
protocol.
## EAS
[Implementation](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/contracts/EAS/EAS.sol)
Address: `0x4200000000000000000000000000000000000021`
The `EAS` predeploy implements the `Ethereum Attestation Service` protocol.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment