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

Merge branch 'develop' into felipe/proxyd-ha

parents 9accb0e2 cd2b3444
---
'@eth-optimism/sdk': patch
---
Adds Sepolia & OP Sepolia support to SDK
---
'@eth-optimism/contracts-bedrock': patch
---
bumps sdk version to have access to sepolia deployments
...@@ -784,7 +784,7 @@ jobs: ...@@ -784,7 +784,7 @@ jobs:
steps: steps:
- checkout - checkout
- check-changed: - check-changed:
patterns: op-(.+),contracts-bedrock patterns: op-(.+),cannon,contracts-bedrock
- run: - run:
name: prep results dir name: prep results dir
command: mkdir -p /tmp/test-results command: mkdir -p /tmp/test-results
...@@ -887,6 +887,18 @@ jobs: ...@@ -887,6 +887,18 @@ jobs:
name: Build name: Build
command: make indexer command: make indexer
working_directory: indexer working_directory: indexer
- run:
name: Install node_modules
command: pnpm install --frozen-lockfile --prefer-offline
working_directory: indexer/api-ts
- run:
name: Install tygo
command: go install github.com/gzuidhof/tygo@latest
working_directory: indexer/api-ts
- run:
name: Check generated code
command: npm run generate && git diff --exit-code
working_directory: indexer/api-ts
devnet: devnet:
machine: machine:
......
...@@ -56,7 +56,7 @@ jobs: ...@@ -56,7 +56,7 @@ jobs:
uses: docker/setup-buildx-action@v1 uses: docker/setup-buildx-action@v1
- name: Login to Docker Hub - name: Login to Docker Hub
uses: docker/login-action@v1 uses: docker/login-action@v3
with: with:
username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }} username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }}
password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }} password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }}
...@@ -83,7 +83,7 @@ jobs: ...@@ -83,7 +83,7 @@ jobs:
uses: docker/setup-buildx-action@v1 uses: docker/setup-buildx-action@v1
- name: Login to Docker Hub - name: Login to Docker Hub
uses: docker/login-action@v1 uses: docker/login-action@v3
with: with:
username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }} username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }}
password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }} password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }}
...@@ -110,7 +110,7 @@ jobs: ...@@ -110,7 +110,7 @@ jobs:
uses: docker/setup-buildx-action@v1 uses: docker/setup-buildx-action@v1
- name: Login to Docker Hub - name: Login to Docker Hub
uses: docker/login-action@v1 uses: docker/login-action@v3
with: with:
username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }} username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }}
password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }} password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }}
...@@ -137,7 +137,7 @@ jobs: ...@@ -137,7 +137,7 @@ jobs:
uses: docker/setup-buildx-action@v1 uses: docker/setup-buildx-action@v1
- name: Login to Docker Hub - name: Login to Docker Hub
uses: docker/login-action@v1 uses: docker/login-action@v3
with: with:
username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }} username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }}
password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }} password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }}
...@@ -164,7 +164,7 @@ jobs: ...@@ -164,7 +164,7 @@ jobs:
uses: docker/setup-buildx-action@v1 uses: docker/setup-buildx-action@v1
- name: Login to Docker Hub - name: Login to Docker Hub
uses: docker/login-action@v1 uses: docker/login-action@v3
with: with:
username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }} username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }}
password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }} password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }}
...@@ -191,7 +191,7 @@ jobs: ...@@ -191,7 +191,7 @@ jobs:
uses: docker/setup-buildx-action@v1 uses: docker/setup-buildx-action@v1
- name: Login to Docker Hub - name: Login to Docker Hub
uses: docker/login-action@v1 uses: docker/login-action@v3
with: with:
username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }} username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }}
password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }} password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }}
...@@ -229,7 +229,7 @@ jobs: ...@@ -229,7 +229,7 @@ jobs:
uses: docker/setup-buildx-action@v1 uses: docker/setup-buildx-action@v1
- name: Login to Docker Hub - name: Login to Docker Hub
uses: docker/login-action@v1 uses: docker/login-action@v3
with: with:
username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }} username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }}
password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }} password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }}
......
...@@ -81,7 +81,7 @@ jobs: ...@@ -81,7 +81,7 @@ jobs:
uses: docker/setup-buildx-action@v1 uses: docker/setup-buildx-action@v1
- name: Login to Docker Hub - name: Login to Docker Hub
uses: docker/login-action@v1 uses: docker/login-action@v3
with: with:
username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }} username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }}
password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }} password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }}
...@@ -118,7 +118,7 @@ jobs: ...@@ -118,7 +118,7 @@ jobs:
uses: docker/setup-buildx-action@v1 uses: docker/setup-buildx-action@v1
- name: Login to Docker Hub - name: Login to Docker Hub
uses: docker/login-action@v1 uses: docker/login-action@v3
with: with:
username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }} username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }}
password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }} password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }}
...@@ -145,7 +145,7 @@ jobs: ...@@ -145,7 +145,7 @@ jobs:
uses: docker/setup-buildx-action@v1 uses: docker/setup-buildx-action@v1
- name: Login to Docker Hub - name: Login to Docker Hub
uses: docker/login-action@v1 uses: docker/login-action@v3
with: with:
username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }} username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }}
password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }} password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }}
...@@ -172,7 +172,7 @@ jobs: ...@@ -172,7 +172,7 @@ jobs:
uses: docker/setup-buildx-action@v1 uses: docker/setup-buildx-action@v1
- name: Login to Docker Hub - name: Login to Docker Hub
uses: docker/login-action@v1 uses: docker/login-action@v3
with: with:
username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }} username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }}
password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }} password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }}
...@@ -199,7 +199,7 @@ jobs: ...@@ -199,7 +199,7 @@ jobs:
uses: docker/setup-buildx-action@v1 uses: docker/setup-buildx-action@v1
- name: Login to Docker Hub - name: Login to Docker Hub
uses: docker/login-action@v1 uses: docker/login-action@v3
with: with:
username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }} username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }}
password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }} password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }}
...@@ -226,7 +226,7 @@ jobs: ...@@ -226,7 +226,7 @@ jobs:
uses: docker/setup-buildx-action@v1 uses: docker/setup-buildx-action@v1
- name: Login to Docker Hub - name: Login to Docker Hub
uses: docker/login-action@v1 uses: docker/login-action@v3
with: with:
username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }} username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }}
password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }} password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }}
...@@ -253,7 +253,7 @@ jobs: ...@@ -253,7 +253,7 @@ jobs:
uses: docker/setup-buildx-action@v1 uses: docker/setup-buildx-action@v1
- name: Login to Docker Hub - name: Login to Docker Hub
uses: docker/login-action@v1 uses: docker/login-action@v3
with: with:
username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }} username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }}
password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }} password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }}
......
...@@ -19,15 +19,14 @@ on: ...@@ -19,15 +19,14 @@ on:
type: choice type: choice
options: options:
- ci-builder - ci-builder
- fault-detector
- indexer - indexer
- chain-mon
- op-node - op-node
- op-batcher - op-batcher
- op-proposer - op-proposer
- op-challenger
- 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
......
...@@ -65,7 +65,7 @@ cannon: ...@@ -65,7 +65,7 @@ cannon:
cannon-prestate: op-program cannon cannon-prestate: op-program cannon
./cannon/bin/cannon load-elf --path op-program/bin/op-program-client.elf --out op-program/bin/prestate.json --meta op-program/bin/meta.json ./cannon/bin/cannon load-elf --path op-program/bin/op-program-client.elf --out op-program/bin/prestate.json --meta op-program/bin/meta.json
./cannon/bin/cannon run --proof-at '=0' --stop-at '=1' --input op-program/bin/prestate.json --meta op-program/bin/meta.json --proof-fmt 'op-program/bin/%d.json' --output /dev/null ./cannon/bin/cannon run --proof-at '=0' --stop-at '=1' --input op-program/bin/prestate.json --meta op-program/bin/meta.json --proof-fmt 'op-program/bin/%d.json' --output ""
mv op-program/bin/0.json op-program/bin/prestate-proof.json mv op-program/bin/0.json op-program/bin/prestate-proof.json
mod-tidy: mod-tidy:
...@@ -145,7 +145,6 @@ clean-node-modules: ...@@ -145,7 +145,6 @@ clean-node-modules:
rm -rf node_modules rm -rf node_modules
rm -rf packages/**/node_modules rm -rf packages/**/node_modules
tag-bedrock-go-modules: tag-bedrock-go-modules:
./ops/scripts/tag-bedrock-go-modules.sh $(BEDROCK_TAGS_REMOTE) $(VERSION) ./ops/scripts/tag-bedrock-go-modules.sh $(BEDROCK_TAGS_REMOTE) $(VERSION)
.PHONY: tag-bedrock-go-modules .PHONY: tag-bedrock-go-modules
......
...@@ -6,6 +6,7 @@ import ( ...@@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"io" "io"
"os" "os"
"path"
"github.com/ethereum-optimism/optimism/op-service/ioutil" "github.com/ethereum-optimism/optimism/op-service/ioutil"
) )
...@@ -27,19 +28,27 @@ func loadJSON[X any](inputPath string) (*X, error) { ...@@ -27,19 +28,27 @@ func loadJSON[X any](inputPath string) (*X, error) {
return &state, nil return &state, nil
} }
func writeJSON[X any](outputPath string, value X, outIfEmpty bool) error { func writeJSON[X any](outputPath string, value X) error {
if outputPath == "" {
return nil
}
var out io.Writer var out io.Writer
if outputPath != "" { finish := func() error { return nil }
f, err := ioutil.OpenCompressed(outputPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0755) if outputPath != "-" {
// Write to a tmp file but reserve the file extension if present
tmpPath := outputPath + "-tmp" + path.Ext(outputPath)
f, err := ioutil.OpenCompressed(tmpPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0755)
if err != nil { if err != nil {
return fmt.Errorf("failed to open output file: %w", err) return fmt.Errorf("failed to open output file: %w", err)
} }
defer f.Close() defer f.Close()
out = f out = f
} else if outIfEmpty { finish = func() error {
out = os.Stdout // Rename the file into place as atomically as the OS will allow
return os.Rename(tmpPath, outputPath)
}
} else { } else {
return nil out = os.Stdout
} }
enc := json.NewEncoder(out) enc := json.NewEncoder(out)
if err := enc.Encode(value); err != nil { if err := enc.Encode(value); err != nil {
...@@ -49,5 +58,8 @@ func writeJSON[X any](outputPath string, value X, outIfEmpty bool) error { ...@@ -49,5 +58,8 @@ func writeJSON[X any](outputPath string, value X, outIfEmpty bool) error {
if err != nil { if err != nil {
return fmt.Errorf("failed to append new-line: %w", err) return fmt.Errorf("failed to append new-line: %w", err)
} }
if err := finish(); err != nil {
return fmt.Errorf("failed to finish write: %w", err)
}
return nil return nil
} }
...@@ -13,7 +13,7 @@ func TestRoundTripJSON(t *testing.T) { ...@@ -13,7 +13,7 @@ func TestRoundTripJSON(t *testing.T) {
dir := t.TempDir() dir := t.TempDir()
file := filepath.Join(dir, "test.json") file := filepath.Join(dir, "test.json")
data := &jsonTestData{A: "yay", B: 3} data := &jsonTestData{A: "yay", B: 3}
err := writeJSON(file, data, false) err := writeJSON(file, data)
require.NoError(t, err) require.NoError(t, err)
// Confirm the file is uncompressed // Confirm the file is uncompressed
...@@ -32,7 +32,7 @@ func TestRoundTripJSONWithGzip(t *testing.T) { ...@@ -32,7 +32,7 @@ func TestRoundTripJSONWithGzip(t *testing.T) {
dir := t.TempDir() dir := t.TempDir()
file := filepath.Join(dir, "test.json.gz") file := filepath.Join(dir, "test.json.gz")
data := &jsonTestData{A: "yay", B: 3} data := &jsonTestData{A: "yay", B: 3}
err := writeJSON(file, data, false) err := writeJSON(file, data)
require.NoError(t, err) require.NoError(t, err)
// Confirm the file isn't raw JSON // Confirm the file isn't raw JSON
......
...@@ -24,7 +24,7 @@ var ( ...@@ -24,7 +24,7 @@ var (
} }
LoadELFOutFlag = &cli.PathFlag{ LoadELFOutFlag = &cli.PathFlag{
Name: "out", Name: "out",
Usage: "Output path to write JSON state to. State is dumped to stdout if set to empty string.", Usage: "Output path to write JSON state to. State is dumped to stdout if set to -. Not written if empty.",
Value: "state.json", Value: "state.json",
Required: false, Required: false,
} }
...@@ -66,10 +66,10 @@ func LoadELF(ctx *cli.Context) error { ...@@ -66,10 +66,10 @@ func LoadELF(ctx *cli.Context) error {
if err != nil { if err != nil {
return fmt.Errorf("failed to compute program metadata: %w", err) return fmt.Errorf("failed to compute program metadata: %w", err)
} }
if err := writeJSON[*mipsevm.Metadata](ctx.Path(LoadELFMetaFlag.Name), meta, false); err != nil { if err := writeJSON[*mipsevm.Metadata](ctx.Path(LoadELFMetaFlag.Name), meta); err != nil {
return fmt.Errorf("failed to output metadata: %w", err) return fmt.Errorf("failed to output metadata: %w", err)
} }
return writeJSON[*mipsevm.State](ctx.Path(LoadELFOutFlag.Name), state, true) return writeJSON[*mipsevm.State](ctx.Path(LoadELFOutFlag.Name), state)
} }
var LoadELFCommand = &cli.Command{ var LoadELFCommand = &cli.Command{
......
...@@ -28,7 +28,7 @@ var ( ...@@ -28,7 +28,7 @@ var (
} }
RunOutputFlag = &cli.PathFlag{ RunOutputFlag = &cli.PathFlag{
Name: "output", Name: "output",
Usage: "path of output JSON state. Stdout if left empty.", Usage: "path of output JSON state. Not written if empty, use - to write to Stdout.",
TakesFile: true, TakesFile: true,
Value: "out.json", Value: "out.json",
Required: false, Required: false,
...@@ -42,7 +42,7 @@ var ( ...@@ -42,7 +42,7 @@ var (
} }
RunProofFmtFlag = &cli.StringFlag{ RunProofFmtFlag = &cli.StringFlag{
Name: "proof-fmt", Name: "proof-fmt",
Usage: "format for proof data output file names. Proof data is written to stdout if empty.", Usage: "format for proof data output file names. Proof data is written to stdout if -.",
Value: "proof-%d.json", Value: "proof-%d.json",
Required: false, Required: false,
} }
...@@ -66,7 +66,7 @@ var ( ...@@ -66,7 +66,7 @@ var (
} }
RunMetaFlag = &cli.PathFlag{ RunMetaFlag = &cli.PathFlag{
Name: "meta", Name: "meta",
Usage: "path to metadata file for symbol lookup for enhanced debugging info durign execution.", Usage: "path to metadata file for symbol lookup for enhanced debugging info during execution.",
Value: "meta.json", Value: "meta.json",
Required: false, Required: false,
} }
...@@ -324,7 +324,7 @@ func Run(ctx *cli.Context) error { ...@@ -324,7 +324,7 @@ func Run(ctx *cli.Context) error {
} }
if snapshotAt(state) { if snapshotAt(state) {
if err := writeJSON(fmt.Sprintf(snapshotFmt, step), state, false); err != nil { if err := writeJSON(fmt.Sprintf(snapshotFmt, step), state); err != nil {
return fmt.Errorf("failed to write state snapshot: %w", err) return fmt.Errorf("failed to write state snapshot: %w", err)
} }
} }
...@@ -360,7 +360,7 @@ func Run(ctx *cli.Context) error { ...@@ -360,7 +360,7 @@ func Run(ctx *cli.Context) error {
proof.OracleValue = witness.PreimageValue proof.OracleValue = witness.PreimageValue
proof.OracleOffset = witness.PreimageOffset proof.OracleOffset = witness.PreimageOffset
} }
if err := writeJSON(fmt.Sprintf(proofFmt, step), proof, true); err != nil { if err := writeJSON(fmt.Sprintf(proofFmt, step), proof); err != nil {
return fmt.Errorf("failed to write proof data: %w", err) return fmt.Errorf("failed to write proof data: %w", err)
} }
} else { } else {
...@@ -371,7 +371,7 @@ func Run(ctx *cli.Context) error { ...@@ -371,7 +371,7 @@ func Run(ctx *cli.Context) error {
} }
} }
if err := writeJSON(ctx.Path(RunOutputFlag.Name), state, true); err != nil { if err := writeJSON(ctx.Path(RunOutputFlag.Name), state); err != nil {
return fmt.Errorf("failed to write state output: %w", err) return fmt.Errorf("failed to write state output: %w", err)
} }
return nil return nil
......
package mipsevm package mipsevm
import ( import (
"bytes"
"compress/zlib"
"encoding/base64"
"encoding/hex" "encoding/hex"
"encoding/json"
"fmt" "fmt"
"io"
"sync"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
) )
var zlibWriterPool = sync.Pool{
New: func() any {
var buf bytes.Buffer
return zlib.NewWriter(&buf)
},
}
type Page [PageSize]byte type Page [PageSize]byte
func (p *Page) MarshalText() ([]byte, error) { func (p *Page) MarshalJSON() ([]byte, error) { // nosemgrep
dst := make([]byte, hex.EncodedLen(len(p))) var out bytes.Buffer
hex.Encode(dst, p[:]) w := zlibWriterPool.Get().(*zlib.Writer)
return dst, nil defer zlibWriterPool.Put(w)
w.Reset(&out)
if _, err := w.Write(p[:]); err != nil {
return nil, err
}
if err := w.Close(); err != nil {
return nil, err
}
return json.Marshal(out.Bytes())
}
func (p *Page) UnmarshalJSON(dat []byte) error {
// Strip off the `"` characters at the start & end.
dat = dat[1 : len(dat)-1]
// Decode b64 then decompress
r, err := zlib.NewReader(base64.NewDecoder(base64.StdEncoding, bytes.NewReader(dat)))
if err != nil {
return err
}
defer r.Close()
if n, err := r.Read(p[:]); n != PageSize {
return fmt.Errorf("epxeted %d bytes, but got %d", PageSize, n)
} else if err == io.EOF {
return nil
} else {
return err
}
} }
func (p *Page) UnmarshalText(dat []byte) error { func (p *Page) UnmarshalText(dat []byte) error {
......
...@@ -29,7 +29,8 @@ determine the root claim to use when creating the game. In simple cases, where t ...@@ -29,7 +29,8 @@ determine the root claim to use when creating the game. In simple cases, where t
arbitrary hash can be used for claim values. For more advanced cases [cannon can be used](./cannon.md) to generate a arbitrary hash can be used for claim values. For more advanced cases [cannon can be used](./cannon.md) to generate a
trace, including the claim values to use at specific steps. Note that it is not valid to create a game that disputes an trace, including the claim values to use at specific steps. Note that it is not valid to create a game that disputes an
output root, using the final hash from a trace that confirms the output root is valid. To dispute an output root output root, using the final hash from a trace that confirms the output root is valid. To dispute an output root
successfully, the trace must resolve that the disputed output root is invalid. successfully, the trace must resolve that the disputed output root is invalid. This is indicated by the first byte of
the claim value being set to the invalid [VM status](../../specs/cannon-fault-proof-vm.md#state-hash) (`0x01`).
The game can then be created by calling the `create` method on the `DisputeGameFactory` contract. This requires three The game can then be created by calling the `create` method on the `DisputeGameFactory` contract. This requires three
parameters: parameters:
......
...@@ -208,6 +208,6 @@ require ( ...@@ -208,6 +208,6 @@ require (
rsc.io/tmplfunc v0.0.3 // indirect rsc.io/tmplfunc v0.0.3 // indirect
) )
replace github.com/ethereum/go-ethereum v1.12.0 => github.com/ethereum-optimism/op-geth v1.101200.0-rc.1.0.20230818191139-f7376a28049b replace github.com/ethereum/go-ethereum v1.12.0 => github.com/ethereum-optimism/op-geth v1.101200.2-rc.1.0.20230914224024-b84ba11915a0
//replace github.com/ethereum/go-ethereum v1.12.0 => ../go-ethereum //replace github.com/ethereum/go-ethereum v1.12.0 => ../go-ethereum
...@@ -162,8 +162,8 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7 ...@@ -162,8 +162,8 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw=
github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3 h1:RWHKLhCrQThMfch+QJ1Z8veEq5ZO3DfIhZ7xgRP9WTc= github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3 h1:RWHKLhCrQThMfch+QJ1Z8veEq5ZO3DfIhZ7xgRP9WTc=
github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3/go.mod h1:QziizLAiF0KqyLdNJYD7O5cpDlaFMNZzlxYNcWsJUxs= github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3/go.mod h1:QziizLAiF0KqyLdNJYD7O5cpDlaFMNZzlxYNcWsJUxs=
github.com/ethereum-optimism/op-geth v1.101200.0-rc.1.0.20230818191139-f7376a28049b h1:YF2FE/QnbhvrHwDYJHnbTKgJvw2aKwB/dd7PO1zKNqY= github.com/ethereum-optimism/op-geth v1.101200.2-rc.1.0.20230914224024-b84ba11915a0 h1:Qcu7OVMbKvbu7aaDC31OY0JCqFIr2N+/SGdBTnxukCs=
github.com/ethereum-optimism/op-geth v1.101200.0-rc.1.0.20230818191139-f7376a28049b/go.mod h1:gRnPb21PoKcHm3kHqj9BQlQkwmhOGUvQoGEbC7z852Q= github.com/ethereum-optimism/op-geth v1.101200.2-rc.1.0.20230914224024-b84ba11915a0/go.mod h1:gRnPb21PoKcHm3kHqj9BQlQkwmhOGUvQoGEbC7z852Q=
github.com/ethereum-optimism/superchain-registry/superchain v0.0.0-20230817174831-5d3ca1966435 h1:2CzkJkkTLuVyoVFkoW5w6vDB2Q7eJzxXw/ybA17xjqM= github.com/ethereum-optimism/superchain-registry/superchain v0.0.0-20230817174831-5d3ca1966435 h1:2CzkJkkTLuVyoVFkoW5w6vDB2Q7eJzxXw/ybA17xjqM=
github.com/ethereum-optimism/superchain-registry/superchain v0.0.0-20230817174831-5d3ca1966435/go.mod h1:v2YpePbdGBF0Gr6VWq49MFFmcTW0kRYZ2ingBJYWEwg= github.com/ethereum-optimism/superchain-registry/superchain v0.0.0-20230817174831-5d3ca1966435/go.mod h1:v2YpePbdGBF0Gr6VWq49MFFmcTW0kRYZ2ingBJYWEwg=
github.com/ethereum/c-kzg-4844 v0.2.0 h1:+cUvymlnoDDQgMInp25Bo3OmLajmmY8mLJ/tLjqd77Q= github.com/ethereum/c-kzg-4844 v0.2.0 h1:+cUvymlnoDDQgMInp25Bo3OmLajmmY8mLJ/tLjqd77Q=
......
MIT License
Copyright (c) 2022 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.
Generated typescript types for https://github.com/ethereum-optimism/optimism/tree/develop/indexer
// Code generated by tygo. DO NOT EDIT.
//////////
// source: deposits.go
export interface DepositItem {
guid: string;
from: string;
to: string;
timestamp: number /* uint64 */;
l1BlockHash: string;
l1TxHash: string;
l2TxHash: string;
amount: string;
l1TokenAddress: string;
l2TokenAddress: string;
}
export interface DepositResponse {
cursor: string;
hasNextPage: boolean;
items: DepositItem[];
}
//////////
// source: routes.go
export interface Routes {
Logger: any /* log.Logger */;
BridgeTransfersView: any /* database.BridgeTransfersView */;
Router?: any /* chi.Mux */;
}
//////////
// source: withdrawals.go
export interface WithdrawalItem {
guid: string;
from: string;
to: string;
transactionHash: string;
timestamp: number /* uint64 */;
l2BlockHash: string;
amount: string;
proofTransactionHash: string;
claimTransactionHash: string;
l1TokenAddress: string;
l2TokenAddress: string;
}
export interface WithdrawalResponse {
cursor: string;
hasNextPage: boolean;
items: WithdrawalItem[];
}
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// indexer.ts
var indexer_exports = {};
__export(indexer_exports, {
depositEndpoint: () => depositEndpoint,
withdrawalEndoint: () => withdrawalEndoint
});
module.exports = __toCommonJS(indexer_exports);
var createQueryString = ({ cursor, limit }) => {
if (cursor === void 0 && limit === void 0) {
return "";
}
const queries = [];
if (cursor) {
queries.push(`cursor=${cursor}`);
}
if (limit) {
queries.push(`limit=${limit}`);
}
return `?${queries.join("&")}`;
};
var depositEndpoint = ({ baseUrl = "", address, cursor, limit }) => {
return [baseUrl, "deposits", `${address}${createQueryString({ cursor, limit })}`].join("/");
};
var withdrawalEndoint = ({ baseUrl = "", address, cursor, limit }) => {
return [baseUrl, "withdrawals", `${address}${createQueryString({ cursor, limit })}`].join("/");
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
depositEndpoint,
withdrawalEndoint
});
//# sourceMappingURL=indexer.cjs.map
\ No newline at end of file
{"version":3,"sources":["indexer.ts"],"sourcesContent":["export * from './generated'\n\ntype PaginationOptions = {\n limit?: number\n cursor?: string\n}\n\ntype Options = {\n baseUrl?: string\n address: `0x${string}`\n} & PaginationOptions\n\nconst createQueryString = ({ cursor, limit }: PaginationOptions): string => {\n if (cursor === undefined && limit === undefined) {\n return ''\n }\n const queries: string[] = []\n if (cursor) {\n queries.push(`cursor=${cursor}`)\n }\n if (limit) {\n queries.push(`limit=${limit}`)\n }\n return `?${queries.join('&')}`\n}\n\nexport const depositEndpoint = ({ baseUrl = '', address, cursor, limit }: Options): string => {\n return [baseUrl, 'deposits', `${address}${createQueryString({ cursor, limit })}`].join('/')\n}\n\nexport const withdrawalEndoint = ({ baseUrl = '', address, cursor, limit }: Options): string => {\n return [baseUrl, 'withdrawals', `${address}${createQueryString({ cursor, limit })}`].join('/')\n}\n\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAYA,IAAM,oBAAoB,CAAC,EAAE,QAAQ,MAAM,MAAiC;AAC1E,MAAI,WAAW,UAAa,UAAU,QAAW;AAC/C,WAAO;AAAA,EACT;AACA,QAAM,UAAoB,CAAC;AAC3B,MAAI,QAAQ;AACV,YAAQ,KAAK,UAAU,MAAM,EAAE;AAAA,EACjC;AACA,MAAI,OAAO;AACT,YAAQ,KAAK,SAAS,KAAK,EAAE;AAAA,EAC/B;AACA,SAAO,IAAI,QAAQ,KAAK,GAAG,CAAC;AAC9B;AAEO,IAAM,kBAAkB,CAAC,EAAE,UAAU,IAAI,SAAS,QAAQ,MAAM,MAAuB;AAC5F,SAAO,CAAC,SAAS,YAAY,GAAG,OAAO,GAAG,kBAAkB,EAAE,QAAQ,MAAM,CAAC,CAAC,EAAE,EAAE,KAAK,GAAG;AAC5F;AAEO,IAAM,oBAAoB,CAAC,EAAE,UAAU,IAAI,SAAS,QAAQ,MAAM,MAAuB;AAC9F,SAAO,CAAC,SAAS,eAAe,GAAG,OAAO,GAAG,kBAAkB,EAAE,QAAQ,MAAM,CAAC,CAAC,EAAE,EAAE,KAAK,GAAG;AAC/F;","names":[]}
\ No newline at end of file
// indexer.ts
var createQueryString = ({ cursor, limit }) => {
if (cursor === void 0 && limit === void 0) {
return "";
}
const queries = [];
if (cursor) {
queries.push(`cursor=${cursor}`);
}
if (limit) {
queries.push(`limit=${limit}`);
}
return `?${queries.join("&")}`;
};
var depositEndpoint = ({ baseUrl = "", address, cursor, limit }) => {
return [baseUrl, "deposits", `${address}${createQueryString({ cursor, limit })}`].join("/");
};
var withdrawalEndoint = ({ baseUrl = "", address, cursor, limit }) => {
return [baseUrl, "withdrawals", `${address}${createQueryString({ cursor, limit })}`].join("/");
};
export {
depositEndpoint,
withdrawalEndoint
};
//# sourceMappingURL=indexer.js.map
\ No newline at end of file
{"version":3,"sources":["indexer.ts"],"sourcesContent":["export * from './generated'\n\ntype PaginationOptions = {\n limit?: number\n cursor?: string\n}\n\ntype Options = {\n baseUrl?: string\n address: `0x${string}`\n} & PaginationOptions\n\nconst createQueryString = ({ cursor, limit }: PaginationOptions): string => {\n if (cursor === undefined && limit === undefined) {\n return ''\n }\n const queries: string[] = []\n if (cursor) {\n queries.push(`cursor=${cursor}`)\n }\n if (limit) {\n queries.push(`limit=${limit}`)\n }\n return `?${queries.join('&')}`\n}\n\nexport const depositEndpoint = ({ baseUrl = '', address, cursor, limit }: Options): string => {\n return [baseUrl, 'deposits', `${address}${createQueryString({ cursor, limit })}`].join('/')\n}\n\nexport const withdrawalEndoint = ({ baseUrl = '', address, cursor, limit }: Options): string => {\n return [baseUrl, 'withdrawals', `${address}${createQueryString({ cursor, limit })}`].join('/')\n}\n\n"],"mappings":";AAYA,IAAM,oBAAoB,CAAC,EAAE,QAAQ,MAAM,MAAiC;AAC1E,MAAI,WAAW,UAAa,UAAU,QAAW;AAC/C,WAAO;AAAA,EACT;AACA,QAAM,UAAoB,CAAC;AAC3B,MAAI,QAAQ;AACV,YAAQ,KAAK,UAAU,MAAM,EAAE;AAAA,EACjC;AACA,MAAI,OAAO;AACT,YAAQ,KAAK,SAAS,KAAK,EAAE;AAAA,EAC/B;AACA,SAAO,IAAI,QAAQ,KAAK,GAAG,CAAC;AAC9B;AAEO,IAAM,kBAAkB,CAAC,EAAE,UAAU,IAAI,SAAS,QAAQ,MAAM,MAAuB;AAC5F,SAAO,CAAC,SAAS,YAAY,GAAG,OAAO,GAAG,kBAAkB,EAAE,QAAQ,MAAM,CAAC,CAAC,EAAE,EAAE,KAAK,GAAG;AAC5F;AAEO,IAAM,oBAAoB,CAAC,EAAE,UAAU,IAAI,SAAS,QAAQ,MAAM,MAAuB;AAC9F,SAAO,CAAC,SAAS,eAAe,GAAG,OAAO,GAAG,kBAAkB,EAAE,QAAQ,MAAM,CAAC,CAAC,EAAE,EAAE,KAAK,GAAG;AAC/F;","names":[]}
\ No newline at end of file
import { test, expect } from 'vitest'
import { depositEndpoint, withdrawalEndoint } from './indexer.ts'
test(depositEndpoint.name, () => {
expect(depositEndpoint({ baseUrl: 'http://localhost:8080/api/v0', address: '0x1234', cursor: '0x1235', limit: 10 })).toMatchInlineSnapshot('"http://localhost:8080/api/v0/deposits/0x1234?cursor=0x1235&limit=10"')
expect(depositEndpoint({ baseUrl: 'http://localhost:8080/api/v0', address: '0x1234' })).toMatchInlineSnapshot('"http://localhost:8080/api/v0/deposits/0x1234"')
})
test(withdrawalEndoint.name, () => {
expect(withdrawalEndoint({ baseUrl: 'http://localhost:8080/api/v0', address: '0x1234', cursor: '0x1235', limit: 10 })).toMatchInlineSnapshot('"http://localhost:8080/api/v0/withdrawals/0x1234?cursor=0x1235&limit=10"')
expect(withdrawalEndoint({ baseUrl: 'http://localhost:8080/api/v0', address: '0x1234' })).toMatchInlineSnapshot('"http://localhost:8080/api/v0/withdrawals/0x1234"')
})
export * from './generated'
type PaginationOptions = {
limit?: number
cursor?: string
}
type Options = {
baseUrl?: string
address: `0x${string}`
} & PaginationOptions
const createQueryString = ({ cursor, limit }: PaginationOptions): string => {
if (cursor === undefined && limit === undefined) {
return ''
}
const queries: string[] = []
if (cursor) {
queries.push(`cursor=${cursor}`)
}
if (limit) {
queries.push(`limit=${limit}`)
}
return `?${queries.join('&')}`
}
export const depositEndpoint = ({ baseUrl = '', address, cursor, limit }: Options): string => {
return [baseUrl, 'deposits', `${address}${createQueryString({ cursor, limit })}`].join('/')
}
export const withdrawalEndoint = ({ baseUrl = '', address, cursor, limit }: Options): string => {
return [baseUrl, 'withdrawals', `${address}${createQueryString({ cursor, limit })}`].join('/')
}
{
"name": "@eth-optimism/indexer-api",
"version": "0.0.3",
"description": "[Optimism] typescript types for the indexer service",
"main": "indexer.cjs",
"module": "indexer.js",
"types": "indexer.ts",
"type": "module",
"files": [
"*.ts",
"*.ts",
"*.js",
"*.js.map",
"*.cjs",
"*.cjs.map",
"LICENSE"
],
"scripts": {
"clean": "rm -rf generated.ts indexer.cjs indexer.js",
"generate": "npm run clean && tygo generate && mv ../api/routes/index.ts generated.ts && tsup",
"test": "vitest"
},
"keywords": [
"optimism",
"ethereum",
"indexer"
],
"homepage": "https://github.com/ethereum-optimism/optimism/tree/develop/indexer#readme",
"license": "MIT",
"author": "Optimism PBC",
"repository": {
"type": "git",
"url": "https://github.com/ethereum-optimism/optimism.git"
},
"devDependencies": {
"tsup": "^7.2.0",
"vitest": "^0.34.4"
}
}
{
"compilerOptions": {
"outDir": "dist",
"strict": true,
"skipLibCheck": true,
"module": "ESNext",
"moduleResolution": "NodeNext",
"jsx": "react",
"target": "ESNext",
"noEmit": true
},
"include": ["."]
}
import packageJson from './package.json'
export default {
name: packageJson.name,
entry: ['indexer.ts'],
outDir: '.',
format: ['esm', 'cjs'],
splitting: false,
sourcemap: true,
clean: false,
}
packages:
- path: "github.com/ethereum-optimism/optimism/indexer/api/routes"
package api package api
import ( import (
"encoding/json"
"fmt" "fmt"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"testing" "testing"
"github.com/ethereum-optimism/optimism/indexer/api/routes"
"github.com/ethereum-optimism/optimism/indexer/config" "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/op-node/testlog" "github.com/ethereum-optimism/optimism/op-node/testlog"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
) )
// MockBridgeTransfersView mocks the BridgeTransfersView interface // MockBridgeTransfersView mocks the BridgeTransfersView interface
...@@ -70,6 +73,8 @@ func (mbv *MockBridgeTransfersView) L1BridgeDepositsByAddress(address common.Add ...@@ -70,6 +73,8 @@ func (mbv *MockBridgeTransfersView) L1BridgeDepositsByAddress(address common.Add
{ {
L1BridgeDeposit: deposit, L1BridgeDeposit: deposit,
L1TransactionHash: common.HexToHash("0x123"), L1TransactionHash: common.HexToHash("0x123"),
L2TransactionHash: common.HexToHash("0x555"),
L1BlockHash: common.HexToHash("0x456"),
}, },
}, },
}, nil }, nil
...@@ -79,8 +84,11 @@ func (mbv *MockBridgeTransfersView) L2BridgeWithdrawalsByAddress(address common. ...@@ -79,8 +84,11 @@ func (mbv *MockBridgeTransfersView) L2BridgeWithdrawalsByAddress(address common.
return &database.L2BridgeWithdrawalsResponse{ return &database.L2BridgeWithdrawalsResponse{
Withdrawals: []database.L2BridgeWithdrawalWithTransactionHashes{ Withdrawals: []database.L2BridgeWithdrawalWithTransactionHashes{
{ {
L2BridgeWithdrawal: withdrawal, L2BridgeWithdrawal: withdrawal,
L2TransactionHash: common.HexToHash("0x789"), L2TransactionHash: common.HexToHash("0x789"),
L2BlockHash: common.HexToHash("0x456"),
ProvenL1TransactionHash: common.HexToHash("0x123"),
FinalizedL1TransactionHash: common.HexToHash("0x123"),
}, },
}, },
}, nil }, nil
...@@ -107,6 +115,17 @@ func TestL1BridgeDepositsHandler(t *testing.T) { ...@@ -107,6 +115,17 @@ func TestL1BridgeDepositsHandler(t *testing.T) {
api.Router.ServeHTTP(responseRecorder, request) api.Router.ServeHTTP(responseRecorder, request)
assert.Equal(t, http.StatusOK, responseRecorder.Code) assert.Equal(t, http.StatusOK, responseRecorder.Code)
var resp routes.DepositResponse
err = json.Unmarshal(responseRecorder.Body.Bytes(), &resp)
assert.Nil(t, err)
require.Len(t, resp.Items, 1)
assert.Equal(t, resp.Items[0].L1BlockHash, common.HexToHash("0x456").String())
assert.Equal(t, resp.Items[0].L1TxHash, common.HexToHash("0x123").String())
assert.Equal(t, resp.Items[0].Timestamp, deposit.Tx.Timestamp)
assert.Equal(t, resp.Items[0].L2TxHash, common.HexToHash("555").String())
} }
func TestL2BridgeWithdrawalsByAddressHandler(t *testing.T) { func TestL2BridgeWithdrawalsByAddressHandler(t *testing.T) {
...@@ -118,5 +137,22 @@ func TestL2BridgeWithdrawalsByAddressHandler(t *testing.T) { ...@@ -118,5 +137,22 @@ func TestL2BridgeWithdrawalsByAddressHandler(t *testing.T) {
responseRecorder := httptest.NewRecorder() responseRecorder := httptest.NewRecorder()
api.Router.ServeHTTP(responseRecorder, request) api.Router.ServeHTTP(responseRecorder, request)
assert.Equal(t, http.StatusOK, responseRecorder.Code) var resp routes.WithdrawalResponse
err = json.Unmarshal(responseRecorder.Body.Bytes(), &resp)
assert.Nil(t, err)
require.Len(t, resp.Items, 1)
assert.Equal(t, resp.Items[0].Guid, withdrawal.TransactionWithdrawalHash.String())
assert.Equal(t, resp.Items[0].L2BlockHash, common.HexToHash("0x456").String())
assert.Equal(t, resp.Items[0].From, withdrawal.Tx.FromAddress.String())
assert.Equal(t, resp.Items[0].To, withdrawal.Tx.ToAddress.String())
assert.Equal(t, resp.Items[0].TransactionHash, common.HexToHash("0x789").String())
assert.Equal(t, resp.Items[0].Amount, withdrawal.Tx.Amount.String())
assert.Equal(t, resp.Items[0].ProofTransactionHash, common.HexToHash("0x123").String())
assert.Equal(t, resp.Items[0].ClaimTransactionHash, common.HexToHash("0x123").String())
assert.Equal(t, resp.Items[0].L1TokenAddress, withdrawal.TokenPair.RemoteTokenAddress.String())
assert.Equal(t, resp.Items[0].L2TokenAddress, withdrawal.TokenPair.LocalTokenAddress.String())
assert.Equal(t, resp.Items[0].Timestamp, withdrawal.Tx.Timestamp)
} }
...@@ -7,32 +7,6 @@ import ( ...@@ -7,32 +7,6 @@ import (
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
) )
// lazily typing numbers fixme
type Transaction struct {
Timestamp uint64 `json:"timestamp"`
TransactionHash string `json:"transactionHash"`
}
type Block struct {
BlockNumber int64 `json:"number"`
BlockHash string `json:"hash"`
// ParentBlockHash string `json:"parentHash"`
}
type Extensions struct {
OptimismBridgeAddress string `json:"OptimismBridgeAddress"`
}
type TokenInfo struct {
// TODO lazily typing ints go through them all with fine tooth comb once api is up
ChainId int `json:"chainId"`
Address string `json:"address"`
Name string `json:"name"`
Symbol string `json:"symbol"`
Decimals int `json:"decimals"`
Extensions Extensions `json:"extensions"`
}
func jsonResponse(w http.ResponseWriter, logger log.Logger, data interface{}, statusCode int) { func jsonResponse(w http.ResponseWriter, logger log.Logger, data interface{}, statusCode int) {
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
jsonData, err := json.Marshal(data) jsonData, err := json.Marshal(data)
......
...@@ -10,16 +10,16 @@ import ( ...@@ -10,16 +10,16 @@ import (
) )
type DepositItem struct { type DepositItem struct {
Guid string `json:"guid"` Guid string `json:"guid"`
From string `json:"from"` From string `json:"from"`
To string `json:"to"` To string `json:"to"`
// TODO could consider OriginTx to be more generic to handling L2 to L2 deposits Timestamp uint64 `json:"timestamp"`
// this seems more clear today though L1BlockHash string `json:"l1BlockHash"`
Tx Transaction `json:"Tx"` L1TxHash string `json:"l1TxHash"`
Block Block `json:"Block"` L2TxHash string `json:"l2TxHash"`
Amount string `json:"amount"` Amount string `json:"amount"`
L1Token TokenInfo `json:"l1Token"` L1TokenAddress string `json:"l1TokenAddress"`
L2Token TokenInfo `json:"l2Token"` L2TokenAddress string `json:"l2TokenAddress"`
} }
type DepositResponse struct { type DepositResponse struct {
...@@ -28,47 +28,22 @@ type DepositResponse struct { ...@@ -28,47 +28,22 @@ type DepositResponse struct {
Items []DepositItem `json:"items"` Items []DepositItem `json:"items"`
} }
// TODO this is original spec but maybe include the l2 block info too for the relayed tx
// FIXME make a pure function that returns a struct instead of newWithdrawalResponse
func newDepositResponse(deposits *database.L1BridgeDepositsResponse) DepositResponse { func newDepositResponse(deposits *database.L1BridgeDepositsResponse) DepositResponse {
items := make([]DepositItem, len(deposits.Deposits)) items := make([]DepositItem, len(deposits.Deposits))
for _, deposit := range deposits.Deposits { for i, deposit := range deposits.Deposits {
item := DepositItem{ item := DepositItem{
Guid: deposit.L1BridgeDeposit.TransactionSourceHash.String(), Guid: deposit.L1BridgeDeposit.TransactionSourceHash.String(),
Block: Block{ L1BlockHash: deposit.L1BlockHash.String(),
BlockNumber: 420420, // TODO Timestamp: deposit.L1BridgeDeposit.Tx.Timestamp,
BlockHash: "0x420", // TODO L1TxHash: deposit.L1TransactionHash.String(),
L2TxHash: deposit.L2TransactionHash.String(),
}, From: deposit.L1BridgeDeposit.Tx.FromAddress.String(),
Tx: Transaction{ To: deposit.L1BridgeDeposit.Tx.ToAddress.String(),
TransactionHash: "0x420", // TODO Amount: deposit.L1BridgeDeposit.Tx.Amount.String(),
Timestamp: deposit.L1BridgeDeposit.Tx.Timestamp, L1TokenAddress: deposit.L1BridgeDeposit.TokenPair.LocalTokenAddress.String(),
}, L2TokenAddress: deposit.L1BridgeDeposit.TokenPair.RemoteTokenAddress.String(),
From: deposit.L1BridgeDeposit.Tx.FromAddress.String(),
To: deposit.L1BridgeDeposit.Tx.ToAddress.String(),
Amount: deposit.L1BridgeDeposit.Tx.Amount.String(),
L1Token: TokenInfo{
ChainId: 1,
Address: deposit.L1BridgeDeposit.TokenPair.LocalTokenAddress.String(),
Name: "TODO",
Symbol: "TODO",
Decimals: 420,
Extensions: Extensions{
OptimismBridgeAddress: "0x420", // TODO
},
},
L2Token: TokenInfo{
ChainId: 10,
Address: deposit.L1BridgeDeposit.TokenPair.RemoteTokenAddress.String(),
Name: "TODO",
Symbol: "TODO",
Decimals: 420,
Extensions: Extensions{
OptimismBridgeAddress: "0x420", // TODO
},
},
} }
items = append(items, item) items[i] = item
} }
return DepositResponse{ return DepositResponse{
......
...@@ -9,31 +9,18 @@ import ( ...@@ -9,31 +9,18 @@ import (
"github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5"
) )
type Proof struct {
TransactionHash string `json:"transactionHash"`
BlockTimestamp uint64 `json:"blockTimestamp"`
BlockNumber int `json:"blockNumber"`
}
type Claim struct {
TransactionHash string `json:"transactionHash"`
BlockTimestamp uint64 `json:"blockTimestamp"`
BlockNumber int `json:"blockNumber"`
}
type WithdrawalItem struct { type WithdrawalItem struct {
Guid string `json:"guid"` Guid string `json:"guid"`
Tx Transaction `json:"Tx"` From string `json:"from"`
Block Block `json:"Block"` To string `json:"to"`
From string `json:"from"` TransactionHash string `json:"transactionHash"`
To string `json:"to"` Timestamp uint64 `json:"timestamp"`
TransactionHash string `json:"transactionHash"` L2BlockHash string `json:"l2BlockHash"`
Amount string `json:"amount"` Amount string `json:"amount"`
Proof Proof `json:"proof"` ProofTransactionHash string `json:"proofTransactionHash"`
Claim Claim `json:"claim"` ClaimTransactionHash string `json:"claimTransactionHash"`
WithdrawalState string `json:"withdrawalState"` L1TokenAddress string `json:"l1TokenAddress"`
L1Token TokenInfo `json:"l1Token"` L2TokenAddress string `json:"l2TokenAddress"`
L2Token TokenInfo `json:"l2Token"`
} }
type WithdrawalResponse struct { type WithdrawalResponse struct {
...@@ -45,55 +32,20 @@ type WithdrawalResponse struct { ...@@ -45,55 +32,20 @@ type WithdrawalResponse struct {
// FIXME make a pure function that returns a struct instead of newWithdrawalResponse // FIXME make a pure function that returns a struct instead of newWithdrawalResponse
func newWithdrawalResponse(withdrawals *database.L2BridgeWithdrawalsResponse) WithdrawalResponse { func newWithdrawalResponse(withdrawals *database.L2BridgeWithdrawalsResponse) WithdrawalResponse {
items := make([]WithdrawalItem, len(withdrawals.Withdrawals)) items := make([]WithdrawalItem, len(withdrawals.Withdrawals))
for _, withdrawal := range withdrawals.Withdrawals { for i, withdrawal := range withdrawals.Withdrawals {
item := WithdrawalItem{ item := WithdrawalItem{
Guid: withdrawal.L2BridgeWithdrawal.TransactionWithdrawalHash.String(), Guid: withdrawal.L2BridgeWithdrawal.TransactionWithdrawalHash.String(),
Block: Block{ L2BlockHash: withdrawal.L2BlockHash.String(),
BlockNumber: 420420, // TODO From: withdrawal.L2BridgeWithdrawal.Tx.FromAddress.String(),
BlockHash: "0x420", // TODO To: withdrawal.L2BridgeWithdrawal.Tx.ToAddress.String(),
TransactionHash: withdrawal.L2TransactionHash.String(),
}, Amount: withdrawal.L2BridgeWithdrawal.Tx.Amount.String(),
Tx: Transaction{ ProofTransactionHash: withdrawal.ProvenL1TransactionHash.String(),
TransactionHash: "0x420", // TODO ClaimTransactionHash: withdrawal.FinalizedL1TransactionHash.String(),
Timestamp: withdrawal.L2BridgeWithdrawal.Tx.Timestamp, L1TokenAddress: withdrawal.L2BridgeWithdrawal.TokenPair.RemoteTokenAddress.String(),
}, L2TokenAddress: withdrawal.L2BridgeWithdrawal.TokenPair.LocalTokenAddress.String(),
From: withdrawal.L2BridgeWithdrawal.Tx.FromAddress.String(),
To: withdrawal.L2BridgeWithdrawal.Tx.ToAddress.String(),
TransactionHash: withdrawal.L2TransactionHash.String(),
Amount: withdrawal.L2BridgeWithdrawal.Tx.Amount.String(),
Proof: Proof{
TransactionHash: withdrawal.ProvenL1TransactionHash.String(),
BlockTimestamp: withdrawal.L2BridgeWithdrawal.Tx.Timestamp,
BlockNumber: 420, // TODO Block struct instead
},
Claim: Claim{
TransactionHash: withdrawal.FinalizedL1TransactionHash.String(),
BlockTimestamp: withdrawal.L2BridgeWithdrawal.Tx.Timestamp, // Using L2 timestamp for now, might need adjustment
BlockNumber: 420, // TODO block struct
},
WithdrawalState: "COMPLETE", // TODO
L1Token: TokenInfo{
ChainId: 1,
Address: withdrawal.L2BridgeWithdrawal.TokenPair.RemoteTokenAddress.String(),
Name: "Example", // TODO
Symbol: "EXAMPLE", // TODO
Decimals: 18, // TODO
Extensions: Extensions{
OptimismBridgeAddress: "0x636Af16bf2f682dD3109e60102b8E1A089FedAa8",
},
},
L2Token: TokenInfo{
ChainId: 10,
Address: withdrawal.L2BridgeWithdrawal.TokenPair.LocalTokenAddress.String(),
Name: "Example", // TODO
Symbol: "EXAMPLE", // TODO
Decimals: 18, // TODO
Extensions: Extensions{
OptimismBridgeAddress: "0x36Af16bf2f682dD3109e60102b8E1A089FedAa86",
},
},
} }
items = append(items, item) items[i] = item
} }
return WithdrawalResponse{ return WithdrawalResponse{
......
...@@ -37,7 +37,6 @@ func Grouped(start, end *big.Int, size uint64) []Range { ...@@ -37,7 +37,6 @@ func Grouped(start, end *big.Int, size uint64) []Range {
if end.Cmp(start) < 0 || size == 0 { if end.Cmp(start) < 0 || size == 0 {
return nil return nil
} }
bigMaxDiff := big.NewInt(int64(size - 1)) bigMaxDiff := big.NewInt(int64(size - 1))
groups := []Range{} groups := []Range{}
......
...@@ -6,8 +6,9 @@ import ( ...@@ -6,8 +6,9 @@ import (
"reflect" "reflect"
"github.com/BurntSushi/toml" "github.com/BurntSushi/toml"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
geth_log "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
) )
const ( const (
...@@ -16,7 +17,7 @@ const ( ...@@ -16,7 +17,7 @@ const (
defaultHeaderBufferSize = 500 defaultHeaderBufferSize = 500
) )
// in future presets can just be onchain config and fetched on initialization // In the future, presets can just be onchain config and fetched on initialization
// Config represents the `indexer.toml` file used to configure the indexer // Config represents the `indexer.toml` file used to configure the indexer
type Config struct { type Config struct {
...@@ -27,47 +28,84 @@ type Config struct { ...@@ -27,47 +28,84 @@ type Config struct {
MetricsServer ServerConfig `toml:"metrics"` MetricsServer ServerConfig `toml:"metrics"`
} }
// fetch this via onchain config from RPCsConfig and remove from config in future // L1Contracts configures deployed contracts
type L1Contracts struct { type L1Contracts struct {
OptimismPortalProxy common.Address `toml:"optimism-portal"` // administrative
L2OutputOracleProxy common.Address `toml:"l2-output-oracle"` AddressManager common.Address `toml:"address-manager"`
SystemConfigProxy common.Address `toml:"system-config"`
// rollup state
OptimismPortalProxy common.Address `toml:"optimism-portal"`
L2OutputOracleProxy common.Address `toml:"l2-output-oracle"`
// bridging
L1CrossDomainMessengerProxy common.Address `toml:"l1-cross-domain-messenger"` L1CrossDomainMessengerProxy common.Address `toml:"l1-cross-domain-messenger"`
L1StandardBridgeProxy common.Address `toml:"l1-standard-bridge"` L1StandardBridgeProxy common.Address `toml:"l1-standard-bridge"`
L1ERC721BridgeProxy common.Address `toml:"l1-erc721-bridge"`
// Some more contracts -- L1ERC721Bridge, ProxyAdmin, SystemConfig, etc // IGNORE: legacy contracts (only settable via presets)
// Ignore the auxiliary contracts? LegacyCanonicalTransactionChain common.Address `toml:"-"`
LegacyStateCommitmentChain common.Address `toml:"-"`
// Legacy contracts? We'll add this in to index the legacy chain.
// Remove afterwards?
} }
// converts struct of to a slice of addresses for easy iteration func (c L1Contracts) ForEach(cb func(string, common.Address) error) error {
// also validates that all fields are addresses contracts := reflect.ValueOf(c)
func (c *L1Contracts) AsSlice() ([]common.Address, error) { fields := reflect.VisibleFields(reflect.TypeOf(c))
clone := *c for _, field := range fields {
contractValue := reflect.ValueOf(clone)
fields := reflect.VisibleFields(reflect.TypeOf(clone))
l1Contracts := make([]common.Address, len(fields))
for i, field := range fields {
// ruleid: unsafe-reflect-by-name // ruleid: unsafe-reflect-by-name
addr, ok := (contractValue.FieldByName(field.Name).Interface()).(common.Address) addr := (contracts.FieldByName(field.Name).Interface()).(common.Address)
if !ok { if err := cb(field.Name, addr); err != nil {
return nil, fmt.Errorf("non-address found in L1Contracts: %s", field.Name) return err
} }
}
return nil
}
// L2Contracts configures core predeploy contracts. We explicitly specify
// fields until we can detect and backfill new addresses
type L2Contracts struct {
L2ToL1MessagePasser common.Address
L2CrossDomainMessenger common.Address
L2StandardBridge common.Address
L2ERC721Bridge common.Address
}
l1Contracts[i] = addr func L2ContractsFromPredeploys() L2Contracts {
return L2Contracts{
L2ToL1MessagePasser: predeploys.L2ToL1MessagePasserAddr,
L2CrossDomainMessenger: predeploys.L2CrossDomainMessengerAddr,
L2StandardBridge: predeploys.L2StandardBridgeAddr,
L2ERC721Bridge: predeploys.L2ERC721BridgeAddr,
}
}
func (c L2Contracts) ForEach(cb func(string, common.Address) error) error {
contracts := reflect.ValueOf(c)
fields := reflect.VisibleFields(reflect.TypeOf(c))
for _, field := range fields {
// ruleid: unsafe-reflect-by-name
addr := (contracts.FieldByName(field.Name).Interface()).(common.Address)
if err := cb(field.Name, addr); err != nil {
return err
}
} }
return l1Contracts, nil return nil
} }
// ChainConfig configures of the chain being indexed // ChainConfig configures of the chain being indexed
type ChainConfig struct { type ChainConfig struct {
// Configure known chains with the l2 chain id // Configure known chains with the l2 chain id
Preset int Preset int
L1StartingHeight uint `toml:"l1-starting-height"`
L1Contracts L1Contracts `toml:"l1-contracts"` L1Contracts L1Contracts `toml:"l1-contracts"`
L1StartingHeight uint `toml:"l1-starting-height"` L2Contracts L2Contracts `toml:"-"`
// Bedrock starting heights only applicable for OP-Mainnet & OP-Goerli
L1BedrockStartingHeight uint `toml:"-"`
L2BedrockStartingHeight uint `toml:"-"`
// These configuration options will be removed once // These configuration options will be removed once
// native reorg handling is implemented // native reorg handling is implemented
...@@ -103,8 +141,8 @@ type ServerConfig struct { ...@@ -103,8 +141,8 @@ type ServerConfig struct {
} }
// LoadConfig loads the `indexer.toml` config file from a given path // LoadConfig loads the `indexer.toml` config file from a given path
func LoadConfig(logger geth_log.Logger, path string) (Config, error) { func LoadConfig(log log.Logger, path string) (Config, error) {
logger.Debug("loading config", "path", path) log.Debug("loading config", "path", path)
var conf Config var conf Config
data, err := os.ReadFile(path) data, err := os.ReadFile(path)
...@@ -113,42 +151,51 @@ func LoadConfig(logger geth_log.Logger, path string) (Config, error) { ...@@ -113,42 +151,51 @@ func LoadConfig(logger geth_log.Logger, path string) (Config, error) {
} }
data = []byte(os.ExpandEnv(string(data))) data = []byte(os.ExpandEnv(string(data)))
logger.Debug("parsed config file", "data", string(data)) log.Debug("parsed config file", "data", string(data))
if _, err := toml.Decode(string(data), &conf); err != nil { if _, err := toml.Decode(string(data), &conf); err != nil {
logger.Info("failed to decode config file", "err", err) log.Info("failed to decode config file", "err", err)
return conf, err return conf, err
} }
if conf.Chain.Preset != 0 { if conf.Chain.Preset != 0 {
knownPreset, ok := presetConfigs[conf.Chain.Preset] preset, ok := Presets[conf.Chain.Preset]
if !ok { if !ok {
return conf, fmt.Errorf("unknown preset: %d", conf.Chain.Preset) return conf, fmt.Errorf("unknown preset: %d", conf.Chain.Preset)
} }
conf.Chain.L1Contracts = knownPreset.L1Contracts
conf.Chain.L1StartingHeight = knownPreset.L1StartingHeight log.Info("detected preset", "preset", conf.Chain.Preset, "name", preset.Name)
log.Info("setting L1 information from preset")
conf.Chain.L1Contracts = preset.ChainConfig.L1Contracts
conf.Chain.L1StartingHeight = preset.ChainConfig.L1StartingHeight
conf.Chain.L1BedrockStartingHeight = preset.ChainConfig.L1BedrockStartingHeight
conf.Chain.L2BedrockStartingHeight = preset.ChainConfig.L1BedrockStartingHeight
} }
// Set polling defaults if not set // Setup L2Contracts from predeploys
conf.Chain.L2Contracts = L2ContractsFromPredeploys()
// Setup defaults for some unset options
if conf.Chain.L1PollingInterval == 0 { if conf.Chain.L1PollingInterval == 0 {
logger.Info("setting default L1 polling interval", "interval", defaultLoopInterval) log.Info("setting default L1 polling interval", "interval", defaultLoopInterval)
conf.Chain.L1PollingInterval = defaultLoopInterval conf.Chain.L1PollingInterval = defaultLoopInterval
} }
if conf.Chain.L2PollingInterval == 0 { if conf.Chain.L2PollingInterval == 0 {
logger.Info("setting default L2 polling interval", "interval", defaultLoopInterval) log.Info("setting default L2 polling interval", "interval", defaultLoopInterval)
conf.Chain.L2PollingInterval = defaultLoopInterval conf.Chain.L2PollingInterval = defaultLoopInterval
} }
if conf.Chain.L1HeaderBufferSize == 0 { if conf.Chain.L1HeaderBufferSize == 0 {
logger.Info("setting default L1 header buffer", "size", defaultHeaderBufferSize) log.Info("setting default L1 header buffer", "size", defaultHeaderBufferSize)
conf.Chain.L1HeaderBufferSize = defaultHeaderBufferSize conf.Chain.L1HeaderBufferSize = defaultHeaderBufferSize
} }
if conf.Chain.L2HeaderBufferSize == 0 { if conf.Chain.L2HeaderBufferSize == 0 {
logger.Info("setting default L2 header buffer", "size", defaultHeaderBufferSize) log.Info("setting default L2 header buffer", "size", defaultHeaderBufferSize)
conf.Chain.L2HeaderBufferSize = defaultHeaderBufferSize conf.Chain.L2HeaderBufferSize = defaultHeaderBufferSize
} }
logger.Info("loaded config") log.Info("loaded config")
return conf, nil return conf, nil
} }
...@@ -54,10 +54,10 @@ func TestLoadConfig(t *testing.T) { ...@@ -54,10 +54,10 @@ func TestLoadConfig(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, conf.Chain.Preset, 420) require.Equal(t, conf.Chain.Preset, 420)
require.Equal(t, conf.Chain.L1Contracts.OptimismPortalProxy.String(), presetConfigs[420].L1Contracts.OptimismPortalProxy.String()) require.Equal(t, conf.Chain.L1Contracts.OptimismPortalProxy.String(), Presets[420].ChainConfig.L1Contracts.OptimismPortalProxy.String())
require.Equal(t, conf.Chain.L1Contracts.L1CrossDomainMessengerProxy.String(), presetConfigs[420].L1Contracts.L1CrossDomainMessengerProxy.String()) require.Equal(t, conf.Chain.L1Contracts.L1CrossDomainMessengerProxy.String(), Presets[420].ChainConfig.L1Contracts.L1CrossDomainMessengerProxy.String())
require.Equal(t, conf.Chain.L1Contracts.L1StandardBridgeProxy.String(), presetConfigs[420].L1Contracts.L1StandardBridgeProxy.String()) require.Equal(t, conf.Chain.L1Contracts.L1StandardBridgeProxy.String(), Presets[420].ChainConfig.L1Contracts.L1StandardBridgeProxy.String())
require.Equal(t, conf.Chain.L1Contracts.L2OutputOracleProxy.String(), presetConfigs[420].L1Contracts.L2OutputOracleProxy.String()) require.Equal(t, conf.Chain.L1Contracts.L2OutputOracleProxy.String(), Presets[420].ChainConfig.L1Contracts.L2OutputOracleProxy.String())
require.Equal(t, conf.RPCs.L1RPC, "https://l1.example.com") require.Equal(t, conf.RPCs.L1RPC, "https://l1.example.com")
require.Equal(t, conf.RPCs.L2RPC, "https://l2.example.com") require.Equal(t, conf.RPCs.L2RPC, "https://l2.example.com")
require.Equal(t, conf.DB.Host, "127.0.0.1") require.Equal(t, conf.DB.Host, "127.0.0.1")
...@@ -71,7 +71,7 @@ func TestLoadConfig(t *testing.T) { ...@@ -71,7 +71,7 @@ func TestLoadConfig(t *testing.T) {
require.Equal(t, conf.MetricsServer.Port, 7300) require.Equal(t, conf.MetricsServer.Port, 7300)
} }
func TestLoadConfig_WithoutPreset(t *testing.T) { func TestLoadConfigWithoutPreset(t *testing.T) {
tmpfile, err := os.CreateTemp("", "test_without_preset.toml") tmpfile, err := os.CreateTemp("", "test_without_preset.toml")
require.NoError(t, err) require.NoError(t, err)
defer os.Remove(tmpfile.Name()) defer os.Remove(tmpfile.Name())
...@@ -103,7 +103,6 @@ func TestLoadConfig_WithoutPreset(t *testing.T) { ...@@ -103,7 +103,6 @@ func TestLoadConfig_WithoutPreset(t *testing.T) {
conf, err := LoadConfig(logger, tmpfile.Name()) conf, err := LoadConfig(logger, tmpfile.Name())
require.NoError(t, err) require.NoError(t, err)
// Enforce default values
require.Equal(t, conf.Chain.L1Contracts.OptimismPortalProxy.String(), common.HexToAddress("0x4205Fc579115071764c7423A4f12eDde41f106Ed").String()) require.Equal(t, conf.Chain.L1Contracts.OptimismPortalProxy.String(), common.HexToAddress("0x4205Fc579115071764c7423A4f12eDde41f106Ed").String())
require.Equal(t, conf.Chain.L1Contracts.L2OutputOracleProxy.String(), common.HexToAddress("0x42097868233d1aa22e815a266982f2cf17685a27").String()) require.Equal(t, conf.Chain.L1Contracts.L2OutputOracleProxy.String(), common.HexToAddress("0x42097868233d1aa22e815a266982f2cf17685a27").String())
require.Equal(t, conf.Chain.L1Contracts.L1CrossDomainMessengerProxy.String(), common.HexToAddress("0x420ce71c97B33Cc4729CF772ae268934F7ab5fA1").String()) require.Equal(t, conf.Chain.L1Contracts.L1CrossDomainMessengerProxy.String(), common.HexToAddress("0x420ce71c97B33Cc4729CF772ae268934F7ab5fA1").String())
...@@ -117,7 +116,7 @@ func TestLoadConfig_WithoutPreset(t *testing.T) { ...@@ -117,7 +116,7 @@ func TestLoadConfig_WithoutPreset(t *testing.T) {
require.Equal(t, conf.Chain.L2HeaderBufferSize, uint(500)) require.Equal(t, conf.Chain.L2HeaderBufferSize, uint(500))
} }
func TestLoadConfig_WithUnknownPreset(t *testing.T) { func TestLoadConfigWithUnknownPreset(t *testing.T) {
tmpfile, err := os.CreateTemp("", "test_bad_preset.toml") tmpfile, err := os.CreateTemp("", "test_bad_preset.toml")
require.NoError(t, err) require.NoError(t, err)
defer os.Remove(tmpfile.Name()) defer os.Remove(tmpfile.Name())
...@@ -148,7 +147,7 @@ func TestLoadConfig_WithUnknownPreset(t *testing.T) { ...@@ -148,7 +147,7 @@ func TestLoadConfig_WithUnknownPreset(t *testing.T) {
require.Equal(t, fmt.Sprintf("unknown preset: %d", faultyPreset), err.Error()) require.Equal(t, fmt.Sprintf("unknown preset: %d", faultyPreset), err.Error())
} }
func Test_LoadConfig_PollingValues(t *testing.T) { func TestLoadConfigPollingValues(t *testing.T) {
tmpfile, err := os.CreateTemp("", "test_user_values.toml") tmpfile, err := os.CreateTemp("", "test_user_values.toml")
require.NoError(t, err) require.NoError(t, err)
defer os.Remove(tmpfile.Name()) defer os.Remove(tmpfile.Name())
...@@ -178,23 +177,3 @@ func Test_LoadConfig_PollingValues(t *testing.T) { ...@@ -178,23 +177,3 @@ func Test_LoadConfig_PollingValues(t *testing.T) {
require.Equal(t, conf.Chain.L1HeaderBufferSize, uint(100)) require.Equal(t, conf.Chain.L1HeaderBufferSize, uint(100))
require.Equal(t, conf.Chain.L2HeaderBufferSize, uint(105)) require.Equal(t, conf.Chain.L2HeaderBufferSize, uint(105))
} }
func Test_AsSliceSuccess(t *testing.T) {
// error cases are intentionally ignored for testing since they can only be
// generated when the L1Contracts struct is developer modified to hold a non-address var field
testCfg := &L1Contracts{
OptimismPortalProxy: common.HexToAddress("0x4205Fc579115071764c7423A4f12eDde41f106Ed"),
L2OutputOracleProxy: common.HexToAddress("0x42097868233d1aa22e815a266982f2cf17685a27"),
L1CrossDomainMessengerProxy: common.HexToAddress("0x420ce71c97B33Cc4729CF772ae268934F7ab5fA1"),
L1StandardBridgeProxy: common.HexToAddress("0x4209fc46f92E8a1c0deC1b1747d010903E884bE1"),
}
slice, err := testCfg.AsSlice()
require.NoError(t, err)
require.Equal(t, len(slice), 4)
require.Equal(t, slice[0].String(), testCfg.OptimismPortalProxy.String())
require.Equal(t, slice[1].String(), testCfg.L2OutputOracleProxy.String())
require.Equal(t, slice[2].String(), testCfg.L1CrossDomainMessengerProxy.String())
require.Equal(t, slice[3].String(), testCfg.L1StandardBridgeProxy.String())
}
...@@ -4,68 +4,115 @@ import ( ...@@ -4,68 +4,115 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
) )
// in future presets can just be onchain config and fetched on initialization type Preset struct {
// Mapping of l2 chain ids to their preset chain configurations Name string
var presetConfigs = map[int]ChainConfig{ ChainConfig ChainConfig
// OP Mainnet }
// In the future, presets can just be onchain config and fetched on initialization
// Mapping of L2 chain ids to their preset chain configurations
var Presets = map[int]Preset{
10: { 10: {
L1Contracts: L1Contracts{ Name: "Optimism",
OptimismPortalProxy: common.HexToAddress("0xbEb5Fc579115071764c7423A4f12eDde41f106Ed"), ChainConfig: ChainConfig{
L2OutputOracleProxy: common.HexToAddress("0xdfe97868233d1aa22e815a266982f2cf17685a27"), L1Contracts: L1Contracts{
L1CrossDomainMessengerProxy: common.HexToAddress("0x25ace71c97B33Cc4729CF772ae268934F7ab5fA1"), AddressManager: common.HexToAddress("0xdE1FCfB0851916CA5101820A69b13a4E276bd81F"),
L1StandardBridgeProxy: common.HexToAddress("0x99C9fc46f92E8a1c0deC1b1747d010903E884bE1"), SystemConfigProxy: common.HexToAddress("0x229047fed2591dbec1eF1118d64F7aF3dB9EB290"),
// LegacyCanonicalTransactionChain: common.HexToAddress("0x5e4e65926ba27467555eb562121fac00d24e9dd2"), OptimismPortalProxy: common.HexToAddress("0xbEb5Fc579115071764c7423A4f12eDde41f106Ed"),
L2OutputOracleProxy: common.HexToAddress("0xdfe97868233d1aa22e815a266982f2cf17685a27"),
L1CrossDomainMessengerProxy: common.HexToAddress("0x25ace71c97B33Cc4729CF772ae268934F7ab5fA1"),
L1StandardBridgeProxy: common.HexToAddress("0x99C9fc46f92E8a1c0deC1b1747d010903E884bE1"),
L1ERC721BridgeProxy: common.HexToAddress("0x5a7749f83b81B301cAb5f48EB8516B986DAef23D"),
// pre-bedrock
LegacyCanonicalTransactionChain: common.HexToAddress("0x5e4e65926ba27467555eb562121fac00d24e9dd2"),
LegacyStateCommitmentChain: common.HexToAddress("0xBe5dAb4A2e9cd0F27300dB4aB94BeE3A233AEB19"),
},
L1StartingHeight: 13596466,
L1BedrockStartingHeight: 17422590,
L2BedrockStartingHeight: 105235063,
}, },
L1StartingHeight: 13596466,
}, },
// OP Goerli
420: { 420: {
L1Contracts: L1Contracts{ Name: "Optimism Goerli",
OptimismPortalProxy: common.HexToAddress("0x5b47E1A08Ea6d985D6649300584e6722Ec4B1383"), ChainConfig: ChainConfig{
L2OutputOracleProxy: common.HexToAddress("0xE6Dfba0953616Bacab0c9A8ecb3a9BBa77FC15c0"), L1Contracts: L1Contracts{
L1CrossDomainMessengerProxy: common.HexToAddress("0x5086d1eEF304eb5284A0f6720f79403b4e9bE294"), AddressManager: common.HexToAddress("0xa6f73589243a6A7a9023b1Fa0651b1d89c177111"),
L1StandardBridgeProxy: common.HexToAddress("0x636Af16bf2f682dD3109e60102b8E1A089FedAa8"), SystemConfigProxy: common.HexToAddress("0xAe851f927Ee40dE99aaBb7461C00f9622ab91d60"),
OptimismPortalProxy: common.HexToAddress("0x5b47E1A08Ea6d985D6649300584e6722Ec4B1383"),
L2OutputOracleProxy: common.HexToAddress("0xE6Dfba0953616Bacab0c9A8ecb3a9BBa77FC15c0"),
L1CrossDomainMessengerProxy: common.HexToAddress("0x5086d1eEF304eb5284A0f6720f79403b4e9bE294"),
L1StandardBridgeProxy: common.HexToAddress("0x636Af16bf2f682dD3109e60102b8E1A089FedAa8"),
L1ERC721BridgeProxy: common.HexToAddress("0x8DD330DdE8D9898d43b4dc840Da27A07dF91b3c9"),
// pre-bedrock
LegacyCanonicalTransactionChain: common.HexToAddress("0x607F755149cFEB3a14E1Dc3A4E2450Cde7dfb04D"),
LegacyStateCommitmentChain: common.HexToAddress("0x9c945aC97Baf48cB784AbBB61399beB71aF7A378"),
},
L1StartingHeight: 7017096,
L1BedrockStartingHeight: 8300214,
L2BedrockStartingHeight: 4061224,
}, },
L1StartingHeight: 7017096,
}, },
// Base Mainnet
8453: { 8453: {
L1Contracts: L1Contracts{ Name: "Base",
OptimismPortalProxy: common.HexToAddress("0x49048044D57e1C92A77f79988d21Fa8fAF74E97e"), ChainConfig: ChainConfig{
L2OutputOracleProxy: common.HexToAddress("0x56315b90c40730925ec5485cf004d835058518A0"), L1Contracts: L1Contracts{
L1CrossDomainMessengerProxy: common.HexToAddress("0x866E82a600A1414e583f7F13623F1aC5d58b0Afa"), AddressManager: common.HexToAddress("0x8EfB6B5c4767B09Dc9AA6Af4eAA89F749522BaE2"),
L1StandardBridgeProxy: common.HexToAddress("0x3154Cf16ccdb4C6d922629664174b904d80F2C35"), SystemConfigProxy: common.HexToAddress("0x73a79Fab69143498Ed3712e519A88a918e1f4072"),
OptimismPortalProxy: common.HexToAddress("0x49048044D57e1C92A77f79988d21Fa8fAF74E97e"),
L2OutputOracleProxy: common.HexToAddress("0x56315b90c40730925ec5485cf004d835058518A0"),
L1CrossDomainMessengerProxy: common.HexToAddress("0x866E82a600A1414e583f7F13623F1aC5d58b0Afa"),
L1StandardBridgeProxy: common.HexToAddress("0x3154Cf16ccdb4C6d922629664174b904d80F2C35"),
L1ERC721BridgeProxy: common.HexToAddress("0x608d94945A64503E642E6370Ec598e519a2C1E53"),
},
L1StartingHeight: 17481768,
}, },
L1StartingHeight: 17481768,
}, },
// Base Goerli
84531: { 84531: {
L1Contracts: L1Contracts{ Name: "Base Goerli",
OptimismPortalProxy: common.HexToAddress("0xe93c8cD0D409341205A592f8c4Ac1A5fe5585cfA"), ChainConfig: ChainConfig{
L2OutputOracleProxy: common.HexToAddress("0x2A35891ff30313CcFa6CE88dcf3858bb075A2298"), L1Contracts: L1Contracts{
L1CrossDomainMessengerProxy: common.HexToAddress("0x8e5693140eA606bcEB98761d9beB1BC87383706D"), AddressManager: common.HexToAddress("0x4Cf6b56b14c6CFcB72A75611080514F94624c54e"),
L1StandardBridgeProxy: common.HexToAddress("0xfA6D8Ee5BE770F84FC001D098C4bD604Fe01284a"), SystemConfigProxy: common.HexToAddress("0xb15eea247eCE011C68a614e4a77AD648ff495bc1"),
OptimismPortalProxy: common.HexToAddress("0xe93c8cD0D409341205A592f8c4Ac1A5fe5585cfA"),
L2OutputOracleProxy: common.HexToAddress("0x2A35891ff30313CcFa6CE88dcf3858bb075A2298"),
L1CrossDomainMessengerProxy: common.HexToAddress("0x8e5693140eA606bcEB98761d9beB1BC87383706D"),
L1StandardBridgeProxy: common.HexToAddress("0xfA6D8Ee5BE770F84FC001D098C4bD604Fe01284a"),
L1ERC721BridgeProxy: common.HexToAddress("0x5E0c967457347D5175bF82E8CCCC6480FCD7e568"),
},
L1StartingHeight: 8410981,
}, },
L1StartingHeight: 8410981,
}, },
// Zora mainnet
7777777: { 7777777: {
L1Contracts: L1Contracts{ Name: "Zora",
OptimismPortalProxy: common.HexToAddress("0x1a0ad011913A150f69f6A19DF447A0CfD9551054"), ChainConfig: ChainConfig{
L2OutputOracleProxy: common.HexToAddress("0x9E6204F750cD866b299594e2aC9eA824E2e5f95c"), L1Contracts: L1Contracts{
L1CrossDomainMessengerProxy: common.HexToAddress("0xdC40a14d9abd6F410226f1E6de71aE03441ca506"), AddressManager: common.HexToAddress("0xEF8115F2733fb2033a7c756402Fc1deaa56550Ef"),
L1StandardBridgeProxy: common.HexToAddress("0x3e2Ea9B92B7E48A52296fD261dc26fd995284631"), SystemConfigProxy: common.HexToAddress("0xA3cAB0126d5F504B071b81a3e8A2BBBF17930d86"),
OptimismPortalProxy: common.HexToAddress("0x1a0ad011913A150f69f6A19DF447A0CfD9551054"),
L2OutputOracleProxy: common.HexToAddress("0x9E6204F750cD866b299594e2aC9eA824E2e5f95c"),
L1CrossDomainMessengerProxy: common.HexToAddress("0xdC40a14d9abd6F410226f1E6de71aE03441ca506"),
L1StandardBridgeProxy: common.HexToAddress("0x3e2Ea9B92B7E48A52296fD261dc26fd995284631"),
L1ERC721BridgeProxy: common.HexToAddress("0x83A4521A3573Ca87f3a971B169C5A0E1d34481c3"),
},
L1StartingHeight: 17473923,
}, },
L1StartingHeight: 17473923,
}, },
// Zora goerli
999: { 999: {
L1Contracts: L1Contracts{ Name: "Zora Goerli",
OptimismPortalProxy: common.HexToAddress("0xDb9F51790365e7dc196e7D072728df39Be958ACe"), ChainConfig: ChainConfig{
L2OutputOracleProxy: common.HexToAddress("0xdD292C9eEd00f6A32Ff5245d0BCd7f2a15f24e00"), L1Contracts: L1Contracts{
L1CrossDomainMessengerProxy: common.HexToAddress("0xD87342e16352D33170557A7dA1e5fB966a60FafC"), AddressManager: common.HexToAddress("0x54f4676203dEDA6C08E0D40557A119c602bFA246"),
L1StandardBridgeProxy: common.HexToAddress("0x7CC09AC2452D6555d5e0C213Ab9E2d44eFbFc956"), SystemConfigProxy: common.HexToAddress("0xF66C9A5E4fE1A8a9bc44a4aF80505a4C3620Ee64"),
OptimismPortalProxy: common.HexToAddress("0xDb9F51790365e7dc196e7D072728df39Be958ACe"),
L2OutputOracleProxy: common.HexToAddress("0xdD292C9eEd00f6A32Ff5245d0BCd7f2a15f24e00"),
L1CrossDomainMessengerProxy: common.HexToAddress("0xD87342e16352D33170557A7dA1e5fB966a60FafC"),
L1StandardBridgeProxy: common.HexToAddress("0x7CC09AC2452D6555d5e0C213Ab9E2d44eFbFc956"),
L1ERC721BridgeProxy: common.HexToAddress("0x57C1C6b596ce90C0e010c358DD4Aa052404bB70F"),
},
L1StartingHeight: 8942381,
}, },
L1StartingHeight: 8942381,
}, },
} }
...@@ -7,8 +7,6 @@ import ( ...@@ -7,8 +7,6 @@ import (
"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/google/uuid"
"gorm.io/gorm" "gorm.io/gorm"
) )
...@@ -44,25 +42,6 @@ type L2BlockHeader struct { ...@@ -44,25 +42,6 @@ type L2BlockHeader struct {
BlockHeader `gorm:"embedded"` BlockHeader `gorm:"embedded"`
} }
type LegacyStateBatch struct {
// `default:0` is added since gorm would interepret 0 as NULL
// violating the primary key constraint.
Index uint64 `gorm:"primaryKey;default:0"`
Root common.Hash `gorm:"serializer:bytes"`
Size uint64
PrevTotal uint64
L1ContractEventGUID uuid.UUID
}
type OutputProposal struct {
OutputRoot common.Hash `gorm:"primaryKey;serializer:bytes"`
L2OutputIndex *big.Int `gorm:"serializer:u256"`
L2BlockNumber *big.Int `gorm:"serializer:u256"`
L1ContractEventGUID uuid.UUID
}
type BlocksView interface { type BlocksView interface {
L1BlockHeader(common.Hash) (*L1BlockHeader, error) L1BlockHeader(common.Hash) (*L1BlockHeader, error)
L1BlockHeaderWithFilter(BlockHeader) (*L1BlockHeader, error) L1BlockHeaderWithFilter(BlockHeader) (*L1BlockHeader, error)
...@@ -72,9 +51,6 @@ type BlocksView interface { ...@@ -72,9 +51,6 @@ type BlocksView interface {
L2BlockHeaderWithFilter(BlockHeader) (*L2BlockHeader, error) L2BlockHeaderWithFilter(BlockHeader) (*L2BlockHeader, error)
L2LatestBlockHeader() (*L2BlockHeader, error) L2LatestBlockHeader() (*L2BlockHeader, error)
LatestCheckpointedOutput() (*OutputProposal, error)
OutputProposal(index *big.Int) (*OutputProposal, error)
LatestEpoch() (*Epoch, error) LatestEpoch() (*Epoch, error)
} }
...@@ -83,9 +59,6 @@ type BlocksDB interface { ...@@ -83,9 +59,6 @@ type BlocksDB interface {
StoreL1BlockHeaders([]L1BlockHeader) error StoreL1BlockHeaders([]L1BlockHeader) error
StoreL2BlockHeaders([]L2BlockHeader) error StoreL2BlockHeaders([]L2BlockHeader) error
StoreLegacyStateBatches([]LegacyStateBatch) error
StoreOutputProposals([]OutputProposal) error
} }
/** /**
...@@ -107,16 +80,6 @@ func (db *blocksDB) StoreL1BlockHeaders(headers []L1BlockHeader) error { ...@@ -107,16 +80,6 @@ func (db *blocksDB) StoreL1BlockHeaders(headers []L1BlockHeader) error {
return result.Error return result.Error
} }
func (db *blocksDB) StoreLegacyStateBatches(stateBatches []LegacyStateBatch) error {
result := db.gorm.CreateInBatches(stateBatches, batchInsertSize)
return result.Error
}
func (db *blocksDB) StoreOutputProposals(outputs []OutputProposal) error {
result := db.gorm.CreateInBatches(outputs, batchInsertSize)
return result.Error
}
func (db *blocksDB) L1BlockHeader(hash common.Hash) (*L1BlockHeader, error) { func (db *blocksDB) L1BlockHeader(hash common.Hash) (*L1BlockHeader, error) {
return db.L1BlockHeaderWithFilter(BlockHeader{Hash: hash}) return db.L1BlockHeaderWithFilter(BlockHeader{Hash: hash})
} }
...@@ -148,34 +111,6 @@ func (db *blocksDB) L1LatestBlockHeader() (*L1BlockHeader, error) { ...@@ -148,34 +111,6 @@ func (db *blocksDB) L1LatestBlockHeader() (*L1BlockHeader, error) {
return &l1Header, nil return &l1Header, nil
} }
func (db *blocksDB) LatestCheckpointedOutput() (*OutputProposal, error) {
var outputProposal 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: index}).Take(&outputProposal)
if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, nil
}
return nil, result.Error
}
return &outputProposal, nil
}
// L2 // L2
func (db *blocksDB) StoreL2BlockHeaders(headers []L2BlockHeader) error { func (db *blocksDB) StoreL2BlockHeaders(headers []L2BlockHeader) error {
......
...@@ -38,6 +38,7 @@ type L1BridgeDeposit struct { ...@@ -38,6 +38,7 @@ type L1BridgeDeposit struct {
type L1BridgeDepositWithTransactionHashes struct { type L1BridgeDepositWithTransactionHashes struct {
L1BridgeDeposit L1BridgeDeposit `gorm:"embedded"` L1BridgeDeposit L1BridgeDeposit `gorm:"embedded"`
L1BlockHash common.Hash `gorm:"serializer:bytes"`
L1TransactionHash common.Hash `gorm:"serializer:bytes"` L1TransactionHash common.Hash `gorm:"serializer:bytes"`
L2TransactionHash common.Hash `gorm:"serializer:bytes"` L2TransactionHash common.Hash `gorm:"serializer:bytes"`
} }
...@@ -50,6 +51,7 @@ type L2BridgeWithdrawal struct { ...@@ -50,6 +51,7 @@ type L2BridgeWithdrawal struct {
type L2BridgeWithdrawalWithTransactionHashes struct { type L2BridgeWithdrawalWithTransactionHashes struct {
L2BridgeWithdrawal L2BridgeWithdrawal `gorm:"embedded"` L2BridgeWithdrawal L2BridgeWithdrawal `gorm:"embedded"`
L2TransactionHash common.Hash `gorm:"serializer:bytes"` L2TransactionHash common.Hash `gorm:"serializer:bytes"`
L2BlockHash common.Hash `gorm:"serializer:bytes"`
ProvenL1TransactionHash common.Hash `gorm:"serializer:bytes"` ProvenL1TransactionHash common.Hash `gorm:"serializer:bytes"`
FinalizedL1TransactionHash common.Hash `gorm:"serializer:bytes"` FinalizedL1TransactionHash common.Hash `gorm:"serializer:bytes"`
...@@ -154,7 +156,7 @@ func (db *bridgeTransfersDB) L1BridgeDepositsByAddress(address common.Address, c ...@@ -154,7 +156,7 @@ func (db *bridgeTransfersDB) L1BridgeDepositsByAddress(address common.Address, c
ethTransactionDeposits = ethTransactionDeposits.Joins("INNER JOIN l1_contract_events ON l1_contract_events.guid = initiated_l1_event_guid") ethTransactionDeposits = ethTransactionDeposits.Joins("INNER JOIN l1_contract_events ON l1_contract_events.guid = initiated_l1_event_guid")
ethTransactionDeposits = ethTransactionDeposits.Select(` ethTransactionDeposits = ethTransactionDeposits.Select(`
from_address, to_address, amount, data, source_hash AS transaction_source_hash, from_address, to_address, amount, data, source_hash AS transaction_source_hash,
l2_transaction_hash, l1_contract_events.transaction_hash AS l1_transaction_hash, l2_transaction_hash, l1_contract_events.transaction_hash AS l1_transaction_hash, l1_contract_events.block_hash as l1_block_hash,
l1_transaction_deposits.timestamp, NULL AS cross_domain_message_hash, ? AS local_token_address, ? AS remote_token_address`, ethAddressString, ethAddressString) l1_transaction_deposits.timestamp, NULL AS cross_domain_message_hash, ? AS local_token_address, ? AS remote_token_address`, ethAddressString, ethAddressString)
ethTransactionDeposits = ethTransactionDeposits.Order("timestamp DESC").Limit(limit + 1) ethTransactionDeposits = ethTransactionDeposits.Order("timestamp DESC").Limit(limit + 1)
if cursorClause != "" { if cursorClause != "" {
...@@ -166,7 +168,7 @@ l1_transaction_deposits.timestamp, NULL AS cross_domain_message_hash, ? AS local ...@@ -166,7 +168,7 @@ l1_transaction_deposits.timestamp, NULL AS cross_domain_message_hash, ? AS local
depositsQuery = depositsQuery.Joins("INNER JOIN l1_contract_events ON l1_contract_events.guid = l1_transaction_deposits.initiated_l1_event_guid") depositsQuery = depositsQuery.Joins("INNER JOIN l1_contract_events ON l1_contract_events.guid = l1_transaction_deposits.initiated_l1_event_guid")
depositsQuery = depositsQuery.Select(` depositsQuery = depositsQuery.Select(`
l1_bridge_deposits.from_address, l1_bridge_deposits.to_address, l1_bridge_deposits.amount, l1_bridge_deposits.data, transaction_source_hash, l1_bridge_deposits.from_address, l1_bridge_deposits.to_address, l1_bridge_deposits.amount, l1_bridge_deposits.data, transaction_source_hash,
l2_transaction_hash, l1_contract_events.transaction_hash AS l1_transaction_hash, l2_transaction_hash, l1_contract_events.transaction_hash AS l1_transaction_hash, l1_contract_events.block_hash as l1_block_hash,
l1_bridge_deposits.timestamp, cross_domain_message_hash, local_token_address, remote_token_address`) l1_bridge_deposits.timestamp, cross_domain_message_hash, local_token_address, remote_token_address`)
depositsQuery = depositsQuery.Order("timestamp DESC").Limit(limit + 1) depositsQuery = depositsQuery.Order("timestamp DESC").Limit(limit + 1)
if cursorClause != "" { if cursorClause != "" {
...@@ -269,7 +271,7 @@ func (db *bridgeTransfersDB) L2BridgeWithdrawalsByAddress(address common.Address ...@@ -269,7 +271,7 @@ func (db *bridgeTransfersDB) L2BridgeWithdrawalsByAddress(address common.Address
ethTransactionWithdrawals = ethTransactionWithdrawals.Joins("LEFT JOIN l1_contract_events AS finalized_l1_events ON finalized_l1_events.guid = l2_transaction_withdrawals.finalized_l1_event_guid") ethTransactionWithdrawals = ethTransactionWithdrawals.Joins("LEFT JOIN l1_contract_events AS finalized_l1_events ON finalized_l1_events.guid = l2_transaction_withdrawals.finalized_l1_event_guid")
ethTransactionWithdrawals = ethTransactionWithdrawals.Select(` ethTransactionWithdrawals = ethTransactionWithdrawals.Select(`
from_address, to_address, amount, data, withdrawal_hash AS transaction_withdrawal_hash, from_address, to_address, amount, data, withdrawal_hash AS transaction_withdrawal_hash,
l2_contract_events.transaction_hash AS l2_transaction_hash, proven_l1_events.transaction_hash AS proven_l1_transaction_hash, finalized_l1_events.transaction_hash AS finalized_l1_transaction_hash, l2_contract_events.transaction_hash AS l2_transaction_hash, l2_contract_events.block_hash as l2_block_hash, proven_l1_events.transaction_hash AS proven_l1_transaction_hash, finalized_l1_events.transaction_hash AS finalized_l1_transaction_hash,
l2_transaction_withdrawals.timestamp, NULL AS cross_domain_message_hash, ? AS local_token_address, ? AS remote_token_address`, ethAddressString, ethAddressString) l2_transaction_withdrawals.timestamp, NULL AS cross_domain_message_hash, ? AS local_token_address, ? AS remote_token_address`, ethAddressString, ethAddressString)
ethTransactionWithdrawals = ethTransactionWithdrawals.Order("timestamp DESC").Limit(limit + 1) ethTransactionWithdrawals = ethTransactionWithdrawals.Order("timestamp DESC").Limit(limit + 1)
if cursorClause != "" { if cursorClause != "" {
...@@ -283,7 +285,7 @@ l2_transaction_withdrawals.timestamp, NULL AS cross_domain_message_hash, ? AS lo ...@@ -283,7 +285,7 @@ l2_transaction_withdrawals.timestamp, NULL AS cross_domain_message_hash, ? AS lo
withdrawalsQuery = withdrawalsQuery.Joins("LEFT JOIN l1_contract_events AS finalized_l1_events ON finalized_l1_events.guid = l2_transaction_withdrawals.finalized_l1_event_guid") withdrawalsQuery = withdrawalsQuery.Joins("LEFT JOIN l1_contract_events AS finalized_l1_events ON finalized_l1_events.guid = l2_transaction_withdrawals.finalized_l1_event_guid")
withdrawalsQuery = withdrawalsQuery.Select(` withdrawalsQuery = withdrawalsQuery.Select(`
l2_bridge_withdrawals.from_address, l2_bridge_withdrawals.to_address, l2_bridge_withdrawals.amount, l2_bridge_withdrawals.data, transaction_withdrawal_hash, l2_bridge_withdrawals.from_address, l2_bridge_withdrawals.to_address, l2_bridge_withdrawals.amount, l2_bridge_withdrawals.data, transaction_withdrawal_hash,
l2_contract_events.transaction_hash AS l2_transaction_hash, proven_l1_events.transaction_hash AS proven_l1_transaction_hash, finalized_l1_events.transaction_hash AS finalized_l1_transaction_hash, l2_contract_events.transaction_hash AS l2_transaction_hash, l2_contract_events.block_hash as l2_block_hash, proven_l1_events.transaction_hash AS proven_l1_transaction_hash, finalized_l1_events.transaction_hash AS finalized_l1_transaction_hash,
l2_bridge_withdrawals.timestamp, cross_domain_message_hash, local_token_address, remote_token_address`) l2_bridge_withdrawals.timestamp, cross_domain_message_hash, local_token_address, remote_token_address`)
withdrawalsQuery = withdrawalsQuery.Order("timestamp DESC").Limit(limit + 1) withdrawalsQuery = withdrawalsQuery.Order("timestamp DESC").Limit(limit + 1)
if cursorClause != "" { if cursorClause != "" {
......
package database package database
import ( import (
"math/big"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/mock" "github.com/stretchr/testify/mock"
...@@ -53,16 +51,6 @@ func (m *MockBlocksView) L2LatestBlockHeader() (*L2BlockHeader, error) { ...@@ -53,16 +51,6 @@ func (m *MockBlocksView) L2LatestBlockHeader() (*L2BlockHeader, error) {
return args.Get(0).(*L2BlockHeader), args.Error(1) return args.Get(0).(*L2BlockHeader), args.Error(1)
} }
func (m *MockBlocksView) LatestCheckpointedOutput() (*OutputProposal, error) {
args := m.Called()
return args.Get(0).(*OutputProposal), args.Error(1)
}
func (m *MockBlocksView) OutputProposal(index *big.Int) (*OutputProposal, error) {
args := m.Called()
return args.Get(0).(*OutputProposal), args.Error(1)
}
func (m *MockBlocksView) LatestEpoch() (*Epoch, error) { func (m *MockBlocksView) LatestEpoch() (*Epoch, error) {
args := m.Called() args := m.Called()
return args.Get(0).(*Epoch), args.Error(1) return args.Get(0).(*Epoch), args.Error(1)
...@@ -82,15 +70,6 @@ func (m *MockBlocksDB) StoreL2BlockHeaders(headers []L2BlockHeader) error { ...@@ -82,15 +70,6 @@ func (m *MockBlocksDB) StoreL2BlockHeaders(headers []L2BlockHeader) error {
return args.Error(1) return args.Error(1)
} }
func (m *MockBlocksDB) StoreLegacyStateBatches(headers []LegacyStateBatch) error {
args := m.Called(headers)
return args.Error(1)
}
func (m *MockBlocksDB) StoreOutputProposals(headers []OutputProposal) error {
args := m.Called(headers)
return args.Error(1)
}
// MockDB is a mock database that can be used for testing // MockDB is a mock database that can be used for testing
type MockDB struct { type MockDB struct {
MockBlocks *MockBlocksDB MockBlocks *MockBlocksDB
......
...@@ -57,6 +57,7 @@ func TestE2EBridgeTransfersStandardBridgeETHDeposit(t *testing.T) { ...@@ -57,6 +57,7 @@ func TestE2EBridgeTransfersStandardBridgeETHDeposit(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.Len(t, aliceDeposits.Deposits, 1) require.Len(t, aliceDeposits.Deposits, 1)
require.Equal(t, depositTx.Hash(), aliceDeposits.Deposits[0].L1TransactionHash) require.Equal(t, depositTx.Hash(), aliceDeposits.Deposits[0].L1TransactionHash)
require.Equal(t, depositReceipt.BlockHash, aliceDeposits.Deposits[0].L1BlockHash)
require.Equal(t, "", aliceDeposits.Cursor) require.Equal(t, "", aliceDeposits.Cursor)
require.Equal(t, false, aliceDeposits.HasNextPage) require.Equal(t, false, aliceDeposits.HasNextPage)
require.Equal(t, types.NewTx(depositInfo.DepositTx).Hash().String(), aliceDeposits.Deposits[0].L2TransactionHash.String()) require.Equal(t, types.NewTx(depositInfo.DepositTx).Hash().String(), aliceDeposits.Deposits[0].L2TransactionHash.String())
...@@ -293,6 +294,7 @@ func TestE2EBridgeTransfersStandardBridgeETHWithdrawal(t *testing.T) { ...@@ -293,6 +294,7 @@ func TestE2EBridgeTransfersStandardBridgeETHWithdrawal(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, proveReceipt.TxHash, aliceWithdrawals.Withdrawals[0].ProvenL1TransactionHash) require.Equal(t, proveReceipt.TxHash, aliceWithdrawals.Withdrawals[0].ProvenL1TransactionHash)
require.Equal(t, finalizeReceipt.TxHash, aliceWithdrawals.Withdrawals[0].FinalizedL1TransactionHash) require.Equal(t, finalizeReceipt.TxHash, aliceWithdrawals.Withdrawals[0].FinalizedL1TransactionHash)
require.Equal(t, withdrawReceipt.BlockHash, aliceWithdrawals.Withdrawals[0].L2BlockHash)
crossDomainBridgeMessage, err = testSuite.DB.BridgeMessages.L2BridgeMessage(*withdrawal.CrossDomainMessageHash) crossDomainBridgeMessage, err = testSuite.DB.BridgeMessages.L2BridgeMessage(*withdrawal.CrossDomainMessageHash)
require.NoError(t, err) require.NoError(t, err)
......
...@@ -71,45 +71,6 @@ func TestE2EETL(t *testing.T) { ...@@ -71,45 +71,6 @@ func TestE2EETL(t *testing.T) {
} }
}) })
/*
TODO: ADD THIS BACK IN WHEN THESE MARKERS ARE INDEXED
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.EthInstances["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 := testSuite.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 blocks with accompanying contract event", func(t *testing.T) { t.Run("indexes L1 blocks with accompanying contract event", func(t *testing.T) {
l1Contracts := []common.Address{} l1Contracts := []common.Address{}
testSuite.OpCfg.L1Deployments.ForEach(func(name string, addr common.Address) { l1Contracts = append(l1Contracts, addr) }) testSuite.OpCfg.L1Deployments.ForEach(func(name string, addr common.Address) { l1Contracts = append(l1Contracts, addr) })
......
...@@ -71,15 +71,17 @@ func createE2ETestSuite(t *testing.T) E2ETestSuite { ...@@ -71,15 +71,17 @@ func createE2ETestSuite(t *testing.T) E2ETestSuite {
L2RPC: opSys.EthInstances["sequencer"].HTTPEndpoint(), L2RPC: opSys.EthInstances["sequencer"].HTTPEndpoint(),
}, },
Chain: config.ChainConfig{ Chain: config.ChainConfig{
L1PollingInterval: uint(opCfg.DeployConfig.L1BlockTime) * 1000, L1PollingInterval: uint(opCfg.DeployConfig.L1BlockTime) * 1000,
L1ConfirmationDepth: 0, L2PollingInterval: uint(opCfg.DeployConfig.L2BlockTime) * 1000,
L2PollingInterval: uint(opCfg.DeployConfig.L2BlockTime) * 1000, L2Contracts: config.L2ContractsFromPredeploys(),
L2ConfirmationDepth: 0,
L1Contracts: config.L1Contracts{ L1Contracts: config.L1Contracts{
AddressManager: opCfg.L1Deployments.AddressManager,
SystemConfigProxy: opCfg.L1Deployments.SystemConfigProxy,
OptimismPortalProxy: opCfg.L1Deployments.OptimismPortalProxy, OptimismPortalProxy: opCfg.L1Deployments.OptimismPortalProxy,
L2OutputOracleProxy: opCfg.L1Deployments.L2OutputOracleProxy, L2OutputOracleProxy: opCfg.L1Deployments.L2OutputOracleProxy,
L1CrossDomainMessengerProxy: opCfg.L1Deployments.L1CrossDomainMessengerProxy, L1CrossDomainMessengerProxy: opCfg.L1Deployments.L1CrossDomainMessengerProxy,
L1StandardBridgeProxy: opCfg.L1Deployments.L1StandardBridgeProxy, L1StandardBridgeProxy: opCfg.L1Deployments.L1StandardBridgeProxy,
L1ERC721BridgeProxy: opCfg.L1Deployments.L1ERC721BridgeProxy,
}, },
}, },
HTTPServer: config.ServerConfig{Host: "127.0.0.1", Port: 0}, HTTPServer: config.ServerConfig{Host: "127.0.0.1", Port: 0},
......
...@@ -9,6 +9,7 @@ import ( ...@@ -9,6 +9,7 @@ import (
"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/crypto"
) )
type CrossDomainMessengerSentMessage struct { type CrossDomainMessengerSentMessage struct {
...@@ -57,5 +58,10 @@ func CrossDomainMessengerSentMessageHash(sentMessage *bindings.CrossDomainMessen ...@@ -57,5 +58,10 @@ func CrossDomainMessengerSentMessageHash(sentMessage *bindings.CrossDomainMessen
return common.Hash{}, err return common.Hash{}, err
} }
return contracts.CrossDomainMessageHash(abi, sentMessage, value) calldata, err := contracts.CrossDomainMessageCalldata(abi, sentMessage, value)
if err != nil {
return common.Hash{}, err
}
return crypto.Keccak256Hash(calldata), nil
} }
...@@ -29,9 +29,10 @@ type ETL struct { ...@@ -29,9 +29,10 @@ type ETL struct {
headerBufferSize uint64 headerBufferSize uint64
headerTraversal *node.HeaderTraversal headerTraversal *node.HeaderTraversal
ethClient node.EthClient
contracts []common.Address contracts []common.Address
etlBatches chan ETLBatch etlBatches chan ETLBatch
EthClient node.EthClient
} }
type ETLBatch struct { type ETLBatch struct {
...@@ -104,7 +105,7 @@ func (etl *ETL) processBatch(headers []types.Header) error { ...@@ -104,7 +105,7 @@ func (etl *ETL) processBatch(headers []types.Header) error {
} }
headersWithLog := make(map[common.Hash]bool, len(headers)) headersWithLog := make(map[common.Hash]bool, len(headers))
logs, err := etl.ethClient.FilterLogs(ethereum.FilterQuery{FromBlock: firstHeader.Number, ToBlock: lastHeader.Number, Addresses: etl.contracts}) logs, err := etl.EthClient.FilterLogs(ethereum.FilterQuery{FromBlock: firstHeader.Number, ToBlock: lastHeader.Number, Addresses: etl.contracts})
if err != nil { if err != nil {
batchLog.Info("unable to extract logs", "err", err) batchLog.Info("unable to extract logs", "err", err)
return err return err
......
...@@ -2,7 +2,9 @@ package etl ...@@ -2,7 +2,9 @@ package etl
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"strings"
"sync" "sync"
"time" "time"
...@@ -10,6 +12,7 @@ import ( ...@@ -10,6 +12,7 @@ import (
"github.com/ethereum-optimism/optimism/indexer/database" "github.com/ethereum-optimism/optimism/indexer/database"
"github.com/ethereum-optimism/optimism/indexer/node" "github.com/ethereum-optimism/optimism/indexer/node"
"github.com/ethereum-optimism/optimism/op-service/retry" "github.com/ethereum-optimism/optimism/op-service/retry"
"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"
) )
...@@ -27,12 +30,25 @@ type L1ETL struct { ...@@ -27,12 +30,25 @@ type L1ETL struct {
func NewL1ETL(cfg Config, log log.Logger, db *database.DB, metrics Metricer, client node.EthClient, contracts config.L1Contracts) (*L1ETL, error) { func NewL1ETL(cfg Config, log log.Logger, db *database.DB, metrics Metricer, client node.EthClient, contracts config.L1Contracts) (*L1ETL, error) {
log = log.New("etl", "l1") log = log.New("etl", "l1")
latestHeader, err := db.Blocks.L1LatestBlockHeader() zeroAddr := common.Address{}
if err != nil { l1Contracts := []common.Address{}
if err := contracts.ForEach(func(name string, addr common.Address) error {
// Since we dont have backfill support yet, we want to make sure all expected
// contracts are specified to ensure consistent behavior. Once backfill support
// is ready, we can relax this requirement.
if addr == zeroAddr && !strings.HasPrefix(name, "Legacy") {
log.Error("address not configured", "name", name)
return errors.New("all L1Contracts must be configured")
}
log.Info("configured contract", "name", name, "addr", addr)
l1Contracts = append(l1Contracts, addr)
return nil
}); err != nil {
return nil, err return nil, err
} }
cSlice, err := contracts.AsSlice() latestHeader, err := db.Blocks.L1LatestBlockHeader()
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -42,7 +58,6 @@ func NewL1ETL(cfg Config, log log.Logger, db *database.DB, metrics Metricer, cli ...@@ -42,7 +58,6 @@ func NewL1ETL(cfg Config, log log.Logger, db *database.DB, metrics Metricer, cli
if latestHeader != nil { if latestHeader != nil {
log.Info("detected last indexed block", "number", latestHeader.Number, "hash", latestHeader.Hash) log.Info("detected last indexed block", "number", latestHeader.Number, "hash", latestHeader.Hash)
fromHeader = latestHeader.RLPHeader.Header() fromHeader = latestHeader.RLPHeader.Header()
} else if cfg.StartHeight.BitLen() > 0 { } else if cfg.StartHeight.BitLen() > 0 {
log.Info("no indexed state starting from supplied L1 height", "height", cfg.StartHeight.String()) log.Info("no indexed state starting from supplied L1 height", "height", cfg.StartHeight.String())
header, err := client.BlockHeaderByNumber(cfg.StartHeight) header, err := client.BlockHeaderByNumber(cfg.StartHeight)
...@@ -51,7 +66,6 @@ func NewL1ETL(cfg Config, log log.Logger, db *database.DB, metrics Metricer, cli ...@@ -51,7 +66,6 @@ func NewL1ETL(cfg Config, log log.Logger, db *database.DB, metrics Metricer, cli
} }
fromHeader = header fromHeader = header
} else { } else {
log.Info("no indexed state, starting from genesis") log.Info("no indexed state, starting from genesis")
} }
...@@ -66,9 +80,10 @@ func NewL1ETL(cfg Config, log log.Logger, db *database.DB, metrics Metricer, cli ...@@ -66,9 +80,10 @@ func NewL1ETL(cfg Config, log log.Logger, db *database.DB, metrics Metricer, cli
log: log, log: log,
metrics: metrics, metrics: metrics,
headerTraversal: node.NewHeaderTraversal(client, fromHeader, cfg.ConfirmationDepth), headerTraversal: node.NewHeaderTraversal(client, fromHeader, cfg.ConfirmationDepth),
ethClient: client, contracts: l1Contracts,
contracts: cSlice,
etlBatches: etlBatches, etlBatches: etlBatches,
EthClient: client,
} }
return &L1ETL{ETL: etl, db: db, mu: new(sync.Mutex)}, nil return &L1ETL{ETL: etl, db: db, mu: new(sync.Mutex)}, nil
......
...@@ -51,10 +51,12 @@ func TestL1ETLConstruction(t *testing.T) { ...@@ -51,10 +51,12 @@ func TestL1ETLConstruction(t *testing.T) {
client.On("GethEthClient").Return(nil) client.On("GethEthClient").Return(nil)
return &testSuite{ return &testSuite{
db: db, db: db,
client: client, client: client,
start: testStart, start: testStart,
contracts: config.L1Contracts{},
// utilize sample l1 contract configuration (optimism)
contracts: config.Presets[10].ChainConfig.L1Contracts,
} }
}, },
assertion: func(etl *L1ETL, err error) { assertion: func(etl *L1ETL, err error) {
...@@ -81,10 +83,12 @@ func TestL1ETLConstruction(t *testing.T) { ...@@ -81,10 +83,12 @@ func TestL1ETLConstruction(t *testing.T) {
client.On("GethEthClient").Return(nil) client.On("GethEthClient").Return(nil)
return &testSuite{ return &testSuite{
db: db, db: db,
client: client, client: client,
start: testStart, start: testStart,
contracts: config.L1Contracts{},
// utilize sample l1 contract configuration (optimism)
contracts: config.Presets[10].ChainConfig.L1Contracts,
} }
}, },
assertion: func(etl *L1ETL, err error) { assertion: func(etl *L1ETL, err error) {
......
...@@ -2,11 +2,12 @@ package etl ...@@ -2,11 +2,12 @@ package etl
import ( import (
"context" "context"
"errors"
"time" "time"
"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/node" "github.com/ethereum-optimism/optimism/indexer/node"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys"
"github.com/ethereum-optimism/optimism/op-service/retry" "github.com/ethereum-optimism/optimism/op-service/retry"
"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"
...@@ -19,14 +20,25 @@ type L2ETL struct { ...@@ -19,14 +20,25 @@ type L2ETL struct {
db *database.DB db *database.DB
} }
func NewL2ETL(cfg Config, log log.Logger, db *database.DB, metrics Metricer, client node.EthClient) (*L2ETL, error) { func NewL2ETL(cfg Config, log log.Logger, db *database.DB, metrics Metricer, client node.EthClient, contracts config.L2Contracts) (*L2ETL, error) {
log = log.New("etl", "l2") log = log.New("etl", "l2")
// allow predeploys to be overridable zeroAddr := common.Address{}
l2Contracts := []common.Address{} l2Contracts := []common.Address{}
for name, addr := range predeploys.Predeploys { if err := contracts.ForEach(func(name string, addr common.Address) error {
// Since we dont have backfill support yet, we want to make sure all expected
// contracts are specified to ensure consistent behavior. Once backfill support
// is ready, we can relax this requirement.
if addr == zeroAddr {
log.Error("address not configured", "name", name)
return errors.New("all L2Contracts must be configured")
}
log.Info("configured contract", "name", name, "addr", addr) log.Info("configured contract", "name", name, "addr", addr)
l2Contracts = append(l2Contracts, *addr) l2Contracts = append(l2Contracts, addr)
return nil
}); err != nil {
return nil, err
} }
latestHeader, err := db.Blocks.L2LatestBlockHeader() latestHeader, err := db.Blocks.L2LatestBlockHeader()
...@@ -50,9 +62,10 @@ func NewL2ETL(cfg Config, log log.Logger, db *database.DB, metrics Metricer, cli ...@@ -50,9 +62,10 @@ func NewL2ETL(cfg Config, log log.Logger, db *database.DB, metrics Metricer, cli
log: log, log: log,
metrics: metrics, metrics: metrics,
headerTraversal: node.NewHeaderTraversal(client, fromHeader, cfg.ConfirmationDepth), headerTraversal: node.NewHeaderTraversal(client, fromHeader, cfg.ConfirmationDepth),
ethClient: client,
contracts: l2Contracts, contracts: l2Contracts,
etlBatches: etlBatches, etlBatches: etlBatches,
EthClient: client,
} }
return &L2ETL{ETL: etl, db: db}, nil return &L2ETL{ETL: etl, db: db}, nil
......
...@@ -76,7 +76,7 @@ func NewIndexer( ...@@ -76,7 +76,7 @@ func NewIndexer(
HeaderBufferSize: chainConfig.L2HeaderBufferSize, HeaderBufferSize: chainConfig.L2HeaderBufferSize,
ConfirmationDepth: big.NewInt(int64(chainConfig.L2ConfirmationDepth)), ConfirmationDepth: big.NewInt(int64(chainConfig.L2ConfirmationDepth)),
} }
l2Etl, err := etl.NewL2ETL(l2Cfg, log, db, etl.NewMetrics(metricsRegistry, "l2"), l2EthClient) l2Etl, err := etl.NewL2ETL(l2Cfg, log, db, etl.NewMetrics(metricsRegistry, "l2"), l2EthClient, chainConfig.L2Contracts)
if err != nil { if err != nil {
return nil, err return nil, err
} }
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
# Can configure them manually or use a preset l2 ChainId for known chains including OP Mainnet, OP Goerli, Base, Base Goerli, Zora, and Zora goerli # Can configure them manually or use a preset l2 ChainId for known chains including OP Mainnet, OP Goerli, Base, Base Goerli, Zora, and Zora goerli
[chain] [chain]
# OP Goerli
preset = $INDEXER_CHAIN_PRESET preset = $INDEXER_CHAIN_PRESET
# L1 Config # L1 Config
......
...@@ -29,7 +29,7 @@ CREATE TABLE IF NOT EXISTS l2_block_headers ( ...@@ -29,7 +29,7 @@ CREATE TABLE IF NOT EXISTS l2_block_headers (
hash VARCHAR PRIMARY KEY, hash VARCHAR PRIMARY KEY,
parent_hash VARCHAR NOT NULL UNIQUE, parent_hash VARCHAR NOT NULL UNIQUE,
number UINT256 NOT NULL UNIQUE, number UINT256 NOT NULL UNIQUE,
timestamp INTEGER NOT NULL UNIQUE CHECK (timestamp > 0), timestamp INTEGER NOT NULL,
-- Raw Data -- Raw Data
rlp_bytes VARCHAR NOT NULL rlp_bytes VARCHAR NOT NULL
...@@ -57,6 +57,7 @@ CREATE TABLE IF NOT EXISTS l1_contract_events ( ...@@ -57,6 +57,7 @@ CREATE TABLE IF NOT EXISTS l1_contract_events (
CREATE INDEX IF NOT EXISTS l1_contract_events_timestamp ON l1_contract_events(timestamp); CREATE INDEX IF NOT EXISTS l1_contract_events_timestamp ON l1_contract_events(timestamp);
CREATE INDEX IF NOT EXISTS l1_contract_events_block_hash ON l1_contract_events(block_hash); CREATE INDEX IF NOT EXISTS l1_contract_events_block_hash ON l1_contract_events(block_hash);
CREATE INDEX IF NOT EXISTS l1_contract_events_event_signature ON l1_contract_events(event_signature); CREATE INDEX IF NOT EXISTS l1_contract_events_event_signature ON l1_contract_events(event_signature);
CREATE INDEX IF NOT EXISTS l1_contract_events_contract_address ON l1_contract_events(contract_address);
CREATE TABLE IF NOT EXISTS l2_contract_events ( CREATE TABLE IF NOT EXISTS l2_contract_events (
-- Searchable fields -- Searchable fields
...@@ -74,52 +75,12 @@ CREATE TABLE IF NOT EXISTS l2_contract_events ( ...@@ -74,52 +75,12 @@ CREATE TABLE IF NOT EXISTS l2_contract_events (
CREATE INDEX IF NOT EXISTS l2_contract_events_timestamp ON l2_contract_events(timestamp); CREATE INDEX IF NOT EXISTS l2_contract_events_timestamp ON l2_contract_events(timestamp);
CREATE INDEX IF NOT EXISTS l2_contract_events_block_hash ON l2_contract_events(block_hash); CREATE INDEX IF NOT EXISTS l2_contract_events_block_hash ON l2_contract_events(block_hash);
CREATE INDEX IF NOT EXISTS l2_contract_events_event_signature ON l2_contract_events(event_signature); CREATE INDEX IF NOT EXISTS l2_contract_events_event_signature ON l2_contract_events(event_signature);
CREATE INDEX IF NOT EXISTS l2_contract_events_contract_address ON l2_contract_events(contract_address);
-- Tables that index finalization markers for L2 blocks.
CREATE TABLE IF NOT EXISTS legacy_state_batches (
index INTEGER PRIMARY KEY,
root VARCHAR NOT NULL UNIQUE,
size INTEGER NOT NULL,
prev_total INTEGER NOT NULL,
state_batch_appended_guid VARCHAR NOT NULL UNIQUE REFERENCES l1_contract_events(guid) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS output_proposals (
output_root VARCHAR PRIMARY KEY,
l2_output_index UINT256 NOT NULL UNIQUE,
l2_block_number UINT256 NOT NULL UNIQUE,
output_proposed_guid VARCHAR NOT NULL UNIQUE REFERENCES l1_contract_events(guid) ON DELETE CASCADE
);
/** /**
* BRIDGING DATA * BRIDGING DATA
*/ */
-- Bridged L1/L2 Tokens
CREATE TABLE IF NOT EXISTS l1_bridged_tokens (
address VARCHAR PRIMARY KEY,
bridge_address VARCHAR NOT NULL,
name VARCHAR NOT NULL,
symbol VARCHAR NOT NULL,
decimals INTEGER NOT NULL CHECK (decimals >= 0 AND decimals <= 18)
);
CREATE TABLE IF NOT EXISTS l2_bridged_tokens (
address VARCHAR PRIMARY KEY,
bridge_address VARCHAR NOT NULL,
-- L1-L2 relationship is 1 to many so this is not necessarily unique
l1_token_address VARCHAR REFERENCES l1_bridged_tokens(address) ON DELETE CASCADE,
name VARCHAR NOT NULL,
symbol VARCHAR NOT NULL,
decimals INTEGER NOT NULL CHECK (decimals >= 0 AND decimals <= 18)
);
-- OptimismPortal/L2ToL1MessagePasser -- OptimismPortal/L2ToL1MessagePasser
CREATE TABLE IF NOT EXISTS l1_transaction_deposits ( CREATE TABLE IF NOT EXISTS l1_transaction_deposits (
source_hash VARCHAR PRIMARY KEY, source_hash VARCHAR PRIMARY KEY,
...@@ -202,6 +163,26 @@ CREATE INDEX IF NOT EXISTS l2_bridge_messages_transaction_withdrawal_hash ON l2_ ...@@ -202,6 +163,26 @@ CREATE INDEX IF NOT EXISTS l2_bridge_messages_transaction_withdrawal_hash ON l2_
CREATE INDEX IF NOT EXISTS l2_bridge_messages_from_address ON l2_bridge_messages(from_address); CREATE INDEX IF NOT EXISTS l2_bridge_messages_from_address ON l2_bridge_messages(from_address);
-- StandardBridge -- StandardBridge
CREATE TABLE IF NOT EXISTS l1_bridged_tokens (
address VARCHAR PRIMARY KEY,
bridge_address VARCHAR NOT NULL,
name VARCHAR NOT NULL,
symbol VARCHAR NOT NULL,
decimals INTEGER NOT NULL CHECK (decimals >= 0 AND decimals <= 18)
);
CREATE TABLE IF NOT EXISTS l2_bridged_tokens (
address VARCHAR PRIMARY KEY,
bridge_address VARCHAR NOT NULL,
-- L1-L2 relationship is 1 to many so this is not necessarily unique
l1_token_address VARCHAR REFERENCES l1_bridged_tokens(address) ON DELETE CASCADE,
name VARCHAR NOT NULL,
symbol VARCHAR NOT NULL,
decimals INTEGER NOT NULL CHECK (decimals >= 0 AND decimals <= 18)
);
CREATE TABLE IF NOT EXISTS l1_bridge_deposits ( CREATE TABLE IF NOT EXISTS l1_bridge_deposits (
transaction_source_hash VARCHAR PRIMARY KEY REFERENCES l1_transaction_deposits(source_hash) ON DELETE CASCADE, transaction_source_hash VARCHAR PRIMARY KEY REFERENCES l1_transaction_deposits(source_hash) ON DELETE CASCADE,
cross_domain_message_hash VARCHAR NOT NULL UNIQUE REFERENCES l1_bridge_messages(message_hash) ON DELETE CASCADE, cross_domain_message_hash VARCHAR NOT NULL UNIQUE REFERENCES l1_bridge_messages(message_hash) ON DELETE CASCADE,
......
...@@ -29,6 +29,8 @@ type EthClient interface { ...@@ -29,6 +29,8 @@ type EthClient interface {
BlockHeaderByHash(common.Hash) (*types.Header, error) BlockHeaderByHash(common.Hash) (*types.Header, error)
BlockHeadersByRange(*big.Int, *big.Int) ([]types.Header, error) BlockHeadersByRange(*big.Int, *big.Int) ([]types.Header, error)
TxByHash(common.Hash) (*types.Transaction, error)
StorageHash(common.Address, *big.Int) (common.Hash, error) StorageHash(common.Address, *big.Int) (common.Hash, error)
FilterLogs(ethereum.FilterQuery) ([]types.Log, error) FilterLogs(ethereum.FilterQuery) ([]types.Log, error)
} }
...@@ -147,6 +149,21 @@ func (c *client) BlockHeadersByRange(startHeight, endHeight *big.Int) ([]types.H ...@@ -147,6 +149,21 @@ func (c *client) BlockHeadersByRange(startHeight, endHeight *big.Int) ([]types.H
return headers, nil return headers, nil
} }
func (c *client) TxByHash(hash common.Hash) (*types.Transaction, error) {
ctxwt, cancel := context.WithTimeout(context.Background(), defaultRequestTimeout)
defer cancel()
var tx *types.Transaction
err := c.rpc.CallContext(ctxwt, &tx, "eth_getTransactionByHash", hash)
if err != nil {
return nil, err
} else if tx == nil {
return nil, ethereum.NotFound
}
return tx, nil
}
// StorageHash returns the sha3 of the storage root for the specified account // 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) { func (c *client) StorageHash(address common.Address, blockNumber *big.Int) (common.Hash, error) {
ctxwt, cancel := context.WithTimeout(context.Background(), defaultRequestTimeout) ctxwt, cancel := context.WithTimeout(context.Background(), defaultRequestTimeout)
......
...@@ -31,6 +31,11 @@ func (m *MockEthClient) BlockHeadersByRange(from, to *big.Int) ([]types.Header, ...@@ -31,6 +31,11 @@ func (m *MockEthClient) BlockHeadersByRange(from, to *big.Int) ([]types.Header,
return args.Get(0).([]types.Header), args.Error(1) return args.Get(0).([]types.Header), args.Error(1)
} }
func (m *MockEthClient) TxByHash(hash common.Hash) (*types.Transaction, error) {
args := m.Called(hash)
return args.Get(0).(*types.Transaction), args.Error(1)
}
func (m *MockEthClient) StorageHash(address common.Address, blockNumber *big.Int) (common.Hash, error) { func (m *MockEthClient) StorageHash(address common.Address, blockNumber *big.Int) (common.Hash, error) {
args := m.Called(address, blockNumber) args := m.Called(address, blockNumber)
return args.Get(0).(common.Hash), args.Error(1) return args.Get(0).(common.Hash), args.Error(1)
......
...@@ -124,30 +124,89 @@ func (b *BridgeProcessor) Start(ctx context.Context) error { ...@@ -124,30 +124,89 @@ func (b *BridgeProcessor) Start(ctx context.Context) error {
fromL2Height = new(big.Int).Add(b.LatestL2Header.Number, bigint.One) fromL2Height = new(big.Int).Add(b.LatestL2Header.Number, bigint.One)
} }
l1BedrockStartingHeight := big.NewInt(int64(b.chainConfig.L1BedrockStartingHeight))
l2BedrockStartingHeight := big.NewInt(int64(b.chainConfig.L2BedrockStartingHeight))
batchLog := b.log.New("epoch_start_number", fromL1Height, "epoch_end_number", toL1Height) batchLog := b.log.New("epoch_start_number", fromL1Height, "epoch_end_number", toL1Height)
batchLog.Info("unobserved epochs") batchLog.Info("unobserved epochs")
err = b.db.Transaction(func(tx *database.DB) error { err = b.db.Transaction(func(tx *database.DB) error {
// In the event where we have a large number of un-observed blocks, group the block range
// on the order of 10k blocks at a time. If this turns out to be a bottleneck, we can
// parallelize these operations
maxBlockRange := uint64(10_000)
l1BridgeLog := b.log.New("bridge", "l1") l1BridgeLog := b.log.New("bridge", "l1")
l2BridgeLog := b.log.New("bridge", "l2") l2BridgeLog := b.log.New("bridge", "l2")
// In the event where we have a large number of un-observed blocks, group the block range // FOR OP-MAINNET, OP-GOERLI ONLY! Specially handle the existence of pre-bedrock blocks
// on the order of 10k blocks at a time. If this turns out to be a bottleneck, we can if l1BedrockStartingHeight.Cmp(fromL1Height) > 0 {
// parallelize these operations for significant improvements as well l1BridgeLog := l1BridgeLog.New("mode", "legacy")
l1BlockGroups := bigint.Grouped(fromL1Height, toL1Height, 10_000) l2BridgeLog := l2BridgeLog.New("mode", "legacy")
l2BlockGroups := bigint.Grouped(fromL2Height, toL2Height, 10_000)
legacyFromL1Height, legacyToL1Height := fromL1Height, toL1Height
legacyFromL2Height, legacyToL2Height := fromL2Height, toL2Height
if l1BedrockStartingHeight.Cmp(toL1Height) <= 0 {
legacyToL1Height = new(big.Int).Sub(l1BedrockStartingHeight, big.NewInt(1))
legacyToL2Height = new(big.Int).Sub(l2BedrockStartingHeight, big.NewInt(1))
}
// First, find all possible initiated bridge events
l1BlockGroups := bigint.Grouped(legacyFromL1Height, legacyToL1Height, maxBlockRange)
l2BlockGroups := bigint.Grouped(legacyFromL2Height, legacyToL2Height, maxBlockRange)
for _, group := range l1BlockGroups {
log := l1BridgeLog.New("from_l1_block_number", group.Start, "to_l1_block_number", group.End)
log.Info("scanning for initiated bridge events")
if err := bridge.LegacyL1ProcessInitiatedBridgeEvents(log, tx, b.chainConfig.L1Contracts, group.Start, group.End); err != nil {
return err
}
}
for _, group := range l2BlockGroups {
log := l2BridgeLog.New("from_l2_block_number", group.Start, "to_l2_block_number", group.End)
log.Info("scanning for initiated bridge events")
if err := bridge.LegacyL2ProcessInitiatedBridgeEvents(log, tx, b.chainConfig.L2Contracts, group.Start, group.End); err != nil {
return err
}
}
// Now that all initiated events have been indexed, it is ensured that all finalization can find their counterpart.
for _, group := range l1BlockGroups {
log := l1BridgeLog.New("from_l1_block_number", group.Start, "to_l1_block_number", group.End)
log.Info("scanning for finalized bridge events")
if err := bridge.LegacyL1ProcessFinalizedBridgeEvents(log, tx, b.l1Etl.EthClient, b.chainConfig.L1Contracts, group.Start, group.End); err != nil {
return err
}
}
for _, group := range l2BlockGroups {
log := l2BridgeLog.New("from_l2_block_number", group.Start, "to_l2_block_number", group.End)
log.Info("scanning for finalized bridge events")
if err := bridge.LegacyL2ProcessFinalizedBridgeEvents(log, tx, b.chainConfig.L2Contracts, group.Start, group.End); err != nil {
return err
}
}
if legacyToL1Height.Cmp(toL1Height) == 0 {
// a-ok! entire batch was legacy blocks
return nil
}
batchLog.Info("detected switch to bedrock", "l1_bedrock_starting_height", l1BedrockStartingHeight, "l2_bedrock_starting_height", l2BedrockStartingHeight)
fromL1Height = l1BedrockStartingHeight
fromL2Height = l2BedrockStartingHeight
}
// First, find all possible initiated bridge events // First, find all possible initiated bridge events
l1BlockGroups := bigint.Grouped(fromL1Height, toL1Height, maxBlockRange)
l2BlockGroups := bigint.Grouped(fromL2Height, toL2Height, maxBlockRange)
for _, group := range l1BlockGroups { for _, group := range l1BlockGroups {
log := l1BridgeLog.New("from_block_number", group.Start, "to_block_number", group.End) log := l1BridgeLog.New("from_block_number", group.Start, "to_block_number", group.End)
log.Info("scanning for initiated bridge events") log.Info("scanning for initiated bridge events")
if err := bridge.L1ProcessInitiatedBridgeEvents(log, tx, b.chainConfig, group.Start, group.End); err != nil { if err := bridge.L1ProcessInitiatedBridgeEvents(log, tx, b.chainConfig.L1Contracts, group.Start, group.End); err != nil {
return err return err
} }
} }
for _, group := range l2BlockGroups { for _, group := range l2BlockGroups {
log := l2BridgeLog.New("from_block_number", group.Start, "to_block_number", group.End) log := l2BridgeLog.New("from_block_number", group.Start, "to_block_number", group.End)
log.Info("scanning for initiated bridge events") log.Info("scanning for initiated bridge events")
if err := bridge.L2ProcessInitiatedBridgeEvents(log, tx, group.Start, group.End); err != nil { if err := bridge.L2ProcessInitiatedBridgeEvents(log, tx, b.chainConfig.L2Contracts, group.Start, group.End); err != nil {
return err return err
} }
} }
...@@ -156,14 +215,14 @@ func (b *BridgeProcessor) Start(ctx context.Context) error { ...@@ -156,14 +215,14 @@ func (b *BridgeProcessor) Start(ctx context.Context) error {
for _, group := range l1BlockGroups { for _, group := range l1BlockGroups {
log := l1BridgeLog.New("from_block_number", group.Start, "to_block_number", group.End) log := l1BridgeLog.New("from_block_number", group.Start, "to_block_number", group.End)
log.Info("scanning for finalized bridge events") log.Info("scanning for finalized bridge events")
if err := bridge.L1ProcessFinalizedBridgeEvents(log, tx, b.chainConfig, group.Start, group.End); err != nil { if err := bridge.L1ProcessFinalizedBridgeEvents(log, tx, b.chainConfig.L1Contracts, group.Start, group.End); err != nil {
return err return err
} }
} }
for _, group := range l2BlockGroups { for _, group := range l2BlockGroups {
log := l2BridgeLog.New("from_block_number", group.Start, "to_block_number", group.End) log := l2BridgeLog.New("from_block_number", group.Start, "to_block_number", group.End)
log.Info("scanning for finalized bridge events") log.Info("scanning for finalized bridge events")
if err := bridge.L2ProcessFinalizedBridgeEvents(log, tx, group.Start, group.End); err != nil { if err := bridge.L2ProcessFinalizedBridgeEvents(log, tx, b.chainConfig.L2Contracts, group.Start, group.End); err != nil {
return err return err
} }
} }
...@@ -181,4 +240,5 @@ func (b *BridgeProcessor) Start(ctx context.Context) error { ...@@ -181,4 +240,5 @@ func (b *BridgeProcessor) Start(ctx context.Context) error {
b.LatestL2Header = latestEpoch.L2BlockHeader.RLPHeader.Header() b.LatestL2Header = latestEpoch.L2BlockHeader.RLPHeader.Header()
} }
} }
} }
...@@ -12,14 +12,14 @@ import ( ...@@ -12,14 +12,14 @@ import (
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
) )
// L1ProcessInitiatedBridgeEvents will query the database for new bridge events that have been initiated between // L1ProcessInitiatedBridgeEvents will query the database for bridge events that have been initiated between
// the specified block range. This covers every part of the multi-layered stack: // the specified block range. This covers every part of the multi-layered stack:
// 1. OptimismPortal // 1. OptimismPortal
// 2. L1CrossDomainMessenger // 2. L1CrossDomainMessenger
// 3. L1StandardBridge // 3. L1StandardBridge
func L1ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, chainConfig config.ChainConfig, fromHeight *big.Int, toHeight *big.Int) error { func L1ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, l1Contracts config.L1Contracts, fromHeight, toHeight *big.Int) error {
// (1) OptimismPortal // (1) OptimismPortal
optimismPortalTxDeposits, err := contracts.OptimismPortalTransactionDepositEvents(chainConfig.L1Contracts.OptimismPortalProxy, db, fromHeight, toHeight) optimismPortalTxDeposits, err := contracts.OptimismPortalTransactionDepositEvents(l1Contracts.OptimismPortalProxy, db, fromHeight, toHeight)
if err != nil { if err != nil {
return err return err
} }
...@@ -47,7 +47,7 @@ func L1ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, chainConfig ...@@ -47,7 +47,7 @@ func L1ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, chainConfig
} }
// (2) L1CrossDomainMessenger // (2) L1CrossDomainMessenger
crossDomainSentMessages, err := contracts.CrossDomainMessengerSentMessageEvents("l1", chainConfig.L1Contracts.L1CrossDomainMessengerProxy, db, fromHeight, toHeight) crossDomainSentMessages, err := contracts.CrossDomainMessengerSentMessageEvents("l1", l1Contracts.L1CrossDomainMessengerProxy, db, fromHeight, toHeight)
if err != nil { if err != nil {
return err return err
} }
...@@ -77,7 +77,7 @@ func L1ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, chainConfig ...@@ -77,7 +77,7 @@ func L1ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, chainConfig
} }
// (3) L1StandardBridge // (3) L1StandardBridge
initiatedBridges, err := contracts.StandardBridgeInitiatedEvents("l1", chainConfig.L1Contracts.L1StandardBridgeProxy, db, fromHeight, toHeight) initiatedBridges, err := contracts.StandardBridgeInitiatedEvents("l1", l1Contracts.L1StandardBridgeProxy, db, fromHeight, toHeight)
if err != nil { if err != nil {
return err return err
} }
...@@ -121,9 +121,9 @@ func L1ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, chainConfig ...@@ -121,9 +121,9 @@ func L1ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, chainConfig
// 1. OptimismPortal (Bedrock prove & finalize steps) // 1. OptimismPortal (Bedrock prove & finalize steps)
// 2. L1CrossDomainMessenger (relayMessage marker) // 2. L1CrossDomainMessenger (relayMessage marker)
// 3. L1StandardBridge (no-op, since this is simply a wrapper over the L1CrossDomainMessenger) // 3. L1StandardBridge (no-op, since this is simply a wrapper over the L1CrossDomainMessenger)
func L1ProcessFinalizedBridgeEvents(log log.Logger, db *database.DB, chainConfig config.ChainConfig, fromHeight *big.Int, toHeight *big.Int) error { func L1ProcessFinalizedBridgeEvents(log log.Logger, db *database.DB, l1Contracts config.L1Contracts, fromHeight, toHeight *big.Int) error {
// (1) OptimismPortal (proven withdrawals) // (1) OptimismPortal (proven withdrawals)
provenWithdrawals, err := contracts.OptimismPortalWithdrawalProvenEvents(chainConfig.L1Contracts.OptimismPortalProxy, db, fromHeight, toHeight) provenWithdrawals, err := contracts.OptimismPortalWithdrawalProvenEvents(l1Contracts.OptimismPortalProxy, db, fromHeight, toHeight)
if err != nil { if err != nil {
return err return err
} }
...@@ -148,7 +148,7 @@ func L1ProcessFinalizedBridgeEvents(log log.Logger, db *database.DB, chainConfig ...@@ -148,7 +148,7 @@ func L1ProcessFinalizedBridgeEvents(log log.Logger, db *database.DB, chainConfig
} }
// (2) OptimismPortal (finalized withdrawals) // (2) OptimismPortal (finalized withdrawals)
finalizedWithdrawals, err := contracts.OptimismPortalWithdrawalFinalizedEvents(chainConfig.L1Contracts.OptimismPortalProxy, db, fromHeight, toHeight) finalizedWithdrawals, err := contracts.OptimismPortalWithdrawalFinalizedEvents(l1Contracts.OptimismPortalProxy, db, fromHeight, toHeight)
if err != nil { if err != nil {
return err return err
} }
...@@ -173,7 +173,7 @@ func L1ProcessFinalizedBridgeEvents(log log.Logger, db *database.DB, chainConfig ...@@ -173,7 +173,7 @@ func L1ProcessFinalizedBridgeEvents(log log.Logger, db *database.DB, chainConfig
} }
// (3) L1CrossDomainMessenger // (3) L1CrossDomainMessenger
crossDomainRelayedMessages, err := contracts.CrossDomainMessengerRelayedMessageEvents("l1", chainConfig.L1Contracts.L1CrossDomainMessengerProxy, db, fromHeight, toHeight) crossDomainRelayedMessages, err := contracts.CrossDomainMessengerRelayedMessageEvents("l1", l1Contracts.L1CrossDomainMessengerProxy, db, fromHeight, toHeight)
if err != nil { if err != nil {
return err return err
} }
...@@ -200,7 +200,7 @@ func L1ProcessFinalizedBridgeEvents(log log.Logger, db *database.DB, chainConfig ...@@ -200,7 +200,7 @@ func L1ProcessFinalizedBridgeEvents(log log.Logger, db *database.DB, chainConfig
} }
// (4) L1StandardBridge // (4) L1StandardBridge
finalizedBridges, err := contracts.StandardBridgeFinalizedEvents("l1", chainConfig.L1Contracts.L1StandardBridgeProxy, db, fromHeight, toHeight) finalizedBridges, err := contracts.StandardBridgeFinalizedEvents("l1", l1Contracts.L1StandardBridgeProxy, db, fromHeight, toHeight)
if err != nil { if err != nil {
return err return err
} }
......
...@@ -5,21 +5,21 @@ import ( ...@@ -5,21 +5,21 @@ import (
"fmt" "fmt"
"math/big" "math/big"
"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/processors/contracts" "github.com/ethereum-optimism/optimism/indexer/processors/contracts"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
) )
// L2ProcessInitiatedBridgeEvents will query the database for new bridge events that have been initiated between // L2ProcessInitiatedBridgeEvents will query the database for bridge events that have been initiated between
// the specified block range. This covers every part of the multi-layered stack: // the specified block range. This covers every part of the multi-layered stack:
// 1. OptimismPortal // 1. OptimismPortal
// 2. L2CrossDomainMessenger // 2. L2CrossDomainMessenger
// 3. L2StandardBridge // 3. L2StandardBridge
func L2ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, fromHeight *big.Int, toHeight *big.Int) error { func L2ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, l2Contracts config.L2Contracts, fromHeight, toHeight *big.Int) error {
// (1) L2ToL1MessagePasser // (1) L2ToL1MessagePasser
l2ToL1MPMessagesPassed, err := contracts.L2ToL1MessagePasserMessagePassedEvents(predeploys.L2ToL1MessagePasserAddr, db, fromHeight, toHeight) l2ToL1MPMessagesPassed, err := contracts.L2ToL1MessagePasserMessagePassedEvents(l2Contracts.L2ToL1MessagePasser, db, fromHeight, toHeight)
if err != nil { if err != nil {
return err return err
} }
...@@ -47,7 +47,7 @@ func L2ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, fromHeight ...@@ -47,7 +47,7 @@ func L2ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, fromHeight
} }
// (2) L2CrossDomainMessenger // (2) L2CrossDomainMessenger
crossDomainSentMessages, err := contracts.CrossDomainMessengerSentMessageEvents("l2", predeploys.L2CrossDomainMessengerAddr, db, fromHeight, toHeight) crossDomainSentMessages, err := contracts.CrossDomainMessengerSentMessageEvents("l2", l2Contracts.L2CrossDomainMessenger, db, fromHeight, toHeight)
if err != nil { if err != nil {
return err return err
} }
...@@ -78,7 +78,7 @@ func L2ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, fromHeight ...@@ -78,7 +78,7 @@ func L2ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, fromHeight
} }
// (3) L2StandardBridge // (3) L2StandardBridge
initiatedBridges, err := contracts.StandardBridgeInitiatedEvents("l2", predeploys.L2StandardBridgeAddr, db, fromHeight, toHeight) initiatedBridges, err := contracts.StandardBridgeInitiatedEvents("l2", l2Contracts.L2StandardBridge, db, fromHeight, toHeight)
if err != nil { if err != nil {
return err return err
} }
...@@ -122,9 +122,9 @@ func L2ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, fromHeight ...@@ -122,9 +122,9 @@ func L2ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, fromHeight
// 2. L2StandardBridge (no-op, since this is simply a wrapper over the L2CrossDomainMEssenger) // 2. L2StandardBridge (no-op, since this is simply a wrapper over the L2CrossDomainMEssenger)
// //
// NOTE: Unlike L1, there's no L2ToL1MessagePasser stage since transaction deposits are apart of the block derivation process. // NOTE: Unlike L1, there's no L2ToL1MessagePasser stage since transaction deposits are apart of the block derivation process.
func L2ProcessFinalizedBridgeEvents(log log.Logger, db *database.DB, fromHeight *big.Int, toHeight *big.Int) error { func L2ProcessFinalizedBridgeEvents(log log.Logger, db *database.DB, l2Contracts config.L2Contracts, fromHeight, toHeight *big.Int) error {
// (1) L2CrossDomainMessenger // (1) L2CrossDomainMessenger
crossDomainRelayedMessages, err := contracts.CrossDomainMessengerRelayedMessageEvents("l2", predeploys.L2CrossDomainMessengerAddr, db, fromHeight, toHeight) crossDomainRelayedMessages, err := contracts.CrossDomainMessengerRelayedMessageEvents("l2", l2Contracts.L2CrossDomainMessenger, db, fromHeight, toHeight)
if err != nil { if err != nil {
return err return err
} }
...@@ -151,7 +151,7 @@ func L2ProcessFinalizedBridgeEvents(log log.Logger, db *database.DB, fromHeight ...@@ -151,7 +151,7 @@ func L2ProcessFinalizedBridgeEvents(log log.Logger, db *database.DB, fromHeight
} }
// (2) L2StandardBridge // (2) L2StandardBridge
finalizedBridges, err := contracts.StandardBridgeFinalizedEvents("l2", predeploys.L2StandardBridgeAddr, db, fromHeight, toHeight) finalizedBridges, err := contracts.StandardBridgeFinalizedEvents("l2", l2Contracts.L2StandardBridge, db, fromHeight, toHeight)
if err != nil { if err != nil {
return err return err
} }
......
This diff is collapsed.
...@@ -18,7 +18,7 @@ var ( ...@@ -18,7 +18,7 @@ var (
bytesType, _ = abi.NewType("bytes", "", nil) bytesType, _ = abi.NewType("bytes", "", nil)
addressType, _ = abi.NewType("address", "", nil) addressType, _ = abi.NewType("address", "", nil)
legacyCrossDomainMessengerRelayMessageMethod = abi.NewMethod( CrossDomainMessengerLegacyRelayMessageEncoding = abi.NewMethod(
"relayMessage", "relayMessage",
"relayMessage", "relayMessage",
abi.Function, abi.Function,
...@@ -26,18 +26,21 @@ var ( ...@@ -26,18 +26,21 @@ var (
false, // isConst false, // isConst
true, // payable true, // payable
abi.Arguments{ // inputs abi.Arguments{ // inputs
{Name: "sender", Type: addressType},
{Name: "target", Type: addressType}, {Name: "target", Type: addressType},
{Name: "sender", Type: addressType},
{Name: "data", Type: bytesType}, {Name: "data", Type: bytesType},
{Name: "nonce", Type: uint256Type}, {Name: "nonce", Type: uint256Type},
// The actual transaction on the legacy L1CrossDomainMessenger has a trailing
// proof argument but is ignored for the `XDomainCallData` encoding
}, },
abi.Arguments{}, // outputs abi.Arguments{}, // outputs
) )
) )
type CrossDomainMessengerSentMessageEvent struct { type CrossDomainMessengerSentMessageEvent struct {
Event *database.ContractEvent Event *database.ContractEvent
BridgeMessage database.BridgeMessage MessageCalldata []byte
BridgeMessage database.BridgeMessage
} }
type CrossDomainMessengerRelayedMessageEvent struct { type CrossDomainMessengerRelayedMessageEvent struct {
...@@ -58,7 +61,6 @@ func CrossDomainMessengerSentMessageEvents(chainSelector string, contractAddress ...@@ -58,7 +61,6 @@ func CrossDomainMessengerSentMessageEvents(chainSelector string, contractAddress
return nil, err return nil, err
} }
if len(sentMessageEvents) == 0 { if len(sentMessageEvents) == 0 {
// prevent the following db queries if we dont need them
return nil, nil return nil, nil
} }
...@@ -68,10 +70,13 @@ func CrossDomainMessengerSentMessageEvents(chainSelector string, contractAddress ...@@ -68,10 +70,13 @@ func CrossDomainMessengerSentMessageEvents(chainSelector string, contractAddress
if err != nil { if err != nil {
return nil, err return nil, err
} }
if len(sentMessageEvents) != len(sentMessageExtensionEvents) { if len(sentMessageExtensionEvents) > len(sentMessageEvents) {
return nil, fmt.Errorf("mismatch in SentMessage events. %d sent messages & %d sent message extensions", len(sentMessageEvents), len(sentMessageExtensionEvents)) return nil, fmt.Errorf("mismatch. %d sent messages & %d sent message extensions", len(sentMessageEvents), len(sentMessageExtensionEvents))
} }
// We handle version zero messages uniquely since the first version of cross domain messages
// do not have the SentMessageExtension1 event emitted, introduced in version 1.
numVersionZeroMessages := len(sentMessageEvents) - len(sentMessageExtensionEvents)
crossDomainSentMessages := make([]CrossDomainMessengerSentMessageEvent, len(sentMessageEvents)) crossDomainSentMessages := make([]CrossDomainMessengerSentMessageEvent, len(sentMessageEvents))
for i := range sentMessageEvents { for i := range sentMessageEvents {
sentMessage := bindings.CrossDomainMessengerSentMessage{Raw: *sentMessageEvents[i].RLPLog} sentMessage := bindings.CrossDomainMessengerSentMessage{Raw: *sentMessageEvents[i].RLPLog}
...@@ -79,34 +84,45 @@ func CrossDomainMessengerSentMessageEvents(chainSelector string, contractAddress ...@@ -79,34 +84,45 @@ func CrossDomainMessengerSentMessageEvents(chainSelector string, contractAddress
if err != nil { if err != nil {
return nil, err return nil, err
} }
sentMessageExtension := bindings.CrossDomainMessengerSentMessageExtension1{Raw: *sentMessageExtensionEvents[i].RLPLog}
err = UnpackLog(&sentMessageExtension, sentMessageExtensionEvents[i].RLPLog, sentMessageExtensionEventAbi.Name, crossDomainMessengerAbi) version, _ := DecodeVersionedNonce(sentMessage.MessageNonce)
if err != nil { if i < numVersionZeroMessages && version != 0 {
return nil, err return nil, fmt.Errorf("expected version zero nonce. nonce %d tx_hash %s", sentMessage.MessageNonce, sentMessage.Raw.TxHash)
} }
messageHash, err := CrossDomainMessageHash(crossDomainMessengerAbi, &sentMessage, sentMessageExtension.Value) // In version zero, to value is bridged through the cross domain messenger.
value := big.NewInt(0)
if version > 0 {
sentMessageExtension := bindings.CrossDomainMessengerSentMessageExtension1{Raw: *sentMessageExtensionEvents[i].RLPLog}
err = UnpackLog(&sentMessageExtension, sentMessageExtensionEvents[i].RLPLog, sentMessageExtensionEventAbi.Name, crossDomainMessengerAbi)
if err != nil {
return nil, err
}
value = sentMessageExtension.Value
}
messageCalldata, err := CrossDomainMessageCalldata(crossDomainMessengerAbi, &sentMessage, value)
if err != nil { if err != nil {
return nil, err return nil, err
} }
crossDomainSentMessages[i] = CrossDomainMessengerSentMessageEvent{ crossDomainSentMessages[i] = CrossDomainMessengerSentMessageEvent{
Event: &sentMessageEvents[i], Event: &sentMessageEvents[i],
MessageCalldata: messageCalldata,
BridgeMessage: database.BridgeMessage{ BridgeMessage: database.BridgeMessage{
MessageHash: messageHash, MessageHash: crypto.Keccak256Hash(messageCalldata),
Nonce: sentMessage.MessageNonce, Nonce: sentMessage.MessageNonce,
SentMessageEventGUID: sentMessageEvents[i].GUID, SentMessageEventGUID: sentMessageEvents[i].GUID,
GasLimit: sentMessage.GasLimit, GasLimit: sentMessage.GasLimit,
Tx: database.Transaction{ Tx: database.Transaction{
FromAddress: sentMessage.Sender, FromAddress: sentMessage.Sender,
ToAddress: sentMessage.Target, ToAddress: sentMessage.Target,
Amount: sentMessageExtension.Value, Amount: value,
Data: sentMessage.Message, Data: sentMessage.Message,
Timestamp: sentMessageEvents[i].Timestamp, Timestamp: sentMessageEvents[i].Timestamp,
}, },
}, },
} }
} }
return crossDomainSentMessages, nil return crossDomainSentMessages, nil
...@@ -142,26 +158,25 @@ func CrossDomainMessengerRelayedMessageEvents(chainSelector string, contractAddr ...@@ -142,26 +158,25 @@ func CrossDomainMessengerRelayedMessageEvents(chainSelector string, contractAddr
return crossDomainRelayedMessages, nil return crossDomainRelayedMessages, nil
} }
// Replica of `Hashing.sol#hashCrossDomainMessage` solidity implementation // Replica of `Encoding.sol#encodeCrossDomainMessage` solidity implementation
func CrossDomainMessageHash(abi *abi.ABI, sentMsg *bindings.CrossDomainMessengerSentMessage, value *big.Int) (common.Hash, error) { func CrossDomainMessageCalldata(abi *abi.ABI, sentMsg *bindings.CrossDomainMessengerSentMessage, value *big.Int) ([]byte, error) {
version, _ := DecodeVersionedNonce(sentMsg.MessageNonce) version, _ := DecodeVersionedNonce(sentMsg.MessageNonce)
switch version { switch version {
case 0: case 0:
// Legacy Message // Legacy Message
inputBytes, err := legacyCrossDomainMessengerRelayMessageMethod.Inputs.Pack(sentMsg.Sender, sentMsg.Target, sentMsg.Message, sentMsg.MessageNonce) inputBytes, err := CrossDomainMessengerLegacyRelayMessageEncoding.Inputs.Pack(sentMsg.Target, sentMsg.Sender, sentMsg.Message, sentMsg.MessageNonce)
if err != nil { if err != nil {
return common.Hash{}, err return nil, err
} }
msgBytes := append(legacyCrossDomainMessengerRelayMessageMethod.ID, inputBytes...) return append(CrossDomainMessengerLegacyRelayMessageEncoding.ID, inputBytes...), nil
return crypto.Keccak256Hash(msgBytes), nil
case 1: case 1:
// Current Message // Current Message
msgBytes, err := abi.Pack("relayMessage", sentMsg.MessageNonce, sentMsg.Sender, sentMsg.Target, value, sentMsg.GasLimit, sentMsg.Message) msgBytes, err := abi.Pack("relayMessage", sentMsg.MessageNonce, sentMsg.Sender, sentMsg.Target, value, sentMsg.GasLimit, sentMsg.Message)
if err != nil { if err != nil {
return common.Hash{}, err return nil, err
} }
return crypto.Keccak256Hash(msgBytes), nil return msgBytes, nil
} }
return common.Hash{}, fmt.Errorf("unsupported cross domain messenger version: %d", version) return nil, fmt.Errorf("unsupported cross domain messenger version: %d", version)
} }
package contracts
import (
"math/big"
"github.com/ethereum-optimism/optimism/indexer/bigint"
"github.com/ethereum-optimism/optimism/indexer/database"
legacy_bindings "github.com/ethereum-optimism/optimism/op-bindings/legacy-bindings"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
type LegacyCTCDepositEvent struct {
Event *database.ContractEvent
Tx database.Transaction
TxHash common.Hash
GasLimit *big.Int
}
func LegacyCTCDepositEvents(contractAddress common.Address, db *database.DB, fromHeight, toHeight *big.Int) ([]LegacyCTCDepositEvent, error) {
ctcAbi, err := legacy_bindings.CanonicalTransactionChainMetaData.GetAbi()
if err != nil {
return nil, err
}
transactionEnqueuedEventAbi := ctcAbi.Events["TransactionEnqueued"]
contractEventFilter := database.ContractEvent{ContractAddress: contractAddress, EventSignature: transactionEnqueuedEventAbi.ID}
events, err := db.ContractEvents.L1ContractEventsWithFilter(contractEventFilter, fromHeight, toHeight)
if err != nil {
return nil, err
}
ctcTxDeposits := make([]LegacyCTCDepositEvent, len(events))
for i := range events {
txEnqueued := legacy_bindings.CanonicalTransactionChainTransactionEnqueued{Raw: *events[i].RLPLog}
err = UnpackLog(&txEnqueued, events[i].RLPLog, transactionEnqueuedEventAbi.Name, ctcAbi)
if err != nil {
return nil, err
}
// Enqueued Deposits do not carry a `msg.value` amount. ETH is only minted on L2 via the L1StandardBrige
ctcTxDeposits[i] = LegacyCTCDepositEvent{
Event: &events[i].ContractEvent,
GasLimit: txEnqueued.GasLimit,
TxHash: types.NewTransaction(0, txEnqueued.Target, bigint.Zero, txEnqueued.GasLimit.Uint64(), nil, txEnqueued.Data).Hash(),
Tx: database.Transaction{
FromAddress: txEnqueued.L1TxOrigin,
ToAddress: txEnqueued.Target,
Amount: bigint.Zero,
Data: txEnqueued.Data,
Timestamp: events[i].Timestamp,
},
}
}
return ctcTxDeposits, nil
}
package contracts
import (
"math/big"
"github.com/ethereum-optimism/optimism/indexer/database"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum/go-ethereum/common"
)
type LegacyBridgeEvent struct {
Event *database.ContractEvent
BridgeTransfer database.BridgeTransfer
}
func L1StandardBridgeLegacyDepositInitiatedEvents(contractAddress common.Address, db *database.DB, fromHeight, toHeight *big.Int) ([]LegacyBridgeEvent, error) {
l1StandardBridgeAbi, err := bindings.L1StandardBridgeMetaData.GetAbi()
if err != nil {
return nil, err
}
// The L1StandardBridge contains the legacy events
ethDepositEventAbi := l1StandardBridgeAbi.Events["ETHDepositInitiated"]
erc20DepositEventAbi := l1StandardBridgeAbi.Events["ERC20DepositInitiated"]
// Grab both ETH & ERC20 Events
ethDepositEvents, err := db.ContractEvents.L1ContractEventsWithFilter(database.ContractEvent{ContractAddress: contractAddress, EventSignature: ethDepositEventAbi.ID}, fromHeight, toHeight)
if err != nil {
return nil, err
}
erc20DepositEvents, err := db.ContractEvents.L1ContractEventsWithFilter(database.ContractEvent{ContractAddress: contractAddress, EventSignature: erc20DepositEventAbi.ID}, fromHeight, toHeight)
if err != nil {
return nil, err
}
// Represent the ETH deposits via the ETH ERC20 predeploy address
deposits := make([]LegacyBridgeEvent, len(ethDepositEvents)+len(erc20DepositEvents))
for i := range ethDepositEvents {
bridgeEvent := bindings.L1StandardBridgeETHDepositInitiated{Raw: *ethDepositEvents[i].RLPLog}
err := UnpackLog(&bridgeEvent, &bridgeEvent.Raw, ethDepositEventAbi.Name, l1StandardBridgeAbi)
if err != nil {
return nil, err
}
deposits[i] = LegacyBridgeEvent{
Event: &ethDepositEvents[i].ContractEvent,
BridgeTransfer: database.BridgeTransfer{
TokenPair: database.ETHTokenPair,
Tx: database.Transaction{
FromAddress: bridgeEvent.From,
ToAddress: bridgeEvent.To,
Amount: bridgeEvent.Amount,
Data: bridgeEvent.ExtraData,
Timestamp: ethDepositEvents[i].Timestamp,
},
},
}
}
for i := range erc20DepositEvents {
bridgeEvent := bindings.L1StandardBridgeERC20DepositInitiated{Raw: *erc20DepositEvents[i].RLPLog}
err := UnpackLog(&bridgeEvent, &bridgeEvent.Raw, erc20DepositEventAbi.Name, l1StandardBridgeAbi)
if err != nil {
return nil, err
}
deposits[len(ethDepositEvents)+i] = LegacyBridgeEvent{
Event: &erc20DepositEvents[i].ContractEvent,
BridgeTransfer: database.BridgeTransfer{
TokenPair: database.TokenPair{LocalTokenAddress: bridgeEvent.L1Token, RemoteTokenAddress: bridgeEvent.L2Token},
Tx: database.Transaction{
FromAddress: bridgeEvent.From,
ToAddress: bridgeEvent.To,
Amount: bridgeEvent.Amount,
Data: bridgeEvent.ExtraData,
Timestamp: erc20DepositEvents[i].Timestamp,
},
},
}
}
return deposits, nil
}
func L2StandardBridgeLegacyWithdrawalInitiatedEvents(contractAddress common.Address, db *database.DB, fromHeight, toHeight *big.Int) ([]LegacyBridgeEvent, error) {
l2StandardBridgeAbi, err := bindings.L2StandardBridgeMetaData.GetAbi()
if err != nil {
return nil, err
}
withdrawalInitiatedEventAbi := l2StandardBridgeAbi.Events["WithdrawalInitiated"]
withdrawalEvents, err := db.ContractEvents.L2ContractEventsWithFilter(database.ContractEvent{ContractAddress: contractAddress, EventSignature: withdrawalInitiatedEventAbi.ID}, fromHeight, toHeight)
if err != nil {
return nil, err
}
withdrawals := make([]LegacyBridgeEvent, len(withdrawalEvents))
for i := range withdrawalEvents {
bridgeEvent := bindings.L2StandardBridgeWithdrawalInitiated{Raw: *withdrawalEvents[i].RLPLog}
err := UnpackLog(&bridgeEvent, &bridgeEvent.Raw, withdrawalInitiatedEventAbi.Name, l2StandardBridgeAbi)
if err != nil {
return nil, err
}
withdrawals[i] = LegacyBridgeEvent{
Event: &withdrawalEvents[i].ContractEvent,
BridgeTransfer: database.BridgeTransfer{
TokenPair: database.ETHTokenPair,
Tx: database.Transaction{
FromAddress: bridgeEvent.From,
ToAddress: bridgeEvent.To,
Amount: bridgeEvent.Amount,
Data: bridgeEvent.ExtraData,
Timestamp: withdrawalEvents[i].Timestamp,
},
},
}
}
return withdrawals, nil
}
...@@ -35,5 +35,6 @@ ...@@ -35,5 +35,6 @@
"PreimageOracle", "PreimageOracle",
"BlockOracle", "BlockOracle",
"EAS", "EAS",
"SchemaRegistry" "SchemaRegistry",
"ProtocolVersions"
] ]
This diff is collapsed.
...@@ -13,7 +13,7 @@ const BaseFeeVaultStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contract\ ...@@ -13,7 +13,7 @@ const BaseFeeVaultStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contract\
var BaseFeeVaultStorageLayout = new(solc.StorageLayout) var BaseFeeVaultStorageLayout = new(solc.StorageLayout)
var BaseFeeVaultDeployedBin = "0x6080604052600436106100695760003560e01c806384411d651161004357806384411d651461010c578063d0e12f9014610130578063d3e5792b1461017157600080fd5b80630d9019e1146100755780633ccfd60b146100d357806354fd4d50146100ea57600080fd5b3661007057005b600080fd5b34801561008157600080fd5b506100a97f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156100df57600080fd5b506100e86101a5565b005b3480156100f657600080fd5b506100ff610591565b6040516100ca91906107eb565b34801561011857600080fd5b5061012260005481565b6040519081526020016100ca565b34801561013c57600080fd5b506101647f000000000000000000000000000000000000000000000000000000000000000081565b6040516100ca919061086f565b34801561017d57600080fd5b506101227f000000000000000000000000000000000000000000000000000000000000000081565b7f0000000000000000000000000000000000000000000000000000000000000000471015610280576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f4665655661756c743a207769746864726177616c20616d6f756e74206d75737460448201527f2062652067726561746572207468616e206d696e696d756d207769746864726160648201527f77616c20616d6f756e7400000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b60004790508060008082825461029691906108b2565b9091555050604080518281527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166020820152338183015290517fc8a211cc64b6ed1b50595a9fcb1932b6d1e5a6e8ef15b60e5b1f988ea9086bba9181900360600190a17f38e04cbeb8c10f8f568618aa75be0f10b6729b8b4237743b4de20cbcde2839ee817f0000000000000000000000000000000000000000000000000000000000000000337f000000000000000000000000000000000000000000000000000000000000000060405161038494939291906108ca565b60405180910390a160017f000000000000000000000000000000000000000000000000000000000000000060018111156103c0576103c0610805565b036104d95760007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d806000811461043f576040519150601f19603f3d011682016040523d82523d6000602084013e610444565b606091505b50509050806104d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4665655661756c743a206661696c656420746f2073656e642045544820746f2060448201527f4c322066656520726563697069656e74000000000000000000000000000000006064820152608401610277565b5050565b604080516020810182526000815290517fe11013dd0000000000000000000000000000000000000000000000000000000081527342000000000000000000000000000000000000109163e11013dd91849161055c917f0000000000000000000000000000000000000000000000000000000000000000916188b89160040161090b565b6000604051808303818588803b15801561057557600080fd5b505af1158015610589573d6000803e3d6000fd5b505050505050565b60606105bc7f0000000000000000000000000000000000000000000000000000000000000000610634565b6105e57f0000000000000000000000000000000000000000000000000000000000000000610634565b61060e7f0000000000000000000000000000000000000000000000000000000000000000610634565b60405160200161062093929190610946565b604051602081830303815290604052905090565b60608160000361067757505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156106a1578061068b816109bc565b915061069a9050600a83610a23565b915061067b565b60008167ffffffffffffffff8111156106bc576106bc610a37565b6040519080825280601f01601f1916602001820160405280156106e6576020820181803683370190505b5090505b8415610769576106fb600183610a66565b9150610708600a86610a7d565b6107139060306108b2565b60f81b81838151811061072857610728610a91565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610762600a86610a23565b94506106ea565b949350505050565b60005b8381101561078c578181015183820152602001610774565b8381111561079b576000848401525b50505050565b600081518084526107b9816020860160208601610771565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006107fe60208301846107a1565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6002811061086b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b6020810161087d8284610834565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156108c5576108c5610883565b500190565b84815273ffffffffffffffffffffffffffffffffffffffff848116602083015283166040820152608081016109026060830184610834565b95945050505050565b73ffffffffffffffffffffffffffffffffffffffff8416815263ffffffff8316602082015260606040820152600061090260608301846107a1565b60008451610958818460208901610771565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551610994816001850160208a01610771565b600192019182015283516109af816002840160208801610771565b0160020195945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036109ed576109ed610883565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082610a3257610a326109f4565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082821015610a7857610a78610883565b500390565b600082610a8c57610a8c6109f4565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea164736f6c634300080f000a" var BaseFeeVaultDeployedBin = "0x6080604052600436106100695760003560e01c806384411d651161004357806384411d6514610140578063d0e12f9014610164578063d3e5792b146101a557600080fd5b80630d9019e1146100755780633ccfd60b146100d357806354fd4d50146100ea57600080fd5b3661007057005b600080fd5b34801561008157600080fd5b506100a97f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156100df57600080fd5b506100e86101d9565b005b3480156100f657600080fd5b506101336040518060400160405280600581526020017f312e342e3000000000000000000000000000000000000000000000000000000081525081565b6040516100ca9190610630565b34801561014c57600080fd5b5061015660005481565b6040519081526020016100ca565b34801561017057600080fd5b506101987f000000000000000000000000000000000000000000000000000000000000000081565b6040516100ca91906106b4565b3480156101b157600080fd5b506101567f000000000000000000000000000000000000000000000000000000000000000081565b7f00000000000000000000000000000000000000000000000000000000000000004710156102b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f4665655661756c743a207769746864726177616c20616d6f756e74206d75737460448201527f2062652067726561746572207468616e206d696e696d756d207769746864726160648201527f77616c20616d6f756e7400000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b6000479050806000808282546102ca91906106c8565b9091555050604080518281527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166020820152338183015290517fc8a211cc64b6ed1b50595a9fcb1932b6d1e5a6e8ef15b60e5b1f988ea9086bba9181900360600190a17f38e04cbeb8c10f8f568618aa75be0f10b6729b8b4237743b4de20cbcde2839ee817f0000000000000000000000000000000000000000000000000000000000000000337f00000000000000000000000000000000000000000000000000000000000000006040516103b89493929190610707565b60405180910390a160017f000000000000000000000000000000000000000000000000000000000000000060018111156103f4576103f461064a565b0361050d5760007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114610473576040519150601f19603f3d011682016040523d82523d6000602084013e610478565b606091505b5050905080610509576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4665655661756c743a206661696c656420746f2073656e642045544820746f2060448201527f4c322066656520726563697069656e740000000000000000000000000000000060648201526084016102ab565b5050565b604080516020810182526000815290517fe11013dd0000000000000000000000000000000000000000000000000000000081527342000000000000000000000000000000000000109163e11013dd918491610590917f0000000000000000000000000000000000000000000000000000000000000000916188b891600401610748565b6000604051808303818588803b1580156105a957600080fd5b505af11580156105bd573d6000803e3d6000fd5b505050505050565b6000815180845260005b818110156105eb576020818501810151868301820152016105cf565b818111156105fd576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061064360208301846105c5565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600281106106b0577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b602081016106c28284610679565b92915050565b60008219821115610702577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b500190565b84815273ffffffffffffffffffffffffffffffffffffffff8481166020830152831660408201526080810161073f6060830184610679565b95945050505050565b73ffffffffffffffffffffffffffffffffffffffff8416815263ffffffff8316602082015260606040820152600061073f60608301846105c556fea164736f6c634300080f000a"
func init() { func init() {
if err := json.Unmarshal([]byte(BaseFeeVaultStorageLayoutJSON), BaseFeeVaultStorageLayout); err != nil { if err := json.Unmarshal([]byte(BaseFeeVaultStorageLayoutJSON), BaseFeeVaultStorageLayout); err != nil {
......
This diff is collapsed.
...@@ -13,7 +13,7 @@ const GasPriceOracleStorageLayoutJSON = "{\"storage\":null,\"types\":{}}" ...@@ -13,7 +13,7 @@ const GasPriceOracleStorageLayoutJSON = "{\"storage\":null,\"types\":{}}"
var GasPriceOracleStorageLayout = new(solc.StorageLayout) var GasPriceOracleStorageLayout = new(solc.StorageLayout)
var GasPriceOracleDeployedBin = "0x608060405234801561001057600080fd5b50600436106100be5760003560e01c806354fd4d5011610076578063de26c4a11161005b578063de26c4a114610123578063f45e65d814610136578063fe173b971461011d57600080fd5b806354fd4d50146101085780636ef25c3a1461011d57600080fd5b8063313ce567116100a7578063313ce567146100e657806349948e0e146100ed578063519b4bd31461010057600080fd5b80630c18c162146100c35780632e0f2625146100de575b600080fd5b6100cb61013e565b6040519081526020015b60405180910390f35b6100cb600681565b60066100cb565b6100cb6100fb3660046105a9565b6101c8565b6100cb610229565b61011061028a565b6040516100d591906106a8565b486100cb565b6100cb6101313660046105a9565b61032d565b6100cb6103dc565b600073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16638b239f736040518163ffffffff1660e01b8152600401602060405180830381865afa15801561019f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101c391906106f9565b905090565b6000806101d48361032d565b905060006101e0610229565b6101ea9083610741565b905060006101fa6006600a6108a0565b905060006102066103dc565b6102109084610741565b9050600061021e83836108e2565b979650505050505050565b600073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16635cf249696040518163ffffffff1660e01b8152600401602060405180830381865afa15801561019f573d6000803e3d6000fd5b60606102b57f000000000000000000000000000000000000000000000000000000000000000061043d565b6102de7f000000000000000000000000000000000000000000000000000000000000000061043d565b6103077f000000000000000000000000000000000000000000000000000000000000000061043d565b604051602001610319939291906108f6565b604051602081830303815290604052905090565b80516000908190815b818110156103b0578481815181106103505761035061096c565b01602001517fff00000000000000000000000000000000000000000000000000000000000000166000036103905761038960048461099b565b925061039e565b61039b60108461099b565b92505b806103a8816109b3565b915050610336565b5060006103bb61013e565b6103c5908461099b565b90506103d38161044061099b565b95945050505050565b600073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16639e8c49666040518163ffffffff1660e01b8152600401602060405180830381865afa15801561019f573d6000803e3d6000fd5b60608160000361048057505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156104aa5780610494816109b3565b91506104a39050600a836108e2565b9150610484565b60008167ffffffffffffffff8111156104c5576104c561057a565b6040519080825280601f01601f1916602001820160405280156104ef576020820181803683370190505b5090505b8415610572576105046001836109eb565b9150610511600a86610a02565b61051c90603061099b565b60f81b8183815181106105315761053161096c565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535061056b600a866108e2565b94506104f3565b949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156105bb57600080fd5b813567ffffffffffffffff808211156105d357600080fd5b818401915084601f8301126105e757600080fd5b8135818111156105f9576105f961057a565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561063f5761063f61057a565b8160405282815287602084870101111561065857600080fd5b826020860160208301376000928101602001929092525095945050505050565b60005b8381101561069357818101518382015260200161067b565b838111156106a2576000848401525b50505050565b60208152600082518060208401526106c7816040850160208701610678565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b60006020828403121561070b57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561077957610779610712565b500290565b600181815b808511156107d757817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156107bd576107bd610712565b808516156107ca57918102915b93841c9390800290610783565b509250929050565b6000826107ee5750600161089a565b816107fb5750600061089a565b8160018114610811576002811461081b57610837565b600191505061089a565b60ff84111561082c5761082c610712565b50506001821b61089a565b5060208310610133831016604e8410600b841016171561085a575081810a61089a565b610864838361077e565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561089657610896610712565b0290505b92915050565b60006108ac83836107df565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826108f1576108f16108b3565b500490565b60008451610908818460208901610678565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551610944816001850160208a01610678565b6001920191820152835161095f816002840160208801610678565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082198211156109ae576109ae610712565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036109e4576109e4610712565b5060010190565b6000828210156109fd576109fd610712565b500390565b600082610a1157610a116108b3565b50069056fea164736f6c634300080f000a" var GasPriceOracleDeployedBin = "0x608060405234801561001057600080fd5b50600436106100be5760003560e01c806354fd4d5011610076578063de26c4a11161005b578063de26c4a114610157578063f45e65d81461016a578063fe173b971461015157600080fd5b806354fd4d50146101085780636ef25c3a1461015157600080fd5b8063313ce567116100a7578063313ce567146100e657806349948e0e146100ed578063519b4bd31461010057600080fd5b80630c18c162146100c35780632e0f2625146100de575b600080fd5b6100cb610172565b6040519081526020015b60405180910390f35b6100cb600681565b60066100cb565b6100cb6100fb3660046103fd565b6101fc565b6100cb61025d565b6101446040518060400160405280600581526020017f312e312e3000000000000000000000000000000000000000000000000000000081525081565b6040516100d591906104cc565b486100cb565b6100cb6101653660046103fd565b6102be565b6100cb61036d565b600073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16638b239f736040518163ffffffff1660e01b8152600401602060405180830381865afa1580156101d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101f7919061053f565b905090565b600080610208836102be565b9050600061021461025d565b61021e9083610587565b9050600061022e6006600a6106e6565b9050600061023a61036d565b6102449084610587565b9050600061025283836106f9565b979650505050505050565b600073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16635cf249696040518163ffffffff1660e01b8152600401602060405180830381865afa1580156101d3573d6000803e3d6000fd5b80516000908190815b81811015610341578481815181106102e1576102e1610734565b01602001517fff00000000000000000000000000000000000000000000000000000000000000166000036103215761031a600484610763565b925061032f565b61032c601084610763565b92505b806103398161077b565b9150506102c7565b50600061034c610172565b6103569084610763565b905061036481610440610763565b95945050505050565b600073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16639e8c49666040518163ffffffff1660e01b8152600401602060405180830381865afa1580156101d3573d6000803e3d6000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561040f57600080fd5b813567ffffffffffffffff8082111561042757600080fd5b818401915084601f83011261043b57600080fd5b81358181111561044d5761044d6103ce565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715610493576104936103ce565b816040528281528760208487010111156104ac57600080fd5b826020860160208301376000928101602001929092525095945050505050565b600060208083528351808285015260005b818110156104f9578581018301518582016040015282016104dd565b8181111561050b576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b60006020828403121561055157600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156105bf576105bf610558565b500290565b600181815b8085111561061d57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561060357610603610558565b8085161561061057918102915b93841c93908002906105c9565b509250929050565b600082610634575060016106e0565b81610641575060006106e0565b816001811461065757600281146106615761067d565b60019150506106e0565b60ff84111561067257610672610558565b50506001821b6106e0565b5060208310610133831016604e8410600b84101617156106a0575081810a6106e0565b6106aa83836105c4565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156106dc576106dc610558565b0290505b92915050565b60006106f28383610625565b9392505050565b60008261072f577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000821982111561077657610776610558565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036107ac576107ac610558565b506001019056fea164736f6c634300080f000a"
func init() { func init() {
if err := json.Unmarshal([]byte(GasPriceOracleStorageLayoutJSON), GasPriceOracleStorageLayout); err != nil { if err := json.Unmarshal([]byte(GasPriceOracleStorageLayoutJSON), GasPriceOracleStorageLayout); err != nil {
......
This diff is collapsed.
...@@ -13,7 +13,7 @@ const L1BlockStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contract\":\"s ...@@ -13,7 +13,7 @@ const L1BlockStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contract\":\"s
var L1BlockStorageLayout = new(solc.StorageLayout) var L1BlockStorageLayout = new(solc.StorageLayout)
var L1BlockDeployedBin = "0x608060405234801561001057600080fd5b50600436106100c95760003560e01c80638381f58a11610081578063b80777ea1161005b578063b80777ea14610170578063e591b28214610190578063e81b2c6d146101d057600080fd5b80638381f58a1461014a5780638b239f731461015e5780639e8c49661461016757600080fd5b806354fd4d50116100b257806354fd4d50146100ff5780635cf249691461011457806364ca23ef1461011d57600080fd5b8063015d8eb9146100ce57806309bd5a60146100e3575b600080fd5b6100e16100dc366004610515565b6101d9565b005b6100ec60025481565b6040519081526020015b60405180910390f35b610107610318565b6040516100f691906105b7565b6100ec60015481565b6003546101319067ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020016100f6565b6000546101319067ffffffffffffffff1681565b6100ec60055481565b6100ec60065481565b6000546101319068010000000000000000900467ffffffffffffffff1681565b6101ab73deaddeaddeaddeaddeaddeaddeaddeaddead000181565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100f6565b6100ec60045481565b3373deaddeaddeaddeaddeaddeaddeaddeaddead000114610280576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603b60248201527f4c31426c6f636b3a206f6e6c7920746865206465706f7369746f72206163636f60448201527f756e742063616e20736574204c3120626c6f636b2076616c7565730000000000606482015260840160405180910390fd5b6000805467ffffffffffffffff98891668010000000000000000027fffffffffffffffffffffffffffffffff00000000000000000000000000000000909116998916999099179890981790975560019490945560029290925560038054919094167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000009190911617909255600491909155600555600655565b60606103437f00000000000000000000000000000000000000000000000000000000000000006103bb565b61036c7f00000000000000000000000000000000000000000000000000000000000000006103bb565b6103957f00000000000000000000000000000000000000000000000000000000000000006103bb565b6040516020016103a793929190610608565b604051602081830303815290604052905090565b6060816000036103fe57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156104285780610412816106ad565b91506104219050600a83610714565b9150610402565b60008167ffffffffffffffff81111561044357610443610728565b6040519080825280601f01601f19166020018201604052801561046d576020820181803683370190505b5090505b84156104f057610482600183610757565b915061048f600a8661076e565b61049a906030610782565b60f81b8183815181106104af576104af61079a565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506104e9600a86610714565b9450610471565b949350505050565b803567ffffffffffffffff8116811461051057600080fd5b919050565b600080600080600080600080610100898b03121561053257600080fd5b61053b896104f8565b975061054960208a016104f8565b9650604089013595506060890135945061056560808a016104f8565b979a969950949793969560a0850135955060c08501359460e001359350915050565b60005b838110156105a257818101518382015260200161058a565b838111156105b1576000848401525b50505050565b60208152600082518060208401526105d6816040850160208701610587565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b6000845161061a818460208901610587565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551610656816001850160208a01610587565b60019201918201528351610671816002840160208801610587565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036106de576106de61067e565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082610723576107236106e5565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000828210156107695761076961067e565b500390565b60008261077d5761077d6106e5565b500690565b600082198211156107955761079561067e565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea164736f6c634300080f000a" var L1BlockDeployedBin = "0x608060405234801561001057600080fd5b50600436106100c95760003560e01c80638381f58a11610081578063b80777ea1161005b578063b80777ea146101a4578063e591b282146101c4578063e81b2c6d1461020457600080fd5b80638381f58a1461017e5780638b239f73146101925780639e8c49661461019b57600080fd5b806354fd4d50116100b257806354fd4d50146100ff5780635cf249691461014857806364ca23ef1461015157600080fd5b8063015d8eb9146100ce57806309bd5a60146100e3575b600080fd5b6100e16100dc366004610369565b61020d565b005b6100ec60025481565b6040519081526020015b60405180910390f35b61013b6040518060400160405280600581526020017f312e312e3000000000000000000000000000000000000000000000000000000081525081565b6040516100f691906103db565b6100ec60015481565b6003546101659067ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020016100f6565b6000546101659067ffffffffffffffff1681565b6100ec60055481565b6100ec60065481565b6000546101659068010000000000000000900467ffffffffffffffff1681565b6101df73deaddeaddeaddeaddeaddeaddeaddeaddead000181565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100f6565b6100ec60045481565b3373deaddeaddeaddeaddeaddeaddeaddeaddead0001146102b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603b60248201527f4c31426c6f636b3a206f6e6c7920746865206465706f7369746f72206163636f60448201527f756e742063616e20736574204c3120626c6f636b2076616c7565730000000000606482015260840160405180910390fd5b6000805467ffffffffffffffff98891668010000000000000000027fffffffffffffffffffffffffffffffff00000000000000000000000000000000909116998916999099179890981790975560019490945560029290925560038054919094167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000009190911617909255600491909155600555600655565b803567ffffffffffffffff8116811461036457600080fd5b919050565b600080600080600080600080610100898b03121561038657600080fd5b61038f8961034c565b975061039d60208a0161034c565b965060408901359550606089013594506103b960808a0161034c565b979a969950949793969560a0850135955060c08501359460e001359350915050565b600060208083528351808285015260005b81811015610408578581018301518582016040015282016103ec565b8181111561041a576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01692909201604001939250505056fea164736f6c634300080f000a"
func init() { func init() {
if err := json.Unmarshal([]byte(L1BlockStorageLayoutJSON), L1BlockStorageLayout); err != nil { if err := json.Unmarshal([]byte(L1BlockStorageLayoutJSON), L1BlockStorageLayout); err != nil {
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -13,7 +13,7 @@ const L1FeeVaultStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contract\": ...@@ -13,7 +13,7 @@ const L1FeeVaultStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contract\":
var L1FeeVaultStorageLayout = new(solc.StorageLayout) var L1FeeVaultStorageLayout = new(solc.StorageLayout)
var L1FeeVaultDeployedBin = "0x6080604052600436106100695760003560e01c806384411d651161004357806384411d651461010c578063d0e12f9014610130578063d3e5792b1461017157600080fd5b80630d9019e1146100755780633ccfd60b146100d357806354fd4d50146100ea57600080fd5b3661007057005b600080fd5b34801561008157600080fd5b506100a97f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156100df57600080fd5b506100e86101a5565b005b3480156100f657600080fd5b506100ff610591565b6040516100ca91906107eb565b34801561011857600080fd5b5061012260005481565b6040519081526020016100ca565b34801561013c57600080fd5b506101647f000000000000000000000000000000000000000000000000000000000000000081565b6040516100ca919061086f565b34801561017d57600080fd5b506101227f000000000000000000000000000000000000000000000000000000000000000081565b7f0000000000000000000000000000000000000000000000000000000000000000471015610280576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f4665655661756c743a207769746864726177616c20616d6f756e74206d75737460448201527f2062652067726561746572207468616e206d696e696d756d207769746864726160648201527f77616c20616d6f756e7400000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b60004790508060008082825461029691906108b2565b9091555050604080518281527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166020820152338183015290517fc8a211cc64b6ed1b50595a9fcb1932b6d1e5a6e8ef15b60e5b1f988ea9086bba9181900360600190a17f38e04cbeb8c10f8f568618aa75be0f10b6729b8b4237743b4de20cbcde2839ee817f0000000000000000000000000000000000000000000000000000000000000000337f000000000000000000000000000000000000000000000000000000000000000060405161038494939291906108ca565b60405180910390a160017f000000000000000000000000000000000000000000000000000000000000000060018111156103c0576103c0610805565b036104d95760007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d806000811461043f576040519150601f19603f3d011682016040523d82523d6000602084013e610444565b606091505b50509050806104d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4665655661756c743a206661696c656420746f2073656e642045544820746f2060448201527f4c322066656520726563697069656e74000000000000000000000000000000006064820152608401610277565b5050565b604080516020810182526000815290517fe11013dd0000000000000000000000000000000000000000000000000000000081527342000000000000000000000000000000000000109163e11013dd91849161055c917f0000000000000000000000000000000000000000000000000000000000000000916188b89160040161090b565b6000604051808303818588803b15801561057557600080fd5b505af1158015610589573d6000803e3d6000fd5b505050505050565b60606105bc7f0000000000000000000000000000000000000000000000000000000000000000610634565b6105e57f0000000000000000000000000000000000000000000000000000000000000000610634565b61060e7f0000000000000000000000000000000000000000000000000000000000000000610634565b60405160200161062093929190610946565b604051602081830303815290604052905090565b60608160000361067757505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156106a1578061068b816109bc565b915061069a9050600a83610a23565b915061067b565b60008167ffffffffffffffff8111156106bc576106bc610a37565b6040519080825280601f01601f1916602001820160405280156106e6576020820181803683370190505b5090505b8415610769576106fb600183610a66565b9150610708600a86610a7d565b6107139060306108b2565b60f81b81838151811061072857610728610a91565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610762600a86610a23565b94506106ea565b949350505050565b60005b8381101561078c578181015183820152602001610774565b8381111561079b576000848401525b50505050565b600081518084526107b9816020860160208601610771565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006107fe60208301846107a1565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6002811061086b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b6020810161087d8284610834565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156108c5576108c5610883565b500190565b84815273ffffffffffffffffffffffffffffffffffffffff848116602083015283166040820152608081016109026060830184610834565b95945050505050565b73ffffffffffffffffffffffffffffffffffffffff8416815263ffffffff8316602082015260606040820152600061090260608301846107a1565b60008451610958818460208901610771565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551610994816001850160208a01610771565b600192019182015283516109af816002840160208801610771565b0160020195945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036109ed576109ed610883565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082610a3257610a326109f4565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082821015610a7857610a78610883565b500390565b600082610a8c57610a8c6109f4565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea164736f6c634300080f000a" var L1FeeVaultDeployedBin = "0x6080604052600436106100695760003560e01c806384411d651161004357806384411d6514610140578063d0e12f9014610164578063d3e5792b146101a557600080fd5b80630d9019e1146100755780633ccfd60b146100d357806354fd4d50146100ea57600080fd5b3661007057005b600080fd5b34801561008157600080fd5b506100a97f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156100df57600080fd5b506100e86101d9565b005b3480156100f657600080fd5b506101336040518060400160405280600581526020017f312e342e3000000000000000000000000000000000000000000000000000000081525081565b6040516100ca9190610630565b34801561014c57600080fd5b5061015660005481565b6040519081526020016100ca565b34801561017057600080fd5b506101987f000000000000000000000000000000000000000000000000000000000000000081565b6040516100ca91906106b4565b3480156101b157600080fd5b506101567f000000000000000000000000000000000000000000000000000000000000000081565b7f00000000000000000000000000000000000000000000000000000000000000004710156102b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f4665655661756c743a207769746864726177616c20616d6f756e74206d75737460448201527f2062652067726561746572207468616e206d696e696d756d207769746864726160648201527f77616c20616d6f756e7400000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b6000479050806000808282546102ca91906106c8565b9091555050604080518281527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166020820152338183015290517fc8a211cc64b6ed1b50595a9fcb1932b6d1e5a6e8ef15b60e5b1f988ea9086bba9181900360600190a17f38e04cbeb8c10f8f568618aa75be0f10b6729b8b4237743b4de20cbcde2839ee817f0000000000000000000000000000000000000000000000000000000000000000337f00000000000000000000000000000000000000000000000000000000000000006040516103b89493929190610707565b60405180910390a160017f000000000000000000000000000000000000000000000000000000000000000060018111156103f4576103f461064a565b0361050d5760007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114610473576040519150601f19603f3d011682016040523d82523d6000602084013e610478565b606091505b5050905080610509576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4665655661756c743a206661696c656420746f2073656e642045544820746f2060448201527f4c322066656520726563697069656e740000000000000000000000000000000060648201526084016102ab565b5050565b604080516020810182526000815290517fe11013dd0000000000000000000000000000000000000000000000000000000081527342000000000000000000000000000000000000109163e11013dd918491610590917f0000000000000000000000000000000000000000000000000000000000000000916188b891600401610748565b6000604051808303818588803b1580156105a957600080fd5b505af11580156105bd573d6000803e3d6000fd5b505050505050565b6000815180845260005b818110156105eb576020818501810151868301820152016105cf565b818111156105fd576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061064360208301846105c5565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600281106106b0577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b602081016106c28284610679565b92915050565b60008219821115610702577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b500190565b84815273ffffffffffffffffffffffffffffffffffffffff8481166020830152831660408201526080810161073f6060830184610679565b95945050505050565b73ffffffffffffffffffffffffffffffffffffffff8416815263ffffffff8316602082015260606040820152600061073f60608301846105c556fea164736f6c634300080f000a"
func init() { func init() {
if err := json.Unmarshal([]byte(L1FeeVaultStorageLayoutJSON), L1FeeVaultStorageLayout); err != nil { if err := json.Unmarshal([]byte(L1FeeVaultStorageLayoutJSON), L1FeeVaultStorageLayout); err != nil {
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -13,7 +13,7 @@ const L2ToL1MessagePasserStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"co ...@@ -13,7 +13,7 @@ const L2ToL1MessagePasserStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"co
var L2ToL1MessagePasserStorageLayout = new(solc.StorageLayout) var L2ToL1MessagePasserStorageLayout = new(solc.StorageLayout)
var L2ToL1MessagePasserDeployedBin = "0x6080604052600436106100695760003560e01c806382e3702d1161004357806382e3702d146100f6578063c2b3e5ac14610136578063ecc704281461014957600080fd5b80633f827a5a1461009257806344df8e70146100bf57806354fd4d50146100d457600080fd5b3661008d5761008b33620186a0604051806020016040528060008152506101ae565b005b600080fd5b34801561009e57600080fd5b506100a7600181565b60405161ffff90911681526020015b60405180910390f35b3480156100cb57600080fd5b5061008b610372565b3480156100e057600080fd5b506100e96103aa565b6040516100b6919061068c565b34801561010257600080fd5b506101266101113660046106a6565b60006020819052908152604090205460ff1681565b60405190151581526020016100b6565b61008b6101443660046106ee565b6101ae565b34801561015557600080fd5b506101a06001547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b6040519081526020016100b6565b60006102446040518060c001604052806102086001547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b815233602082015273ffffffffffffffffffffffffffffffffffffffff871660408201523460608201526080810186905260a00184905261044d565b600081815260208190526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055905073ffffffffffffffffffffffffffffffffffffffff8416336102df6001547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b7f02a52367d10742d8032712c1bb8e0144ff1ec5ffda1ed7d70bb05a27449550543487878760405161031494939291906107f2565b60405180910390a45050600180547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8082168301167fffff0000000000000000000000000000000000000000000000000000000000009091161790555050565b4761037c8161049a565b60405181907f7967de617a5ac1cc7eba2d6f37570a0135afa950d8bb77cdd35f0d0b4e85a16f90600090a250565b60606103d57f00000000000000000000000000000000000000000000000000000000000000006104c9565b6103fe7f00000000000000000000000000000000000000000000000000000000000000006104c9565b6104277f00000000000000000000000000000000000000000000000000000000000000006104c9565b60405160200161043993929190610822565b604051602081830303815290604052905090565b80516020808301516040808501516060860151608087015160a0880151935160009761047d979096959101610898565b604051602081830303815290604052805190602001209050919050565b806040516104a790610606565b6040518091039082f09050801580156104c4573d6000803e3d6000fd5b505050565b60608160000361050c57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b811561053657806105208161091e565b915061052f9050600a83610985565b9150610510565b60008167ffffffffffffffff811115610551576105516106bf565b6040519080825280601f01601f19166020018201604052801561057b576020820181803683370190505b5090505b84156105fe57610590600183610999565b915061059d600a866109b0565b6105a89060306109c4565b60f81b8183815181106105bd576105bd6109dc565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506105f7600a86610985565b945061057f565b949350505050565b600880610a0c83390190565b60005b8381101561062d578181015183820152602001610615565b8381111561063c576000848401525b50505050565b6000815180845261065a816020860160208601610612565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061069f6020830184610642565b9392505050565b6000602082840312156106b857600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60008060006060848603121561070357600080fd5b833573ffffffffffffffffffffffffffffffffffffffff8116811461072757600080fd5b925060208401359150604084013567ffffffffffffffff8082111561074b57600080fd5b818601915086601f83011261075f57600080fd5b813581811115610771576107716106bf565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156107b7576107b76106bf565b816040528281528960208487010111156107d057600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b8481528360208201526080604082015260006108116080830185610642565b905082606083015295945050505050565b60008451610834818460208901610612565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551610870816001850160208a01610612565b6001920191820152835161088b816002840160208801610612565b0160020195945050505050565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a08301526108e360c0830184610642565b98975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361094f5761094f6108ef565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261099457610994610956565b500490565b6000828210156109ab576109ab6108ef565b500390565b6000826109bf576109bf610956565b500690565b600082198211156109d7576109d76108ef565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfe608060405230fffea164736f6c634300080f000a" var L2ToL1MessagePasserDeployedBin = "0x6080604052600436106100695760003560e01c806382e3702d1161004357806382e3702d1461012a578063c2b3e5ac1461016a578063ecc704281461017d57600080fd5b80633f827a5a1461009257806344df8e70146100bf57806354fd4d50146100d457600080fd5b3661008d5761008b33620186a0604051806020016040528060008152506101e2565b005b600080fd5b34801561009e57600080fd5b506100a7600181565b60405161ffff90911681526020015b60405180910390f35b3480156100cb57600080fd5b5061008b6103a6565b3480156100e057600080fd5b5061011d6040518060400160405280600581526020017f312e312e3000000000000000000000000000000000000000000000000000000081525081565b6040516100b691906104d1565b34801561013657600080fd5b5061015a6101453660046104eb565b60006020819052908152604090205460ff1681565b60405190151581526020016100b6565b61008b610178366004610533565b6101e2565b34801561018957600080fd5b506101d46001547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b6040519081526020016100b6565b60006102786040518060c0016040528061023c6001547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b815233602082015273ffffffffffffffffffffffffffffffffffffffff871660408201523460608201526080810186905260a0018490526103de565b600081815260208190526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055905073ffffffffffffffffffffffffffffffffffffffff8416336103136001547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b7f02a52367d10742d8032712c1bb8e0144ff1ec5ffda1ed7d70bb05a2744955054348787876040516103489493929190610637565b60405180910390a45050600180547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8082168301167fffff0000000000000000000000000000000000000000000000000000000000009091161790555050565b476103b08161042b565b60405181907f7967de617a5ac1cc7eba2d6f37570a0135afa950d8bb77cdd35f0d0b4e85a16f90600090a250565b80516020808301516040808501516060860151608087015160a0880151935160009761040e979096959101610667565b604051602081830303815290604052805190602001209050919050565b806040516104389061045a565b6040518091039082f0905080158015610455573d6000803e3d6000fd5b505050565b6008806106bf83390190565b6000815180845260005b8181101561048c57602081850181015186830182015201610470565b8181111561049e576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006104e46020830184610466565b9392505050565b6000602082840312156104fd57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60008060006060848603121561054857600080fd5b833573ffffffffffffffffffffffffffffffffffffffff8116811461056c57600080fd5b925060208401359150604084013567ffffffffffffffff8082111561059057600080fd5b818601915086601f8301126105a457600080fd5b8135818111156105b6576105b6610504565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156105fc576105fc610504565b8160405282815289602084870101111561061557600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b8481528360208201526080604082015260006106566080830185610466565b905082606083015295945050505050565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a08301526106b260c0830184610466565b9897505050505050505056fe608060405230fffea164736f6c634300080f000a"
func init() { func init() {
if err := json.Unmarshal([]byte(L2ToL1MessagePasserStorageLayoutJSON), L2ToL1MessagePasserStorageLayout); err != nil { if err := json.Unmarshal([]byte(L2ToL1MessagePasserStorageLayoutJSON), L2ToL1MessagePasserStorageLayout); err != nil {
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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